Esempio n. 1
0
def ReportShutdownException():

    text = 'A serious error occured while trying to exit the program. Its traceback may be shown next. It should have also been written to client.log. You may need to quit the program from task manager.'

    HydrusData.DebugPrint(text)

    HydrusData.DebugPrint(traceback.format_exc())

    wx.CallAfter(wx.MessageBox, traceback.format_exc())
    wx.CallAfter(wx.MessageBox, text)
Esempio n. 2
0
    def _DisplayCatastrophicError(self, text):

        message = 'The db encountered a serious error! This is going to be written to the log as well, but here it is for a screenshot:'
        message += os.linesep * 2
        message += text

        HydrusData.DebugPrint(message)
    def _TryEndModal(self, value):

        try:

            self.EndModal(value)

        except Exception as e:

            HydrusData.ShowText(
                'This dialog seems to have been unable to close for some reason. I am printing the stack to the log. The dialog may have already closed, or may attempt to close now. Please inform hydrus dev of this situation. I recommend you restart the client if you can. If the UI is locked, you will have to kill it via task manager.'
            )

            HydrusData.PrintException(e)

            import traceback

            HydrusData.DebugPrint(''.join(traceback.format_stack()))

            try:

                self.Close()

            except:

                HydrusData.ShowText('The dialog would not close on command.')

            try:

                self.Destroy()

            except:

                HydrusData.ShowText('The dialog would not destroy on command.')
Esempio n. 4
0
    def THREADExitEverything(self):

        try:

            self.pub('splash_set_title_text', 'shutting down gui...')

            self.ShutdownView()

            self.pub('splash_set_title_text', 'shutting down db...')

            self.ShutdownModel()

            HydrusData.CleanRunningFile(HC.DB_DIR, 'client')

        except HydrusExceptions.PermissionException:
            pass
        except HydrusExceptions.ShutdownException:
            pass
        except:

            text = 'A serious error occured while trying to exit the program. Its traceback may be shown next. It should have also been written to client.log. You may need to quit the program from task manager.'

            HydrusData.DebugPrint(text)

            traceback.print_exc()

            wx.CallAfter(wx.MessageBox, traceback.format_exc())
            wx.CallAfter(wx.MessageBox, text)

        finally:

            self.pub('splash_destroy')
Esempio n. 5
0
def ShowExceptionClient(e, do_wait=True):

    (etype, value, tb) = sys.exc_info()

    if etype is None:

        etype = type(e)
        value = HydrusData.ToUnicode(e)

        trace = 'No error trace--here is the stack:' + os.linesep + ''.join(
            traceback.format_stack())

    else:

        trace = ''.join(traceback.format_exception(etype, value, tb))

    trace = HydrusData.ToUnicode(trace)

    pretty_value = HydrusData.ToUnicode(value)

    if os.linesep in pretty_value:

        (first_line,
         anything_else) = HydrusData.ToUnicode(value).split(os.linesep, 1)

        trace = trace + os.linesep + anything_else

    else:

        first_line = pretty_value

    job_key = ClientThreading.JobKey()

    if isinstance(e, HydrusExceptions.ShutdownException):

        return

    else:

        if hasattr(etype, '__name__'):
            title = HydrusData.ToUnicode(etype.__name__)
        else:
            title = HydrusData.ToUnicode(etype)

        job_key.SetVariable('popup_title', title)

        job_key.SetVariable('popup_text_1', first_line)
        job_key.SetVariable('popup_traceback', trace)

    text = job_key.ToString()

    HydrusData.Print('Exception:')

    HydrusData.DebugPrint(text)

    HG.client_controller.pub('message', job_key)

    if do_wait:

        time.sleep(1)
Esempio n. 6
0
def DeletePath( path ):
    
    if os.path.exists( path ):
        
        MakeFileWritable( path )
        
        try:
            
            if os.path.isdir( path ):
                
                shutil.rmtree( path )
                
            else:
                
                os.remove( path )
                
            
        except Exception as e:
            
            if 'Error 32' in HydrusData.ToUnicode( e ):
                
                # file in use by another process
                
                HydrusData.DebugPrint( 'Trying to delete ' + path + ' failed because it was in use by another process.' )
                
            else:
                
                HydrusData.ShowText( 'Trying to delete ' + path + ' caused the following error:' )
                HydrusData.ShowException( e )
Esempio n. 7
0
    def Exit(self):

        if HydrusGlobals.emergency_exit:

            self.ShutdownView()
            self.ShutdownModel()

        else:

            try:

                self.CreateSplash()

                idle_shutdown_action = self._options['idle_shutdown']

                if idle_shutdown_action in (CC.IDLE_ON_SHUTDOWN,
                                            CC.IDLE_ON_SHUTDOWN_ASK_FIRST):

                    idle_shutdown_max_minutes = self._options[
                        'idle_shutdown_max_minutes']

                    time_to_stop = HydrusData.GetNow() + (
                        idle_shutdown_max_minutes * 60)

                    if self.ThereIsIdleShutdownWorkDue(time_to_stop):

                        if idle_shutdown_action == CC.IDLE_ON_SHUTDOWN_ASK_FIRST:

                            text = 'Is now a good time for the client to do up to ' + HydrusData.ConvertIntToPrettyString(
                                idle_shutdown_max_minutes
                            ) + ' minutes\' maintenance work?'

                            with ClientGUIDialogs.DialogYesNo(
                                    self._splash, text,
                                    title='Maintenance is due') as dlg_yn:

                                if dlg_yn.ShowModal() == wx.ID_YES:

                                    HydrusGlobals.do_idle_shutdown_work = True

                        else:

                            HydrusGlobals.do_idle_shutdown_work = True

                exit_thread = threading.Thread(
                    target=self.THREADExitEverything,
                    name='Application Exit Thread')

                exit_thread.start()

            except:

                self.pub('splash_destroy')

                HydrusData.DebugPrint(traceback.format_exc())

                HydrusGlobals.emergency_exit = True

                self.Exit()
Esempio n. 8
0
    def THREADBootEverything(self):

        try:

            self.CheckAlreadyRunning()

            self._last_shutdown_was_bad = HydrusData.LastShutdownWasBad(
                self.db_dir, 'client')

            HydrusData.RecordRunningStart(self.db_dir, 'client')

            self.InitModel()

            self.InitView()

            self._is_booted = True

        except HydrusExceptions.PermissionException as e:

            HydrusData.Print(e)

            HG.emergency_exit = True

            self.Exit()

        except Exception as e:

            text = 'A serious error occurred while trying to start the program. The error will be shown next in a window. More information may have been written to client.log.'

            HydrusData.DebugPrint(
                'If the db crashed, another error may be written just above ^.'
            )
            HydrusData.DebugPrint(text)

            HydrusData.DebugPrint(traceback.format_exc())

            wx.CallAfter(wx.MessageBox, traceback.format_exc())
            wx.CallAfter(wx.MessageBox, text)

            HG.emergency_exit = True

            self.Exit()

        finally:

            self._DestroySplash()
Esempio n. 9
0
 def Exit( self ):
     
     if HG.emergency_exit:
         
         self.ShutdownView()
         self.ShutdownModel()
         
     else:
         
         try:
             
             self._CreateSplash()
             
             idle_shutdown_action = self.options[ 'idle_shutdown' ]
             
             if idle_shutdown_action in ( CC.IDLE_ON_SHUTDOWN, CC.IDLE_ON_SHUTDOWN_ASK_FIRST ):
                 
                 idle_shutdown_max_minutes = self.options[ 'idle_shutdown_max_minutes' ]
                 
                 time_to_stop = HydrusData.GetNow() + ( idle_shutdown_max_minutes * 60 )
                 
                 if self.ThereIsIdleShutdownWorkDue( time_to_stop ):
                     
                     if idle_shutdown_action == CC.IDLE_ON_SHUTDOWN_ASK_FIRST:
                         
                         text = 'Is now a good time for the client to do up to ' + HydrusData.ConvertIntToPrettyString( idle_shutdown_max_minutes ) + ' minutes\' maintenance work? (Will auto-no in 15 seconds)'
                         
                         with ClientGUIDialogs.DialogYesNo( self._splash, text, title = 'Maintenance is due' ) as dlg_yn:
                             
                             call_later = wx.CallLater( 15000, dlg_yn.EndModal, wx.ID_NO )
                             
                             if dlg_yn.ShowModal() == wx.ID_YES:
                                 
                                 HG.do_idle_shutdown_work = True
                                 
                             
                             call_later.Stop()
                             
                         
                     else:
                         
                         HG.do_idle_shutdown_work = True
                         
                     
                 
             
             self.CallToThreadLongRunning( self.THREADExitEverything )
             
         except:
             
             self._DestroySplash()
             
             HydrusData.DebugPrint( traceback.format_exc() )
             
             HG.emergency_exit = True
             
             self.Exit()
Esempio n. 10
0
def RecyclePath( path ):
    
    original_path = path
    
    if HC.PLATFORM_LINUX:
        
        # send2trash for Linux tries to do some Python3 str() stuff in prepping non-str paths for recycling
        
        if not isinstance( path, str ):
            
            try:
                
                path = path.encode( sys.getfilesystemencoding() )
                
            except:
                
                HydrusData.Print( 'Trying to prepare ' + path + ' for recycling created this error:' )
                
                HydrusData.DebugPrint( traceback.format_exc() )
                
                return
                
            
        
    
    if os.path.exists( path ):
        
        MakeFileWritable( path )
        
        try:
            
            send2trash.send2trash( path )
            
        except:
            
            HydrusData.Print( 'Trying to recycle ' + path + ' created this error:' )
            
            HydrusData.DebugPrint( traceback.format_exc() )
            
            HydrusData.Print( 'It has been fully deleted instead.' )
            
            DeletePath( original_path )
Esempio n. 11
0
    def THREADBootEverything(self):

        try:

            self.CheckAlreadyRunning()

            self._last_shutdown_was_bad = HydrusData.LastShutdownWasBad(
                self._db_dir, 'client')

            HydrusData.RecordRunningStart(self._db_dir, 'client')

            self.InitModel()

            self.InitView()

        except HydrusExceptions.PermissionException as e:

            HydrusData.Print(e)

            HydrusGlobals.emergency_exit = True

            self.Exit()

        except Exception as e:

            text = 'A serious error occured while trying to start the program. Its traceback will be shown next. It should have also been written to client.log.'

            HydrusData.DebugPrint(text)

            HydrusData.DebugPrint(traceback.format_exc())

            wx.CallAfter(wx.MessageBox, traceback.format_exc())
            wx.CallAfter(wx.MessageBox, text)

            HydrusGlobals.emergency_exit = True

            self.Exit()

        finally:

            self.pub('splash_destroy')
Esempio n. 12
0
 def _errbackHandleEmergencyError( self, failure, request ):
     
     try: self._CleanUpTempFile( request )
     except: pass
     
     try: HydrusData.DebugPrint( failure.getTraceback() )
     except: pass
     
     try: request.write( failure.getTraceback() )
     except: pass
     
     try: request.finish()
     except: pass
Esempio n. 13
0
 def _errbackHandleProcessingError( self, failure, request ):
     
     self._CleanUpTempFile( request )
     
     default_mime = HC.TEXT_HTML
     default_encoding = HydrusData.ToByteString
     
     if failure.type == KeyError:
         
         response_context = ResponseContext( 400, mime = default_mime, body = default_encoding( 'It appears one or more parameters required for that request were missing:' + os.linesep + failure.getTraceback() ) )
         
     elif failure.type == HydrusExceptions.BandwidthException:
         
         response_context = ResponseContext( 509, mime = default_mime, body = default_encoding( failure.value ) )
         
     elif failure.type == HydrusExceptions.PermissionException:
         
         response_context = ResponseContext( 401, mime = default_mime, body = default_encoding( failure.value ) )
         
     elif failure.type == HydrusExceptions.ForbiddenException:
         
         response_context = ResponseContext( 403, mime = default_mime, body = default_encoding( failure.value ) )
         
     elif failure.type in ( HydrusExceptions.NotFoundException, HydrusExceptions.DataMissing, HydrusExceptions.FileMissingException ):
         
         response_context = ResponseContext( 404, mime = default_mime, body = default_encoding( failure.value ) )
         
     elif failure.type == HydrusExceptions.NetworkVersionException:
         
         response_context = ResponseContext( 426, mime = default_mime, body = default_encoding( failure.value ) )
         
     elif failure.type == HydrusExceptions.ServerBusyException:
         
         response_context = ResponseContext( 503, mime = default_mime, body = default_encoding( failure.value ) )
         
     elif failure.type == HydrusExceptions.SessionException:
         
         response_context = ResponseContext( 419, mime = default_mime, body = default_encoding( failure.value ) )
         
     else:
         
         HydrusData.DebugPrint( failure.getTraceback() )
         
         response_context = ResponseContext( 500, mime = default_mime, body = default_encoding( 'The repository encountered an error it could not handle! Here is a dump of what happened, which will also be written to your client.log file. If it persists, please forward it to [email protected]:' + os.linesep * 2 + failure.getTraceback() ) )
         
     
     request.hydrus_response_context = response_context
     
     return request
Esempio n. 14
0
def RequestsCheckResponse( response ):
    
    if not response.ok:
        
        error_text = response.content
        
        if len( error_text ) > 1024:
            
            large_chunk = error_text[:4096]
            
            smaller_chunk = large_chunk[:256]
            
            HydrusData.DebugPrint( large_chunk )
            
            error_text = 'The server\'s error text was too long to display. The first part follows, while a larger chunk has been written to the log.'
            error_text += os.linesep
            error_text += smaller_chunk
            
        
        if response.status_code == 304:
            
            eclass = HydrusExceptions.NotModifiedException
            
        elif response.status_code == 401:
            
            eclass = HydrusExceptions.PermissionException
            
        elif response.status_code == 403:
            
            eclass = HydrusExceptions.ForbiddenException
            
        elif response.status_code == 404:
            
            eclass = HydrusExceptions.NotFoundException
            
        elif response.status_code == 419:
            
            eclass = HydrusExceptions.SessionException
            
        elif response.status_code == 426:
            
            eclass = HydrusExceptions.NetworkVersionException
            
        else:
            
            eclass = HydrusExceptions.NetworkException
            
        
        raise eclass( error_text )
Esempio n. 15
0
 def _errbackHandleProcessingError( self, failure, request ):
     
     self._CleanUpTempFile( request )
     
     do_yaml = True
     
     try:
         
         # the error may have occured before user agent was set up!
         if not request.is_hydrus_user_agent: do_yaml = False
         
     except: pass
     
     if do_yaml:
         
         default_mime = HC.APPLICATION_YAML
         default_encoding = lambda x: yaml.safe_dump( HydrusData.ToUnicode( x ) )
         
     else:
         
         default_mime = HC.TEXT_HTML
         default_encoding = lambda x: HydrusData.ToByteString( x )
         
     
     if failure.type == KeyError: response_context = ResponseContext( 403, mime = default_mime, body = default_encoding( 'It appears one or more parameters required for that request were missing:' + os.linesep + failure.getTraceback() ) )
     elif failure.type == HydrusExceptions.PermissionException: response_context = ResponseContext( 401, mime = default_mime, body = default_encoding( failure.value ) )
     elif failure.type == HydrusExceptions.ForbiddenException: response_context = ResponseContext( 403, mime = default_mime, body = default_encoding( failure.value ) )
     elif failure.type == HydrusExceptions.NotFoundException: response_context = ResponseContext( 404, mime = default_mime, body = default_encoding( failure.value ) )
     elif failure.type == HydrusExceptions.NetworkVersionException: response_context = ResponseContext( 426, mime = default_mime, body = default_encoding( failure.value ) )
     elif failure.type == HydrusExceptions.ServerBusyException: response_context = ResponseContext( 503, mime = default_mime, body = default_encoding( failure.value ) )
     elif failure.type == HydrusExceptions.SessionException: response_context = ResponseContext( 419, mime = default_mime, body = default_encoding( failure.value ) )
     else:
         
         HydrusData.DebugPrint( failure.getTraceback() )
         
         response_context = ResponseContext( 500, mime = default_mime, body = default_encoding( 'The repository encountered an error it could not handle! Here is a dump of what happened, which will also be written to your client.log file. If it persists, please forward it to [email protected]:' + os.linesep * 2 + failure.getTraceback() ) )
         
     
     request.hydrus_response_context = response_context
     
     return request
Esempio n. 16
0
        def wx_code(job_key):

            try:

                result = callable(*args, **kwargs)

                job_key.SetVariable('result', result)

            except HydrusExceptions.PermissionException as e:

                job_key.SetVariable('error', e)

            except Exception as e:

                job_key.SetVariable('error', e)

                HydrusData.Print('CallBlockingToWx just caught this error:')
                HydrusData.DebugPrint(traceback.format_exc())

            finally:
                job_key.Finish()
Esempio n. 17
0
 def _errbackHandleEmergencyError( self, failure, request ):
     
     try: self._CleanUpTempFile( request )
     except: pass
     
     try: HydrusData.DebugPrint( failure.getTraceback() )
     except: pass
     
     if request.channel is not None:
         
         try: request.setResponseCode( 500 )
         except: pass
         
         try: request.write( failure.getTraceback() )
         except: pass
         
     
     if not request.finished:
         
         try: request.finish()
         except: pass
Esempio n. 18
0
def CatchExceptionClient(etype, value, tb):

    try:

        trace_list = traceback.format_tb(tb)

        trace = ''.join(trace_list)

        pretty_value = HydrusData.ToUnicode(value)

        if os.linesep in pretty_value:

            (first_line, anything_else) = pretty_value.split(os.linesep, 1)

            trace = trace + os.linesep + anything_else

        else:

            first_line = pretty_value

        trace = HydrusData.ToUnicode(trace)

        job_key = ClientThreading.JobKey()

        if etype == HydrusExceptions.ShutdownException:

            return

        else:

            try:
                job_key.SetVariable('popup_title',
                                    HydrusData.ToUnicode(etype.__name__))
            except:
                job_key.SetVariable('popup_title', HydrusData.ToUnicode(etype))

            job_key.SetVariable('popup_text_1', first_line)
            job_key.SetVariable('popup_traceback', trace)

        text = job_key.ToString()

        HydrusData.Print('Uncaught exception:')

        HydrusData.DebugPrint(text)

        HG.client_controller.pub('message', job_key)

    except:

        text = 'Encountered an error I could not parse:'

        text += os.linesep

        text += HydrusData.ToUnicode((etype, value, tb))

        try:
            text += traceback.format_exc()
        except:
            pass

        HydrusData.ShowText(text)

    time.sleep(1)
Esempio n. 19
0
def ConvertStatusCodeAndDataIntoExceptionInfo(status_code,
                                              data,
                                              is_hydrus_service=False):

    error_text = data

    if len(error_text) > 1024:

        large_chunk = error_text[:4096]

        smaller_chunk = large_chunk[:256]

        HydrusData.DebugPrint(large_chunk)

        error_text = 'The server\'s error text was too long to display. The first part follows, while a larger chunk has been written to the log.'
        error_text += os.linesep
        error_text += smaller_chunk

    if status_code == 304:

        eclass = HydrusExceptions.NotModifiedException

    elif status_code == 401:

        eclass = HydrusExceptions.PermissionException

    elif status_code == 403:

        eclass = HydrusExceptions.ForbiddenException

    elif status_code == 404:

        eclass = HydrusExceptions.NotFoundException

    elif status_code == 419:

        eclass = HydrusExceptions.SessionException

    elif status_code == 426:

        eclass = HydrusExceptions.NetworkVersionException

    elif status_code == 509:

        eclass = HydrusExceptions.BandwidthException

    elif status_code >= 500:

        if is_hydrus_service and status_code == 503:

            eclass = HydrusExceptions.ServerBusyException

        else:

            eclass = HydrusExceptions.ServerException

    else:

        eclass = HydrusExceptions.NetworkException

    e = eclass(error_text)

    return (e, error_text)
Esempio n. 20
0
    def Exit(self):

        if HG.emergency_exit:

            self.ShutdownView()
            self.ShutdownModel()

            HydrusData.CleanRunningFile(self.db_dir, 'client')

        else:

            try:

                last_shutdown_work_time = self.Read('last_shutdown_work_time')

                shutdown_work_period = self.new_options.GetInteger(
                    'shutdown_work_period')

                we_can_shutdown_work = HydrusData.TimeHasPassed(
                    last_shutdown_work_time + shutdown_work_period)

                idle_shutdown_action = self.options['idle_shutdown']

                if we_can_shutdown_work and idle_shutdown_action in (
                        CC.IDLE_ON_SHUTDOWN, CC.IDLE_ON_SHUTDOWN_ASK_FIRST):

                    idle_shutdown_max_minutes = self.options[
                        'idle_shutdown_max_minutes']

                    time_to_stop = HydrusData.GetNow() + (
                        idle_shutdown_max_minutes * 60)

                    work_to_do = self.GetIdleShutdownWorkDue(time_to_stop)

                    if len(work_to_do) > 0:

                        if idle_shutdown_action == CC.IDLE_ON_SHUTDOWN_ASK_FIRST:

                            text = 'Is now a good time for the client to do up to ' + HydrusData.ToHumanInt(
                                idle_shutdown_max_minutes
                            ) + ' minutes\' maintenance work? (Will auto-no in 15 seconds)'
                            text += os.linesep * 2
                            text += 'The outstanding jobs appear to be:'
                            text += os.linesep * 2
                            text += os.linesep.join(work_to_do)

                            with ClientGUIDialogs.DialogYesNo(
                                    self._splash, text,
                                    title='Maintenance is due') as dlg_yn:

                                job = self.CallLaterWXSafe(
                                    dlg_yn, 15, dlg_yn.EndModal, wx.ID_NO)

                                try:

                                    if dlg_yn.ShowModal() == wx.ID_YES:

                                        HG.do_idle_shutdown_work = True

                                    else:

                                        self.Write('last_shutdown_work_time',
                                                   HydrusData.GetNow())

                                finally:

                                    job.Cancel()

                        else:

                            HG.do_idle_shutdown_work = True

                self.CallToThreadLongRunning(self.THREADExitEverything)

            except:

                self._DestroySplash()

                HydrusData.DebugPrint(traceback.format_exc())

                HG.emergency_exit = True

                self.Exit()
Esempio n. 21
0
    def _InitDBCursor(self):

        self._CloseDBCursor()

        db_path = os.path.join(self._db_dir, self._db_filenames['main'])

        db_just_created = not os.path.exists(db_path)

        self._db = sqlite3.connect(db_path,
                                   isolation_level=None,
                                   detect_types=sqlite3.PARSE_DECLTYPES)

        self._connection_timestamp = HydrusData.GetNow()

        self._c = self._db.cursor()

        self._c.execute('PRAGMA temp_store = 2;')

        self._c.execute('PRAGMA main.cache_size = -10000;')

        self._c.execute('ATTACH ":memory:" AS mem;')

        self._AttachExternalDatabases()

        db_names = [
            name
            for (index, name, path) in self._c.execute('PRAGMA database_list;')
            if name not in ('mem', 'temp')
        ]

        for db_name in db_names:

            self._c.execute('PRAGMA ' + db_name + '.cache_size = -10000;')

            if self._no_wal:

                self._c.execute('PRAGMA ' + db_name +
                                '.journal_mode = TRUNCATE;')

                self._c.execute('PRAGMA ' + db_name + '.synchronous = 2;')

                self._c.execute('SELECT * FROM ' + db_name +
                                '.sqlite_master;').fetchone()

            else:

                self._c.execute('PRAGMA ' + db_name + '.journal_mode = WAL;')

                # if this is set to 1, transactions are not immediately synced to the journal and can be undone following a power-loss
                # if set to 2, all transactions are synced
                # either way, transactions are atomically consistent, but let's not mess around when power-cut during heavy file import or w/e
                self._c.execute('PRAGMA ' + db_name + '.synchronous = 2;')

                try:

                    self._c.execute('SELECT * FROM ' + db_name +
                                    '.sqlite_master;').fetchone()

                except sqlite3.OperationalError:

                    HydrusData.DebugPrint(traceback.format_exc())

                    def create_no_wal_file():

                        HG.controller.CreateNoWALFile()

                        self._no_wal = True

                    if db_just_created:

                        del self._c
                        del self._db

                        os.remove(db_path)

                        create_no_wal_file()

                        self._InitDBCursor()

                    else:

                        self._c.execute('PRAGMA ' + db_name +
                                        '.journal_mode = TRUNCATE;')

                        self._c.execute('PRAGMA ' + db_name +
                                        '.synchronous = 2;')

                        self._c.execute('SELECT * FROM ' + db_name +
                                        '.sqlite_master;').fetchone()

                        create_no_wal_file()

        try:

            self._BeginImmediate()

        except Exception as e:

            raise HydrusExceptions.DBAccessException(HydrusData.ToUnicode(e))
Esempio n. 22
0
    def _InitDBCursor(self):

        self._CloseDBCursor()

        db_path = os.path.join(self._db_dir, self._db_filenames['main'])

        db_just_created = not os.path.exists(db_path)

        self._db = sqlite3.connect(db_path,
                                   isolation_level=None,
                                   detect_types=sqlite3.PARSE_DECLTYPES)

        self._connection_timestamp = HydrusData.GetNow()

        self._c = self._db.cursor()

        self._c.execute('PRAGMA main.cache_size = -10000;')

        self._c.execute('ATTACH ":memory:" AS mem;')

        self._AttachExternalDatabases()

        db_names = [
            name
            for (index, name, path) in self._c.execute('PRAGMA database_list;')
            if name not in ('mem', 'temp')
        ]

        for db_name in db_names:

            self._c.execute('PRAGMA ' + db_name + '.cache_size = -10000;')

            if self._no_wal:

                self._c.execute('PRAGMA ' + db_name +
                                '.journal_mode = TRUNCATE;')

                self._c.execute('PRAGMA ' + db_name + '.synchronous = 2;')

                self._c.execute('SELECT * FROM ' + db_name +
                                '.sqlite_master;').fetchone()

            else:

                self._c.execute('PRAGMA ' + db_name + '.journal_mode = WAL;')

                self._c.execute('PRAGMA ' + db_name + '.synchronous = 1;')

                try:

                    self._c.execute('SELECT * FROM ' + db_name +
                                    '.sqlite_master;').fetchone()

                except sqlite3.OperationalError:

                    HydrusData.DebugPrint(traceback.format_exc())

                    def create_no_wal_file():

                        HydrusGlobals.controller.CreateNoWALFile()

                        self._no_wal = True

                    if db_just_created:

                        del self._c
                        del self._db

                        os.remove(db_path)

                        create_no_wal_file()

                        self._InitDBCursor()

                    else:

                        self._c.execute('PRAGMA ' + db_name +
                                        '.journal_mode = TRUNCATE;')

                        self._c.execute('PRAGMA ' + db_name +
                                        '.synchronous = 2;')

                        self._c.execute('SELECT * FROM ' + db_name +
                                        '.sqlite_master;').fetchone()

                        create_no_wal_file()