python-objectbroker/objectbroker/ObjectBroker.py

150 lines
3.4 KiB
Python

import weakref
import collections
import pickle
from simplelog import log,LLDEBUGCALL,LLDEBUG,LLINFO,LLERROR
from objectbroker import Persistence,NoPersistence
def dump_state(state):
print("Persistent ID: %s" % (state["pid"],))
print("Type: %s.%s" % (state["module"],state["class"]))
print("Non-Persistent:")
for n in state["fields"].keys():
print("K: %s = %s" % (n,state["fields"][n]))
print("Persistent:")
for n in state["pfields"].keys():
print("K: %s = %s" % (n,state["pfields"][n]))
print("")
def obj_getstate(o):
if not isinstance(o, Persistence):
raise TypeError("obj_getstate() needs Persistence object")
state = {}
state["pid"] = Persistence._persistence_id( o )
state["module"] = o.__class__.__module__
state["class"] = o.__class__.__name__
state["fields"] = {}
state["pfields"] = {}
state["pvalues"] = {}
nopersistence = getattr(o,"NOPERSIST",())
d = object.__getattribute__(o, "__dict__")
for n in d.keys():
a = getattr( o, n )
if (not isinstance( a, collections.Callable)) or isinstance( a, object ):
if (isinstance( a, NoPersistence)) or (n in nopersistence):
state["fields"][n] = None
elif (isinstance( a, Persistence)):
state["pvalues"][n] = a
state["pfields"][n] = Persistence._persistence_id( a )
else:
state["fields"][n] = a
return state
class ObjectBroker:
"""ObjectBroker """
def __init__(self, store={}):
self.__store = store
self.__cache = weakref.WeakValueDictionary()
self.__unsaved = {}
log("ObjectBroker instantiated", LLDEBUGCALL)
self.check()
def save(self,o,recursed=False):
if (o in self.__unsaved):
return
state = obj_getstate(o)
# dump_state( state )
self.__cache[ state["pid"] ] = o
self.__unsaved[o] = state
for pn in state["pvalues"]:
self.save( state["pvalues"][pn], recursed=True )
# dump_state(state)
if not recursed:
for n in list( self.__unsaved.keys() ):
s = self.__unsaved[n]
s["pvalues"] = None
try:
self.__store[ s["pid"] ] = pickle.dumps(s)
del self.__unsaved[n]
except AttributeError as ae:
log("AttributeError while storing object: %s" % (s,))
return state["pid"]
def load(self,persistence_id):
if (persistence_id in self.__cache):
o = self.__cache[persistence_id]
if not o is None:
return o
state = pickle.loads(self.__store[ persistence_id ])
dump_state(state)
m = __import__(state["module"],fromlist=[state["class"]])
cls = getattr(m, state["class"] )
o = cls.__new__(cls)
self.__cache[ persistence_id ] = o
for n in state["fields"]:
setattr( o, n, state["fields"][n] )
for n in state["pfields"]:
print("SS: %s = %s" % (n,state["pfields"][n]))
setattr( o, n, self.load( state["pfields"][n] ))
return o
def remove(self,o=None,persistence_id=None):
pass
def check(self):
log("ObjectBroker: checking consistency of store",LLINFO)
clean = True
for uid in dir(self.__store):
if not uid == "ROOT":
try:
state = pickle.loads(self.__store[ uid ])
for n in state["pfields"]:
if not state["pfields"][n] in self.__store:
log("Found Object {0} referencing non-existent {1} = {2}".format(uid,n,state["pfields"][n]))
clean = False
except:
clean = False
# if not clean:
# log("ObjectBroker: consistency check failed!",LLERROR)
# raise Exception("ObjectBroker not consistent")
log("ObjectBroker: consistency check successful",LLINFO)