Mercurial > libervia-pubsub
annotate idavoll/memory_storage.py @ 162:84cfe9fe38c5
Comply with the access model 'open'.
Currently, the only implemented access model is 'open', so we should not check
for the subscription of the requestor for item retrieval. We do reject
outcasts.
author | Ralph Meijer <ralphm@ik.nu> |
---|---|
date | Wed, 06 Sep 2006 12:57:53 +0000 |
parents | 5191ba7c4df8 |
children | ef22e4150caa |
rev | line source |
---|---|
155
5191ba7c4df8
Work towards first release 0.5.0.
Ralph Meijer <ralphm@ik.nu>
parents:
148
diff
changeset
|
1 # Copyright (c) 2003-2006 Ralph Meijer |
5191ba7c4df8
Work towards first release 0.5.0.
Ralph Meijer <ralphm@ik.nu>
parents:
148
diff
changeset
|
2 # See LICENSE for details. |
5191ba7c4df8
Work towards first release 0.5.0.
Ralph Meijer <ralphm@ik.nu>
parents:
148
diff
changeset
|
3 |
107 | 4 import copy |
5 from zope.interface import implements | |
6 from twisted.internet import defer | |
7 from twisted.words.protocols.jabber import jid | |
8 import storage | |
9 | |
115 | 10 default_config = {"pubsub#persist_items": True, |
11 "pubsub#deliver_payloads": True} | |
107 | 12 |
13 class Storage: | |
14 | |
15 implements(storage.IStorage) | |
16 | |
17 def __init__(self): | |
18 self._nodes = {} | |
19 | |
20 def get_node(self, node_id): | |
21 try: | |
22 node = self._nodes[node_id] | |
23 except KeyError: | |
24 return defer.fail(storage.NodeNotFound()) | |
25 | |
26 return defer.succeed(node) | |
27 | |
28 def get_node_ids(self): | |
29 return defer.succeed(self._nodes.keys()) | |
30 | |
31 def create_node(self, node_id, owner, config = None, type='leaf'): | |
32 if node_id in self._nodes: | |
33 return defer.fail(storage.NodeExists()) | |
34 | |
35 if not config: | |
36 config = copy.copy(default_config) | |
37 | |
38 if type != 'leaf': | |
39 raise NotImplementedError | |
40 | |
41 node = LeafNode(node_id, owner, config) | |
42 self._nodes[node_id] = node | |
43 | |
44 return defer.succeed(None) | |
45 | |
46 def delete_node(self, node_id): | |
47 try: | |
48 del self._nodes[node_id] | |
49 except KeyError: | |
50 return defer.fail(storage.NodeNotFound()) | |
51 | |
52 return defer.succeed(None) | |
53 | |
54 def get_affiliations(self, entity): | |
112 | 55 entity = entity.userhost() |
56 return defer.succeed([(node.id, node._affiliations[entity]) | |
107 | 57 for name, node in self._nodes.iteritems() |
112 | 58 if entity in node._affiliations]) |
107 | 59 |
60 def get_subscriptions(self, entity): | |
61 subscriptions = [] | |
62 for node in self._nodes.itervalues(): | |
63 for subscriber, subscription in node._subscriptions.iteritems(): | |
148
b03e5ad81173
Change all calls to jid.JID to jid.internJID to avoid redoing stringprep.
Ralph Meijer <ralphm@ik.nu>
parents:
146
diff
changeset
|
64 subscriber = jid.internJID(subscriber) |
112 | 65 if subscriber.userhostJID() == entity.userhostJID(): |
107 | 66 subscriptions.append((node.id, subscriber, |
67 subscription.state)) | |
68 | |
69 return defer.succeed(subscriptions) | |
70 | |
71 class Node: | |
72 | |
73 implements(storage.INode) | |
74 | |
75 def __init__(self, node_id, owner, config): | |
76 self.id = node_id | |
112 | 77 self._affiliations = {owner.userhost(): 'owner'} |
107 | 78 self._subscriptions = {} |
79 self._config = config | |
80 | |
81 def get_type(self): | |
82 return self.type | |
83 | |
84 def get_configuration(self): | |
85 return self._config | |
86 | |
87 def get_meta_data(self): | |
88 config = copy.copy(self._config) | |
89 config["pubsub#node_type"] = self.type | |
90 return config | |
91 | |
92 def set_configuration(self, options): | |
93 for option in options: | |
94 if option in self._config: | |
95 self._config[option] = options[option] | |
96 | |
97 return defer.succeed(None) | |
98 | |
99 def get_affiliation(self, entity): | |
100 return defer.succeed(self._affiliations.get(entity.full())) | |
101 | |
120
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
102 def get_subscription(self, subscriber): |
107 | 103 try: |
104 subscription = self._subscriptions[subscriber.full()] | |
120
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
105 except KeyError: |
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
106 state = None |
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
107 else: |
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
108 state = subscription.state |
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
109 return defer.succeed(state) |
107 | 110 |
120
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
111 def add_subscription(self, subscriber, state): |
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
112 if self._subscriptions.get(subscriber.full()): |
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
113 return defer.fail(storage.SubscriptionExists()) |
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
114 |
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
115 subscription = Subscription(state) |
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
116 self._subscriptions[subscriber.full()] = subscription |
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
117 return defer.succeed(None) |
107 | 118 |
119 def remove_subscription(self, subscriber): | |
120
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
120 try: |
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
121 del self._subscriptions[subscriber.full()] |
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
122 except KeyError: |
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
123 return defer.fail(storage.SubscriptionNotFound()) |
107 | 124 |
125 return defer.succeed(None) | |
126 | |
127 def get_subscribers(self): | |
148
b03e5ad81173
Change all calls to jid.JID to jid.internJID to avoid redoing stringprep.
Ralph Meijer <ralphm@ik.nu>
parents:
146
diff
changeset
|
128 subscribers = [jid.internJID(subscriber) for subscriber, subscription |
107 | 129 in self._subscriptions.iteritems() |
130 if subscription.state == 'subscribed'] | |
131 | |
132 return defer.succeed(subscribers) | |
133 | |
146
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
134 def is_subscribed(self, entity): |
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
135 for subscriber, subscription in self._subscriptions.iteritems(): |
148
b03e5ad81173
Change all calls to jid.JID to jid.internJID to avoid redoing stringprep.
Ralph Meijer <ralphm@ik.nu>
parents:
146
diff
changeset
|
136 if jid.internJID(subscriber).userhost() == entity.userhost() and \ |
146
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
137 subscription.state == 'subscribed': |
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
138 return defer.succeed(True) |
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
139 |
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
140 return defer.succeed(False) |
107 | 141 |
145
f393bccec4bc
Add get_affiliations to Node class in storage facilities in preparation of
Ralph Meijer <ralphm@ik.nu>
parents:
142
diff
changeset
|
142 def get_affiliations(self): |
148
b03e5ad81173
Change all calls to jid.JID to jid.internJID to avoid redoing stringprep.
Ralph Meijer <ralphm@ik.nu>
parents:
146
diff
changeset
|
143 affiliations = [(jid.internJID(entity), affiliation) for entity, affiliation |
145
f393bccec4bc
Add get_affiliations to Node class in storage facilities in preparation of
Ralph Meijer <ralphm@ik.nu>
parents:
142
diff
changeset
|
144 in self._affiliations.iteritems()] |
f393bccec4bc
Add get_affiliations to Node class in storage facilities in preparation of
Ralph Meijer <ralphm@ik.nu>
parents:
142
diff
changeset
|
145 |
f393bccec4bc
Add get_affiliations to Node class in storage facilities in preparation of
Ralph Meijer <ralphm@ik.nu>
parents:
142
diff
changeset
|
146 return defer.succeed(affiliations) |
f393bccec4bc
Add get_affiliations to Node class in storage facilities in preparation of
Ralph Meijer <ralphm@ik.nu>
parents:
142
diff
changeset
|
147 |
146
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
148 class LeafNodeMixin: |
107 | 149 |
150 type = 'leaf' | |
151 | |
146
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
152 def __init__(self): |
107 | 153 self._items = {} |
154 self._itemlist = [] | |
155 | |
156 def store_items(self, items, publisher): | |
157 for data in items: | |
158 id = data["id"] | |
139
8f6956b9a688
Follow API change in Twisted Xish, while still being compatible with
Ralph Meijer <ralphm@ik.nu>
parents:
126
diff
changeset
|
159 data = data.toXml() |
8f6956b9a688
Follow API change in Twisted Xish, while still being compatible with
Ralph Meijer <ralphm@ik.nu>
parents:
126
diff
changeset
|
160 if isinstance(data, str): |
8f6956b9a688
Follow API change in Twisted Xish, while still being compatible with
Ralph Meijer <ralphm@ik.nu>
parents:
126
diff
changeset
|
161 data = data.decode('utf-8') |
8f6956b9a688
Follow API change in Twisted Xish, while still being compatible with
Ralph Meijer <ralphm@ik.nu>
parents:
126
diff
changeset
|
162 item = (data, publisher) |
107 | 163 if id in self._items: |
164 self._itemlist.remove(self._items[id]) | |
165 self._items[id] = item | |
166 self._itemlist.append(item) | |
167 | |
168 return defer.succeed(None) | |
169 | |
170 def remove_items(self, item_ids): | |
171 deleted = [] | |
172 | |
173 for item_id in item_ids: | |
142
812300cdbc22
Changed behaviour of retraction of items so that only the actually deleted
Ralph Meijer <ralphm@ik.nu>
parents:
139
diff
changeset
|
174 try: |
812300cdbc22
Changed behaviour of retraction of items so that only the actually deleted
Ralph Meijer <ralphm@ik.nu>
parents:
139
diff
changeset
|
175 item = self._items[item_id] |
812300cdbc22
Changed behaviour of retraction of items so that only the actually deleted
Ralph Meijer <ralphm@ik.nu>
parents:
139
diff
changeset
|
176 except KeyError: |
812300cdbc22
Changed behaviour of retraction of items so that only the actually deleted
Ralph Meijer <ralphm@ik.nu>
parents:
139
diff
changeset
|
177 pass |
812300cdbc22
Changed behaviour of retraction of items so that only the actually deleted
Ralph Meijer <ralphm@ik.nu>
parents:
139
diff
changeset
|
178 else: |
812300cdbc22
Changed behaviour of retraction of items so that only the actually deleted
Ralph Meijer <ralphm@ik.nu>
parents:
139
diff
changeset
|
179 self._itemlist.remove(item) |
812300cdbc22
Changed behaviour of retraction of items so that only the actually deleted
Ralph Meijer <ralphm@ik.nu>
parents:
139
diff
changeset
|
180 del self._items[item_id] |
812300cdbc22
Changed behaviour of retraction of items so that only the actually deleted
Ralph Meijer <ralphm@ik.nu>
parents:
139
diff
changeset
|
181 deleted.append(item_id) |
107 | 182 |
142
812300cdbc22
Changed behaviour of retraction of items so that only the actually deleted
Ralph Meijer <ralphm@ik.nu>
parents:
139
diff
changeset
|
183 return defer.succeed(deleted) |
107 | 184 |
185 def get_items(self, max_items=None): | |
186 if max_items: | |
187 list = self._itemlist[-max_items:] | |
188 else: | |
189 list = self._itemlist | |
139
8f6956b9a688
Follow API change in Twisted Xish, while still being compatible with
Ralph Meijer <ralphm@ik.nu>
parents:
126
diff
changeset
|
190 return defer.succeed([item[0] for item in list]) |
107 | 191 |
192 def get_items_by_id(self, item_ids): | |
193 items = [] | |
194 for item_id in item_ids: | |
195 try: | |
196 item = self._items[item_id] | |
197 except KeyError: | |
198 pass | |
199 else: | |
139
8f6956b9a688
Follow API change in Twisted Xish, while still being compatible with
Ralph Meijer <ralphm@ik.nu>
parents:
126
diff
changeset
|
200 items.append(item[0]) |
107 | 201 return defer.succeed(items) |
202 | |
203 def purge(self): | |
204 self._items = {} | |
205 self._itemlist = [] | |
206 | |
207 return defer.succeed(None) | |
208 | |
146
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
209 class LeafNode(Node, LeafNodeMixin): |
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
210 |
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
211 implements(storage.ILeafNode) |
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
212 |
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
213 def __init__(self, node_id, owner, config): |
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
214 Node.__init__(self, node_id, owner, config) |
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
215 LeafNodeMixin.__init__(self) |
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
216 |
107 | 217 class Subscription: |
218 | |
219 implements(storage.ISubscription) | |
220 | |
221 def __init__(self, state): | |
222 self.state = state |