mirror of
https://git.code.sf.net/p/archivemail/code
synced 2024-12-22 15:56:27 +00:00
Append to the archive, and don't use rename()
This is WIP to prepare locking for the archive. Since we no longer copy the whole archive before appending, archiving should also be faster.
This commit is contained in:
parent
37f96c1c84
commit
df680c19be
1 changed files with 20 additions and 40 deletions
|
@ -519,75 +519,55 @@ class RetainMbox(Mbox):
|
||||||
class ArchiveMbox(Mbox):
|
class ArchiveMbox(Mbox):
|
||||||
"""Class for holding messages that will be archived from the original
|
"""Class for holding messages that will be archived from the original
|
||||||
mailbox (ie. the messages that are considered 'old'). Extends the 'Mbox'
|
mailbox (ie. the messages that are considered 'old'). Extends the 'Mbox'
|
||||||
class. This 'mbox' file starts off as a temporary file, copied from any
|
class. This 'mbox' file starts off as a temporary file, and will eventually
|
||||||
pre-existing archive. It will eventually overwrite the original archive
|
be appended to the original archive mailbox if everything is OK.
|
||||||
mailbox if everything is OK.
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
__final_name = None
|
__final_name = None
|
||||||
|
|
||||||
def __init__(self, final_name):
|
def __init__(self, final_name):
|
||||||
"""Constructor -- copy any pre-existing compressed archive to a
|
"""Constructor -- create a temporary archive.
|
||||||
temporary file which we use as the new 'mbox' archive for this
|
|
||||||
mailbox.
|
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
final_name -- the final name for this archive mailbox. This function
|
final_name -- the final name for this archive mailbox. The temporary
|
||||||
will check to see if the filename already exists, and
|
archive will be appended to this file when we call
|
||||||
copy it to a temporary file if it does. It will also
|
finalise()
|
||||||
rename itself to this name when we call finalise()
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
assert(final_name)
|
assert(final_name)
|
||||||
if options.no_compress:
|
if options.no_compress:
|
||||||
self.__init_uncompressed(final_name)
|
self.__init_uncompressed()
|
||||||
else:
|
else:
|
||||||
self.__init_compressed(final_name)
|
self.__init_compressed()
|
||||||
self.__final_name = final_name
|
self.__final_name = final_name
|
||||||
|
|
||||||
def __init_uncompressed(self, final_name):
|
def __init_uncompressed(self):
|
||||||
"""Used internally by __init__ when archives are uncompressed"""
|
"""Used internally by __init__ when archives are uncompressed"""
|
||||||
assert(final_name)
|
|
||||||
temp_name = tempfile.mkstemp("archive")[1]
|
temp_name = tempfile.mkstemp("archive")[1]
|
||||||
if os.path.isfile(final_name):
|
|
||||||
vprint("file already exists that is named: %s" % final_name)
|
|
||||||
shutil.copy2(final_name, temp_name)
|
|
||||||
_stale.archive = temp_name
|
_stale.archive = temp_name
|
||||||
self.mbox_file = open(temp_name, "a")
|
self.mbox_file = open(temp_name, "w")
|
||||||
self.mbox_file_name = temp_name
|
self.mbox_file_name = temp_name
|
||||||
|
|
||||||
def __init_compressed(self, final_name):
|
def __init_compressed(self):
|
||||||
"""Used internally by __init__ when archives are compressed"""
|
"""Used internally by __init__ when archives are compressed"""
|
||||||
assert(final_name)
|
|
||||||
compressed_filename = final_name + ".gz"
|
|
||||||
temp_name = tempfile.mkstemp("archive.gz")[1]
|
temp_name = tempfile.mkstemp("archive.gz")[1]
|
||||||
if os.path.isfile(compressed_filename):
|
|
||||||
vprint("file already exists that is named: %s" % \
|
|
||||||
compressed_filename)
|
|
||||||
shutil.copy2(compressed_filename, temp_name)
|
|
||||||
_stale.archive = temp_name
|
_stale.archive = temp_name
|
||||||
self.mbox_file = gzip.GzipFile(temp_name, "a")
|
self.mbox_file = gzip.GzipFile(temp_name, "w")
|
||||||
self.mbox_file_name = temp_name
|
self.mbox_file_name = temp_name
|
||||||
|
|
||||||
def finalise(self):
|
def finalise(self):
|
||||||
"""Close the archive and rename this archive temporary file to the
|
"""Append the temporary archive to the final archive, and delete it
|
||||||
final archive filename, overwriting any pre-existing archive if it
|
afterwards."""
|
||||||
exists.
|
|
||||||
|
|
||||||
"""
|
|
||||||
assert(self.__final_name)
|
assert(self.__final_name)
|
||||||
self.close()
|
self.close()
|
||||||
|
mbox_file = open(self.mbox_file_name, "r")
|
||||||
final_name = self.__final_name
|
final_name = self.__final_name
|
||||||
if not options.no_compress:
|
if not options.no_compress:
|
||||||
final_name = final_name + ".gz"
|
final_name = final_name + ".gz"
|
||||||
vprint("renaming '%s' to '%s'" % (self.mbox_file_name,
|
vprint("writing back '%s' to '%s'" % (self.mbox_file_name, final_name))
|
||||||
final_name))
|
final_archive = open(final_name, "a")
|
||||||
try:
|
shutil.copyfileobj(mbox_file, final_archive)
|
||||||
os.rename(self.mbox_file_name, final_name)
|
final_archive.close()
|
||||||
except OSError:
|
Mbox.remove(self)
|
||||||
# file might be on a different filesystem -- move it manually
|
|
||||||
shutil.copy2(self.mbox_file_name, final_name)
|
|
||||||
os.remove(self.mbox_file_name)
|
|
||||||
_stale.archive = None
|
_stale.archive = None
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue