def __init__(self, controller, db_dir, db_name): if HydrusPaths.GetFreeSpace(db_dir) < 500 * 1048576: raise Exception( 'Sorry, it looks like the db partition has less than 500MB, please free up some space.' ) HydrusDBBase.DBBase.__init__(self) self._controller = controller self._db_dir = db_dir self._db_name = db_name self._modules = [] HydrusDBBase.TemporaryIntegerTableNameCache() self._ssl_cert_filename = '{}.crt'.format(self._db_name) self._ssl_key_filename = '{}.key'.format(self._db_name) self._ssl_cert_path = os.path.join(self._db_dir, self._ssl_cert_filename) self._ssl_key_path = os.path.join(self._db_dir, self._ssl_key_filename) main_db_filename = db_name if not main_db_filename.endswith('.db'): main_db_filename += '.db' self._db_filenames = {} self._db_filenames['main'] = main_db_filename self._durable_temp_db_filename = db_name + '.temp.db' durable_temp_db_path = os.path.join(self._db_dir, self._durable_temp_db_filename) if os.path.exists(durable_temp_db_path): HydrusPaths.DeletePath(durable_temp_db_path) wal_lad = durable_temp_db_path + '-wal' if os.path.exists(wal_lad): HydrusPaths.DeletePath(wal_lad) shm_lad = durable_temp_db_path + '-shm' if os.path.exists(shm_lad): HydrusPaths.DeletePath(shm_lad) HydrusData.Print( 'Found and deleted the durable temporary database on boot. The last exit was probably not clean.' ) self._InitExternalDatabases() self._is_first_start = False self._is_db_updated = False self._local_shutdown = False self._pause_and_disconnect = False self._loop_finished = False self._ready_to_serve_requests = False self._could_not_initialise = False self._jobs = queue.Queue() self._currently_doing_job = False self._current_status = '' self._current_job_name = '' self._db = None self._is_connected = False self._cursor_transaction_wrapper = None if os.path.exists( os.path.join(self._db_dir, self._db_filenames['main'])): # open and close to clean up in case last session didn't close well self._InitDB() self._CloseDBConnection() self._InitDB() (version, ) = self._Execute('SELECT version FROM version;').fetchone() if version > HC.SOFTWARE_VERSION: self._ReportOverupdatedDB(version) if version < (HC.SOFTWARE_VERSION - 15): self._ReportUnderupdatedDB(version) if version < HC.SOFTWARE_VERSION - 50: raise Exception('Your current database version of hydrus ' + str(version) + ' is too old for this software version ' + str(HC.SOFTWARE_VERSION) + ' to update. Please try updating with version ' + str(version + 45) + ' or earlier first.') self._RepairDB(version) while version < HC.SOFTWARE_VERSION: time.sleep(self.UPDATE_WAIT) try: self._cursor_transaction_wrapper.BeginImmediate() except Exception as e: raise HydrusExceptions.DBAccessException(str(e)) try: self._UpdateDB(version) self._cursor_transaction_wrapper.Commit() self._is_db_updated = True except: e = Exception('Updating the ' + self._db_name + ' db to version ' + str(version + 1) + ' caused this error:' + os.linesep + traceback.format_exc()) try: self._cursor_transaction_wrapper.Rollback() except Exception as rollback_e: HydrusData.Print( 'When the update failed, attempting to rollback the database failed.' ) HydrusData.PrintException(rollback_e) raise e (version, ) = self._Execute('SELECT version FROM version;').fetchone() self._CloseDBConnection() self._controller.CallToThreadLongRunning(self.MainLoop) while not self._ready_to_serve_requests: time.sleep(0.1) if self._could_not_initialise: raise Exception( 'Could not initialise the db! Error written to the log!')
def __init__( self, controller, db_dir, db_name ): if HydrusPaths.GetFreeSpace( db_dir ) < 500 * 1048576: raise Exception( 'Sorry, it looks like the db partition has less than 500MB, please free up some space.' ) self._controller = controller self._db_dir = db_dir self._db_name = db_name self._transaction_started = 0 self._in_transaction = False self._transaction_contains_writes = False self._connection_timestamp = 0 main_db_filename = db_name if not main_db_filename.endswith( '.db' ): main_db_filename += '.db' self._db_filenames = {} self._db_filenames[ 'main' ] = main_db_filename self._durable_temp_db_filename = db_name + '.temp.db' self._InitExternalDatabases() if distutils.version.LooseVersion( sqlite3.sqlite_version ) < distutils.version.LooseVersion( '3.11.0' ): self._fast_big_transaction_wal = False else: self._fast_big_transaction_wal = True self._is_first_start = False self._is_db_updated = False self._local_shutdown = False self._pause_and_disconnect = False self._loop_finished = False self._ready_to_serve_requests = False self._could_not_initialise = False self._jobs = queue.Queue() self._pubsubs = [] self._currently_doing_job = False self._current_status = '' self._current_job_name = '' self._db = None self._c = None if os.path.exists( os.path.join( self._db_dir, self._db_filenames[ 'main' ] ) ): # open and close to clean up in case last session didn't close well self._InitDB() self._CloseDBCursor() self._InitDB() self._RepairDB() ( version, ) = self._c.execute( 'SELECT version FROM version;' ).fetchone() if version > HC.SOFTWARE_VERSION: self._ReportOverupdatedDB( version ) if version < ( HC.SOFTWARE_VERSION - 15 ): self._ReportUnderupdatedDB( version ) if version < HC.SOFTWARE_VERSION - 50: raise Exception( 'Your current database version of hydrus ' + str( version ) + ' is too old for this software version ' + str( HC.SOFTWARE_VERSION ) + ' to update. Please try updating with version ' + str( version + 45 ) + ' or earlier first.' ) while version < HC.SOFTWARE_VERSION: time.sleep( self.UPDATE_WAIT ) try: self._BeginImmediate() except Exception as e: raise HydrusExceptions.DBAccessException( str( e ) ) try: self._UpdateDB( version ) self._Commit() self._is_db_updated = True except: e = Exception( 'Updating the ' + self._db_name + ' db to version ' + str( version + 1 ) + ' caused this error:' + os.linesep + traceback.format_exc() ) try: self._Rollback() except Exception as rollback_e: HydrusData.Print( 'When the update failed, attempting to rollback the database failed.' ) HydrusData.PrintException( rollback_e ) raise e ( version, ) = self._c.execute( 'SELECT version FROM version;' ).fetchone() self._CloseDBCursor() self._controller.CallToThreadLongRunning( self.MainLoop ) while not self._ready_to_serve_requests: time.sleep( 0.1 ) if self._could_not_initialise: raise Exception( 'Could not initialise the db! Error written to the log!' )
def CheckHasSpaceForDBTransaction(db_dir, num_bytes): if HG.no_db_temp_files: space_needed = int(num_bytes * 1.1) approx_available_memory = psutil.virtual_memory().available * 4 / 5 if approx_available_memory < num_bytes: raise Exception( 'I believe you need about ' + HydrusData.ToHumanBytes(space_needed) + ' available memory, since you are running in no_db_temp_files mode, but you only seem to have ' + HydrusData.ToHumanBytes(approx_available_memory) + '.') db_disk_free_space = HydrusPaths.GetFreeSpace(db_dir) if db_disk_free_space < space_needed: raise Exception( 'I believe you need about ' + HydrusData.ToHumanBytes(space_needed) + ' on your db\'s disk partition, but you only seem to have ' + HydrusData.ToHumanBytes(db_disk_free_space) + '.') else: temp_dir = HydrusTemp.GetCurrentTempDir() temp_disk_free_space = HydrusPaths.GetFreeSpace(temp_dir) temp_and_db_on_same_device = HydrusPaths.GetDevice( temp_dir) == HydrusPaths.GetDevice(db_dir) if temp_and_db_on_same_device: space_needed = int(num_bytes * 2.2) if temp_disk_free_space < space_needed: raise Exception( 'I believe you need about ' + HydrusData.ToHumanBytes(space_needed) + ' on your db\'s disk partition, which I think also holds your temporary path, but you only seem to have ' + HydrusData.ToHumanBytes(temp_disk_free_space) + '.') else: space_needed = int(num_bytes * 1.1) if temp_disk_free_space < space_needed: raise Exception( 'I believe you need about ' + HydrusData.ToHumanBytes(space_needed) + ' on your temporary path\'s disk partition, which I think is ' + temp_dir + ', but you only seem to have ' + HydrusData.ToHumanBytes(temp_disk_free_space) + '.') db_disk_free_space = HydrusPaths.GetFreeSpace(db_dir) if db_disk_free_space < space_needed: raise Exception( 'I believe you need about ' + HydrusData.ToHumanBytes(space_needed) + ' on your db\'s disk partition, but you only seem to have ' + HydrusData.ToHumanBytes(db_disk_free_space) + '.')