1#
2# Copyright (c) 2014 Gilles Chehade <gilles@poolp.org>
3#
4# Permission to use, copy, modify, and distribute this software for any
5# purpose with or without fee is hereby granted, provided that the above
6# copyright notice and this permission notice appear in all copies.
7#
8# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15#
16
17import random
18import tempfile
19# import time
20import os
21
22queue = {}
23
24
25def generate_msgid():
26    while True:
27        msgid = random.randint(1, 0xffffffff)
28        if msgid not in queue:
29            return msgid
30
31
32def generate_evpid(msgid):
33    if msgid not in queue:
34        return 0
35    while True:
36        evpid = random.randint(1, 0xffffffff)
37        if evpid not in queue[msgid]:
38            return (msgid << 32) | evpid
39
40
41# message_create must allocate a message entry and return a stricly positive
42# 32-bit unique message identifier.
43#
44def message_create():
45    msgid = generate_msgid()
46    queue[msgid] = {'envelopes': {}, 'message': None}
47    return msgid
48
49
50# message_commit must write content of "path" into message and return
51# either 0 for failure, or 1 for success.
52#
53def message_commit(msgid, path):
54    queue[msgid]['message'] = open(path, 'rb').read()
55    os.unlink(path)
56    return 1
57
58
59# message_delete must remove a message and all associate envelopes,
60# returns either 0 for failure, or 1 for success
61#
62def message_delete(msgid):
63    del queue[msgid]
64    return 1
65
66
67# message_fd_r must return a readable file descriptor pointing to the
68# content of the message, or -1 in case of failure
69#
70def message_fd_r(msgid):
71    tmp = tempfile.TemporaryFile(mode="w+")
72    tmp.write(queue[msgid]['message'])
73    tmp.flush()
74    tmp.seek(0, os.SEEK_SET)
75    return os.dup(tmp.fileno())
76
77
78def message_corrupt():
79    return 1
80
81
82# envelope_create must create an envelope within a message and return a
83# 64-bit unique envelope identifier where upper 32-bit == msgid
84#
85def envelope_create(msgid, envelope):
86    evpid = generate_evpid(msgid)
87    if evpid == 0:
88        return 0
89    queue[msgid]['envelopes'][evpid] = envelope
90    return evpid
91
92
93def envelope_delete(evpid):
94    msgid = (evpid >> 32) & 0xffffffff
95    del queue[msgid]['envelopes'][evpid]
96    if len(queue[msgid]['envelopes']) == 0:
97        del queue[msgid]
98    return 1
99
100
101# envelope_update  must create an envelope within a message and return a
102# 64-bit unique envelope identifier where upper 32-bit == msgid
103#
104def envelope_update(evpid, envelope):
105    queue[(evpid >> 32) & 0xffffffff]['envelopes'][evpid] = envelope
106    return 1
107
108
109def envelope_load(evpid):
110    msgid = (evpid >> 32) & 0xffffffff
111    if msgid not in queue:
112        return 0
113    if evpid not in queue[msgid]['envelopes']:
114        return 0
115    return queue[msgid]['envelopes'][evpid]
116
117
118def envelope_walk():
119    return -1
120