[PATCH 4/4] Implement single threading mode

Sebastian Spaeth Sebastian at SSpaeth.de
Wed Dec 22 14:27:20 GMT 2010


Don't sync accounts in subthreads when:
 1) option singlethreading has been chosen
 2) There is only 1 account to sync
 3) maxacountsync setting is 1

Signed-off-by: Sebastian Spaeth <Sebastian at SSpaeth.de>
---
 offlineimap/init.py       |   61 +++++++++++++++++++++++++++++---------------
 offlineimap/syncmaster.py |    4 +--
 2 files changed, 41 insertions(+), 24 deletions(-)

diff --git a/offlineimap/init.py b/offlineimap/init.py
index 828d696..db27bd4 100644
--- a/offlineimap/init.py
+++ b/offlineimap/init.py
@@ -17,10 +17,6 @@
 #    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 
 import imaplib
-from offlineimap import imapserver, threadutil, version, syncmaster, accounts
-from offlineimap.localeval import LocalEval
-from offlineimap.threadutil import InstanceLimitedThread, ExitNotifyThread
-from offlineimap.CustomConfig import CustomConfigParser
 from optparse import OptionParser
 import re, os, sys
 from threading import *
@@ -28,6 +24,10 @@ import threading, socket
 import signal
 import logging
 import offlineimap
+import offlineimap.accounts
+from offlineimap.threadutil import InstanceLimitedThread, ExitNotifyThread
+from offlineimap.localeval import LocalEval
+from offlineimap.CustomConfig import CustomConfigParser
 
 try:
     import fcntl
@@ -171,7 +171,7 @@ class OfflineImap:
                 options.singlethreaded = True
             profiledir = options.profiledir
             os.mkdir(profiledir)
-            threadutil.setprofiledir(profiledir)
+            offlineimap.threadutil.setprofiledir(profiledir)
             logging.warn("Profile mode: Potentially large data will be "
                          "created in '%s'" % profiledir)
 
@@ -218,18 +218,18 @@ class OfflineImap:
 
         if options.runonce:
             # FIXME: maybe need a better
-            for section in accounts.getaccountlist(config):
+            for section in offlineimap.accounts.getaccountlist(config):
                 config.remove_option('Account ' + section, "autorefresh")
 
         if options.quick:
-            for section in accounts.getaccountlist(config):
+            for section in offlineimap.accounts.getaccountlist(config):
                 config.set('Account ' + section, "quick", '-1')
 
         if options.folders:
             foldernames = options.folders.replace(" ", "").split(",")
             folderfilter = "lambda f: f in %s" % foldernames
             folderincludes = "[]"
-            for accountname in accounts.getaccountlist(config):
+            for accountname in offlineimap.accounts.getaccountlist(config):
                 account_section = 'Account ' + accountname
                 remote_repo_section = 'Repository ' + \
                                       config.get(account_section, 'remoterepository')
@@ -269,7 +269,7 @@ class OfflineImap:
                 activeaccounts = options.accounts
             activeaccounts = activeaccounts.replace(" ", "")
             activeaccounts = activeaccounts.split(",")
-            allaccounts = accounts.AccountHashGenerator(config)
+            allaccounts = offlineimap.accounts.AccountHashGenerator(config)
     
             syncaccounts = []
             for account in activeaccounts:
@@ -288,19 +288,16 @@ class OfflineImap:
             remoterepos = None
             localrepos = None
     
-            if options.singlethreading:
-                threadutil.initInstanceLimit("ACCOUNTLIMIT", 1)
-            else:
-                threadutil.initInstanceLimit("ACCOUNTLIMIT",
-                                             config.getdefaultint("general", "maxsyncaccounts", 1))
+            offlineimap.threadutil.initInstanceLimit("ACCOUNTLIMIT",
+                                   config.getdefaultint("general", "maxsyncaccounts", 1))
     
             for reposname in config.getsectionlist('Repository'):
                 for instancename in ["FOLDER_" + reposname,
                                      "MSGCOPY_" + reposname]:
                     if options.singlethreading:
-                        threadutil.initInstanceLimit(instancename, 1)
+                        offlineimap.threadutil.initInstanceLimit(instancename, 1)
                     else:
-                        threadutil.initInstanceLimit(instancename,
+                        offlineimap.threadutil.initInstanceLimit(instancename,
                                                      config.getdefaultint('Repository ' + reposname, "maxconnections", 1))
             siglisteners = []
             def sig_handler(signum, frame):
@@ -321,14 +318,24 @@ class OfflineImap:
             signal.signal(signal.SIGUSR1,sig_handler)
             signal.signal(signal.SIGUSR2,sig_handler)
     
-            threadutil.initexitnotify()
-            t = ExitNotifyThread(target=syncmaster.syncitall,
+            #various initializations that need to be performed:
+            offlineimap.threadutil.initexitnotify()       #TODO: Why?
+            offlineimap.mbnames.init(config, syncaccounts)
+
+            if options.singlethreading or len(syncaccounts) == 1 \
+                    or config.getdefaultint("general", "maxsyncaccounts", 1) == 1:
+                #singlethreaded
+                self.sync_singlethreaded(syncaccounts, config, siglisteners)
+            else:
+                # multithreaded
+                t = ExitNotifyThread(target=offlineimap.syncmaster.syncitall,
                                  name='Sync Runner',
                                  kwargs = {'accounts': syncaccounts,
                                            'config': config,
                                            'siglisteners': siglisteners})
-            t.setDaemon(1)
-            t.start()
+                t.setDaemon(1)
+                t.start()
+
             offlineimap.threadutil.exitnotifymonitorloop(offlineimap.threadutil.threadexited)
 
         except KeyboardInterrupt:
@@ -339,4 +346,16 @@ class OfflineImap:
         except:
             ui.mainException()
 
-        
+    def sync_singlethreaded(self, accounts, config, siglisteners):
+        """Executed if we do not want a separate syncmaster thread
+
+        :param accounts: A list of accounts that should be synced
+        :param config: The CustomConfig object
+        :param siglisteners: The signal listeners list, defined in run()
+        """
+        for accountname in accounts:
+            account = offlineimap.accounts.SyncableAccount(config, accountname)
+            siglistener = offlineimap.accounts.SigListener()
+            siglisteners.append(siglistener)
+            currentThread().name = "Account sync %s" % accountname
+            account.syncrunner(siglistener=siglistener)
diff --git a/offlineimap/syncmaster.py b/offlineimap/syncmaster.py
index 2da8e3e..5a0a2fb 100644
--- a/offlineimap/syncmaster.py
+++ b/offlineimap/syncmaster.py
@@ -16,7 +16,6 @@
 #    along with this program; if not, write to the Free Software
 #    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 
-from offlineimap import mbnames
 from offlineimap.threadutil import threadlist, InstanceLimitedThread, ExitNotifyThread
 from offlineimap.accounts import SyncableAccount, SigListener
 from threading import currentThread
@@ -33,11 +32,10 @@ def syncaccount(threads, config, accountname, siglisteners):
     thread.setDaemon(1)
     thread.start()
     threads.add(thread)
-    
+
 def syncitall(accounts, config, siglisteners):
     currentThread().setExitMessage('SYNC_WITH_TIMER_TERMINATE')
     threads = threadlist()
-    mbnames.init(config, accounts)
     for accountname in accounts:
         syncaccount(threads, config, accountname, siglisteners)
     # Wait for the threads to finish.
-- 
1.7.1





More information about the OfflineIMAP-project mailing list