diff roundup/backends/back_metakit.py @ 1333:80d27b7d6db5

implemented whole-database locking
author Richard Jones <richard@users.sourceforge.net>
date Thu, 12 Dec 2002 09:31:04 +0000
parents 6c24a86a12ae
children d1bfb479e527
line wrap: on
line diff
--- a/roundup/backends/back_metakit.py	Wed Dec 11 11:37:07 2002 +0000
+++ b/roundup/backends/back_metakit.py	Thu Dec 12 09:31:04 2002 +0000
@@ -43,8 +43,7 @@
             for nodeid in klass.list():
                 klass.index(nodeid)
         self.indexer.save_index()
-        
-            
+
     # --- defined in ping's spec
     def __getattr__(self, classname):
         if classname == 'curuserid':
@@ -247,14 +246,18 @@
                               'activity' : hyperdb.Date(),
                               'creation' : hyperdb.Date(),
                               'creator'  : hyperdb.Link('user') }
-        self.auditors = {'create': [], 'set': [], 'retire': []} # event -> list of callables
-        self.reactors = {'create': [], 'set': [], 'retire': []} # ditto
+
+        # event -> list of callables
+        self.auditors = {'create': [], 'set': [], 'retire': []}
+        self.reactors = {'create': [], 'set': [], 'retire': []}
+
         view = self.__getview()
         self.maxid = 1
         if view:
             self.maxid = view[-1].id + 1
         self.uncommitted = {}
         self.rbactions = []
+
         # people reach inside!!
         self.properties = self.ruprops
         self.db.addclass(self)
@@ -288,6 +291,7 @@
         l = self.reactors[event]
         if detector not in l:
             self.reactors[event].append(detector)
+
     # --- the hyperdb.Class methods
     def create(self, **propvalues):
         self.fireAuditors('create', None, propvalues)
@@ -345,6 +349,7 @@
         if self.db.journaltag is None:
             raise hyperdb.DatabaseError, 'Database open read-only'
         view = self.getview(1)
+
         # node must exist & not be retired
         id = int(nodeid)
         ndx = view.find(id=id)
@@ -536,7 +541,7 @@
                 setattr(row, key, v)
                 changes[key] = oldvalue
                 propvalues[key] = value
-                
+
             elif isinstance(prop, hyperdb.Boolean):
                 if value is None:
                     bv = 0
@@ -593,15 +598,18 @@
                 iv.delete(ndx)
         self.db.dirty = 1
         self.fireReactors('retire', nodeid, None)
+
     def history(self, nodeid):
         if not self.do_journal:
             raise ValueError, 'Journalling is disabled for this class'
         return self.db.getjournal(self.classname, nodeid)
+
     def setkey(self, propname):
         if self.keyname:
             if propname == self.keyname:
                 return
-            raise ValueError, "%s already indexed on %s" % (self.classname, self.keyname)
+            raise ValueError, "%s already indexed on %s"%(self.classname,
+                self.keyname)
         prop = self.properties.get(propname, None)
         if prop is None:
             prop = self.privateprops.get(propname, None)
@@ -609,21 +617,24 @@
             raise KeyError, "no property %s" % propname
         if not isinstance(prop, hyperdb.String):
             raise TypeError, "%s is not a String" % propname
+
         # first setkey for this run
         self.keyname = propname
         iv = self.db._db.view('_%s' % self.classname)
         if self.db.fastopen and iv.structure():
             return
+
         # very first setkey ever
         self.db.dirty = 1
         iv = self.db._db.getas('_%s[k:S,i:I]' % self.classname)
         iv = iv.ordered(1)
-#        print "setkey building index"
         for row in self.getview():
             iv.append(k=getattr(row, propname), i=row.id)
         self.db.commit()
+
     def getkey(self):
         return self.keyname
+
     def lookup(self, keyvalue):
         if type(keyvalue) is not _STRINGTYPE:
             raise TypeError, "%r is not a string" % keyvalue
@@ -721,30 +732,34 @@
         for row in self.getview().select(_isdel=0):
             l.append(str(row.id))
         return l
+
     def count(self):
         return len(self.getview())
+
     def getprops(self, protected=1):
         # protected is not in ping's spec
         allprops = self.ruprops.copy()
         if protected and self.privateprops is not None:
             allprops.update(self.privateprops)
         return allprops
+
     def addprop(self, **properties):
         for key in properties.keys():
             if self.ruprops.has_key(key):
-                raise ValueError, "%s is already a property of %s" % (key, self.classname)
+                raise ValueError, "%s is already a property of %s"%(key,
+                    self.classname)
         self.ruprops.update(properties)
         self.db.fastopen = 0
         view = self.__getview()
         self.db.commit()
     # ---- end of ping's spec
+
     def filter(self, search_matches, filterspec, sort=(None,None),
             group=(None,None)):
         # search_matches is None or a set (dict of {nodeid: {propname:[nodeid,...]}})
         # filterspec is a dict {propname:value}
         # sort and group are (dir, prop) where dir is '+', '-' or None
         #                    and prop is a prop name or None
-
         where = {'_isdel':0}
         mlcriteria = {}
         regexes = {}
@@ -807,11 +822,10 @@
         if where:
             v = v.select(where)
         #print "filter where at  %s" % time.time() 
-            
+
         if mlcriteria:
-                    # multilink - if any of the nodeids required by the
-                    # filterspec aren't in this node's property, then skip
-                    # it
+            # multilink - if any of the nodeids required by the
+            # filterspec aren't in this node's property, then skip it
             def ff(row, ml=mlcriteria):
                 for propname, values in ml.items():
                     sv = getattr(row, propname)
@@ -919,6 +933,7 @@
         props = props.keys()
         props.sort()
         return props[0]
+
     def stringFind(self, **requirements):
         """Locate a particular node by matching a set of its String
         properties in a caseless search.
@@ -1001,7 +1016,8 @@
         view.append(d)
         creator = d.get('creator', None)
         creation = d.get('creation', None)
-        self.db.addjournal(self.classname, newid, 'create', {}, creator, creation)
+        self.db.addjournal(self.classname, newid, 'create', {}, creator,
+            creation)
         return newid
 
     # --- used by Database
@@ -1113,13 +1129,15 @@
     hyperdb.Number    : 'I',
 }
 class FileClass(Class):
-    ' like Class but with a content property '
+    ''' like Class but with a content property
+    '''
     default_mime_type = 'text/plain'
     def __init__(self, db, classname, **properties):
         properties['content'] = FileName()
         if not properties.has_key('type'):
             properties['type'] = hyperdb.String()
         Class.__init__(self, db, classname, **properties)
+
     def get(self, nodeid, propname, default=_marker, cache=1):
         x = Class.get(self, nodeid, propname, default, cache)
         if propname == 'content':
@@ -1130,6 +1148,7 @@
                 except Exception, e:
                     x = repr(e)
         return x
+
     def create(self, **propvalues):
         content = propvalues['content']
         del propvalues['content']
@@ -1145,11 +1164,13 @@
         open(nm, 'wb').write(content)
         self.set(newid, content = 'file:'+nm)
         mimetype = propvalues.get('type', self.default_mime_type)
-        self.db.indexer.add_text((self.classname, newid, 'content'), content, mimetype)
+        self.db.indexer.add_text((self.classname, newid, 'content'), content,
+            mimetype)
         def undo(fnm=nm, action1=os.remove, indexer=self.db.indexer):
             action1(fnm)
         self.rollbackaction(undo)
         return newid
+
     def index(self, nodeid):
         Class.index(self, nodeid)
         mimetype = self.get(nodeid, 'type')
@@ -1159,12 +1180,12 @@
                     self.get(nodeid, 'content'), mimetype)
  
 class IssueClass(Class, roundupdb.IssueClass):
-    # Overridden methods:
-    def __init__(self, db, classname, **properties):
-        """The newly-created class automatically includes the "messages",
+    ''' The newly-created class automatically includes the "messages",
         "files", "nosy", and "superseder" properties.  If the 'properties'
         dictionary attempts to specify any of these properties or a
-        "creation" or "activity" property, a ValueError is raised."""
+        "creation" or "activity" property, a ValueError is raised.
+    '''
+    def __init__(self, db, classname, **properties):
         if not properties.has_key('title'):
             properties['title'] = hyperdb.String(indexme='yes')
         if not properties.has_key('messages'):
@@ -1204,6 +1225,7 @@
             self.reindex = 1
         self.changed = 0
         self.propcache = {}
+
     def force_reindex(self):
         v = self.db.view('ids')
         v[:] = []
@@ -1211,8 +1233,10 @@
         v[:] = []
         self.db.commit()
         self.reindex = 1
+
     def should_reindex(self):
         return self.reindex
+
     def _getprops(self, classname):
         props = self.propcache.get(classname, None)
         if props is None:
@@ -1220,8 +1244,10 @@
             props = [prop.name for prop in props]
             self.propcache[classname] = props
         return props
+
     def _getpropid(self, classname, propname):
         return self._getprops(classname).index(propname)
+
     def _getpropname(self, classname, propid):
         return self._getprops(classname)[propid]
 
@@ -1287,12 +1313,15 @@
                 property = self._getpropname(classname, hit.propid)
                 rslt[i] = (classname, nodeid, property)
         return rslt
+
     def save_index(self):
         if self.changed:
             self.db.commit()
         self.changed = 0
+
     def rollback(self):
         if self.changed:
             self.db.rollback()
             self.db = metakit.storage(self.path, 1)
         self.changed = 0
+

Roundup Issue Tracker: http://roundup-tracker.org/