threading: improve variable names and factorize code

Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
This commit is contained in:
Nicolas Sebrecht 2016-05-18 02:42:09 +02:00
parent 0addcbabf0
commit e0fdcb3852
5 changed files with 29 additions and 24 deletions

View File

@ -29,6 +29,8 @@ from offlineimap.threadutil import InstanceLimitedThread
import six import six
FOLDER_NAMESPACE = 'LIMITED_FOLDER_'
try: try:
import fcntl import fcntl
except: except:
@ -354,9 +356,11 @@ class SyncableAccount(Account):
continue # Ignore filtered folder continue # Ignore filtered folder
if not globals.options.singlethreading: if not globals.options.singlethreading:
thread = InstanceLimitedThread( thread = InstanceLimitedThread(
instancename = 'FOLDER_' + self.remoterepos.getname(), limitNamespace = "%s%s"% (
FOLDER_NAMESPACE, self.remoterepos.getname()),
target = syncfolder, target = syncfolder,
name = "Folder %s [acc: %s]"% (remotefolder.getexplainedname(), self), name = "Folder %s [acc: %s]"% (
remotefolder.getexplainedname(), self),
args = (self, remotefolder, quick) args = (self, remotefolder, quick)
) )
thread.start() thread.start()

View File

@ -134,7 +134,7 @@ class BaseFolder(object):
return True return True
def getcopyinstancelimit(self): def getinstancelimitnamespace(self):
"""For threading folders, returns the instancelimitname for """For threading folders, returns the instancelimitname for
InstanceLimitedThreads.""" InstanceLimitedThreads."""
@ -872,7 +872,7 @@ class BaseFolder(object):
if self.suggeststhreads() and not globals.options.singlethreading: if self.suggeststhreads() and not globals.options.singlethreading:
self.waitforthread() self.waitforthread()
thread = threadutil.InstanceLimitedThread( thread = threadutil.InstanceLimitedThread(
self.getcopyinstancelimit(), self.getinstancelimitnamespace(),
target = self.copymessageto, target = self.copymessageto,
name = "Copy message from %s:%s" % (self.repository, self), name = "Copy message from %s:%s" % (self.repository, self),
args = (uid, dstfolder, statusfolder) args = (uid, dstfolder, statusfolder)

View File

@ -32,6 +32,7 @@ import six
# Globals # Globals
CRLF = '\r\n' CRLF = '\r\n'
MSGCOPY_NAMESPACE = 'MSGCOPY_'
# NB: message returned from getmessage() will have '\n' all over the place, # NB: message returned from getmessage() will have '\n' all over the place,
@ -88,8 +89,8 @@ class IMAPFolder(BaseFolder):
OfflineImapError.ERROR.REPO), None, exc_info()[2]) OfflineImapError.ERROR.REPO), None, exc_info()[2])
# Interface from BaseFolder # Interface from BaseFolder
def getcopyinstancelimit(self): def getinstancelimitnamespace(self):
return 'MSGCOPY_' + self.repository.getname() return MSGCOPY_NAMESPACE + self.repository.getname()
# Interface from BaseFolder # Interface from BaseFolder
def get_uidvalidity(self): def get_uidvalidity(self):

View File

@ -31,6 +31,7 @@ from offlineimap.ui import UI_LIST, setglobalui, getglobalui
from offlineimap.CustomConfig import CustomConfigParser from offlineimap.CustomConfig import CustomConfigParser
from offlineimap.utils import stacktrace from offlineimap.utils import stacktrace
from offlineimap.repository import Repository from offlineimap.repository import Repository
from offlineimap.folder.IMAP import MSGCOPY_NAMESPACE
import traceback import traceback
import collections import collections
@ -45,7 +46,7 @@ def syncitall(list_accounts, config):
# Start a new thread per account and store it in the collection. # Start a new thread per account and store it in the collection.
account = accounts.SyncableAccount(config, accountname) account = accounts.SyncableAccount(config, accountname)
thread = threadutil.InstanceLimitedThread( thread = threadutil.InstanceLimitedThread(
instancename = ACCOUNT_LIMITED_THREAD_NAME, ACCOUNT_LIMITED_THREAD_NAME,
target = account.syncrunner, target = account.syncrunner,
name = "Account sync %s"% accountname name = "Account sync %s"% accountname
) )
@ -298,8 +299,8 @@ class OfflineImap:
# connections for a remote IMAP server, why do we allow twice this # connections for a remote IMAP server, why do we allow twice this
# number? The max connections number is used by both the FOLDER_ and # number? The max connections number is used by both the FOLDER_ and
# the MSGCOPY_ prefixes! # the MSGCOPY_ prefixes!
for instancename in ["FOLDER_" + reposname, for instancename in [accounts.FOLDER_NAMESPACE + reposname,
"MSGCOPY_" + reposname]: MSGCOPY_NAMESPACE + reposname]:
if options.singlethreading: if options.singlethreading:
threadutil.initInstanceLimit(instancename, 1) threadutil.initInstanceLimit(instancename, 1)
else: else:

View File

@ -221,37 +221,36 @@ class ExitNotifyThread(Thread):
# Instance-limited threads # Instance-limited threads
###################################################################### ######################################################################
instancelimitedsems = {} limitedNamespaces = {}
def initInstanceLimit(instancename, instancemax): def initInstanceLimit(limitNamespace, instancemax):
"""Initialize the instance-limited thread implementation. """Initialize the instance-limited thread implementation.
Run up to intancemax threads for the given instancename. This allows Run up to intancemax threads for the given limitNamespace. This allows to
to honor maxsyncaccounts and maxconnections.""" honor maxsyncaccounts and maxconnections."""
global instancelimitedsems global limitedNamespaces
if not instancename in instancelimitedsems: if not limitNamespace in limitedNamespaces:
instancelimitedsems[instancename] = BoundedSemaphore(instancemax) limitedNamespaces[limitNamespace] = BoundedSemaphore(instancemax)
class InstanceLimitedThread(ExitNotifyThread): class InstanceLimitedThread(ExitNotifyThread):
def __init__(self, instancename, *args, **kwargs): def __init__(self, limitNamespace, *args, **kwargs):
# XXX: this is not a instance name, is it? self.limitNamespace = limitNamespace
self.instancename = instancename
super(InstanceLimitedThread, self).__init__(*args, **kwargs) super(InstanceLimitedThread, self).__init__(*args, **kwargs)
def start(self): def start(self):
global instancelimitedsems global limitedNamespaces
instancelimitedsems[self.instancename].acquire() limitedNamespaces[self.limitNamespace].acquire()
ExitNotifyThread.start(self) ExitNotifyThread.start(self)
def run(self): def run(self):
global instancelimitedsems global limitedNamespaces
try: try:
ExitNotifyThread.run(self) ExitNotifyThread.run(self)
finally: finally:
if instancelimitedsems and instancelimitedsems[self.instancename]: if limitedNamespaces and limitedNamespaces[self.limitNamespace]:
instancelimitedsems[self.instancename].release() limitedNamespaces[self.limitNamespace].release()