Checkpointing

This commit is contained in:
John Goerzen 2007-07-05 14:49:54 +01:00
parent 1d6589a3ce
commit 7a287cef57
3 changed files with 129 additions and 46 deletions

View File

@ -59,17 +59,20 @@ class MachineUI(UIBase):
def warn(s, msg, minor): def warn(s, msg, minor):
s._printData('warn', '%s\n%d' % (msg, int(minor))) s._printData('warn', '%s\n%d' % (msg, int(minor)))
def registerthread(s, account): def registerthread(s, threadname, accountname):
UIBase.registerthread(s, account) UIBase.registerthread(s, threadname, accountname)
s._printData('registerthread', account) s._printData('registerthread', accountname)
def unregisterthread(s, thread): def unregisterthread(s, threadname):
UIBase.unregisterthread(s, thread) UIBase.unregisterthread(s, threadname)
s._printData('unregisterthread', thread.getName()) s._printData('unregisterthread', threadname)
def debugging(s, debugtype): def debugging(s, debugtype):
s._printData('debugging', debugtype) s._printData('debugging', debugtype)
def print_debug(s, debugtype, msg):
s._printData('print_debug', "%s\n%s" % (debugtype, msg))
def acct(s, accountname): def acct(s, accountname):
s._printData('acct', accountname) s._printData('acct', accountname)
@ -161,7 +164,7 @@ class MachineUI(UIBase):
return 0 return 0
def getpass(s, accountname, config, errmsg = None): def getpass(s, accountname, errmsg = None):
s.outputlock.acquire() s.outputlock.acquire()
try: try:
if errmsg: if errmsg:
@ -175,3 +178,10 @@ class MachineUI(UIBase):
def init_banner(s): def init_banner(s):
s._printData('initbanner', offlineimap.version.banner) s._printData('initbanner', offlineimap.version.banner)
def msgtoreadonly(s, destfoldernice, destfoldername, uid):
s._printData('msgtoreadonly', "%s\n%s\n%d" % (destfoldernice, destfoldername, uid))
def flagstoreadonly(s, destfoldernice, destfoldername, uidlist):
s._printData('flagstoreadonly', "%s\n%s\n%s" % (destfoldernice, destfoldername, "\f".join(

View File

@ -24,21 +24,11 @@ debugtypes = {'imap': 'IMAP protocol debugging',
'maildir': 'Maildir repository debugging', 'maildir': 'Maildir repository debugging',
'thread': 'Threading debugging'} 'thread': 'Threading debugging'}
globalui = None
def setglobalui(newui):
global globalui
globalui = newui
def getglobalui():
global globalui
return globalui
class UIBase: class UIBase:
def __init__(s, config, verbose = 0): def __init__(s, config, verbose = 0):
s.verbose = verbose s.verbose = verbose
s.config = config s.config = config
s.debuglist = [] s.debuglist = []
s.debugmessages = {}
s.debugmsglen = 50
s.threadaccounts = {} s.threadaccounts = {}
s.logfile = None s.logfile = None
@ -76,19 +66,19 @@ class UIBase:
else: else:
s._msg("WARNING: " + msg) s._msg("WARNING: " + msg)
def registerthread(s, account): def registerthread(s, threadname, accountname): #FIX IN CODE
"""Provides a hint to UIs about which account this particular """Provides a hint to UIs about which account this particular
thread is processing.""" thread is processing."""
if s.threadaccounts.has_key(threading.currentThread()): if s.threadaccounts.has_key(threadname):
raise ValueError, "Thread %s already registered (old %s, new %s)" %\ raise ValueError, "Thread %s already registered (old %s, new %s)" %\
(threading.currentThread().getName(), (threadname
s.getthreadaccount(s), account) s.getthreadaccount(s), account)
s.threadaccounts[threading.currentThread()] = account s.threadaccounts[threadname] = account
def unregisterthread(s, thr): def unregisterthread(s, threadname): #FIX IN CODE
"""Recognizes a thread has exited.""" """Recognizes a thread has exited."""
if s.threadaccounts.has_key(thr): if s.threadaccounts.has_key(threadname):
del s.threadaccounts[thr] del s.threadaccounts[threadname]
def getthreadaccount(s, thr = None): def getthreadaccount(s, thr = None):
if not thr: if not thr:
@ -97,16 +87,7 @@ class UIBase:
return s.threadaccounts[thr] return s.threadaccounts[thr]
return '*Control' return '*Control'
def debug(s, debugtype, msg): def print_debug(s, debugtype, msg):
thisthread = threading.currentThread()
if s.debugmessages.has_key(thisthread):
s.debugmessages[thisthread].append("%s: %s" % (debugtype, msg))
else:
s.debugmessages[thisthread] = ["%s: %s" % (debugtype, msg)]
while len(s.debugmessages[thisthread]) > s.debugmsglen:
s.debugmessages[thisthread] = s.debugmessages[thisthread][1:]
if debugtype in s.debuglist: if debugtype in s.debuglist:
if not s._log("DEBUG[%s]: %s" % (debugtype, msg)): if not s._log("DEBUG[%s]: %s" % (debugtype, msg)):
s._display("DEBUG[%s]: %s" % (debugtype, msg)) s._display("DEBUG[%s]: %s" % (debugtype, msg))
@ -124,17 +105,9 @@ class UIBase:
global debugtypes global debugtypes
s._msg("Now debugging for %s: %s" % (debugtype, debugtypes[debugtype])) s._msg("Now debugging for %s: %s" % (debugtype, debugtypes[debugtype]))
def invaliddebug(s, debugtype):
s.warn("Invalid debug type: %s" % debugtype)
def locked(s): def locked(s):
raise Exception, "Another OfflineIMAP is running with the same metadatadir; exiting." raise Exception, "Another OfflineIMAP is running with the same metadatadir; exiting."
def getnicename(s, object):
prelimname = str(object.__class__).split('.')[-1]
# Strip off extra stuff.
return re.sub('(Folder|Repository)', '', prelimname)
def isusable(s): def isusable(s):
"""Returns true if this UI object is usable in the current """Returns true if this UI object is usable in the current
environment. For instance, an X GUI would return true if it's environment. For instance, an X GUI would return true if it's
@ -143,19 +116,19 @@ class UIBase:
################################################## INPUT ################################################## INPUT
def getpass(s, accountname, config, errmsg = None): def getpass(s, accountname, errmsg = None): # FIX IN CODE
raise NotImplementedError raise NotImplementedError
def folderlist(s, list): def folderlist(s, list):
return ', '.join(["%s[%s]" % (s.getnicename(x), x.getname()) for x in list]) return ', '.join(["%s[%s]" % (s.getnicename(x), x.getname()) for x in list])
################################################## WARNINGS ################################################## WARNINGS
def msgtoreadonly(s, destfolder, uid, content, flags): def msgtoreadonly(s, destfoldernicename, destfoldername, uid): #FIX IN CODE # FIX IN CODE
if not (config.has_option('general', 'ignore-readonly') and config.getboolean("general", "ignore-readonly")): if not (config.has_option('general', 'ignore-readonly') and config.getboolean("general", "ignore-readonly")):
s.warn("Attempted to synchronize message %d to folder %s[%s], but that folder is read-only. The message will not be copied to that folder." % \ s.warn("Attempted to synchronize message %d to folder %s[%s], but that folder is read-only. The message will not be copied to that folder." % \
(uid, s.getnicename(destfolder), destfolder.getname())) (uid, destfoldernicename, destfoldername))
def flagstoreadonly(s, destfolder, uidlist, flags): def flagstoreadonly(s, destfolder, uidlist): #FIX IN CODE
if not (config.has_option('general', 'ignore-readonly') and config.getboolean("general", "ignore-readonly")): if not (config.has_option('general', 'ignore-readonly') and config.getboolean("general", "ignore-readonly")):
s.warn("Attempted to modify flags for messages %s in folder %s[%s], but that folder is read-only. No flags have been modified for that message." % \ s.warn("Attempted to modify flags for messages %s in folder %s[%s], but that folder is read-only. No flags have been modified for that message." % \
(str(uidlist), s.getnicename(destfolder), destfolder.getname())) (str(uidlist), s.getnicename(destfolder), destfolder.getname()))

View File

@ -0,0 +1,100 @@
# User interface transmitter
#
# Used by per-account OfflineIMAP threads
#
# Transmits messages using Machine
#
# Copyright (C) 2002-2007 John Goerzen
# <jgoerzen@complete.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import offlineimap.version
import re, time, sys, traceback, threading, thread
from StringIO import StringIO
debugtypes = {'imap': 'IMAP protocol debugging',
'maildir': 'Maildir repository debugging',
'thread': 'Threading debugging'}
globalui = None
def setglobalui(newui):
global globalui
globalui = newui
def getglobalui():
global globalui
return globalui
class UITransmitter:
"""This class is designed to transmit UI messages to the OfflineIMAP
ui process. It receives raw data and formats it nicely."""
def __init__(s, config, verbose = 0):
s.verbose = verbose
s.config = config
s.debuglist = []
s.debugmessages = {}
s.debugmsglen = 50
s.threadaccounts = {}
s.logfile = None
s.m = Machine.MachineUI(config, verbose)
def warn(s, msg, minor = 0):
s.m.warn(msg, minor)
def registerthread(s, accountname):
s.m.registerthread(threading.currentThread().getName(), accountname)
def unregisterthread(s, threadobj):
s.m.unregisterthread(threadobj.getName())
def debugging(s, debugtype):
s.m.debugging(s, debugtype)
def debug(s, debugtype, msg):
thisthread = threading.currentThread()
if s.debugmessages.has_key(thisthread):
s.debugmessages[thisthread].append("%s: %s" % (debugtype, msg))
else:
s.debugmessages[thisthread] = ["%s: %s" % (debugtype, msg)]
while len(s.debugmessages[thisthread]) > s.debugmsglen:
s.debugmessages[thisthread] = s.debugmessages[thisthread][1:]
s.print_debug(debugtype, msg)
def print_debug(s, debugtype, msg):
s.m.print_debug(s, debugtype, msg)
def debugging(s, debugtype):
s.m.debugging(s, debugtype)
def invaliddebug(s, debugtype):
s.warn("Invalid debug type: %s" % debugtype)
def getnicename(s, object):
prelimname = str(object.__class__).split('.')[-1]
# Strip off extra stuff.
return re.sub('(Folder|Repository)', '', prelimname)
################################################## INPUT
def getpass(s, accountname, errmsg = None):
s.m.getpass(accountname, errmsg)
################################################## WARNINGS
def msgtoreadonly(s, destfolder, uid):
s.m.msgtoreadonly(s, s.getnicename(destfolder),
destfolder.getname(), uid)