hydrus/hydrus/hydrus_server_boot.py

232 lines
6.8 KiB
Python

#!/usr/bin/env python3
# Hydrus is released under WTFPL
# You just DO WHAT THE FUCK YOU WANT TO.
# https://github.com/sirkris/WTFPL/blob/master/WTFPL.md
action = 'start'
import sys
try:
import locale
try: locale.setlocale( locale.LC_ALL, '' )
except: pass
import os
import threading
from hydrus.core import HydrusBoot
HydrusBoot.AddBaseDirToEnvPath()
from hydrus.core import HydrusConstants as HC
HC.RUNNING_SERVER = True
from hydrus.core import HydrusExceptions
from hydrus.core import HydrusData
from hydrus.core import HydrusGlobals as HG
from hydrus.core import HydrusLogger
from hydrus.core import HydrusPaths
from hydrus.core import HydrusTemp
from hydrus.core import HydrusTime
from hydrus.server import ServerController
from twisted.internet import reactor
#
import argparse
argparser = argparse.ArgumentParser( description = 'hydrus network server' )
argparser.add_argument( 'action', default = 'start', nargs = '?', choices = [ 'start', 'stop', 'restart' ], help = 'either start this server (default), or stop an existing server, or both' )
argparser.add_argument( '-d', '--db_dir', help = 'set an external db location' )
argparser.add_argument( '--temp_dir', help = 'override the program\'s temporary directory' )
argparser.add_argument( '--db_journal_mode', default = 'WAL', choices = [ 'WAL', 'TRUNCATE', 'PERSIST', 'MEMORY' ], help = 'change db journal mode (default=WAL)' )
argparser.add_argument( '--db_cache_size', type = int, help = 'override SQLite cache_size per db file, in MB (default=256)' )
argparser.add_argument( '--db_transaction_commit_period', type = int, help = 'override how often (in seconds) database changes are saved to disk (default=120,min=10)' )
argparser.add_argument( '--db_synchronous_override', type = int, choices = range(4), help = 'override SQLite Synchronous PRAGMA (default=2)' )
argparser.add_argument( '--no_db_temp_files', action='store_true', help = 'run db temp operations entirely in memory' )
argparser.add_argument( '--boot_debug', action='store_true', help = 'print additional bootup information to the log' )
argparser.add_argument( '--profile_mode', action='store_true', help = 'start the server with profile mode on' )
argparser.add_argument( '--no_wal', action='store_true', help = 'OBSOLETE: run using TRUNCATE db journaling' )
argparser.add_argument( '--db_memory_journaling', action='store_true', help = 'OBSOLETE: run using MEMORY db journaling (DANGEROUS)' )
result = argparser.parse_args()
HG.server_action = result.action
db_dir = HydrusPaths.FigureOutDBDir( result.db_dir )
HG.db_journal_mode = result.db_journal_mode
if result.no_wal:
HG.db_journal_mode = 'TRUNCATE'
if result.db_memory_journaling:
HG.db_journal_mode = 'MEMORY'
if result.db_cache_size is not None:
HG.db_cache_size = result.db_cache_size
else:
HG.db_cache_size = 256
if result.db_transaction_commit_period is not None:
HG.db_transaction_commit_period = max( 10, result.db_transaction_commit_period )
else:
HG.db_transaction_commit_period = 30
if result.db_synchronous_override is not None:
HG.db_synchronous = int( result.db_synchronous_override )
else:
if HG.db_journal_mode == 'WAL':
HG.db_synchronous = 1
else:
HG.db_synchronous = 2
HG.no_db_temp_files = result.no_db_temp_files
HG.boot_debug = result.boot_debug
HG.profile_mode = result.profile_mode
HG.profile_start_time = HydrusTime.GetNow()
if result.temp_dir is not None:
HydrusTemp.SetEnvTempDir( result.temp_dir )
except Exception as e:
import traceback
error_trace = traceback.format_exc()
print( error_trace )
if 'db_dir' in locals() and os.path.exists( db_dir ):
emergency_dir = db_dir
else:
emergency_dir = os.path.expanduser( '~' )
possible_desktop = os.path.join( emergency_dir, 'Desktop' )
if os.path.exists( possible_desktop ) and os.path.isdir( possible_desktop ):
emergency_dir = possible_desktop
dest_path = os.path.join( emergency_dir, 'hydrus_crash.log' )
with open( dest_path, 'w', encoding = 'utf-8' ) as f:
f.write( error_trace )
print( 'Critical boot error occurred! Details written to hydrus_crash.log in either db dir or user dir!' )
sys.exit( 1 )
def boot():
try:
HG.server_action = ServerController.ProcessStartingAction( db_dir, HG.server_action )
except HydrusExceptions.ShutdownException as e:
HydrusData.Print( e )
HG.server_action = 'exit'
if HG.server_action == 'exit':
sys.exit( 0 )
controller = None
with HydrusLogger.HydrusLogger( db_dir, 'server' ) as logger:
try:
if HG.server_action in ( 'stop', 'restart' ):
ServerController.ShutdownSiblingInstance( db_dir )
if HG.server_action in ( 'start', 'restart' ):
HydrusData.Print( 'Initialising controller' + HC.UNICODE_ELLIPSIS )
threading.Thread( target = reactor.run, name = 'twisted', kwargs = { 'installSignalHandlers' : 0 } ).start()
controller = ServerController.Controller( db_dir )
controller.Run()
except ( HydrusExceptions.DBCredentialsException, HydrusExceptions.ShutdownException ) as e:
error = str( e )
HydrusData.Print( error )
except:
import traceback
error = traceback.format_exc()
HydrusData.Print( 'Hydrus server failed' )
HydrusData.Print( error )
finally:
HG.started_shutdown = True
HG.view_shutdown = True
HG.model_shutdown = True
if controller is not None:
controller.pubimmediate( 'wake_daemons' )
reactor.callFromThread( reactor.stop )
HydrusData.Print( 'hydrus server shut down' )