Back to index

nordugrid-arc-nox  1.1.0~rc6
cachedpicklestore.py
Go to the documentation of this file.
00001 import arc
00002 import copy, os, base64
00003 import cPickle as pickle
00004 
00005 from arcom.store.picklestore import PickleStore
00006 
00007 from arcom.logger import Logger
00008 log = Logger(arc.Logger(arc.Logger_getRootLogger(), 'arcom.CachedPickleStore'))
00009 
00010 class CachedPickleStore(PickleStore):
00011     """ Class for storing object in a serialized python format. """
00012 
00013     def __init__(self, storecfg, non_existent_object = {}):
00014         """ Constructor of CachedPickleStore.
00015 
00016         CachedPickleStore(storecfg)
00017 
00018         'storecfg' is an XMLNode with a 'DataDir'
00019         'non_existent_object' will be returned if an object not found
00020         """
00021         PickleStore.__init__(self, storecfg, non_existent_object)
00022         log.msg(arc.VERBOSE, "PickleStore with datadir '%s' is a CachedPickleStore" % self.datadir)
00023         self.store = {}
00024         self._load_storage()
00025 
00026     def _load_storage(self):
00027         filelist = self._list()
00028         for f in filelist:
00029             self.store[base64.b64decode(f)] = pickle.load(file(os.path.join(self.datadir,f[:2],f), 'rb'))
00030             
00031     def list(self):
00032         """ List the IDs of the existing entries.
00033         
00034         list()
00035         
00036         Returns a list of IDs.
00037         """
00038         return self.store.keys()
00039             
00040     def get(self, ID):
00041         """ Returns the object with the given ID.
00042 
00043         get(ID)
00044 
00045         'ID' is the ID of the requested object.
00046         If there is no object with this ID, returns the given non_existent_object value.
00047         """
00048         try:
00049             # return a copy of the in-memory stored object
00050             return copy.deepcopy(self.store[ID])
00051         except KeyError:
00052             # don't print 'KeyError' if there is no such ID
00053             pass
00054         except:
00055             # print whatever exception happened
00056             log.msg()
00057             log.msg(arc.ERROR, "ID", ID)
00058         # if there was an exception, return the given non_existent_object
00059         return copy.deepcopy(self.non_existent_object)
00060 
00061     def set(self, ID, obj):
00062         """ Stores an object with the given ID..
00063 
00064         set(ID, obj)
00065 
00066         'ID' is the ID of the object
00067         'obj' is the object itself
00068         If there is already an object with this ID it will be overwritten completely.
00069         """
00070         if not ID:
00071             raise Exception, 'ID is empty'
00072         try:
00073             # generates a filename from the ID
00074             fn = self._filename(ID)
00075             tmp_fn = self._tmpfilename(ID)
00076             # if 'obj' is empty, don't make file
00077             if obj:
00078                 # TODO: what if something happens between the disk write and the in-memory store update, and only the disk gets updated?
00079                 # serialize the given list into tmp_fn
00080                 pickle.dump(obj, file(tmp_fn,'wb'))
00081                 # try to rename the file
00082                 try:
00083                     os.rename(tmp_fn,fn)
00084                 except:
00085                     # try to create parent dir first, then rename the file
00086                     os.mkdir(os.path.dirname(fn))
00087                     os.rename(tmp_fn,fn)
00088                 # store a copy of the object
00089                 self.store[ID] = copy.deepcopy(obj)
00090             elif os.path.isfile(fn):
00091                 # object empty, file is not needed anymore
00092                 os.remove(fn)
00093                 del(self.store[ID])
00094         except:
00095             log.msg()