/offlineimap/head: changeset 308

More progress at debugging. The curses blinkenlights is now working
well, though it still has an occasional tendency to corrupt the light
display with comments from the log. I suspect a locking problem --
need to be more strict with iolock I suspect. Updated various modules
to register the threads' account names, etc.
This commit is contained in:
jgoerzen 2003-01-06 00:07:58 +01:00
parent c48d8d4fda
commit d6b790a7da
9 changed files with 57 additions and 25 deletions

View File

@ -81,6 +81,7 @@ class Account:
class AccountSynchronizationMixin: class AccountSynchronizationMixin:
def syncrunner(self): def syncrunner(self):
self.ui.registerthread(self.name)
self.ui.acct(self.name) self.ui.acct(self.name)
if not self.refreshperiod: if not self.refreshperiod:
self.sync() self.sync()
@ -109,7 +110,7 @@ class AccountSynchronizationMixin:
localrepos = repository.Maildir.MaildirRepository(os.path.expanduser(self.config.get(self.name, "localfolders")), self.name, self.config) localrepos = repository.Maildir.MaildirRepository(os.path.expanduser(self.config.get(self.name, "localfolders")), self.name, self.config)
# Connect to the local cache. # Connect to the local cache.
statusrepos = repository.LocalStatus.LocalStatusRepository(accountmetadata) statusrepos = repository.LocalStatus.LocalStatusRepository(accountmetadata, self.name)
self.ui.syncfolders(remoterepos, localrepos) self.ui.syncfolders(remoterepos, localrepos)
remoterepos.syncfoldersto(localrepos) remoterepos.syncfoldersto(localrepos)
@ -139,6 +140,7 @@ def syncfolder(accountname, remoterepos, remotefolder, localrepos,
statusrepos): statusrepos):
global mailboxes global mailboxes
ui = UIBase.getglobalui() ui = UIBase.getglobalui()
ui.registerthread(accountname)
# Load local folder. # Load local folder.
localfolder = localrepos.\ localfolder = localrepos.\
getfolder(remotefolder.getvisiblename().\ getfolder(remotefolder.getvisiblename().\

View File

@ -186,12 +186,14 @@ class BaseFolder:
# Did not find any server to take this message. Ignore. # Did not find any server to take this message. Ignore.
pass pass
def copymessageto(self, uid, applyto): def copymessageto(self, uid, applyto, register = 1):
# Sometimes, it could be the case that if a sync takes awhile, # Sometimes, it could be the case that if a sync takes awhile,
# a message might be deleted from the maildir before it can be # a message might be deleted from the maildir before it can be
# synced to the status cache. This is only a problem with # synced to the status cache. This is only a problem with
# self.getmessage(). So, don't call self.getmessage unless # self.getmessage(). So, don't call self.getmessage unless
# really needed. # really needed.
if register:
UIBase.getglobalui().registerthread(self.getaccountname())
UIBase.getglobalui().copyingmessage(uid, self, applyto) UIBase.getglobalui().copyingmessage(uid, self, applyto)
message = '' message = ''
# If any of the destinations actually stores the message body, # If any of the destinations actually stores the message body,
@ -233,7 +235,7 @@ class BaseFolder:
thread.start() thread.start()
threads.append(thread) threads.append(thread)
else: else:
self.copymessageto(uid, applyto) self.copymessageto(uid, applyto, register = 0)
for thread in threads: for thread in threads:
thread.join() thread.join()

View File

@ -39,6 +39,9 @@ class IMAPFolder(BaseFolder):
self.accountname = accountname self.accountname = accountname
self.repository = repository self.repository = repository
def getaccountname(self):
return self.accountname
def suggeststhreads(self): def suggeststhreads(self):
return 1 return 1

View File

@ -1,5 +1,5 @@
# Local status cache virtual folder # Local status cache virtual folder
# Copyright (C) 2002 John Goerzen # Copyright (C) 2002 - 2003 John Goerzen
# <jgoerzen@complete.org> # <jgoerzen@complete.org>
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
@ -22,7 +22,7 @@ import os, threading
magicline = "OFFLINEIMAP LocalStatus CACHE DATA - DO NOT MODIFY - FORMAT 1" magicline = "OFFLINEIMAP LocalStatus CACHE DATA - DO NOT MODIFY - FORMAT 1"
class LocalStatusFolder(BaseFolder): class LocalStatusFolder(BaseFolder):
def __init__(self, root, name, repository): def __init__(self, root, name, repository, accountname):
self.name = name self.name = name
self.root = root self.root = root
self.sep = '.' self.sep = '.'
@ -31,6 +31,10 @@ class LocalStatusFolder(BaseFolder):
self.repository = repository self.repository = repository
self.savelock = threading.Lock() self.savelock = threading.Lock()
self.doautosave = 1 self.doautosave = 1
self.accountname = accountname
def getaccountname(self):
return self.accountname
def storesmessages(self): def storesmessages(self):
return 0 return 0

View File

@ -39,13 +39,17 @@ def gettimeseq():
return timeseq return timeseq
class MaildirFolder(BaseFolder): class MaildirFolder(BaseFolder):
def __init__(self, root, name, sep, repository): def __init__(self, root, name, sep, repository, accountname):
self.name = name self.name = name
self.root = root self.root = root
self.sep = sep self.sep = sep
self.uidfilename = os.path.join(self.getfullname(), "offlineimap.uidvalidity") self.uidfilename = os.path.join(self.getfullname(), "offlineimap.uidvalidity")
self.messagelist = None self.messagelist = None
self.repository = repository self.repository = repository
self.accountname = accountname
def getaccountname(self):
return self.accountname
def getfullname(self): def getfullname(self):
return os.path.join(self.getroot(), self.getname()) return os.path.join(self.getroot(), self.getname())

View File

@ -21,9 +21,10 @@ from offlineimap import folder
import os import os
class LocalStatusRepository(BaseRepository): class LocalStatusRepository(BaseRepository):
def __init__(self, directory): def __init__(self, directory, accountname):
self.directory = directory self.directory = directory
self.folders = None self.folders = None
self.accountname = accountname
def getsep(self): def getsep(self):
return '.' return '.'
@ -42,12 +43,12 @@ class LocalStatusRepository(BaseRepository):
retval = [] retval = []
for folder in os.listdir(self.directory): for folder in os.listdir(self.directory):
retval.append(folder.LocalStatus.LocalStatusFolder(self.directory, retval.append(folder.LocalStatus.LocalStatusFolder(self.directory,
folder, self)) folder, self, self.accountname))
return retval return retval
def getfolder(self, foldername): def getfolder(self, foldername):
return folder.LocalStatus.LocalStatusFolder(self.directory, foldername, return folder.LocalStatus.LocalStatusFolder(self.directory, foldername,
self) self, self.accountname)

View File

@ -87,7 +87,7 @@ class MaildirRepository(BaseRepository):
def getfolder(self, foldername): def getfolder(self, foldername):
return folder.Maildir.MaildirFolder(self.root, foldername, return folder.Maildir.MaildirFolder(self.root, foldername,
self.getsep(), self) self.getsep(), self, self.accountname)
def _getfolders_scandir(self, root, extension = None): def _getfolders_scandir(self, root, extension = None):
self.debug("_GETFOLDERS_SCANDIR STARTING. root = %s, extension = %s" \ self.debug("_GETFOLDERS_SCANDIR STARTING. root = %s, extension = %s" \
@ -131,7 +131,7 @@ class MaildirRepository(BaseRepository):
self.debug(" foldername = %s" % foldername) self.debug(" foldername = %s" % foldername)
retval.append(folder.Maildir.MaildirFolder(self.root, foldername, retval.append(folder.Maildir.MaildirFolder(self.root, foldername,
self.getsep(), self)) self.getsep(), self, self.accountname))
if self.getsep() == '/': if self.getsep() == '/':
# Check sub-directories for folders. # Check sub-directories for folders.
retval.extend(self._getfolders_scandir(root, foldername)) retval.extend(self._getfolders_scandir(root, foldername))

View File

@ -84,19 +84,23 @@ class CursesUtil:
self.start() self.start()
class CursesAccountFrame: class CursesAccountFrame:
def __init__(s, master): def __init__(s, master, accountname):
s.c = master s.c = master
s.children = [] s.children = []
s.accountname = accountname
def setwindow(s, window): def setwindow(s, window):
s.window = window s.window = window
location = 0 acctstr = '%15.15s: ' % s.accountname
s.window.addstr(0, 0, acctstr)
s.location = len(acctstr)
for child in s.children: for child in s.children:
child.update(window, 0, location) child.update(window, 0, s.location)
location += 1 s.location += 1
def getnewthreadframe(s): def getnewthreadframe(s):
tf = CursesThreadFrame(s.c, s.window, 0, len(s.children)) tf = CursesThreadFrame(s.c, s.window, 0, s.location)
s.location += 1
s.children.append(tf) s.children.append(tf)
return tf return tf
@ -120,21 +124,32 @@ class CursesThreadFrame:
'orange': s.c.getpair(curses.COLOR_YELLOW, bg), 'orange': s.c.getpair(curses.COLOR_YELLOW, bg),
'yellow': curses.A_BOLD | s.c.getpair(curses.COLOR_YELLOW, bg), 'yellow': curses.A_BOLD | s.c.getpair(curses.COLOR_YELLOW, bg),
'pink': curses.A_BOLD | s.c.getpair(curses.COLOR_RED, bg)} 'pink': curses.A_BOLD | s.c.getpair(curses.COLOR_RED, bg)}
s.setcolor('gray') #s.setcolor('gray')
s.setcolor('black')
def setcolor(self, color): def setcolor(self, color):
self.color = self.colormap[color] self.color = self.colormap[color]
self.display()
def display(self):
self.window.addstr(self.y, self.x, '.', self.color) self.window.addstr(self.y, self.x, '.', self.color)
self.window.refresh() self.window.refresh()
def getcolor(self): def getcolor(self):
return self.color return self.color
def update(self, window, y, x):
self.window = window
self.y = y
self.x = x
self.display()
def setthread(self, newthread): def setthread(self, newthread):
if newthread: self.setcolor('black')
self.setcolor('gray') #if newthread:
else: # self.setcolor('gray')
self.setcolor('black') #else:
# self.setcolor('black')
class InputHandler: class InputHandler:
def __init__(s, util): def __init__(s, util):
@ -293,7 +308,7 @@ class Blinkenlights(BlinkenBase, UIBase):
return s.af[accountname] return s.af[accountname]
# New one. # New one.
s.af[accountname] = CursesAccountFrame(s.c) s.af[accountname] = CursesAccountFrame(s.c, accountname)
#s.iolock.acquire() #s.iolock.acquire()
s.c.reset() s.c.reset()
s.setupwindows(dolock = 0) s.setupwindows(dolock = 0)

View File

@ -55,8 +55,9 @@ class UIBase:
"""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(threading.currentThread()):
raise ValueError, "Thread already registered (old %s, new %s)" % \ raise ValueError, "Thread %s already registered (old %s, new %s)" %\
(s.getthreadaccount(s), account) (threading.currentThread().getName(),
s.getthreadaccount(s), account)
s.threadaccounts[threading.currentThread()] = account s.threadaccounts[threading.currentThread()] = account
def unregisterthread(s, thr): def unregisterthread(s, thr):
@ -69,7 +70,7 @@ class UIBase:
thr = threading.currentThread() thr = threading.currentThread()
if s.threadaccounts.has_key(thr): if s.threadaccounts.has_key(thr):
return s.threadaccounts[thr] return s.threadaccounts[thr]
return None return '*Control'
def debug(s, debugtype, msg): def debug(s, debugtype, msg):
thisthread = threading.currentThread() thisthread = threading.currentThread()