Mercurial > p > roundup > code
comparison roundup/backends/back_anydbm.py @ 1780:d2801a2b0a77
Initial implementation (half-baked) at new Tracker instance.
Cleaned up caching API / comments in backends.
Fixes to docs.
| author | Richard Jones <richard@users.sourceforge.net> |
|---|---|
| date | Thu, 04 Sep 2003 00:47:01 +0000 |
| parents | ab7760caf6ff |
| children | c8614db86be2 |
comparison
equal
deleted
inserted
replaced
| 1777:fbe08359511a | 1780:d2801a2b0a77 |
|---|---|
| 13 # BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | 13 # BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
| 14 # FOR A PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" | 14 # FOR A PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" |
| 15 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, | 15 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, |
| 16 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | 16 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
| 17 # | 17 # |
| 18 #$Id: back_anydbm.py,v 1.123 2003-08-26 00:06:55 richard Exp $ | 18 #$Id: back_anydbm.py,v 1.124 2003-09-04 00:47:01 richard Exp $ |
| 19 ''' | 19 ''' |
| 20 This module defines a backend that saves the hyperdatabase in a database | 20 This module defines a backend that saves the hyperdatabase in a database |
| 21 chosen by anydbm. It is guaranteed to always be available in python | 21 chosen by anydbm. It is guaranteed to always be available in python |
| 22 versions >2.1.1 (the dumbdbm fallback in 2.1.1 and earlier has several | 22 versions >2.1.1 (the dumbdbm fallback in 2.1.1 and earlier has several |
| 23 serious bugs, and is not available) | 23 serious bugs, and is not available) |
| 281 print >>hyperdb.DEBUG, 'savenode', (self, classname, nodeid, node) | 281 print >>hyperdb.DEBUG, 'savenode', (self, classname, nodeid, node) |
| 282 self.transactions.append((self.doSaveNode, (classname, nodeid, node))) | 282 self.transactions.append((self.doSaveNode, (classname, nodeid, node))) |
| 283 | 283 |
| 284 def getnode(self, classname, nodeid, db=None, cache=1): | 284 def getnode(self, classname, nodeid, db=None, cache=1): |
| 285 ''' get a node from the database | 285 ''' get a node from the database |
| 286 | |
| 287 Note the "cache" parameter is not used, and exists purely for | |
| 288 backward compatibility! | |
| 286 ''' | 289 ''' |
| 287 if __debug__: | 290 if __debug__: |
| 288 print >>hyperdb.DEBUG, 'getnode', (self, classname, nodeid, db) | 291 print >>hyperdb.DEBUG, 'getnode', (self, classname, nodeid, db) |
| 289 if cache: | 292 |
| 290 # try the cache | 293 # try the cache |
| 291 cache_dict = self.cache.setdefault(classname, {}) | 294 cache_dict = self.cache.setdefault(classname, {}) |
| 292 if cache_dict.has_key(nodeid): | 295 if cache_dict.has_key(nodeid): |
| 293 if __debug__: | 296 if __debug__: |
| 294 print >>hyperdb.TRACE, 'get %s %s cached'%(classname, | 297 print >>hyperdb.TRACE, 'get %s %s cached'%(classname, |
| 295 nodeid) | 298 nodeid) |
| 296 return cache_dict[nodeid] | 299 return cache_dict[nodeid] |
| 297 | 300 |
| 298 if __debug__: | 301 if __debug__: |
| 299 print >>hyperdb.TRACE, 'get %s %s'%(classname, nodeid) | 302 print >>hyperdb.TRACE, 'get %s %s'%(classname, nodeid) |
| 300 | 303 |
| 301 # get from the database and save in the cache | 304 # get from the database and save in the cache |
| 1006 | 1009 |
| 1007 'nodeid' must be the id of an existing node of this class or an | 1010 'nodeid' must be the id of an existing node of this class or an |
| 1008 IndexError is raised. 'propname' must be the name of a property | 1011 IndexError is raised. 'propname' must be the name of a property |
| 1009 of this class or a KeyError is raised. | 1012 of this class or a KeyError is raised. |
| 1010 | 1013 |
| 1011 'cache' indicates whether the transaction cache should be queried | 1014 'cache' exists for backward compatibility, and is not used. |
| 1012 for the node. If the node has been modified and you need to | |
| 1013 determine what its values prior to modification are, you need to | |
| 1014 set cache=0. | |
| 1015 | 1015 |
| 1016 Attempts to get the "creation" or "activity" properties should | 1016 Attempts to get the "creation" or "activity" properties should |
| 1017 do the right thing. | 1017 do the right thing. |
| 1018 ''' | 1018 ''' |
| 1019 if propname == 'id': | 1019 if propname == 'id': |
| 1020 return nodeid | 1020 return nodeid |
| 1021 | 1021 |
| 1022 # get the node's dict | 1022 # get the node's dict |
| 1023 d = self.db.getnode(self.classname, nodeid, cache=cache) | 1023 d = self.db.getnode(self.classname, nodeid) |
| 1024 | 1024 |
| 1025 # check for one of the special props | 1025 # check for one of the special props |
| 1026 if propname == 'creation': | 1026 if propname == 'creation': |
| 1027 if d.has_key('creation'): | 1027 if d.has_key('creation'): |
| 1028 return d['creation'] | 1028 return d['creation'] |
| 1089 ''' Return a convenience wrapper for the node. | 1089 ''' Return a convenience wrapper for the node. |
| 1090 | 1090 |
| 1091 'nodeid' must be the id of an existing node of this class or an | 1091 'nodeid' must be the id of an existing node of this class or an |
| 1092 IndexError is raised. | 1092 IndexError is raised. |
| 1093 | 1093 |
| 1094 'cache' indicates whether the transaction cache should be queried | 1094 'cache' exists for backwards compatibility, and is not used. |
| 1095 for the node. If the node has been modified and you need to | 1095 ''' |
| 1096 determine what its values prior to modification are, you need to | 1096 return Node(self, nodeid) |
| 1097 set cache=0. | |
| 1098 ''' | |
| 1099 return Node(self, nodeid, cache=cache) | |
| 1100 | 1097 |
| 1101 def set(self, nodeid, **propvalues): | 1098 def set(self, nodeid, **propvalues): |
| 1102 '''Modify a property on an existing node of this class. | 1099 '''Modify a property on an existing node of this class. |
| 1103 | 1100 |
| 1104 'nodeid' must be the id of an existing node of this class or an | 1101 'nodeid' must be the id of an existing node of this class or an |
| 1132 raise DatabaseError, 'Database open read-only' | 1129 raise DatabaseError, 'Database open read-only' |
| 1133 | 1130 |
| 1134 self.fireAuditors('set', nodeid, propvalues) | 1131 self.fireAuditors('set', nodeid, propvalues) |
| 1135 # Take a copy of the node dict so that the subsequent set | 1132 # Take a copy of the node dict so that the subsequent set |
| 1136 # operation doesn't modify the oldvalues structure. | 1133 # operation doesn't modify the oldvalues structure. |
| 1137 try: | 1134 oldvalues = copy.deepcopy(self.db.getnode(self.classname, nodeid)) |
| 1138 # try not using the cache initially | |
| 1139 oldvalues = copy.deepcopy(self.db.getnode(self.classname, nodeid, | |
| 1140 cache=0)) | |
| 1141 except IndexError: | |
| 1142 # this will be needed if somone does a create() and set() | |
| 1143 # with no intervening commit() | |
| 1144 oldvalues = copy.deepcopy(self.db.getnode(self.classname, nodeid)) | |
| 1145 | 1135 |
| 1146 node = self.db.getnode(self.classname, nodeid) | 1136 node = self.db.getnode(self.classname, nodeid) |
| 1147 if node.has_key(self.db.RETIRED_FLAG): | 1137 if node.has_key(self.db.RETIRED_FLAG): |
| 1148 raise IndexError | 1138 raise IndexError |
| 1149 num_re = re.compile('^\d+$') | 1139 num_re = re.compile('^\d+$') |
| 2038 # save off the "content" file | 2028 # save off the "content" file |
| 2039 self.db.storefile(self.classname, newid, None, content) | 2029 self.db.storefile(self.classname, newid, None, content) |
| 2040 return newid | 2030 return newid |
| 2041 | 2031 |
| 2042 def get(self, nodeid, propname, default=_marker, cache=1): | 2032 def get(self, nodeid, propname, default=_marker, cache=1): |
| 2043 ''' trap the content propname and get it from the file | 2033 ''' Trap the content propname and get it from the file |
| 2034 | |
| 2035 'cache' exists for backwards compatibility, and is not used. | |
| 2044 ''' | 2036 ''' |
| 2045 poss_msg = 'Possibly an access right configuration problem.' | 2037 poss_msg = 'Possibly an access right configuration problem.' |
| 2046 if propname == 'content': | 2038 if propname == 'content': |
| 2047 try: | 2039 try: |
| 2048 return self.db.getfile(self.classname, nodeid, None) | 2040 return self.db.getfile(self.classname, nodeid, None) |
| 2049 except IOError, (strerror): | 2041 except IOError, (strerror): |
| 2050 # XXX by catching this we donot see an error in the log. | 2042 # XXX by catching this we donot see an error in the log. |
| 2051 return 'ERROR reading file: %s%s\n%s\n%s'%( | 2043 return 'ERROR reading file: %s%s\n%s\n%s'%( |
| 2052 self.classname, nodeid, poss_msg, strerror) | 2044 self.classname, nodeid, poss_msg, strerror) |
| 2053 if default is not _marker: | 2045 if default is not _marker: |
| 2054 return Class.get(self, nodeid, propname, default, cache=cache) | 2046 return Class.get(self, nodeid, propname, default) |
| 2055 else: | 2047 else: |
| 2056 return Class.get(self, nodeid, propname, cache=cache) | 2048 return Class.get(self, nodeid, propname) |
| 2057 | 2049 |
| 2058 def getprops(self, protected=1): | 2050 def getprops(self, protected=1): |
| 2059 ''' In addition to the actual properties on the node, these methods | 2051 ''' In addition to the actual properties on the node, these methods |
| 2060 provide the "content" property. If the "protected" flag is true, | 2052 provide the "content" property. If the "protected" flag is true, |
| 2061 we include protected properties - those which may not be | 2053 we include protected properties - those which may not be |
