def _AttachExternalDatabases(self): for (name, filename) in self._db_filenames.items(): if name == 'main': continue db_path = os.path.join(self._db_dir, filename) if os.path.exists( db_path) and not HydrusPaths.FileisWriteable(db_path): raise HydrusExceptions.DBAccessException( '"{}" seems to be read-only!'.format(db_path)) self._Execute('ATTACH ? AS ' + name + ';', (db_path, )) db_path = os.path.join(self._db_dir, self._durable_temp_db_filename) self._Execute('ATTACH ? AS durable_temp;', (db_path, ))
def _InitDBConnection(self): self._CloseDBConnection() db_path = os.path.join(self._db_dir, self._db_filenames['main']) try: if os.path.exists( db_path) and not HydrusPaths.FileisWriteable(db_path): raise HydrusExceptions.DBAccessException( '"{}" seems to be read-only!'.format(db_path)) self._db = sqlite3.connect(db_path, isolation_level=None, detect_types=sqlite3.PARSE_DECLTYPES) c = self._db.cursor() self._SetCursor(c) self._is_connected = True self._cursor_transaction_wrapper = HydrusDBBase.DBCursorTransactionWrapper( self._c, HG.db_transaction_commit_period) if HG.no_db_temp_files: self._Execute('PRAGMA temp_store = 2;' ) # use memory for temp store exclusively self._AttachExternalDatabases() self._LoadModules() self._Execute('ATTACH ":memory:" AS mem;') except HydrusExceptions.DBAccessException as e: raise except Exception as e: raise HydrusExceptions.DBAccessException( 'Could not connect to database! If the answer is not obvious to you, please let hydrus dev know. Error follows:' + os.linesep * 2 + str(e)) HydrusDBBase.TemporaryIntegerTableNameCache.instance().Clear() # durable_temp is not excluded here db_names = [ name for (index, name, path) in self._Execute('PRAGMA database_list;') if name not in ('mem', 'temp') ] for db_name in db_names: # MB -> KB cache_size = HG.db_cache_size * 1024 self._Execute('PRAGMA {}.cache_size = -{};'.format( db_name, cache_size)) self._Execute('PRAGMA {}.journal_mode = {};'.format( db_name, HG.db_journal_mode)) if HG.db_journal_mode in ('PERSIST', 'WAL'): # We tried 1GB here, but I have reports of larger ones that don't seem to truncate ever? # Not sure what that is about, but I guess the db sometimes doesn't want to (expensively?) recover pages from the journal and just appends more data # In any case, this pragma is not a 'don't allow it to grow larger than', it's a 'after commit, truncate back to this', so no need to make it so large # default is -1, which means no limit self._Execute('PRAGMA {}.journal_size_limit = {};'.format( db_name, HydrusDBBase.JOURNAL_SIZE_LIMIT)) self._Execute('PRAGMA {}.synchronous = {};'.format( db_name, HG.db_synchronous)) try: self._Execute('SELECT * FROM {}.sqlite_master;'.format( db_name)).fetchone() except sqlite3.OperationalError as e: message = 'The database seemed valid, but hydrus failed to read basic data from it. You may need to run the program in a different journal mode using --db_journal_mode. Full error information:' message += os.linesep * 2 message += str(e) HydrusData.DebugPrint(message) raise HydrusExceptions.DBAccessException(message) try: self._cursor_transaction_wrapper.BeginImmediate() except Exception as e: if 'locked' in str(e): raise HydrusExceptions.DBAccessException( 'Database appeared to be locked. Please ensure there is not another client already running on this database, and then try restarting the client.' ) raise HydrusExceptions.DBAccessException(str(e))