def open(self): self.synclock.acquire() try: self.storage = MapStorage(self.path, self.name, self.extension, encode=None, decode=None) self.storage.open() finally: self.synclock.release()
class PersistentDictionary(Persistent, dict): def __init__(self, name, initdata=(), **kw): self.removed = set() self.modified = set() kw.setdefault('extension', 'dict') self.keyencode = kw.get('keyencode', None) self.keydecode = kw.get('keydecode', None) Persistent.__init__(self, name, **kw) dict.__init__(self, initdata) def open(self): self.synclock.acquire() try: self.storage = MapStorage(self.path, self.name, self.extension, encode=None, decode=None) self.storage.open() finally: self.synclock.release() def getmodified(self): self.synclock.acquire() try: modkeys = self.modified.copy() finally: self.synclock.release() return modkeys def getremoved(self): self.synclock.acquire() try: rmkeys = self.removed.copy() finally: self.synclock.release() return rmkeys def update_storage(self): """ Serialize and data associated with object and update storage record to match serialization. Overridden here to insert efficiency code which only changes those items which have been modified or removed, instead of hammer-method used by super. """ self.synclock.acquire() try: for key in self.getremoved(): self.storage.remove(self.encodedkey(key)) self.removed.remove(key) for key in self.getmodified(): self.storage[self.encodedkey(key)] = self.encodedvalue(key) self.modified.remove(key) finally: self.synclock.release() def encodedkey(self, key): return self.serializekey(key) def encodedvalue(self, key): self.synclock.acquire() try: value = self[key] finally: self.synclock.release() return self.serialize(value) def encodeditem(self, key): return (self.encodedkey(key), self.encodedvalue(key)) def getencoded(self): self.synclock.acquire() try: items = [self.encodeditem(key) for key in self.keys()] finally: self.synclock.release() return dict(items) def setencoded(self, data): decodeditems = [] self.synclock.acquire() try: for key, value in data.items(): try: decodedkey = self.unserializekey(key) decodedvalue = self.unserialize(value) except: msglog.log("broadway", msglog.types.WARN, "Failed to decoded: (%s, %s)" % (key, value)) msglog.exception() else: decodeditems.append((decodedkey, decodedvalue)) dict.update(self, decodeditems) finally: self.synclock.release() def notify_changed(self, keys): if not isinstance(keys, (set, list, tuple)): keys = [keys] self.synclock.acquire() try: map(self.modified.add, keys) map(self.removed.discard, keys) if self.autopersist: self.commit() finally: self.synclock.release() def notify_removed(self, keys): if not isinstance(keys, (set, list, tuple)): keys = [keys] self.synclock.acquire() try: map(self.removed.add, keys) map(self.modified.discard, keys) if self.autopersist: self.commit() finally: self.synclock.release() def clear(self): self.synclock.acquire() try: keys = set(self) dict.clear(self) self.notify_removed(keys) finally: self.synclock.release() def popitem(self): self.synclock.acquire() try: (key, value) = dict.popitem(self) self.notify_removed(key) finally: self.synclock.release() return (key, value) def update(self, value): # By doing the dict(items) we ensure the value is a # dictionary type, even if a list of tuples was passed in. valuedict = dict(value) self.synclock.acquire() try: dict.update(self, valuedict) self.notify_changed(valuedict.keys()) finally: self.synclock.release() def pop(self, key): self.synclock.acquire() try: value = dict.pop(self, key) self.notify_removed(key) finally: self.synclock.release() return value def setdefault(self, name, value): self.synclock.acquire() try: if not self.has_key(name): self[key] = value self.notify_changed(key) finally: self.synclock.release() return self[key] def serializekey(self, key): if self.keyencode is not None: key = self.keyencode(key) return key def unserializekey(self, key): if self.keydecode is not None: key = self.keydecode(key) return key def __delitem__(self, key): self.pop(key) def __setitem__(self, key, value): self.synclock.acquire() try: dict.__setitem__(self, key, value) self.notify_changed(key) finally: self.synclock.release()
class PersistentDictionary(Persistent, dict): def __init__(self, name, initdata=(), **kw): self.removed = set() self.modified = set() kw.setdefault('extension', 'dict') self.keyencode = kw.get('keyencode', None) self.keydecode = kw.get('keydecode', None) Persistent.__init__(self, name, **kw) dict.__init__(self, initdata) def open(self): self.synclock.acquire() try: self.storage = MapStorage(self.path, self.name, self.extension, encode=None, decode=None) self.storage.open() finally: self.synclock.release() def getmodified(self): self.synclock.acquire() try: modkeys = self.modified.copy() finally: self.synclock.release() return modkeys def getremoved(self): self.synclock.acquire() try: rmkeys = self.removed.copy() finally: self.synclock.release() return rmkeys def update_storage(self): """ Serialize and data associated with object and update storage record to match serialization. Overridden here to insert efficiency code which only changes those items which have been modified or removed, instead of hammer-method used by super. """ self.synclock.acquire() try: for key in self.getremoved(): self.storage.remove(self.encodedkey(key)) self.removed.remove(key) for key in self.getmodified(): self.storage[self.encodedkey(key)] = self.encodedvalue(key) self.modified.remove(key) finally: self.synclock.release() def encodedkey(self, key): return self.serializekey(key) def encodedvalue(self, key): self.synclock.acquire() try: value = self[key] finally: self.synclock.release() return self.serialize(value) def encodeditem(self, key): return (self.encodedkey(key), self.encodedvalue(key)) def getencoded(self): self.synclock.acquire() try: items = [self.encodeditem(key) for key in self.keys()] finally: self.synclock.release() return dict(items) def setencoded(self, data): decodeditems = [] self.synclock.acquire() try: for key,value in data.items(): try: decodedkey = self.unserializekey(key) decodedvalue = self.unserialize(value) except: msglog.log("broadway", msglog.types.WARN, "Failed to decoded: (%s, %s)" % (key, value)) msglog.exception() else: decodeditems.append((decodedkey, decodedvalue)) dict.update(self, decodeditems) finally: self.synclock.release() def notify_changed(self, keys): if not isinstance(keys, (set, list, tuple)): keys = [keys] self.synclock.acquire() try: map(self.modified.add, keys) map(self.removed.discard, keys) if self.autopersist: self.commit() finally: self.synclock.release() def notify_removed(self, keys): if not isinstance(keys, (set, list, tuple)): keys = [keys] self.synclock.acquire() try: map(self.removed.add, keys) map(self.modified.discard, keys) if self.autopersist: self.commit() finally: self.synclock.release() def clear(self): self.synclock.acquire() try: keys = set(self) dict.clear(self) self.notify_removed(keys) finally: self.synclock.release() def popitem(self): self.synclock.acquire() try: (key,value) = dict.popitem(self) self.notify_removed(key) finally: self.synclock.release() return (key,value) def update(self, value): # By doing the dict(items) we ensure the value is a # dictionary type, even if a list of tuples was passed in. valuedict = dict(value) self.synclock.acquire() try: dict.update(self, valuedict) self.notify_changed(valuedict.keys()) finally: self.synclock.release() def pop(self, key): self.synclock.acquire() try: value = dict.pop(self, key) self.notify_removed(key) finally: self.synclock.release() return value def setdefault(self, name, value): self.synclock.acquire() try: if not self.has_key(name): self[key] = value self.notify_changed(key) finally: self.synclock.release() return self[key] def serializekey(self, key): if self.keyencode is not None: key = self.keyencode(key) return key def unserializekey(self, key): if self.keydecode is not None: key = self.keydecode(key) return key def __delitem__(self, key): self.pop(key) def __setitem__(self, key, value): self.synclock.acquire() try: dict.__setitem__(self, key, value) self.notify_changed(key) finally: self.synclock.release()