From cb59b8abbd23db860dd3b4a6204a2ae5c23efc82 Mon Sep 17 00:00:00 2001 From: f97ada87 Date: Mon, 9 Apr 2018 14:38:48 +1000 Subject: [PATCH] component control switches --- src/bitmessagemain.py | 139 +++++++++++++++++++++---------------- src/class_singleCleaner.py | 4 +- src/helper_generic.py | 3 +- src/shutdown.py | 2 +- src/state.py | 8 +++ 5 files changed, 91 insertions(+), 65 deletions(-) diff --git a/src/bitmessagemain.py b/src/bitmessagemain.py index 11f71b47..695bb9d8 100755 --- a/src/bitmessagemain.py +++ b/src/bitmessagemain.py @@ -218,10 +218,12 @@ class Main: sys.exit() elif opt in ("-d", "--daemon"): daemon = True + state.enableGUI = False # run without a UI elif opt in ("-c", "--curses"): state.curses = True elif opt in ("-t", "--test"): state.testmode = daemon = True + state.enableGUI = False # run without a UI # is the application already running? If yes then exit. shared.thisapp = singleinstance("", daemon) @@ -241,15 +243,19 @@ class Main: state.dandelion = 0 helper_bootstrap.knownNodes() - # Start the address generation thread - addressGeneratorThread = addressGenerator() - addressGeneratorThread.daemon = True # close the main program even if there are threads left - addressGeneratorThread.start() - # Start the thread that calculates POWs - singleWorkerThread = singleWorker() - singleWorkerThread.daemon = True # close the main program even if there are threads left - singleWorkerThread.start() + # Not needed if objproc is disabled + if state.enableObjProc: + + # Start the address generation thread + addressGeneratorThread = addressGenerator() + addressGeneratorThread.daemon = True # close the main program even if there are threads left + addressGeneratorThread.start() + + # Start the thread that calculates POWs + singleWorkerThread = singleWorker() + singleWorkerThread.daemon = True # close the main program even if there are threads left + singleWorkerThread.start() # Start the SQL thread sqlLookup = sqlThread() @@ -259,73 +265,84 @@ class Main: Inventory() # init Dandelion() # init, needs to be early because other thread may access it early - # SMTP delivery thread - if daemon and BMConfigParser().safeGet("bitmessagesettings", "smtpdeliver", '') != '': - smtpDeliveryThread = smtpDeliver() - smtpDeliveryThread.start() + # Enable object processor and SMTP only if objproc enabled + if state.enableObjProc: - # SMTP daemon thread - if daemon and BMConfigParser().safeGetBoolean("bitmessagesettings", "smtpd"): - smtpServerThread = smtpServer() - smtpServerThread.start() + # SMTP delivery thread + if daemon and BMConfigParser().safeGet("bitmessagesettings", "smtpdeliver", '') != '': + smtpDeliveryThread = smtpDeliver() + smtpDeliveryThread.start() - # Start the thread that calculates POWs - objectProcessorThread = objectProcessor() - objectProcessorThread.daemon = False # DON'T close the main program even the thread remains. This thread checks the shutdown variable after processing each object. - objectProcessorThread.start() + # SMTP daemon thread + if daemon and BMConfigParser().safeGetBoolean("bitmessagesettings", "smtpd"): + smtpServerThread = smtpServer() + smtpServerThread.start() + + # Start the thread that calculates POWs + objectProcessorThread = objectProcessor() + objectProcessorThread.daemon = False # DON'T close the main program even the thread remains. This thread checks the shutdown variable after processing each object. + objectProcessorThread.start() # Start the cleanerThread singleCleanerThread = singleCleaner() singleCleanerThread.daemon = True # close the main program even if there are threads left singleCleanerThread.start() - shared.reloadMyAddressHashes() - shared.reloadBroadcastSendersForWhichImWatching() + # Not needed if objproc disabled + if state.enableObjProc: + shared.reloadMyAddressHashes() + shared.reloadBroadcastSendersForWhichImWatching() - if BMConfigParser().safeGetBoolean('bitmessagesettings', 'apienabled'): - try: - apiNotifyPath = BMConfigParser().get( - 'bitmessagesettings', 'apinotifypath') - except: - apiNotifyPath = '' - if apiNotifyPath != '': - with shared.printLock: - print('Trying to call', apiNotifyPath) + # API is also objproc dependent + if BMConfigParser().safeGetBoolean('bitmessagesettings', 'apienabled'): + try: + apiNotifyPath = BMConfigParser().get( + 'bitmessagesettings', 'apinotifypath') + except: + apiNotifyPath = '' + if apiNotifyPath != '': + with shared.printLock: + print('Trying to call', apiNotifyPath) - call([apiNotifyPath, "startingUp"]) - singleAPIThread = singleAPI() - singleAPIThread.daemon = True # close the main program even if there are threads left - singleAPIThread.start() + call([apiNotifyPath, "startingUp"]) + singleAPIThread = singleAPI() + singleAPIThread.daemon = True # close the main program even if there are threads left + singleAPIThread.start() - BMConnectionPool() - asyncoreThread = BMNetworkThread() - asyncoreThread.daemon = True - asyncoreThread.start() - for i in range(BMConfigParser().getint("threads", "receive")): - receiveQueueThread = ReceiveQueueThread(i) - receiveQueueThread.daemon = True - receiveQueueThread.start() - announceThread = AnnounceThread() - announceThread.daemon = True - announceThread.start() - state.invThread = InvThread() - state.invThread.daemon = True - state.invThread.start() - state.addrThread = AddrThread() - state.addrThread.daemon = True - state.addrThread.start() - state.downloadThread = DownloadThread() - state.downloadThread.daemon = True - state.downloadThread.start() + # start network components if networking is enabled + if state.enableNetwork: + BMConnectionPool() + asyncoreThread = BMNetworkThread() + asyncoreThread.daemon = True + asyncoreThread.start() + for i in range(BMConfigParser().getint("threads", "receive")): + receiveQueueThread = ReceiveQueueThread(i) + receiveQueueThread.daemon = True + receiveQueueThread.start() + announceThread = AnnounceThread() + announceThread.daemon = True + announceThread.start() + state.invThread = InvThread() + state.invThread.daemon = True + state.invThread.start() + state.addrThread = AddrThread() + state.addrThread.daemon = True + state.addrThread.start() + state.downloadThread = DownloadThread() + state.downloadThread.daemon = True + state.downloadThread.start() - connectToStream(1) + connectToStream(1) - if BMConfigParser().safeGetBoolean('bitmessagesettings','upnp'): - import upnp - upnpThread = upnp.uPnPThread() - upnpThread.start() + if BMConfigParser().safeGetBoolean('bitmessagesettings','upnp'): + import upnp + upnpThread = upnp.uPnPThread() + upnpThread.start() + else: + # Populate with hardcoded value (same as connectToStream above) + state.streamsInWhichIAmParticipating.append(1) - if daemon == False and BMConfigParser().safeGetBoolean('bitmessagesettings', 'daemon') == False: + if daemon == False or state.enableGUI: # FIXME redundant? if state.curses == False: if not depends.check_pyqt(): sys.exit( diff --git a/src/class_singleCleaner.py b/src/class_singleCleaner.py index ca77881c..b9f35620 100644 --- a/src/class_singleCleaner.py +++ b/src/class_singleCleaner.py @@ -65,7 +65,7 @@ class singleCleaner(threading.Thread, StoppableThread): # If we are running as a daemon then we are going to fill up the UI # queue which will never be handled by a UI. We should clear it to # save memory. - if shared.thisapp.daemon: + if shared.thisapp.daemon or not state.enableGUI: # FIXME redundant? queues.UISignalQueue.queue.clear() if timeWeLastClearedInventoryAndPubkeysTables < int(time.time()) - 7380: timeWeLastClearedInventoryAndPubkeysTables = int(time.time()) @@ -120,7 +120,7 @@ class singleCleaner(threading.Thread, StoppableThread): if "Errno 28" in str(err): logger.fatal('(while receiveDataThread knownnodes.needToWriteKnownNodesToDisk) Alert: Your disk or data storage volume is full. ') queues.UISignalQueue.put(('alert', (tr._translate("MainWindow", "Disk full"), tr._translate("MainWindow", 'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'), True))) - if shared.thisapp.daemon: + if shared.thisapp.daemon or not state.enableGUI: # FIXME redundant? os._exit(0) shared.needToWriteKnownNodesToDisk = False diff --git a/src/helper_generic.py b/src/helper_generic.py index 699df8b8..03d962b5 100644 --- a/src/helper_generic.py +++ b/src/helper_generic.py @@ -12,6 +12,7 @@ import threading import traceback import shared +import state from debug import logger import queues import shutdown @@ -66,7 +67,7 @@ def signal_handler(signal, frame): "PyBitmessage", "MainThread"): return logger.error("Got signal %i", signal) - if shared.thisapp.daemon: + if shared.thisapp.daemon or not state.enableGUI: # FIXME redundant? shutdown.doCleanShutdown() else: allThreadTraceback(frame) diff --git a/src/shutdown.py b/src/shutdown.py index 814362ca..ac96d235 100644 --- a/src/shutdown.py +++ b/src/shutdown.py @@ -61,7 +61,7 @@ def doCleanShutdown(): except Queue.Empty: break - if shared.thisapp.daemon: + if shared.thisapp.daemon or not state.enableGUI: # FIXME redundant? logger.info('Clean shutdown complete.') shared.thisapp.cleanup() os._exit(0) diff --git a/src/state.py b/src/state.py index 3e2b6487..50490423 100644 --- a/src/state.py +++ b/src/state.py @@ -17,6 +17,14 @@ appdata = '' #holds the location of the application data storage directory shutdown = 0 #Set to 1 by the doCleanShutdown function. Used to tell the proof of work worker threads to exit. + +# Component control flags - set on startup, do not change during runtime +# The defaults are for standalone GUI (default operating mode) +enableNetwork = True # enable network threads +enableObjProc = True # enable object processing threads +enableAPI = True # enable API (if configured) +enableGUI = True # enable GUI (QT or ncurses) +enableSTDIO = False # enable STDIO threads curses = False sqlReady = False # set to true by sqlTread when ready for processing