Viewing file: __init__.py (35.76 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
#!/usr/bin/env python """ A persistent Repository driver using Berkeley (BSD) database files
Requires pybsddb (http://pybsddb.sourceforge.net/bsddb3.html), which is the standard bsddb module in Python 2.3 and up. However, even if you are using Python 2.3 up, it is possible that you won't have a functioning bsddb at all, or it may be wrapping the db185 Berkeley DB C libraries.
If necessary, update your C libs (db-4.3.27 preferred for compatibility with Berkeley DB XML). And if possible, upgrade or install pybsddb (this is mandatory on Python 2.2, if you want this driver to work).
You can determine your pbsddb3 version this way: Type "help", "copyright", "credits" or "license" for more information. >>> from bsddb3 import db >>> db.version() (4, 3, 27)
This driver can also store XML content in a heirarchy of Berkeley DB XML (2.0.9) Containers
see:
* http://www.sleepycat.com/xmldocs/gsg_xml/cxx/containers.html * http://www.sleepycat.com/xmldocs/gsg_xml/cxx/xquery.html * http://www.sleepycat.com/xmldocs/gsg_xml/cxx/examineresults.html * http://www.sleepycat.com/xmldocs/gsg_xml/cxx/indices.html
Documents are stored as Whole Documents (not individual nodes) unless the 'OneMBDocuments' driver property is set to true (it's false by default). When the 'DbXml' driver property is 'true', the following containers are setup
XML Databases (containers which key resources by their reposository paths)): - ftss_metadata_xml.dbxml ('path' --> content) Metadata Documents - ftss_repo_xml.dbxml ('path' --> content) Repsitory XML Documents - ftss_user_all.dbxml ('path' --> content) User, non-repository Documents o used when 'DataStoreContainers' driver property is 'false' (by default)
Repository Documents are:
Servers,Users,Groups,Containers,Document Definitions, RDF Documents,Commands, and Aliases
Non-XML content is stored in the following databases nonXML Databases (Berkeley DB databases keyed by their repository paths): - ftss_content.db ('path' --> content) o stores XML content here as well when 'DbXml' driver property is 'false' (default) - ftss_cache.db ('path --> cache) - ftss_session.db ('path' --> session) - ftss_types.db ('path' -> ResourceType) (an index of resource types) - ftss_metadata_strings.db ('path' --> metadata document string) o used when 'DbXml' driver property is 'false' (default)
Copyright 2005 Fourthought, Inc. (USA). Detailed license and copyright information: http://4suite.org/COPYRIGHT Project home, documentation, distributions: http://4suite.org/ """
from distutils.dir_util import remove_tree import urllib, types, sys, cStringIO, re,os,sha from Ft.Server.Server.Drivers.PathImp import Path from Ft.Rdf import Model from Ft.Xml import XPath from Ft.Xml.Domlette import NonvalidatingReader, PrettyPrint from string import join, split from Ft.Server import FTSERVER_NAMESPACE from Ft.Server.Server import FtServerServerException, Error from Ft.Server.Common import ResourceTypes from Ft.Rdf.Drivers import BerkeleyDB as BerkeleyDB4RDF from Ft.Server.Common.Schema import g_resourceTypeFromRdf, g_rdfResourceTypes from BerkeleyDBContainer import BerkeleyDBContainer,FTSS_CONTAIMENT_DB_NAME from Util import GetContainer,GetDB,BerkeleyDBFlags from Ft import GetConfigVar
VERSION="0.1" SYSTEM_MODEL_NAME = 'ftss_system.db' USER_MODEL_NAME = 'ftss_user.db' SESSION_DB_NAME = 'ftss_session.db' CACHE_DB_NAME = 'ftss_cache.db' CONTENT_DB_NAME = 'ftss_content.db' RESOURCE_TYPE_DB_NAME = 'ftss_types.db' MD_STRINGS_DB_NAME = 'ftss_metadata_strings.db'
MD_XML_CONTENT_DB_NAME = 'ftss_metdata_xml.dbxml' REPOSITORY_DOCUMENTS_DB_NAME = 'ftss_repo_xml.dbxml' USER_XML_CONTENT_DB_NAME = 'ftss_user_all.dbxml'
XmlDbNames = [MD_XML_CONTENT_DB_NAME,REPOSITORY_DOCUMENTS_DB_NAME]
nonXmlDbNames = [SESSION_DB_NAME, CACHE_DB_NAME, CONTENT_DB_NAME, RESOURCE_TYPE_DB_NAME, FTSS_CONTAIMENT_DB_NAME]
DATABASE_DIR = os.path.join(GetConfigVar('LOCALSTATEDIR'), 'BsdDb') DATABASE_DIR = os.environ.get('FT_DATABASE_DIR', DATABASE_DIR)
DBXML_FETCH_FTSS_CONTAINERS_XQUERY="""declare namespace ftss = '%s';for $container in collection('%s')/ftss:MetaData[@type='%s'] return dbxml:metadata('dbxml:name', $container)"""%( FTSERVER_NAMESPACE, MD_XML_CONTENT_DB_NAME, g_rdfResourceTypes[ResourceTypes.ResourceType.CONTAINER] )
XML_INDICES=True
FILE_RESOURCE_CLASS=0 USER_DOCUMENT_RESOURCE_CLASS=1 REPOSITORY_DOCUMENT_RESOURCE_CLASS=2 METADATA_DOCUMENT_RESOURCE_CLASS=3
def createDbXmlContainerPath(path): """ Influenced by the old Ft.Server.Server.Drivers.FlatFile.createFlatFilePath Takes a repository path and creates a name for the corresponding Bdb Xml container. XQuery can be used to search within non-repository XML documents in containers using the name mapped by this mechanism Drivers setup with DataStoreContainer = 'true' (currently disabled) make use of this to map repository container paths to a Filesystem path (relative to the driver root) of a corresponding Berkeley DB XML container FIXME: DB_RUNRECOVERY (PANIC: No such file or directory) is raised when DataStoreContainer is set to true """ return sha.new(path).hexdigest() # Enforce sanity if path[:1] != '/': raise TypeError('createDbXmlContainerPath called with a bad path: %r' % path)
path = path[1:]
# FIXME: Replace filesystem-unsafe characters in path segments. # (Mainly affects Windows). This cannot be done right now because # FtssDriver and PathImp cannot handle anything the least bit # weird in a repo path, like "<", "&", ":", "%" ...
# Replace path separators as needed if os.sep != '/': path = path.replace('/', os.sep)
path = path.replace('/', '#')
return path
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 DBXML_TRANSACTIONAL,DBEnv,XmlManager,XmlContainer,XmlValue,RepositoryTypeXPath RepositoryTypeXPath = XPath.Compile('string(/ftss:MetaData/@type)')
try: # For Pythons w/distutils pybsddb from bsddb3.db import DBEnv, DB_THREAD except ImportError: # For Python 2.3 - not advised from bsddb.db import DBEnv, DB_THREAD try: from dbxml import DBXML_TRANSACTIONAL,XmlManager,XmlContainer,XmlValue except ImportError: #Can't DbXml pass from Ft.Rdf.Drivers import BerkeleyDB as BerkeleyDB4RDF BerkeleyDB4RDF.InitializeModule()
def _DbNames(dbXmlContainers=False,dbXml=False): DbNames = [SESSION_DB_NAME, CACHE_DB_NAME, CONTENT_DB_NAME, RESOURCE_TYPE_DB_NAME, FTSS_CONTAIMENT_DB_NAME, SYSTEM_MODEL_NAME, USER_MODEL_NAME, ] if dbXml: DbNames += XmlDbNames if not dbXmlContainers: DbNames.append(USER_XML_CONTENT_DB_NAME) else: DbNames.append(MD_STRINGS_DB_NAME)
return DbNames
def Exists(properties): """See if this repo exists. The return value for this is three state. 1. Everything is present 0. Some things are there -1 Nothing is there. """ dbList = _DbNames(properties.get('DataStoreContainers','false') in ['1','true'], properties.get('DbXml','false') in ['1','true'])
root = os.path.join(DATABASE_DIR, properties['Root']) existingDbs = [dbName for dbName in dbList if os.path.exists(os.path.join(root,dbName))]
if len(existingDbs) == 0 and not os.path.exists(root): rt = -1 elif len(existingDbs) < len(dbList) - 2: rt = 0 else: InitializeModule() if BerkeleyDB4RDF.ExistsDb(SYSTEM_MODEL_NAME) == 1 and BerkeleyDB4RDF.ExistsDb(USER_MODEL_NAME) == 1: rt = 1 else: rt = 0 return rt 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 """ root = os.path.join(DATABASE_DIR, properties['Root']) if os.path.isdir(DATABASE_DIR): try: os.makedirs(root) except OSError, e: raise FtServerServerException(Error.UNABLE_TO_INITALIZE_REPO, msg=str(e), traceback="creating root directory") else: raise FtServerServerException(Error.UNABLE_TO_INITALIZE_REPO, msg="Directory %s does not exist" % DATABASE_DIR) #Create BerkeleyDB4RDF Datastore InitializeModule() BerkeleyDB4RDF.CreateDb(SYSTEM_MODEL_NAME) BerkeleyDB4RDF.CreateDb(USER_MODEL_NAME)
#Create Berkeley DB Environment (used with all databases) environment = DBEnv() environment.open(root, BerkeleyDBFlags,0) xmlEnvironment = DBEnv() xmlEnvironment.open(root, BerkeleyDBFlags,0)
#Basically, this property indicates whether or not to store XML Documents as 'Whole Documents' or as individual nodes bigDocs = properties.get('OneMBDocuments','false') #Use Berkeley DB XML for XML content? useDbXml = properties.get('DbXml','false') #Create Berkeley DB XML containers per 4Suite Repository container? dataStoreContainers = properties.get('DataStoreContainers','false')
txn = environment.txn_begin()
if useDbXml in ['1','true']: #Use BerkeleyDB XML for XML content #Fetch XmlManager mgr = XmlManager(xmlEnvironment, 0)
if bigDocs in ['false','0']: mgr.setDefaultContainerType(XmlContainer.WholedocContainer)
mgr.setDefaultContainerType(XmlContainer.WholedocContainer)
_xmlDbs = XmlDbNames if not properties.get('DataStoreContainers','false') in ['1','true']: _xmlDbs.append(USER_XML_CONTENT_DB_NAME) xtxn = mgr.createTransaction() createdContainers=[] for xmlContainer in _xmlDbs: container = mgr.createContainer(xtxn,xmlContainer) createdContainers.append(container) #Add indices #Indices for common metadata elements/attributes #Indices for common repository document elements / attributes if xmlContainer == MD_XML_CONTENT_DB_NAME and XML_INDICES: container.addIndex(xtxn,"", "name", "node-metadata-substring-string", mgr.createUpdateContext()) container.addIndex(xtxn,"", "type", "node-attribute-equality-string", mgr.createUpdateContext()) container.addIndex(xtxn,"", "path", "node-attribute-equality-string", mgr.createUpdateContext()) container.addIndex(xtxn,"", "creation-date", "node-attribute-equality-string", mgr.createUpdateContext()) container.addIndex(xtxn,FTSERVER_NAMESPACE, "Owner", "node-element-equality-string", mgr.createUpdateContext()) container.addIndex(xtxn,FTSERVER_NAMESPACE, "Imt", "node-element-equality-string", mgr.createUpdateContext()) container.addIndex(xtxn,FTSERVER_NAMESPACE, "Size", "node-element-equality-string", mgr.createUpdateContext())
elif xmlContainer == REPOSITORY_DOCUMENTS_DB_NAME and XML_INDICES: container.addIndex(xtxn,"", "userName", "node-attribute-equality-string", mgr.createUpdateContext()) container.addIndex(xtxn,"", "key", "node-attribute-equality-string", mgr.createUpdateContext()) container.addIndex(xtxn,"", "name", "edge-attribute-equality-string", mgr.createUpdateContext()) container.addIndex(xtxn,FTSERVER_NAMESPACE, "ServerName", "edge-element-equality-string", mgr.createUpdateContext()) container.addIndex(xtxn,"", "running", "node-element-equality-boolean", mgr.createUpdateContext()) xtxn.commit() else: pass
liveDbs = [GetDB(name,environment,txn=txn)[-1] for name in nonXmlDbNames]
if not useDbXml in ['1','true']: liveDbs.append(GetDB(MD_STRINGS_DB_NAME,environment,txn=txn)[-1])
txn.commit()
for db in liveDbs: db.close() del db
if useDbXml in ['1','true']: for container in createdContainers: container.close() del container
environment.close(0) xmlEnvironment.close(0) def Destroy(properties,tryOnly=0): """Completly destroy the repo""" root = os.path.join(DATABASE_DIR,properties['Root'])
#This is a simple as a rm -rf :) if os.path.exists(root): try: remove_tree(root) InitializeModule() BerkeleyDB4RDF.DestroyDb(SYSTEM_MODEL_NAME) BerkeleyDB4RDF.DestroyDb(USER_MODEL_NAME) except OSError: if not tryOnly: raise
def Maintain(properties): """ Perform any maintenance on the db or periodic actions (inference, integrity check..?!) """ pass
def LocateContent(path,typ,typeDB): """ 0 - NonXmlContent 1 - Non-repository Document 2 - Repository Document (not Metadata) 3 - Metadata 4 - Cache 5 - Session """ if typ == ResourceTypes.RESOURCE_METADATA: return 3 elif typ == ResourceTypes.RESOURCE_CONTENT: txn,typeDb = typeDB _type = typeDb.get(path,txn=txn) repositoryType=int(_type) if repositoryType in ResourceTypes.XML_DOCUMENTS: if repositoryType in REPO_DOCUMENTS: return 2 else: return 1 else: return 0 elif typ == ResourceTypes.SESSION_DATA: return 4 elif typ == ResourceTypes.RESOURCE_CACHE: return 5
class BerkeleyDBDriver(BerkeleyDBContainer): """ Store information in an RDF and Berleley DB (XML)? store"""
def __init__(self,properties): self.__dbProperties = properties self.root = os.path.join(DATABASE_DIR, properties['Root']) self._dBs = {} self.__useDbXml = properties.get('DbXml','false') in ['1','true']
root = os.path.join(DATABASE_DIR, properties['Root']) self.environment = DBEnv() self.environment.open(root,BerkeleyDBFlags,0) self.xmlEnvironment = DBEnv() self.xmlEnvironment.open(root,BerkeleyDBFlags,0) self.dbTxn = self.environment.txn_begin()
if self.__useDbXml: self.XmlMgr = XmlManager(self.xmlEnvironment, 0) self.dbXmlTxn = self.XmlMgr.createTransaction()
if properties.get('OneMBDocuments','false') in ['false','0']: self.XmlMgr.setDefaultContainerType(XmlContainer.WholedocContainer)
self._repositorydB = GetContainer(REPOSITORY_DOCUMENTS_DB_NAME,self.root,self.xmlEnvironment,txn=self.dbXmlTxn)
if not properties.get('DataStoreContainers','false') in ['1','true']: self._userXmldB = GetContainer(USER_XML_CONTENT_DB_NAME,self.root,self.xmlEnvironment,self.dbXmlTxn)
self._dBs[ResourceTypes.RESOURCE_METADATA] = GetContainer(MD_XML_CONTENT_DB_NAME,self.root,self.xmlEnvironment,self.dbXmlTxn) else: self._dBs[ResourceTypes.RESOURCE_METADATA] = GetDB(MD_STRINGS_DB_NAME,self.environment,self.dbTxn) self._contentType = GetDB(RESOURCE_TYPE_DB_NAME,self.environment,txn=self.dbTxn) self._dBs[ResourceTypes.RESOURCE_CONTENT] = GetDB(CONTENT_DB_NAME,self.environment,self.dbTxn) self._dBs[ResourceTypes.RESOURCE_CACHE] = GetDB(CACHE_DB_NAME,self.environment,self.dbTxn) self._dBs[ResourceTypes.SESSION_DATA] = GetDB(SESSION_DB_NAME,self.environment,self.dbTxn) self._dBs[FTSS_CONTAIMENT_DB_NAME] = GetDB(FTSS_CONTAIMENT_DB_NAME, self.environment,self.dbTxn)
d = BerkeleyDB4RDF.DbAdapter(SYSTEM_MODEL_NAME) d.begin() self._systemRdfModel = Model.Model(d) d = BerkeleyDB4RDF.DbAdapter(USER_MODEL_NAME) d.begin() self._userRdfModel = Model.Model(d) def createFile(self,path,typ,content): #print "creating %s of type %s"%(path,typ) if not isinstance(content, types.StringType): type_name = type(content).__name__ raise TypeError("Content must be a string, not %r" % type_name) #Necessary for BerkeleyDB (expects strings for names, not unicode) path = path.encode('utf-8') if typ in [ResourceTypes.RESOURCE_METADATA,ResourceTypes.RESOURCE_CACHE]: #Resource metadata or resource cache if typ == ResourceTypes.RESOURCE_METADATA: #Determine database to store content via metadata and store in metadata container mdDOM = NonvalidatingReader.parseString(content.encode('utf-8'), uri='urn:uuid:metadata') mdContext = XPath.Context.Context(mdDOM,processorNss={'ftss':'http://xmlns.4suite.org/reserved'}) typRes = RepositoryTypeXPath.evaluate(mdContext) typRes = str(g_resourceTypeFromRdf[typRes]) txn,typeDB = self._contentType #Store Repository type for later reference typeDB.put(path,typRes,self.dbTxn)
if self.__useDbXml: #Store metadata document DbXml Container for metadata txn,xmlDB = self._dBs[ResourceTypes.RESOURCE_METADATA] uc = self.XmlMgr.createUpdateContext() xmlDB.putDocument(self.dbXmlTxn,path, content,uc) else: #Store metadata XML string in Berkeley DB for metadata strings txn,db = self._dBs[typ] db.put(path,content,self.dbTxn) else: #resource cache, put in Berkeley DB txn,db = self._dBs[typ] db.put(path,content,self.dbTxn) elif typ == ResourceTypes.SESSION_DATA: txn,db = self._dBs[typ] db.put(path,content,self.dbTxn) else: #Actual content #Store in db specified by looking at repositoryType txn,typeDb = self._contentType repositoryType=int(typeDb.get(path,txn=self.dbTxn))
if repositoryType in ResourceTypes.XML_DOCUMENTS and self.__useDbXml: #An XML Document (and we are configured to use Berkeley DB XML) #Check if resource is a repository object. if not repositoryType in REPO_DOCUMENTS: #Non-repository XML documents #Store in user xml container, if data store containers aren't being used #Otherwise, map the repository path to the mirror-heirarchy of user xml content and store in container #NOTE: Currently disabled but should be considered in future updates #if self.__dbProperties.get('DataStoreContainers','false') in ['1','true']: #Using Data Store containers, store in dbxml container #dataStorePath=createDbXmlContainerPath(self.root,path.getParentPath().absolutePath()) #dataStorePath=RepoPath2DataStoreContainer(path.getParentPath().absolutePath(),DATASTORE_XML_CONTAINER_NAME) #dataStorePath=createDbXmlContainerPath(path.getParentPath().absolutePath()) #txn,container = GetContainer(dataStorePath,self.root,self.environment,self.dbXmlTxn) #else: txn,container = self._userXmldB else: #A Repository Document txn,container = self._repositorydB
#NOTE: Currently disabled but should be considered in future updates #if repositoryType == ResourceTypes.ResourceType.CONTAINER and self.__dbProperties.get('DataStoreContainers','false') in ['1','true'] and path != '/': #A repository container modeled as a Berkeley DB XML Container for non-repo XML documents #Create the physical dbxml container #dbxmlContPath=createDbXmlContainerPath(path) #print " creating %s as datastore container (%s)"%(path,dbxmlContPath) #self.XmlMgr.createContainer(self.dbXmlTxn,dbxmlContPath) try: uc = self.XmlMgr.createUpdateContext() container.putDocument(self.dbXmlTxn,path, content, uc) except Exception, e: if str(e).find('Parse error') != -1: print e, ':\n',content self.rollback() raise NotImplementedError('Xerces parse error - DTD and DTD entity references?') else: raise else: #Non XML content txn,contentDB = self._dBs[typ] contentDB.put(path,content,self.dbTxn) def hasFile(self,path,typ): """See if we have any meta information about this resource""" #print "hasFile(%s,%s)"%(path,typ) #Necessary for BerkeleyDB (expects strings for names, not unicode) path = path.encode('utf-8') #First, if not cache or session, check typeDB - there should be an entry there if it exists if not typ in [ResourceTypes.SESSION_DATA,ResourceTypes.RESOURCE_CACHE]: txn,typeDb = self._contentType if not typeDb.has_key(path,txn): return None
#Entry in typeDB, check if it exists in the appropriate DB locationCode = LocateContent(path,typ,self._contentType) #Necessary for BerkeleyDB (expects strings for names, not unicode) path = path.encode('utf-8') if locationCode == FILE_RESOURCE_CLASS: txn,db = self._dBs[typ] return not not db.get(path,txn=txn) elif locationCode == USER_DOCUMENT_RESOURCE_CLASS: if self.__useDbXml: if self.__dbProperties.get('DataStoreContainers','false') in ['1','true']: #Check within underlying DbXml container #NOTE: Disabled right now #txn,container = GetContainer( # createDbXmlContainerPath(path.getParentPath().absolutePath()), # self.root, # self.environment, # self.dbXmlTxn) pass else: txn,container = self._userXmldB
doc=container.getDocument(self.dbXmlTxn,path) del doc return True
else: #Not using DbXml, check in content DB txn,db = self._dBs[typ] return not not db.get(path,txn=txn)
elif locationCode == REPOSITORY_DOCUMENT_RESOURCE_CLASS: if self.__useDbXml: txn,repoDB = self._repositorydB doc=repoDB.getDocument(self.dbXmlTxn,path) del doc return True
else: #Not using DbXml, check in content DB txn,db = self._dBs[typ] return not not db.get(path,txn=txn) elif locationCode == METADATA_DOCUMENT_RESOURCE_CLASS: if self.__useDbXml: txn,mdContainer = self._dBs[typ] doc=mdContainer.getDocument(self.dbXmlTxn,path) del doc return True else: #Not using DbXml, check in metadata strings DB txn,db = self._dBs[typ] return not not db.get(path,txn=txn) else: txn,db = self._dBs[typ] return not not db.get(path,txn=txn)
def fetchFile(self, path, typ): #print "fetching %s (type: %s)"%(path,typ) #Necessary for BerkeleyDB (expects strings for names, not unicode) path = path.encode('utf-8') #If it's not session data or cache and there isn't an entry in the Type DB then we can assume it doesn't exist if not typ in [ResourceTypes.SESSION_DATA,ResourceTypes.RESOURCE_CACHE]: txn,typeDb = self._contentType if not typeDb.has_key(path,txn): return None locationCode = LocateContent(path,typ,self._contentType) if locationCode == FILE_RESOURCE_CLASS: txn,db = self._dBs[typ] return db.get(path,txn=self.dbTxn)
elif locationCode == USER_DOCUMENT_RESOURCE_CLASS: if self.__useDbXml: if self.__dbProperties.get('DataStoreContainers','false') in ['1','true']: #Check within underlying DbXml container #NOTE: Disabled right now #txn,container = GetContainer( # createDbXmlContainerPath(path.getParentPath().absolutePath()), # self.root, # self.environment, # self.dbXmlTxn) pass else: txn,container = self._userXmldB
doc=container.getDocument(self.dbXmlTxn,path) return doc.getContent() else: #Not using DbXml, retrieve from content DB txn,db = self._dBs[typ] return db.get(path,txn=self.dbTxn) elif locationCode == REPOSITORY_DOCUMENT_RESOURCE_CLASS: if self.__useDbXml: txn,repoDB = self._repositorydB doc=repoDB.getDocument(self.dbXmlTxn,path) return doc.getContent() else: #Not using DbXml, check in content DB txn,db = self._dBs[typ] return db.get(path,txn=self.dbTxn) elif locationCode == METADATA_DOCUMENT_RESOURCE_CLASS: if self.__useDbXml: txn,mdContainer = self._dBs[typ] doc=mdContainer.getDocument(self.dbXmlTxn,path) rt=doc.getContent() return rt else: #Not using DbXml, check in MD strings DB txn,db = self._dBs[typ] return db.get(path,txn=self.dbTxn)
else: txn,db = self._dBs[typ] return db.get(path,txn=self.dbTxn) def updateFile(self, path, typ, content): #print "updateFile(%s,%s,%s)"%(path,typ,len(content)) #Necessary for BerkeleyDB (expects strings for names, not unicode) path = path.encode('utf-8') #If it's not session data or cache and there isn't an entry in the Type DB then we can assume it doesn't exist if not typ in [ResourceTypes.SESSION_DATA,ResourceTypes.RESOURCE_CACHE]: txn,typeDb = self._contentType if not typeDb.has_key(path,txn): return
locationCode = LocateContent(path,typ,self._contentType) if locationCode == FILE_RESOURCE_CLASS: txn,db = self._dBs[typ] db.put(path,content,self.dbTxn) elif locationCode == USER_DOCUMENT_RESOURCE_CLASS: if self.__useDbXml: if self.__dbProperties.get('DataStoreContainers','false') in ['1','true']: #Check within underlying DbXml container #NOTE: Disabled right now #txn,container = GetContainer( # createDbXmlContainerPath(path.getParentPath().absolutePath()), # self.root, # self.environment, # self.dbXmlTxn) pass else: txn,container = self._userXmldB
doc=container.getDocument(self.dbXmlTxn,path) doc.setContent(content) container.updateDocument(self.dbXmlTxn,doc,self.XmlMgr.createUpdateContext()) else: #Not using DbXml, update in content DB txn,db = self._dBs[typ] db.put(path,content,self.dbTxn) elif locationCode == REPOSITORY_DOCUMENT_RESOURCE_CLASS: if self.__useDbXml: txn,repoDB = self._repositorydB doc=repoDB.getDocument(self.dbXmlTxn,path) doc.setContent(content) repoDB.updateDocument(self.dbXmlTxn,doc,self.XmlMgr.createUpdateContext()) else: #Not using DbXml, update in content DB txn,db = self._dBs[typ] db.put(path,content,self.dbTxn) elif locationCode == METADATA_DOCUMENT_RESOURCE_CLASS: if self.__useDbXml: txn,mdContainer = self._dBs[typ] doc=mdContainer.getDocument(self.dbXmlTxn,path) doc.setContent(content) mdContainer.updateDocument(self.dbXmlTxn,doc,self.XmlMgr.createUpdateContext())
else: #Not using DbXml, update in metadata strings DB txn,db = self._dBs[typ] db.put(path,content,self.dbTxn)
else: txn,db = self._dBs[typ] db.put(path,content,self.dbTxn) def deleteFile(self, path, typ): """Delete an object""" #print "deleteFile(%s,%s)"%(path,typ) #Necessary for BerkeleyDB (expects strings for names, not unicode) path = path.encode('utf-8') #If it's not session or cache data and there isn't an entry in the Type DB then we can assume it doesn't exist
if not typ in [ResourceTypes.SESSION_DATA,ResourceTypes.RESOURCE_CACHE]: txn,typeDb = self._contentType if not typeDb.has_key(path,txn): return locationCode = LocateContent(path,typ,self._contentType) if locationCode == FILE_RESOURCE_CLASS: txn,db = self._dBs[typ] db.delete(path,self.dbTxn) elif locationCode == USER_DOCUMENT_RESOURCE_CLASS: if self.__useDbXml: if self.__dbProperties.get('DataStoreContainers','false') in ['1','true']: #Check within underlying DbXml container #NOTE: Disabled right now #txn,container = GetContainer( # createDbXmlContainerPath(path.getParentPath().absolutePath()), # self.root, # self.environment, # self.dbXmlTxn) pass else: txn,container = self._userXmldB
container.deleteDocument(self.dbXmlTxn,path,self.XmlMgr.createUpdateContext()) else: #Not using DbXml, delete from content DB txn,db = self._dBs[typ] db.delete(path,self.dbTxn) elif locationCode == REPOSITORY_DOCUMENT_RESOURCE_CLASS: if self.__useDbXml: txn,repoDB = self._repositorydB repoDB.deleteDocument(self.dbXmlTxn,path,self.XmlMgr.createUpdateContext()) #txn,typeDB = self._contentType #repositoryType=int(typeDb.get(path,txn=self.dbTxn)) #if repositoryType == ResourceTypes.ResourceType.CONTAINER and self.__dbProperties.get('DataStoreContainers','false') in ['1','true'] and path != '/': #A container and the driver is using berkeley dbxml containers, so delete the underlying container as well # self.XmlMgr.removeContainer(self.dbXmlTxn,createDbXmlContainerPath(path)) else: #Not using DbXml, delete from content DB txn,db = self._dBs[typ] db.delete(path,self.dbTxn) elif locationCode == METADATA_DOCUMENT_RESOURCE_CLASS: if self.__useDbXml: txn,mdContainer = self._dBs[typ] mdContainer.deleteDocument(self.dbXmlTxn,path,self.XmlMgr.createUpdateContext()) else: #Not using DBXml delete from metadata strings DB txn,db = self._dBs[typ] db.delete(path,self.dbTxn)
else: txn,db = self._dBs[typ] db.delete(path,self.dbTxn)
#Delete it from Type DB if it's resource content (assume it's metadata has already been deleted) if typ == ResourceTypes.RESOURCE_CONTENT: txn,typeDb = self._contentType typeDb.delete(path,txn) def getSystemModel(self): return self._systemRdfModel
def getUserModel(self): return self._userRdfModel
def commit(self): if self.__useDbXml: self.dbXmlTxn.commit(0) self.dbTxn.commit(0) self._closeDatabase() def _closeDatabase(self): #NOTE: If datastore containers are being used, they must retrieved and closed individually by #searching for the paths of of all containers and retrieving them by name #if self.__dbProperties.get('DataStoreContainers','false') in ['1','true']: # print DBXML_FETCH_FTSS_CONTAINERS_XQUERY # rt = self.XmlMgr.query(self.dbXmlTxn,DBXML_FETCH_FTSS_CONTAINERS_XQUERY,self.XmlMgr.createQueryContext()) # print "containers: " # rt.reset() # for value in rt: # repoContainerPath=value.asString() # if repoContainerPath == '/': # continue # print repoContainerPath # c = GetContainer(createDbXmlContainerPath(repoContainerPath),self.root,self.environment,txn=self.dbXmlTxn) # c.close() if self.__useDbXml: self._userXmldB[-1].close() self._repositorydB[-1].close() self._contentType[-1].close() self._dBs[ResourceTypes.RESOURCE_METADATA][-1].close() self._dBs[ResourceTypes.RESOURCE_CONTENT][-1].close() self._dBs[ResourceTypes.RESOURCE_CACHE][-1].close() self._dBs[ResourceTypes.SESSION_DATA][-1].close() self._dBs[FTSS_CONTAIMENT_DB_NAME][-1].close() self.environment.close(0) self.xmlEnvironment.close(0) self._dBs = {} self._systemRdfModel._driver.commit() self._userRdfModel._driver.commit() self._repositorydB = self._contentType = self._systemRdfModel._db = self._systemRdfModel = self._userRdfModel._db = self._userRdfModel = None def rollback(self): """Undo it""" if self.__useDbXml: self.dbXmlTxn.abort() self.dbTxn.abort() self._closeDatabase()
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 BerkeleyDBDriver(properties)
NAME='BerkeleyDB'
REPO_DOCUMENTS = [ ResourceTypes.ResourceType.CONTAINER, ResourceTypes.ResourceType.ALIAS, ResourceTypes.ResourceType.USER, ResourceTypes.ResourceType.GROUP, ResourceTypes.ResourceType.XPATH_DOCUMENT_DEFINITION, ResourceTypes.ResourceType.COMMAND, ResourceTypes.ResourceType.SERVER, ResourceTypes.ResourceType.XSLT_DOCUMENT, ResourceTypes.ResourceType.XSLT_DOCUMENT_DEFINITION, ResourceTypes.ResourceType.RDF_DOCUMENT ]
|