Fixed some index bugs.
[didex.git] / didex / store.py
index 15d2eca..43c1348 100644 (file)
@@ -2,16 +2,26 @@ import threading, pickle
 from . import db, index, cache
 from .db import txnfun
 
+__all__ = ["environment", "datastore", "autostore"]
+
 class environment(object):
-    def __init__(self, path):
-        self.path = path
+    def __init__(self, *, path=None, getpath=None, recover=False):
+        if path is not None:
+            self.path = path
+            self.getpath = None
+        else:
+            self.path = None
+            self.getpath = getpath
+        self.recover = recover
         self.lk = threading.Lock()
         self.bk = None
 
     def __call__(self):
         with self.lk:
             if self.bk is None:
-                self.bk = db.environment(self.path)
+                if self.path is None:
+                    self.path = self.getpath()
+                self.bk = db.environment(self.path, recover=self.recover)
             return self.bk
 
     def close(self):
@@ -34,14 +44,14 @@ def storedescs(obj):
         t.__didex_attr = ret
     return ret
 
-class store(object):
+class datastore(object):
     def __init__(self, name, *, env=None, path=".", ncache=None):
         self.name = name
         self.lk = threading.Lock()
         if env:
             self.env = env
         else:
-            self.env = environment(path)
+            self.env = environment(path=path)
         self._db = None
         if ncache is None:
             ncache = cache.cache()
@@ -75,16 +85,38 @@ class store(object):
         return id
 
     @txnfun(lambda self: self.db().env.env)
-    def unregister(self, id, *, tx):
+    def unregister(self, id, *, vfy=None, tx):
         obj = self.get(id)
+        if vfy is not None and obj is not vfy:
+            raise RuntimeError("object identity crisis: " + str(vfy) + " is not cached object " + obj)
         for nm, attr in storedescs(obj):
             attr.unregister(id, obj, tx)
         self.db().remove(id, tx=tx)
         self.cache.remove(id)
 
     @txnfun(lambda self: self.db().env.env)
-    def update(self, id, *, tx):
+    def update(self, id, *, vfy=None, tx):
         obj = self.get(id, load=False)
+        if vfy is not None and obj is not vfy:
+            raise RuntimeError("object identity crisis: " + str(vfy) + " is not cached object " + obj)
         for nm, attr, in storedescs(obj):
             attr.update(id, obj, tx)
         self.db().replace(id, self._encode(obj), tx=tx)
+
+class autotype(type):
+    def __call__(self, *args, **kwargs):
+        new = super().__call__(*args, **kwargs)
+        new.id = self.store.register(new)
+        self.store.update(new.id, vfy=new) # This doesn't feel too nice.
+        return new
+
+class autostore(object, metaclass=autotype):
+    def __init__(self):
+        self.id = None
+
+    def save(self):
+        self.store.update(self.id, vfy=self)
+
+    def remove(self):
+        self.store.unregister(self.id, vfy=self)
+        self.id = None