Mercurial > libervia-pubsub
annotate idavoll/memory_storage.py @ 155:5191ba7c4df8
Work towards first release 0.5.0.
- Add licensing information (MIT)
- Improve installation instructions.
- Use new plugins framework in twisted.
author | Ralph Meijer <ralphm@ik.nu> |
---|---|
date | Mon, 21 Aug 2006 16:05:35 +0000 |
parents | b03e5ad81173 |
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 |