1- # $Id: rdbms_common.py,v 1.5 2002-09-19 03:56:20 richard Exp $
1+ # $Id: rdbms_common.py,v 1.6 2002-09-19 05:30:25 richard Exp $
22
33# standard python modules
44import sys , os , time , re , errno , weakref , copy
1313from roundup .indexer import Indexer
1414from sessions import Sessions
1515
16+ # number of rows to keep in memory
17+ ROW_CACHE_SIZE = 100
18+
1619class Database (FileStorage , hyperdb .Database , roundupdb .Database ):
20+ ''' Wrapper around an SQL database that presents a hyperdb interface.
21+
22+ - some functionality is specific to the actual SQL database, hence
23+ the sql_* methods that are NotImplemented
24+ - we keep a cache of the latest ROW_CACHE_SIZE row fetches.
25+ '''
1726 # flag to set on retired entries
1827 RETIRED_FLAG = '__hyperdb_retired'
1928
@@ -30,6 +39,11 @@ def __init__(self, config, journaltag=None):
3039 # additional transaction support for external files and the like
3140 self .transactions = []
3241
42+ # keep a cache of the N most recently retrieved rows of any kind
43+ # (classname, nodeid) = row
44+ self .cache = {}
45+ self .cache_lru = []
46+
3347 # open a connection to the database, creating the "conn" attribute
3448 self .open_connection ()
3549
@@ -453,6 +467,13 @@ def addnode(self, classname, nodeid, node):
453467 if not node .has_key (col ):
454468 node [col ] = None
455469
470+ # clear this node out of the cache if it's in there
471+ key = (classname , nodeid )
472+ if self .cache .has_key (key ):
473+ del self .cache [key ]
474+ self .cache_lru .remove (key )
475+
476+ # make the node data safe for the DB
456477 node = self .serialise (classname , node )
457478
458479 # make sure the ordering is correct for column name -> column value
@@ -483,6 +504,13 @@ def setnode(self, classname, nodeid, node, multilink_changes):
483504 '''
484505 if __debug__ :
485506 print >> hyperdb .DEBUG , 'setnode' , (self , classname , nodeid , node )
507+
508+ # clear this node out of the cache if it's in there
509+ key = (classname , nodeid )
510+ if self .cache .has_key (key ):
511+ del self .cache [key ]
512+ self .cache_lru .remove (key )
513+
486514 node = self .serialise (classname , node )
487515
488516 cl = self .classes [classname ]
@@ -531,6 +559,16 @@ def getnode(self, classname, nodeid):
531559 '''
532560 if __debug__ :
533561 print >> hyperdb .DEBUG , 'getnode' , (self , classname , nodeid )
562+
563+ # see if we have this node cached
564+ key = (classname , nodeid )
565+ if self .cache .has_key (key ):
566+ # push us back to the top of the LRU
567+ self .cache_lru .remove (key )
568+ self .cache_lry .insert (0 , key )
569+ # return the cached information
570+ return self .cache [key ]
571+
534572 # figure the columns we're fetching
535573 cl = self .classes [classname ]
536574 cols , mls = self .determine_columns (cl .properties .items ())
@@ -559,7 +597,17 @@ def getnode(self, classname, nodeid):
559597 # extract the first column from the result
560598 node [col ] = [x [0 ] for x in cursor .fetchall ()]
561599
562- return self .unserialise (classname , node )
600+ # un-dbificate the node data
601+ node = self .unserialise (classname , node )
602+
603+ # save off in the cache
604+ key = (classname , nodeid )
605+ self .cache [key ] = node
606+ # update the LRU
607+ self .cache_lru .insert (0 , key )
608+ del self .cache [self .cache_lru .pop ()]
609+
610+ return node
563611
564612 def destroynode (self , classname , nodeid ):
565613 '''Remove a node from the database. Called exclusively by the
@@ -572,6 +620,10 @@ def destroynode(self, classname, nodeid):
572620 if not self .hasnode (classname , nodeid ):
573621 raise IndexError , '%s has no node %s' % (classname , nodeid )
574622
623+ # see if we have this node cached
624+ if self .cache .has_key ((classname , nodeid )):
625+ del self .cache [(classname , nodeid )]
626+
575627 # see if there's any obvious commit actions that we should get rid of
576628 for entry in self .transactions [:]:
577629 if entry [1 ][:2 ] == (classname , nodeid ):
@@ -1636,6 +1688,8 @@ def filter(self, search_matches, filterspec, sort, group):
16361688 if '-1' in v :
16371689 v .remove ('-1' )
16381690 xtra = ' or _%s is NULL' % k
1691+ else :
1692+ xtra = ''
16391693 s = ',' .join ([a for x in v ])
16401694 where .append ('(_%s in (%s)%s)' % (k , s , xtra ))
16411695 args = args + v
0 commit comments