Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/src/olpc/datastore/backingstore.py
diff options
context:
space:
mode:
authorBenjamin Saller <bcsaller@objectrealms.net>2007-04-27 22:20:27 (GMT)
committer Benjamin Saller <bcsaller@objectrealms.net>2007-04-27 22:20:27 (GMT)
commitfcf7ffeca964c31925c0ba275b2b09715070d541 (patch)
treede9a1a52ea31a539a4f05f6eefb2f029f8162fb2 /src/olpc/datastore/backingstore.py
Milestone 1 import
Diffstat (limited to 'src/olpc/datastore/backingstore.py')
-rw-r--r--src/olpc/datastore/backingstore.py129
1 files changed, 129 insertions, 0 deletions
diff --git a/src/olpc/datastore/backingstore.py b/src/olpc/datastore/backingstore.py
new file mode 100644
index 0000000..81d1f9a
--- /dev/null
+++ b/src/olpc/datastore/backingstore.py
@@ -0,0 +1,129 @@
+"""
+olpc.datastore.backingstore
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+management of stable storage for the datastore
+
+"""
+
+__author__ = 'Benjamin Saller <bcsaller@objectrealms.net>'
+__docformat__ = 'restructuredtext'
+__copyright__ = 'Copyright ObjectRealms, LLC, 2007'
+__license__ = 'The GNU Public License V2+'
+
+import hashlib
+import os
+
+class BackingStore(object):
+ """Backing stores manage stable storage. We abstract out the
+ management of file/blob storage through this class, as well as the
+ location of the backing store itself (it may be done via a network
+ connection for example).
+
+ While the backingstore is responsible for implementing the
+ metadata interface no implementation is provided here. It is
+ assumed by that interface that all the features enumerated in
+ olpc.datastore.model are provided.
+
+ """
+ def __init__(self, uri, **kwargs):
+ """The kwargs are used to configure the backend so it can
+ provide its interface. See specific backends for details
+ """
+ pass
+
+ def connect(self):
+ """connect to the metadata store"""
+ self._connect()
+
+
+ def prepare(self, datastore, querymanager):
+ """Verify the backingstore is ready to begin its duties"""
+ return False
+
+
+
+
+class FileBackingStore(BackingStore):
+ """ A backing store that directs maps the storage of content
+ objects to an available filesystem.
+
+
+ # not really true, the change would result in the older version
+ having the last content and the new version as well. The old one
+ is left in the newest start rather than start state. if that can work...
+ The semantics of interacting
+ with the repositories mean that the current copy _can_ be edited
+ in place. Its the actions create/update that create new revisions
+ in the datastore and hence new versions.
+ """
+
+ def __init__(self, uri, **kwargs):
+ """ FileSystemStore(path=<root of managed storage>)
+ """
+ self.base = uri
+ super(FileBackingStore, self).__init__(uri, **kwargs)
+ self.options = kwargs
+
+ def prepare(self, datastore, querymanager):
+ if not os.path.exists(self.base):
+ os.makedirs(self.base)
+ self.datastore = datastore
+ self.querymanager = querymanager
+ return True
+
+ def _translatePath(self, uid):
+ """translate a UID to a path name"""
+ # this backend maps back the file checksum as a sha224 hex uid
+ # so this works
+ return os.path.join(self.base, str(uid))
+
+ def create(self, content, filelike):
+ self._writeContent(content, filelike, replace=False)
+
+
+ def get(self, uid):
+ path = self._translatePath(uid)
+ if not os.path.exists(path):
+ raise KeyError("object for uid:%s missing" % uid)
+
+ fp = open(path, 'r')
+ # now return a Content object from the model associated with
+ # this file object
+ return self._mapContent(uid, fp, path)
+
+ def set(self, uid, filelike):
+ self._writeContent(self.get(uid), filelike)
+
+ def delete(self, uid, allowMissing=False):
+ path = self._translatePath(uid)
+ if os.path.exists(path):
+ os.unlink(path)
+ else:
+ if not allowMissing:
+ raise KeyError("object for uid:%s missing" % uid)
+
+
+
+ def _mapContent(self, uid, fp, path):
+ """map a content object and the file in the repository to a
+ working copy.
+ """
+ content = self.querymanager.get(uid)
+ content.file = fp
+ return content
+
+ def _writeContent(self, content, filelike, replace=True):
+ path = self._translatePath(content.id)
+ if replace is False and os.path.exists(path):
+ raise KeyError("objects with path:%s for uid:%s exists" %(
+ path, content.id))
+ fp = open(path, 'w')
+ c = hashlib.sha224()
+ for line in filelike:
+ c.update(line)
+ fp.write(line)
+ fp.close()
+ content.checksum = c.hexdigest()
+
+
+