Viewing file: MetaKit.py (7.41 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
"""4SuiteServer storage driver for MetaKit RDF back-end
Copyright 2002 Fourthought Inc, USA. """
"""History: 20-aug-2002 [als] created 22-aug-2002 [als] fix: SystemModel was used instead of UserModel """
# $RCSfile: MetaKit.py,v $ __version__ = "$Revision: 1.2 $"[11:-2] __date__ = "$Date: 2005/02/27 04:17:32 $"[7:-2]
import os, sys
from Ft.Rdf import Model from Ft.Rdf.Drivers import MetaKit from Ft.Rdf.Drivers.MetaKit import dec_utf8, enc_utf8
SYSTEM_MODEL_NAME = 'system' USER_MODEL_NAME = 'user'
STRING_VIEW = "ftss_strings[path:S,type:I,data:B]"
def InitializeModule(): """ Post-import hook to initialize module's runtime variables that are not required at import time, but will be needed before the module-level functions are called. """ global metakit global DATABASE_DIR
# Load the required database interface module import metakit
from Ft import GetConfigVar dbdir = os.path.join(GetConfigVar('LOCALSTATEDIR'), 'FlatFile') dbdir = os.environ.get('FT_DATABASE_DIR', dbdir)
# Normalize path, remove unnecessary slashes DATABASE_DIR = os.path.abspath(dbdir)
# FIXME: l10n if not os.path.isdir(DATABASE_DIR): raise ValueError("Directory %r does not exist" % DATABASE_DIR)
# Incorporate the RDF driver module MetaKit.InitializeModule() return
def Exists(properties): """See if this repo exists. Return value: 1 - Everything is present 0 - Some things are there -1 - Nothing is there. """ _mk_db_name = properties["DbName"] _fname = MetaKit.CreateFileName(_mk_db_name) # XXX should we use os.path.isfile() instead? if not os.path.exists(_fname): return -1 # since MetaKit is very tolerant about the database structure, # there is no actual need to see if the database file # contains anything at all # do the version check to behave rigorously try: MetaKit.CheckVersion(_mk_db_name) return 1 except TypeError: return 0
def Initialize(properties): """Initialize a new copy of the repo. This is not the same as a 4ss_manager init. This is very raw. The adapter will take care of calling our other interfaces (createContainer, createUser, etc) with all of the information about the rest of the 'init' stuff to do """ _mk_db_name = properties["DbName"] MetaKit.CreateDb(_mk_db_name, SYSTEM_MODEL_NAME) MetaKit.CreateDb(_mk_db_name, USER_MODEL_NAME)
_fname = MetaKit.CreateFileName(_mk_db_name) # Note: Initialization is done in single-user mode # dependless of MetaKit.MODE_RW setting _db = metakit.storage(_fname, 1) _vw = _db.getas(STRING_VIEW) _db.commit()
def Destroy(properties,tryOnly=0): """Completly destroy the repo""" _fname = MetaKit.CreateFileName(properties["DbName"]) if os.path.exists(_fname): os.unlink(_fname)
def Maintain(properties): """Perform any maintenance on the db""" _fname = MetaKit.CreateFileName(properties["DbName"]) _tmp_fname = _fname + ".tmp" _bak_fname = _fname + ".bak" # open the database read-only _db = metakit.storage(_fname, 0) # serialize the database to tmp-file _f = open(_tmp_fname, "wb") _db.save(_f) _f.close() del _db # rename current db file to .bak if os.path.exists(_bak_fname): os.unlink(_bak_fname) os.rename(_fname, _bak_fname) # expose the serialized storage file os.rename(_tmp_fname, _fname)
class MetaKitDriver:
"""Store information in a MetaKit Database Concurrent access may be supported by setting MODE_RW=2 in MetaKit RDF driver. """
def __init__(self, dbName): # string storage self._dbFile = MetaKit.CreateFileName(dbName) self._db = metakit.storage(self._dbFile, MetaKit.MODE_RW) # restructure the view if needed _vw = self._db.getas(STRING_VIEW) self._db.commit() # RDF models _db = MetaKit.DbAdapter(dbName, SYSTEM_MODEL_NAME) # XXX i do not really like the storage object sharing like this # shouldn't we call .begin() method instead? _db._db = self._db self._systemRdfModel = Model.Model(_db) _db = MetaKit.DbAdapter(dbName, USER_MODEL_NAME) _db._db = self._db self._userRdfModel = Model.Model(_db)
def mk_strings_view(self): """return the MetaKit view containing contents data""" return self._db.view("ftss_strings")
def createFile(self, path, typ, content): """When creating a resource, store the content""" # Verify that we were given a string object if type(content) != str: raise TypeError("Content must be a string, not %s" % type(content)) _vw = self.mk_strings_view() _path = enc_utf8(path) # duplicates aren't allowed, are they? _idx = _vw.find(path=_path, type=typ) if _idx >= 0: # row found # XXX should we raise an exception better # than silently overwrite old resource? _vw[_idx].data = content else: # new row _vw.append(path=_path, type=typ, data=content)
def hasFile(self, path, typ): """return True if the resource exists""" _vw = self.mk_strings_view() return (_vw.find(path=enc_utf8(path), type=typ) >= 0)
def fetchFile(self, path, typ): """return contents""" _vw = self.mk_strings_view() _idx = _vw.find(path=enc_utf8(path), type=typ) if _idx >= 0: # row found return _vw[_idx].data else: return None
def updateFile(self, path, typ, content): """Update only the content about this resource""" # Verify that we were given a string object if type(content) != str: raise TypeError("Content must be a string, not %s" % type(content)) _vw = self.mk_strings_view() _idx = _vw.find(path=enc_utf8(path), type=typ) if _idx >= 0: # row found _vw[_idx].data = content
def deleteFile(self, path, typ): """Delete an object""" _vw = self.mk_strings_view() _idx = _vw.find(path=enc_utf8(path), type=typ) if _idx >= 0: # row found del _vw[_idx]
def getSystemModel(self): return self._systemRdfModel
def getUserModel(self): return self._userRdfModel
def commit(self): # due to the storage object sharing (see comments in __init__) # we have to commit only once. self._db.commit() self._close_db()
def rollback(self): # due to the storage object sharing (see comments in __init__) # we have to rollback only once. # Note: In fact, MetaKit rollback is performed automatically # upon release of the storage object self._db.rollback() self._close_db()
def _close_db(self): """release all storage objects and RDF models""" self._db = None self._systemRdfModel._db = None self._systemRdfModel = None self._userRdfModel._db = None self._userRdfModel = None
def Begin(**properties): """Begin a new transaction. Every driver must support this interface. The properties keyword arguments are passed from the config file (or where ever) to the driver. The Begin file is responsible for doing what ever is needed to validate these arguements """ return MetaKitDriver(properties["DbName"])
NAME="MetaKit"
# vim: set ts=4 et :
|