/head: changeset 90

Commited changes for 2.0.6
This commit is contained in:
jgoerzen 2002-07-10 12:18:07 +01:00
parent bd9873632c
commit 097d30e987
7 changed files with 153 additions and 26 deletions

View File

@ -1,3 +1,22 @@
2002-07-09 20:17 jgoerzen
* offlineimap.conf, offlineimap.py, debian/changelog,
offlineimap/imapserver.py, offlineimap/version.py,
offlineimap/folder/IMAP.py: Commited changes for 2.0.6
2002-07-09 13:13 jgoerzen
* offlineimap/folder/IMAP.py: Another attempt at the read-only bug
2002-07-08 12:05 jgoerzen
* offlineimap/folder/IMAP.py: Another attempt at fixing read-only
folders
2002-07-08 11:38 jgoerzen
* ChangeLog: Updated for 2.0.5
2002-07-08 11:32 jgoerzen
* debian/changelog, offlineimap/folder/IMAP.py,

View File

@ -1,3 +1,16 @@
offlineimap (2.0.6) unstable; urgency=low
* Added support for holdconnectionopen and keepalive. This feature
allows for an IMAP server connection(s) to be held open until
the next sync process, permitting faster restart times.
* Another try at read-only folder support. This is nasty because I
have no way to test it and imaplib's read-only support is weird.
* Closing out old bug; fixed in 1.0.2. Closes: #150803.
* Optimized algorithm so that a SELECT is never issued for folders
that contain no messages.
-- John Goerzen <jgoerzen@complete.org> Tue, 9 Jul 2002 20:05:24 -0500
offlineimap (2.0.5) unstable; urgency=low
* Fixed a folderfilter example. Partially fixes #152079.

View File

@ -215,3 +215,19 @@ remoteuser = username
maxconnections = 1
# OfflineIMAP normally closes IMAP server connections between refreshes if
# the global option autorefresh is specified. If you wish it to keep the
# connection open, set this to true. If not specified, the default is
# false. Keeping the connection open means a faster sync start the
# next time and may use fewer server resources on connection, but uses
# more server memory. This setting has no effect if autorefresh is not set.
holdconnectionopen = no
# If you want to have "keepalives" sent while waiting between syncs,
# specify the amount of time IN SECONDS between keepalives here. Note that
# sometimes more than this amount of time might pass, so don't make it
# tight. This setting has no effect if autorefresh and holdconnectionopen
# are not both set.
# keepalive = 60

View File

@ -74,6 +74,8 @@ for account in accounts:
mailboxes = []
mailboxlock = Lock()
servers = {}
def addmailbox(accountname, remotefolder):
mailboxlock.acquire()
mailboxes.append({'accountname' : accountname,
@ -88,28 +90,14 @@ def syncaccount(accountname, *args):
accountmetadata = os.path.join(metadatadir, accountname)
if not os.path.exists(accountmetadata):
os.mkdir(accountmetadata, 0700)
host = config.get(accountname, "remotehost")
user = config.get(accountname, "remoteuser")
port = None
if config.has_option(accountname, "remoteport"):
port = config.getint(accountname, "remoteport")
ssl = config.getboolean(accountname, "ssl")
usetunnel = config.has_option(accountname, "preauthtunnel")
reference = '""'
if config.has_option(accountname, "reference"):
reference = config.get(accountname, "reference")
server = None
# Connect to the remote server.
if usetunnel:
server = imapserver.IMAPServer(tunnel = tunnels[accountname],
reference = reference,
maxconnections = config.getint(accountname, "maxconnections"))
if accountname in servers:
server = servers[accountname]
else:
server = imapserver.IMAPServer(user, passwords[accountname],
host, port, ssl,
config.getint(accountname, "maxconnections"),
reference = reference)
server = imapserver.ConfigedIMAPServer(config, accountname, passwords)
servers[accountname] = server
remoterepos = repository.IMAP.IMAPRepository(config, accountname, server)
# Connect to the Maildirs.
@ -134,7 +122,9 @@ def syncaccount(accountname, *args):
thread.start()
folderthreads.append(thread)
threadutil.threadsreset(folderthreads)
server.close()
if not (config.has_option(accountname, 'holdconnectionopen') and \
config.getboolean(accountname, 'holdconnectionopen')):
server.close()
finally:
pass
@ -213,9 +203,31 @@ def sync_with_timer():
if config.has_option('general', 'autorefresh'):
refreshperiod = config.getint('general', 'autorefresh') * 60
while 1:
# Set up keep-alives.
kaevents = {}
kathreads = {}
for accountname in accounts:
if config.has_option(accountname, 'holdconnectionopen') and \
config.getboolean(accountname, 'holdconnectionopen') and \
config.has_option(accountname, 'keepalive'):
event = Event()
kaevents[accountname] = event
thread = ExitNotifyThread(target = servers[accountname].keepalive,
args = (config.getint(accountname, 'keepalive'), event))
thread.setDaemon(1)
thread.start()
kathreads[accountname] = thread
if ui.sleep(refreshperiod) == 2:
# Cancel keep-alives, but don't bother terminating threads
for event in kaevents.values():
event.set()
break
else:
# Cancel keep-alives and wait for threads to terminate.
for event in kaevents.values():
event.set()
for thread in kathreads.values():
thread.join()
syncitall()
def threadexited(thread):

View File

@ -59,8 +59,6 @@ class IMAPFolder(BaseFolder):
def cachemessagelist(self):
imapobj = self.imapserver.acquireconnection()
try:
# Needed for fetch below
imapobj.select(self.getfullname(), readonly = 1)
self.messagelist = {}
response = imapobj.status(self.getfullname(), '(MESSAGES)')[1][0]
result = imaputil.imapsplit(response)[1]
@ -69,6 +67,8 @@ class IMAPFolder(BaseFolder):
# No messages? return.
return
# Needed for fetch below
imapobj.select(self.getfullname(), readonly = 1)
# Now, get the flags and UIDs for these.
response = imapobj.fetch('1:%d' % maxmsgid, '(FLAGS UID)')[1]
finally:

View File

@ -28,13 +28,14 @@ class UsefulIMAPMixIn:
return None
def select(self, mailbox='INBOX', readonly=None):
if self.getselectedfolder() == mailbox and not readonly:
if self.getselectedfolder() == mailbox:
self.is_readonly = readonly
# No change; return.
return
result = self.__class__.__bases__[1].select(self, mailbox, readonly)
if result[0] != 'OK':
raise ValueError, "Error from select: %s" % str(result)
if self.getstate() == 'SELECTED' and not readonly:
if self.getstate() == 'SELECTED':
self.selectedfolder = mailbox
else:
self.selectedfolder = None
@ -146,5 +147,71 @@ class IMAPServer:
self.assignedconnections = []
self.availableconnections = []
self.connectionlock.release()
def keepalive(self, timeout, event):
"""Sends a NOOP to each connection recorded. It will wait a maximum
of timeout seconds between doing this, and will continue to do so
until the Event object as passed is true. This method is expected
to be invoked in a separate thread, which should be join()'d after
the event is set."""
while 1:
event.wait(timeout)
if event.isSet():
return
self.connectionlock.acquire()
numconnections = len(self.assignedconnections) + \
len(self.availableconnections)
self.connectionlock.release()
threads = []
imapobjs = []
for i in range(numconnections):
imapobj = self.acquireconnection()
imapobjs.append(imapobj)
thread = threadutil.ExitNotifyThread(target = imapobj.noop)
thread.setDaemon(1)
thread.start()
threads.append(thread)
for thread in threads:
# Make sure all the commands have completed.
thread.join()
for imapobj in imapobjs:
self.releaseconnection(imapobj)
class ConfigedIMAPServer(IMAPServer):
"""This class is designed for easier initialization given a ConfigParser
object and an account name. The passwordhash is used if
passwords for certain accounts are known. If the password for this
account is listed, it will be obtained from there."""
def __init__(self, config, accountname, passwordhash = {}):
"""Initialize the object. If the account is not a tunnel,
the password is required."""
host = config.get(accountname, "remotehost")
user = config.get(accountname, "remoteuser")
port = None
if config.has_option(accountname, "remoteport"):
port = config.getint(accountname, "remoteport")
ssl = config.getboolean(accountname, "ssl")
usetunnel = config.has_option(accountname, "preauthtunnel")
reference = '""'
if config.has_option(accountname, "reference"):
reference = config.get(accountname, "reference")
server = None
password = None
if accountname in passwordhash:
password = passwordhash[accountname]
# Connect to the remote server.
if usetunnel:
IMAPServer.__init__(self,
tunnel = config.get(accountname, "preauthtunnel"),
reference = reference,
maxconnections = config.getint(accountname, "maxconnections"))
else:
if not password:
password = config.get(accountname, 'remotepass')
IMAPServer.__init__(self, user, password, host, port, ssl,
config.getint(accountname, "maxconnections"),
reference = reference)

View File

@ -1,5 +1,5 @@
productname = 'OfflineIMAP'
versionstr = "2.0.5"
versionstr = "2.0.6"
versionlist = versionstr.split(".")
major = versionlist[0]