from ConfigParser import ConfigParser import cPickle as pickle from threading import Lock #TODO replace ConfigParser for better performance class PersistentContainer(object): cfgparsers = dict() locks = dict() def __init__(self,namespace,path): self.namespace = namespace self.path = path self.trans_cache = dict() self.trans_del = [] if not path in PersistentContainer.locks: PersistentContainer.locks[path] = Lock() self.transaction = PersistentContainer.locks[path] if not path in PersistentContainer.cfgparsers: PersistentContainer.cfgparsers[path] = ConfigParser() PersistentContainer.cfgparsers[path].read([path]) self.cp = PersistentContainer.cfgparsers[path] if not self.cp.has_section(namespace): self.cp.add_section(namespace) def start_transaction(self,blocking=True): return self.transaction.acquire(blocking) def commit_transaction(self): self._write() self.transaction.release() def rollback(self): for k in self.trans_cache: del self.trans_cache[k] self.transaction.release() def is_owned(self): return self.transaction.locked() def __getitem__(self, name): if self.cp.has_option(self.namespace,name): return pickle.loads(self.cp.get(self.namespace,name)) return None def __setitem__(self, name,val): self.trans_cache[name]=val if not self.is_owned(): self._write() def __delitem__(self, name): if name not in self.trans_del: self.trans_del.append(name) if name in self.trans_cache: del self.trans_cache[name] if not self.is_owned(): self._write() def __contains__(self,name): return self.cp.has_option(self.namespace,name) def _write(self): for k in self.trans_cache: val = self.trans_cache[k] self.cp.set(self.namespace,k,pickle.dumps(val)) while len(self.trans_del): n = self.trans_del.pop() self.cp.remove_option(self.namespace,n) f = open(self.path,'w') self.cp.write(f) f.close()