2222from lib .core .exception import SqlmapConnectionException
2323from lib .core .settings import HASHDB_END_TRANSACTION_RETRIES
2424from lib .core .settings import HASHDB_FLUSH_RETRIES
25- from lib .core .settings import HASHDB_FLUSH_THRESHOLD
25+ from lib .core .settings import HASHDB_FLUSH_THRESHOLD_ITEMS
26+ from lib .core .settings import HASHDB_FLUSH_THRESHOLD_TIME
2627from lib .core .settings import HASHDB_RETRIEVE_RETRIES
2728from lib .core .threads import getCurrentThreadData
2829from lib .core .threads import getCurrentThreadName
@@ -34,15 +35,17 @@ def __init__(self, filepath):
3435 self ._write_cache = {}
3536 self ._cache_lock = threading .Lock ()
3637 self ._connections = []
38+ self ._last_flush_time = time .time ()
3739
3840 def _get_cursor (self ):
3941 threadData = getCurrentThreadData ()
4042
4143 if threadData .hashDBCursor is None :
4244 try :
43- connection = sqlite3 .connect (self .filepath , timeout = 3 , isolation_level = None )
45+ connection = sqlite3 .connect (self .filepath , timeout = 3 , isolation_level = None , check_same_thread = False )
4446 self ._connections .append (connection )
4547 threadData .hashDBCursor = connection .cursor ()
48+ threadData .hashDBCursor .execute ("PRAGMA journal_mode=WAL" )
4649 threadData .hashDBCursor .execute ("CREATE TABLE IF NOT EXISTS storage (id INTEGER PRIMARY KEY, value TEXT)" )
4750 connection .commit ()
4851 except Exception as ex :
@@ -86,7 +89,7 @@ def hashKey(key):
8689 def retrieve (self , key , unserialize = False ):
8790 retVal = None
8891
89- if key and (self ._write_cache or os .path .isfile (self .filepath )):
92+ if key and (self ._write_cache or self . _connections or os .path .isfile (self .filepath )):
9093 hash_ = HashDB .hashKey (key )
9194 retVal = self ._write_cache .get (hash_ )
9295 if not retVal :
@@ -123,28 +126,26 @@ def retrieve(self, key, unserialize=False):
123126 def write (self , key , value , serialize = False ):
124127 if key :
125128 hash_ = HashDB .hashKey (key )
126- self ._cache_lock .acquire ()
127- self ._write_cache [hash_ ] = getUnicode (value ) if not serialize else serializeObject (value )
128- self ._cache_lock .release ()
129+ with self ._cache_lock :
130+ self ._write_cache [hash_ ] = getUnicode (value ) if not serialize else serializeObject (value )
131+ cache_size = len (self ._write_cache )
132+ time_since_flush = time .time () - self ._last_flush_time
129133
130- if getCurrentThreadName () in ( '0' , "MainThread" ) :
131- self .flush ()
134+ if cache_size >= HASHDB_FLUSH_THRESHOLD_ITEMS or time_since_flush >= HASHDB_FLUSH_THRESHOLD_TIME :
135+ self .flush ()
132136
133- def flush (self , forced = False ):
134- if not self ._write_cache :
135- return
137+ def flush (self ):
138+ with self ._cache_lock :
139+ if not self ._write_cache :
140+ return
136141
137- if not forced and len (self ._write_cache ) < HASHDB_FLUSH_THRESHOLD :
138- return
139-
140- self ._cache_lock .acquire ()
141- _ = self ._write_cache
142- self ._write_cache = {}
143- self ._cache_lock .release ()
142+ flush_cache = self ._write_cache
143+ self ._write_cache = {}
144+ self ._last_flush_time = time .time ()
144145
145146 try :
146147 self .beginTransaction ()
147- for hash_ , value in _ .items ():
148+ for hash_ , value in flush_cache .items ():
148149 retries = 0
149150 while True :
150151 try :
@@ -160,7 +161,8 @@ def flush(self, forced=False):
160161 logger .debug (debugMsg )
161162 break
162163
163- if retries == 0 :
164+ # NOTE: skipping the retries == 0 for graceful resolution of multi-threaded runs
165+ if retries == 1 :
164166 warnMsg = "there has been a problem while writing to "
165167 warnMsg += "the session file ('%s')" % getSafeExString (ex )
166168 logger .warning (warnMsg )
0 commit comments