You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
75 lines
1.9 KiB
75 lines
1.9 KiB
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()
|
|
|
|
|