Reuse LocalStatus() folders rather than recreate instances

If we ask twice for a LocalStatusFolder via getfolder(), we would
get a newly created instance each time. This can lead to problems,
as e.g. write locks protecting files only work within the same Folder
instance. Make it so, that we cache all Folder instances that we have
asked for and hand back the existing one if we ask again for it,
rather than recreate a new instance.

Also, make getfolders() a noop for LocalStatus. We attempted to
derive the foldername from the name of the LocalStatusfile. However,
this is not really possible, as we do file name mangling
(".$" -> "dot", "/" -> ".") and there is no way to get the original folder
name from the LocalStatus file name anyway.

This commit could potentially solve the "file not found" errors, that people
have been seeing with their LocalStatusCache files. If we have 2
instances of a LocalStatusFolder pointing to the same file, our locking
system would not work.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
This commit is contained in:
Sebastian Spaeth 2012-09-01 01:02:20 +02:00
parent a1dc76ae91
commit 1b54b85f20
2 changed files with 15 additions and 12 deletions

View File

@ -295,7 +295,6 @@ class SyncableAccount(Account):
# folder delimiter etc) # folder delimiter etc)
remoterepos.getfolders() remoterepos.getfolders()
localrepos.getfolders() localrepos.getfolders()
statusrepos.getfolders()
remoterepos.sync_folder_structure(localrepos, statusrepos) remoterepos.sync_folder_structure(localrepos, statusrepos)
# replicate the folderstructure between REMOTE to LOCAL # replicate the folderstructure between REMOTE to LOCAL

View File

@ -43,8 +43,8 @@ class LocalStatusRepository(BaseRepository):
if not os.path.exists(self.root): if not os.path.exists(self.root):
os.mkdir(self.root, 0o700) os.mkdir(self.root, 0o700)
# self._folders is a list of LocalStatusFolders() # self._folders is a dict of name:LocalStatusFolders()
self._folders = None self._folders = {}
def getsep(self): def getsep(self):
return '.' return '.'
@ -83,19 +83,23 @@ class LocalStatusRepository(BaseRepository):
def getfolder(self, foldername): def getfolder(self, foldername):
"""Return the Folder() object for a foldername""" """Return the Folder() object for a foldername"""
return self.LocalStatusFolderClass(foldername, self) if foldername in self._folders:
return self._folders[foldername]
folder = self.LocalStatusFolderClass(foldername, self)
self._folders[foldername] = folder
return folder
def getfolders(self): def getfolders(self):
"""Returns a list of all cached folders.""" """Returns a list of all cached folders.
if self._folders != None:
return self._folders
self._folders = [] Does nothing for this backend. We mangle the folder file names
for folder in os.listdir(self.root): (see getfolderfilename) so we can not derive folder names from
self._folders.append(self.getfolder(folder)) the file names that we have available. TODO: need to store a
return self._folders list of folder names somehow?"""
pass
def forgetfolders(self): def forgetfolders(self):
"""Forgets the cached list of folders, if any. Useful to run """Forgets the cached list of folders, if any. Useful to run
after a sync run.""" after a sync run."""
self._folders = None self._folders = {}