1818#  You should have received a copy of the GNU Affero General Public License 
1919#  along with Elixir.  If not, see <http://www.gnu.org/licenses/>. 
2020
21+ from  typing  import  OrderedDict 
2122import  berkeleydb 
2223import  re 
2324from  . import  lib 
@@ -208,18 +209,94 @@ def close(self):
208209    def  __len__ (self ):
209210        return  self .db .stat ()["nkeys" ]
210211
212+ class  CachedBsdDB :
213+     def  __init__ (self , filename , readonly , contentType , cachesize ):
214+         self .filename  =  filename 
215+         self .db  =  berkeleydb .db .DB ()
216+         flags  =  0 
217+ 
218+         self .cachesize  =  cachesize 
219+         self .cache  =  OrderedDict ()
220+ 
221+         if  readonly :
222+             flags  |=  berkeleydb .db .DB_RDONLY 
223+             self .db .open (filename , flags = flags )
224+         else :
225+             flags  |=  berkeleydb .db .DB_CREATE 
226+             self .db .open (filename , flags = flags , mode = 0o644 , dbtype = berkeleydb .db .DB_BTREE )
227+         self .ctype  =  contentType 
228+ 
229+     def  exists (self , key ):
230+         if  key  in  self .cache :
231+             return  True 
232+ 
233+         key  =  autoBytes (key )
234+         return  self .db .exists (key )
235+ 
236+     def  get (self , key ):
237+         if  key  in  self .cache :
238+             self .cache .move_to_end (key )
239+             return  self .cache [key ]
240+ 
241+         key  =  autoBytes (key )
242+         p  =  self .db .get (key )
243+         if  p  is  None :
244+             return  None 
245+         p  =  self .ctype (p )
246+ 
247+         self .cache [key ] =  p 
248+         self .cache .move_to_end (key )
249+         if  len (self .cache ) >  self .cachesize :
250+             old_k , old_v  =  self .cache .popitem (last = False )
251+             self .put_raw (old_k , old_v )
252+ 
253+         return  p 
254+ 
255+     def  get_keys (self ):
256+         return  self .db .keys ()
257+ 
258+     def  put (self , key , val ):
259+         self .cache [key ] =  val 
260+         self .cache .move_to_end (key )
261+         if  len (self .cache ) >  self .cachesize :
262+             old_k , old_v  =  self .cache .popitem (last = False )
263+             self .put_raw (old_k , old_v )
264+ 
265+     def  put_raw (self , key , val , sync = False ):
266+         key  =  autoBytes (key )
267+         val  =  autoBytes (val )
268+         if  type (val ) is  not bytes :
269+             val  =  val .pack ()
270+         self .db .put (key , val )
271+         if  sync :
272+             self .db .sync ()
273+ 
274+     def  sync (self ):
275+         for  k , v  in  self .cache .items ():
276+             self .put_raw (k , v )
277+ 
278+         self .db .sync ()
279+     
280+     def  close (self ):
281+         self .sync ()
282+         self .db .close ()
283+ 
284+     def  __len__ (self ):
285+         return  self .db .stat ()["nkeys" ]
286+ 
211287class  DB :
212-     def  __init__ (self , dir , readonly = True , dtscomp = False , shared = False , update_cache = False ):
288+     def  __init__ (self , dir , readonly = True , dtscomp = False , shared = False , update_cache = None ):
213289        if  os .path .isdir (dir ):
214290            self .dir  =  dir 
215291        else :
216292            raise  FileNotFoundError (errno .ENOENT , os .strerror (errno .ENOENT ), dir )
217293
218294        ro  =  readonly 
219-         cachesize  =  None 
220295
221296        if  update_cache :
222-             cachesize  =  CACHESIZE 
297+             db_cls  =  lambda  dir , ro , ctype : CachedBsdDB (dir , ro , ctype , cachesize = update_cache )
298+         else :
299+             db_cls  =  lambda  dir , ro , ctype : BsdDB (dir , ro , ctype , shared = shared )
223300
224301        self .vars  =  BsdDB (dir  +  '/variables.db' , ro , lambda  x : int (x .decode ()), shared = shared )
225302            # Key-value store of basic information 
@@ -230,20 +307,20 @@ def __init__(self, dir, readonly=True, dtscomp=False, shared=False, update_cache
230307        self .file  =  BsdDB (dir  +  '/filenames.db' , ro , lambda  x : x .decode (), shared = shared )
231308            # Map serial number to filename 
232309        self .vers  =  BsdDB (dir  +  '/versions.db' , ro , PathList , shared = shared )
233-         self .defs  =  BsdDB (dir  +  '/definitions.db' , ro , DefList ,  shared = shared ,  cachesize = cachesize )
310+         self .defs  =  db_cls (dir  +  '/definitions.db' , ro , DefList )
234311        self .defs_cache  =  {}
235312        NOOP  =  lambda  x : x 
236313        self .defs_cache ['C' ] =  BsdDB (dir  +  '/definitions-cache-C.db' , ro , NOOP , shared = shared )
237314        self .defs_cache ['K' ] =  BsdDB (dir  +  '/definitions-cache-K.db' , ro , NOOP , shared = shared )
238315        self .defs_cache ['D' ] =  BsdDB (dir  +  '/definitions-cache-D.db' , ro , NOOP , shared = shared )
239316        self .defs_cache ['M' ] =  BsdDB (dir  +  '/definitions-cache-M.db' , ro , NOOP , shared = shared )
240317        assert  sorted (self .defs_cache .keys ()) ==  sorted (lib .CACHED_DEFINITIONS_FAMILIES )
241-         self .refs  =  BsdDB (dir  +  '/references.db' , ro , RefList ,  shared = shared ,  cachesize = cachesize )
242-         self .docs  =  BsdDB (dir  +  '/doccomments.db' , ro , RefList ,  shared = shared ,  cachesize = cachesize )
318+         self .refs  =  db_cls (dir  +  '/references.db' , ro , RefList )
319+         self .docs  =  db_cls (dir  +  '/doccomments.db' , ro , RefList )
243320        self .dtscomp  =  dtscomp 
244321        if  dtscomp :
245-             self .comps  =  BsdDB (dir  +  '/compatibledts.db' , ro , RefList ,  shared = shared ,  cachesize = cachesize )
246-             self .comps_docs  =  BsdDB (dir  +  '/compatibledts_docs.db' , ro , RefList ,  shared = shared ,  cachesize = cachesize )
322+             self .comps  =  db_cls (dir  +  '/compatibledts.db' , ro , RefList )
323+             self .comps_docs  =  db_cls (dir  +  '/compatibledts_docs.db' , ro , RefList )
247324            # Use a RefList in case there are multiple doc comments for an identifier 
248325
249326    def  close (self ):
0 commit comments