diff --git a/src/modules/dbxmldatabases.py b/src/modules/dbxmldatabases.py index 38a8bc9..1666b19 100644 --- a/src/modules/dbxmldatabases.py +++ b/src/modules/dbxmldatabases.py @@ -26,6 +26,8 @@ """Berkeley DB XML Database Manager Module""" +import os.path +import shutil import sys import bsddb3.db as db @@ -106,40 +108,66 @@ def __init__(): , 0 ) - DbXmlDatabase._manager = dbxml.XmlManager(DbXmlDatabase._environment, dbxml.DBXML_ADOPT_DBENV) + manager = dbxml.XmlManager(DbXmlDatabase._environment, dbxml.DBXML_ADOPT_DBENV) + DbXmlDatabase._manager = manager DbXmlDatabase._containers = {} - for name in configuration.getConfigList("""yep:module[@name="%s"]/yep:container/@name""" % __init__.__module__): + updateContext = manager.createUpdateContext() + for containerName in configuration.getConfigList("""yep:module[@name="%s"]/yep:container/@name""" % __init__.__module__): try: - container = DbXmlDatabase._manager.openContainer( - name, 0 + container = manager.openContainer( + containerName, 0 |dbxml.DBXML_CHKSUM ) - except RuntimeError: - logs.debug("Container %s was not found. Creating it." % name) - try: - container = DbXmlDatabase._manager.createContainer( - name, 0 - |dbxml.DBXML_CHKSUM - ) - except RuntimeError: - logs.error("Could not open nor create container %s." % name) - __del__() - raise + except RuntimeError, e: + logs.warning("Container %s could not be open: %s" % (containerName, e)) + filePath = os.path.join(dbHome, containerName) + if os.path.exists(filePath): + logs.debug("File %s exists. Attempting to upgrade it.", filePath) + backupPath = filePath + "_backup" + shutil.copyfile(filePath, backupPath) + try: + manager.upgradeContainer(containerName, updateContext) + except RuntimeError, e: + logs.error("Container %s could not be upgraded: %s" % (containerName, e)) + shutil.move(backupPath, filePath) + __del__() + raise + else: + logs.debug("File %s was succesfully upgraded.", filePath) + os.unlink(backupPath) else: + try: + logs.debug("File %s does not exist. Creating it.", filePath) + container = manager.createContainer( + containerName, 0 + |dbxml.DBXML_CHKSUM + ) + except RuntimeError, e: + logs.error("Could not create container %s: %s" % (containerName, e)) + __del__() + raise populationPath = configuration.getConfigAbsolutePath( """yep:module[@name="%s"]/yep:population/@path""" % __init__.__module__, ) if populationPath: populationDoc = libxml2.readFile(populationPath, "utf-8", 0) setNode = populationDoc.getRootElement() - updateContext = container.getManager().createUpdateContext() - for documentNode in setNode.xpathEval("container[@name='%s']/*" % name): + for documentNode in setNode.xpathEval("container[@name='%s']/*" % containerName): for node in documentNode.xpathEval("*"): doc = libxml2.newDoc("1.0") doc.setRootElement(node) container.putDocument(documentNode.prop("name"), doc.serialize(), updateContext) - DbXmlDatabase._containers[name] = container - + indexSpecification = dbxml.XmlIndexSpecification() + for node in configuration.evaluateXpath( + """yep:module[@name="%s"]/yep:container[@name="%s"]/yep:index""" % ( + __init__.__module__, + containerName, + ) + ): + uri, name, index = node.prop("uri"), node.prop("name"), node.prop("index") + indexSpecification.addIndex(uri, name, index) + container.setIndexSpecification(indexSpecification, updateContext) + DbXmlDatabase._containers[containerName] = container def __del__(): """ Closes containers and the database environment.