hydrus/include/HydrusController.py

261 lines
6.7 KiB
Python
Raw Normal View History

2015-04-01 20:44:54 +00:00
import collections
import gc
import HydrusConstants as HC
2015-08-26 21:18:39 +00:00
import HydrusDaemons
2015-04-01 20:44:54 +00:00
import HydrusData
2015-04-22 22:57:25 +00:00
import HydrusDB
2015-04-01 20:44:54 +00:00
import HydrusExceptions
import HydrusGlobals
import HydrusPubSub
2015-08-26 21:18:39 +00:00
import HydrusThreading
import random
2015-04-01 20:44:54 +00:00
import sys
import threading
import time
import traceback
2015-09-02 23:16:09 +00:00
class HydrusController( object ):
2015-04-01 20:44:54 +00:00
2015-08-26 21:18:39 +00:00
pubsub_binding_errors_to_ignore = []
2015-04-01 20:44:54 +00:00
2015-09-02 23:16:09 +00:00
def __init__( self ):
HydrusGlobals.controller = self
2015-11-04 22:30:28 +00:00
self._model_shutdown = False
self._view_shutdown = False
2015-09-02 23:16:09 +00:00
self._pubsub = HydrusPubSub.HydrusPubSub( self, self.pubsub_binding_errors_to_ignore )
self._currently_doing_pubsub = False
self._daemons = []
self._caches = {}
self._managers = {}
2015-12-23 22:51:04 +00:00
self._call_to_threads = [ HydrusThreading.THREADCallToThread( self ) for i in range( 10 ) ]
2015-09-02 23:16:09 +00:00
self._timestamps = collections.defaultdict( lambda: 0 )
self._timestamps[ 'boot' ] = HydrusData.GetNow()
self._just_woke_from_sleep = False
self._system_busy = False
def _InitDB( self ):
raise NotImplementedError()
2015-04-01 20:44:54 +00:00
def _Read( self, action, *args, **kwargs ):
result = self._db.Read( action, HC.HIGH_PRIORITY, *args, **kwargs )
time.sleep( 0.00001 )
return result
2015-09-16 18:11:00 +00:00
def _ShutdownDaemons( self ):
for daemon in self._daemons:
daemon.shutdown()
while True in ( daemon.is_alive() for daemon in self._daemons ):
time.sleep( 0.1 )
self._daemons = []
2015-04-01 20:44:54 +00:00
def _Write( self, action, priority, synchronous, *args, **kwargs ):
result = self._db.Write( action, priority, synchronous, *args, **kwargs )
time.sleep( 0.00001 )
return result
2015-08-26 21:18:39 +00:00
def pub( self, topic, *args, **kwargs ):
2015-04-01 20:44:54 +00:00
2015-08-26 21:18:39 +00:00
self._pubsub.pub( topic, *args, **kwargs )
2015-04-01 20:44:54 +00:00
2015-08-26 21:18:39 +00:00
def pubimmediate( self, topic, *args, **kwargs ):
self._pubsub.pubimmediate( topic, *args, **kwargs )
2015-04-01 20:44:54 +00:00
2015-08-26 21:18:39 +00:00
def sub( self, object, method_name, topic ):
2015-04-01 20:44:54 +00:00
2015-08-26 21:18:39 +00:00
self._pubsub.sub( object, method_name, topic )
2015-04-01 20:44:54 +00:00
2015-08-26 21:18:39 +00:00
def CallToThread( self, callable, *args, **kwargs ):
call_to_thread = random.choice( self._call_to_threads )
2015-04-01 20:44:54 +00:00
2015-08-26 21:18:39 +00:00
while call_to_thread == threading.current_thread: call_to_thread = random.choice( self._call_to_threads )
call_to_thread.put( callable, *args, **kwargs )
def ClearCaches( self ):
for cache in self._caches.values(): cache.Clear()
def CurrentlyIdle( self ): return True
2015-04-01 20:44:54 +00:00
def GetCache( self, name ): return self._caches[ name ]
def GetManager( self, name ): return self._managers[ name ]
2015-08-26 21:18:39 +00:00
def GoodTimeToDoBackgroundWork( self ):
return not ( self.JustWokeFromSleep() or self.SystemBusy() )
2015-04-01 20:44:54 +00:00
def JustWokeFromSleep( self ):
2015-08-26 21:18:39 +00:00
self.SleepCheck()
2015-04-01 20:44:54 +00:00
return self._just_woke_from_sleep
2015-09-02 23:16:09 +00:00
def InitModel( self ):
2015-08-26 21:18:39 +00:00
2015-12-23 22:51:04 +00:00
for thread in self._call_to_threads:
thread.start()
2015-09-02 23:16:09 +00:00
self._db = self._InitDB()
2015-04-01 20:44:54 +00:00
2015-09-02 23:16:09 +00:00
threading.Thread( target = self._db.MainLoop, name = 'Database Main Loop' ).start()
2015-04-01 20:44:54 +00:00
2015-08-26 21:18:39 +00:00
2015-09-02 23:16:09 +00:00
def InitView( self ):
2015-04-01 20:44:54 +00:00
2015-09-02 23:16:09 +00:00
self._daemons.append( HydrusThreading.DAEMONWorker( self, 'SleepCheck', HydrusDaemons.DAEMONSleepCheck, period = 120 ) )
self._daemons.append( HydrusThreading.DAEMONWorker( self, 'MaintainDB', HydrusDaemons.DAEMONMaintainDB, period = 300 ) )
self._daemons.append( HydrusThreading.DAEMONWorker( self, 'MaintainMemory', HydrusDaemons.DAEMONMaintainMemory, period = 300 ) )
2015-04-01 20:44:54 +00:00
2015-08-26 21:18:39 +00:00
def MaintainDB( self ):
2015-04-01 20:44:54 +00:00
2015-09-02 23:16:09 +00:00
pass
2015-04-01 20:44:54 +00:00
2015-08-26 21:18:39 +00:00
def MaintainMemory( self ):
sys.stdout.flush()
sys.stderr.flush()
gc.collect()
2015-11-04 22:30:28 +00:00
def ModelIsShutdown( self ):
return self._model_shutdown
2015-08-26 21:18:39 +00:00
def NotifyPubSubs( self ):
raise NotImplementedError()
def ProcessPubSub( self ):
self._currently_doing_pubsub = True
try: self._pubsub.Process()
finally: self._currently_doing_pubsub = False
2015-04-01 20:44:54 +00:00
def Read( self, action, *args, **kwargs ): return self._Read( action, *args, **kwargs )
2015-09-02 23:16:09 +00:00
def ShutdownModel( self ):
2015-08-05 18:42:35 +00:00
2015-11-04 22:30:28 +00:00
self._model_shutdown = True
2015-09-02 23:16:09 +00:00
HydrusGlobals.model_shutdown = True
2015-04-01 20:44:54 +00:00
while not self._db.LoopIsFinished(): time.sleep( 0.1 )
2015-09-02 23:16:09 +00:00
def ShutdownView( self ):
2015-11-04 22:30:28 +00:00
self._view_shutdown = True
2015-09-02 23:16:09 +00:00
HydrusGlobals.view_shutdown = True
2015-09-16 18:11:00 +00:00
self._ShutdownDaemons()
2015-09-02 23:16:09 +00:00
2015-09-16 18:11:00 +00:00
def ShutdownFromServer( self ):
raise Exception( 'This hydrus application cannot be shut down from the server!' )
2015-09-02 23:16:09 +00:00
2015-08-26 21:18:39 +00:00
def SleepCheck( self ):
2015-04-01 20:44:54 +00:00
2015-08-26 21:18:39 +00:00
if HydrusData.TimeHasPassed( self._timestamps[ 'now_awake' ] ):
last_sleep_check = self._timestamps[ 'last_sleep_check' ]
if last_sleep_check == 0:
self._just_woke_from_sleep = False
else:
if HydrusData.TimeHasPassed( last_sleep_check + 600 ):
self._just_woke_from_sleep = True
self._timestamps[ 'now_awake' ] = HydrusData.GetNow() + 180
else:
self._just_woke_from_sleep = False
2015-04-01 20:44:54 +00:00
2015-08-26 21:18:39 +00:00
self._timestamps[ 'last_sleep_check' ] = HydrusData.GetNow()
2015-04-01 20:44:54 +00:00
2015-08-26 21:18:39 +00:00
def SystemBusy( self ):
2015-04-01 20:44:54 +00:00
2015-08-26 21:18:39 +00:00
return self._system_busy
2015-04-01 20:44:54 +00:00
2015-11-04 22:30:28 +00:00
def ViewIsShutdown( self ):
return self._view_shutdown
2015-08-26 21:18:39 +00:00
def WaitUntilPubSubsEmpty( self ):
2015-04-01 20:44:54 +00:00
while True:
2015-11-04 22:30:28 +00:00
if self._view_shutdown: raise HydrusExceptions.ShutdownException( 'Application shutting down!' )
2015-08-26 21:18:39 +00:00
elif self._pubsub.NoJobsQueued() and not self._currently_doing_pubsub: return
2015-04-01 20:44:54 +00:00
else: time.sleep( 0.00001 )
def Write( self, action, *args, **kwargs ):
return self._Write( action, HC.HIGH_PRIORITY, False, *args, **kwargs )
def WriteSynchronous( self, action, *args, **kwargs ):
return self._Write( action, HC.LOW_PRIORITY, True, *args, **kwargs )