Back to index

nordugrid-arc-nox  1.1.0~rc6
picklestore.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.basestore import BaseStore
00006 
00007 from arcom.logger import Logger
00008 log = Logger(arc.Logger(arc.Logger_getRootLogger(), 'arcom.PickleStore'))
00009 
00010 class PickleStore(BaseStore):
00011     """ Class for storing object in a serialized python format. """
00012 
00013     def __init__(self, storecfg, non_existent_object = {}):
00014         """ Constructor of PickleStore.
00015 
00016         PickleStore(storecfg)
00017 
00018         'storecfg' is an XMLNode with a 'DataDir'
00019         'non_existent_object' will be returned if an object not found
00020         """
00021         BaseStore.__init__(self, storecfg, non_existent_object)
00022         log.msg(arc.VERBOSE, "PickleStore constructor called")
00023         log.msg(arc.VERBOSE, "datadir:", self.datadir)
00024 
00025     def _filename(self, ID):
00026         """ Creates a filename from an ID.
00027 
00028         _filename(ID)
00029 
00030         'ID' is the ID of the given object.
00031         The filename will be 
00032         datadir/<two first letters of base64 encoded form of the ID>/<base64 encoded form of the ID>.
00033         """
00034         name = base64.b64encode(ID)
00035         return os.path.join(self.datadir, name[:2], name)
00036 
00037     def _tmpfilename(self, ID):
00038         """ Creates a tmpfilename from an ID.
00039 
00040         _tmpfilename(ID)
00041 
00042         'ID' is the ID of the given object.
00043         The filename will be datadir/<base64 encoded form of the ID>.
00044         The corresponding file to _tmpfilename should always be moved to _filename(ID)
00045         """
00046         name = base64.b64encode(ID)
00047         return os.path.join(self.datadir, name)
00048 
00049     def _list(self):
00050         """ List all the existing files.
00051         
00052         _list()
00053         
00054         Returns a list of filenames.
00055         """
00056         names = []
00057         # list the contects of each subdirectory withtin the data directory
00058         for subdir in os.listdir(self.datadir):
00059             if os.path.isdir(os.path.join(self.datadir,subdir)):
00060                 names.extend(os.listdir(os.path.join(self.datadir, subdir)))
00061         return names
00062 
00063     def list(self):
00064         """ List the IDs of the existing entries.
00065         
00066         list()
00067         
00068         Returns a list of IDs.
00069         """
00070         IDs = []
00071         # get all the filenames
00072         for name in self._list():
00073             try: # decode the filename
00074                 ID = base64.b64decode(name)
00075                 IDs.append(ID)
00076             except:
00077                 log.msg()
00078         return IDs
00079 
00080     def get(self, ID):
00081         """ Returns the object with the given ID.
00082 
00083         get(ID)
00084 
00085         'ID' is the ID of the requested object.
00086         If there is no object with this ID, returns the given non_existent_object value.
00087         """
00088         try:
00089             # generates a filename from the ID
00090             # then use pickle to load the previously serialized data
00091             return pickle.load(file(self._filename(ID), 'rb'))
00092         except IOError:
00093             # don't print 'file not found' if there is no such ID
00094             pass
00095         except EOFError:
00096             # TODO: find out what causes this problem
00097             pass
00098         except:
00099             # print whatever exception happened
00100             log.msg()
00101             log.msg(arc.ERROR, "filename:", self._filename(ID))
00102         # if there was an exception, return the given non_existent_object
00103         return copy.deepcopy(self.non_existent_object)
00104 
00105     def set(self, ID, object):
00106         """ Stores an object with the given ID..
00107 
00108         set(ID, object)
00109 
00110         'ID' is the ID of the object
00111         'object' is the object itself
00112         If there is already an object with this ID it will be overwritten completely.
00113         """
00114         if not ID:
00115             raise Exception, 'ID is empty'
00116         try:
00117             # generates a filename from the ID
00118             fn = self._filename(ID)
00119             tmp_fn = self._tmpfilename(ID)
00120             # if 'object' is empty, don't make file
00121             if object:
00122                 # serialize the given list into tmp_fn
00123                 pickle.dump(object, file(tmp_fn,'wb'))
00124                 # try to rename the file
00125                 try:
00126                     os.rename(tmp_fn,fn)
00127                 except:
00128                     # try to create parent dir first, then rename the file
00129                     os.mkdir(os.path.dirname(fn))
00130                     os.rename(tmp_fn,fn)
00131             elif os.path.isfile(fn):
00132                 # object empty, file is not needed anymore
00133                 os.remove(fn)
00134         except:
00135             log.msg()