Ejemplo n.º 1
0
    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, ))
Ejemplo n.º 2
0
    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))