3838_dbs = {}
3939
4040def Database (config , journaltag = None ):
41+ ''' Only have a single instance of the Database class for each instance
42+ '''
4143 db = _dbs .get (config .DATABASE , None )
4244 if db is None or db ._db is None :
4345 db = _Database (config , journaltag )
@@ -81,8 +83,10 @@ def __getattr__(self, classname):
8183 if self .journaltag is None :
8284 return None
8385
86+ # try to set the curuserid from the journaltag
8487 try :
85- self .curuserid = x = int (self .classes ['user' ].lookup (self .journaltag ))
88+ x = int (self .classes ['user' ].lookup (self .journaltag ))
89+ self .curuserid = x
8690 except KeyError :
8791 if self .journaltag == 'admin' :
8892 self .curuserid = x = 1
@@ -91,6 +95,7 @@ def __getattr__(self, classname):
9195 return x
9296 elif classname == 'transactions' :
9397 return self .dirty
98+ # fall back on the classes
9499 return self .getclass (classname )
95100 def getclass (self , classname ):
96101 try :
@@ -100,6 +105,7 @@ def getclass(self, classname):
100105 def getclasses (self ):
101106 return self .classes .keys ()
102107 # --- end of ping's spec
108+
103109 # --- exposed methods
104110 def commit (self ):
105111 if self .dirty :
@@ -182,9 +188,10 @@ def getjournal(self, tablenm, nodeid):
182188 #usernm = userclass.get(str(row.user), 'username')
183189 dt = date .Date (time .gmtime (row .date ))
184190 #rslt.append((nodeid, dt, usernm, _actionnames[row.action], params))
185- rslt .append ((nodeid , dt , str (row .user ), _actionnames [row .action ], params ))
191+ rslt .append ((nodeid , dt , str (row .user ), _actionnames [row .action ],
192+ params ))
186193 return rslt
187-
194+
188195 def destroyjournal (self , tablenm , nodeid ):
189196 nodeid = int (nodeid )
190197 tblid = self .tables .find (name = tablenm )
@@ -215,13 +222,22 @@ def close(self):
215222
216223 # --- internal
217224 def __open (self ):
225+ ''' Open the metakit database
226+ '''
227+ # make the database dir if it doesn't exist
218228 if not os .path .exists (self .config .DATABASE ):
219229 os .makedirs (self .config .DATABASE )
230+
231+ # figure the file names
220232 self .dbnm = db = os .path .join (self .config .DATABASE , 'tracker.mk4' )
221233 lockfilenm = db [:- 3 ]+ 'lck'
234+
235+ # get the database lock
222236 self .lockfile = locking .acquire_lock (lockfilenm )
223237 self .lockfile .write (str (os .getpid ()))
224238 self .lockfile .flush ()
239+
240+ # see if the schema has changed since last db access
225241 self .fastopen = 0
226242 if os .path .exists (db ):
227243 dbtm = os .path .getmtime (db )
@@ -236,18 +252,28 @@ def __open(self):
236252 else :
237253 # can't find schemamod - must be frozen
238254 self .fastopen = 1
255+
256+ # open the db
239257 db = metakit .storage (db , 1 )
240258 hist = db .view ('history' )
241259 tables = db .view ('tables' )
242260 if not self .fastopen :
261+ # create the database if it's brand new
243262 if not hist .structure ():
244263 hist = db .getas ('history[tableid:I,nodeid:I,date:I,user:I,action:I,params:B]' )
245264 if not tables .structure ():
246265 tables = db .getas ('tables[name:S]' )
247266 db .commit ()
267+
268+ # we now have an open, initialised database
248269 self .tables = tables
249270 self .hist = hist
250271 return db
272+
273+ def setid (self , classname , maxid ):
274+ ''' No-op in metakit
275+ '''
276+ pass
251277
252278_STRINGTYPE = type ('' )
253279_LISTTYPE = type ([])
@@ -632,10 +658,12 @@ def retire(self, nodeid):
632658 ndx = view .find (id = int (nodeid ))
633659 if ndx < 0 :
634660 raise KeyError , "nodeid %s not found" % nodeid
661+
635662 row = view [ndx ]
636663 oldvalues = self .uncommitted .setdefault (row .id , {})
637664 oldval = oldvalues ['_isdel' ] = row ._isdel
638665 row ._isdel = 1
666+
639667 if self .do_journal :
640668 self .db .addjournal (self .classname , nodeid , _RETIRE , {})
641669 if self .keyname :
@@ -646,6 +674,16 @@ def retire(self, nodeid):
646674 self .db .dirty = 1
647675 self .fireReactors ('retire' , nodeid , None )
648676
677+ def is_retired (self , nodeid ):
678+ view = self .getview (1 )
679+ # node must exist & not be retired
680+ id = int (nodeid )
681+ ndx = view .find (id = id )
682+ if ndx < 0 :
683+ raise IndexError , "%s has no node %s" % (self .classname , nodeid )
684+ row = view [ndx ]
685+ return row ._isdel
686+
649687 def history (self , nodeid ):
650688 if not self .do_journal :
651689 raise ValueError , 'Journalling is disabled for this class'
@@ -796,6 +834,7 @@ def addprop(self, **properties):
796834 raise ValueError , "%s is already a property of %s" % (key ,
797835 self .classname )
798836 self .ruprops .update (properties )
837+ # Class structure has changed
799838 self .db .fastopen = 0
800839 view = self .__getview ()
801840 self .db .commit ()
@@ -1037,6 +1076,10 @@ def export_list(self, propnames, nodeid):
10371076 elif isinstance (proptype , hyperdb .Password ):
10381077 value = str (value )
10391078 l .append (repr (value ))
1079+
1080+ # append retired flag
1081+ l .append (self .is_retired (nodeid ))
1082+
10401083 return l
10411084
10421085 def import_list (self , propnames , proplist ):
@@ -1064,11 +1107,24 @@ def import_list(self, propnames, proplist):
10641107 value = int (calendar .timegm (value ))
10651108 elif isinstance (prop , hyperdb .Interval ):
10661109 value = str (date .Interval (value ))
1110+ elif isinstance (prop , hyperdb .Number ):
1111+ value = int (value )
1112+ elif isinstance (prop , hyperdb .Boolean ):
1113+ value = int (value )
1114+ elif isinstance (prop , hyperdb .Link ):
1115+ value = int (value )
1116+ elif isinstance (prop , hyperdb .Multilink ):
1117+ value = map (int , value )
10671118 d [propname ] = value
1068- view .append (d )
1069- creator = d .get ('creator' , None )
1070- creation = d .get ('creation' , None )
1071- self .db .addjournal (self .classname , newid , 'create' , {}, creator ,
1119+ # is the item retired?
1120+ if int (proplist [- 1 ]):
1121+ d ['_isdel' ] = 1
1122+ # XXX this is BROKEN for reasons I don't understand!
1123+ ndx = view .append (d )
1124+
1125+ creator = d .get ('creator' , 0 )
1126+ creation = d .get ('creation' , 0 )
1127+ self .db .addjournal (self .classname , newid , _CREATE , {}, creator ,
10721128 creation )
10731129 return newid
10741130
@@ -1101,11 +1157,20 @@ def rollbackaction(self, action):
11011157 self .rbactions .append (action )
11021158 # --- internal
11031159 def __getview (self ):
1160+ ''' Find the interface for a specific Class in the hyperdb.
1161+
1162+ This method checks to see whether the schema has changed and
1163+ re-works the underlying metakit structure if it has.
1164+ '''
11041165 db = self .db ._db
11051166 view = db .view (self .classname )
11061167 mkprops = view .structure ()
1168+
1169+ # if we have structure in the database, and the structure hasn't
1170+ # changed
11071171 if mkprops and self .db .fastopen :
11081172 return view .ordered (1 )
1173+
11091174 # is the definition the same?
11101175 for nm , rutyp in self .ruprops .items ():
11111176 for mkprop in mkprops :
@@ -1136,7 +1201,7 @@ def getview(self, RW=0):
11361201 return self .db ._db .view (self .classname ).ordered (1 )
11371202 def getindexview (self , RW = 0 ):
11381203 return self .db ._db .view ("_%s" % self .classname ).ordered (1 )
1139-
1204+
11401205def _fetchML (sv ):
11411206 l = []
11421207 for row in sv :
@@ -1155,7 +1220,7 @@ def _fetchPW(s):
11551220 return p
11561221
11571222def _fetchLink (n ):
1158- ''' Return None if the string is empty ? otherwise ensure it's a string?
1223+ ''' Return None if the link is 0 - otherwise strify it.
11591224 '''
11601225 return n and str (n ) or None
11611226
0 commit comments