Commit 64fced28 authored by Tim Peters's avatar Tim Peters

FileStoragePacker: the change yesterday to speed packing by doing most

of pack in buffered mode, then switching to unbuffered mode to copy the
tail, actually broke pack completely on Windows:  we didn't close the
buffered file handle before opening the unbuffered one, and self.gc held
on to the still-open former handle.  This prevented the caller from
renaming Data.fs to Data.fs.old (a handle on Data.fs was still open).
The cure is simply to close a handle when we stop using it.
parent f09b2346
...@@ -416,6 +416,10 @@ class FileStoragePacker(FileStorageFormatter): ...@@ -416,6 +416,10 @@ class FileStoragePacker(FileStorageFormatter):
# progress after it). # progress after it).
def __init__(self, path, stop, la, lr, cla, clr, current_size): def __init__(self, path, stop, la, lr, cla, clr, current_size):
self._name = path self._name = path
# We open our own handle on the storage so that much of pack can
# proceed in parallel. It's important to close this file at every
# return point, else on Windows the caller won't be able to rename
# or remove the storage file.
self._file = open(path, "rb") self._file = open(path, "rb")
self._path = path self._path = path
self._stop = stop self._stop = stop
...@@ -481,6 +485,7 @@ class FileStoragePacker(FileStorageFormatter): ...@@ -481,6 +485,7 @@ class FileStoragePacker(FileStorageFormatter):
if ipos == opos: if ipos == opos:
# pack didn't free any data. there's no point in continuing. # pack didn't free any data. there's no point in continuing.
self._tfile.close() self._tfile.close()
self._file.close()
os.remove(self._name + ".pack") os.remove(self._name + ".pack")
return None return None
self._commit_lock_acquire() self._commit_lock_acquire()
...@@ -499,6 +504,7 @@ class FileStoragePacker(FileStorageFormatter): ...@@ -499,6 +504,7 @@ class FileStoragePacker(FileStorageFormatter):
# trailing 0 argument, and then on every platform except # trailing 0 argument, and then on every platform except
# native Windows it was observed that we could read stale # native Windows it was observed that we could read stale
# data from the tail end of the file. # data from the tail end of the file.
self._file.close() # else self.gc keeps the original alive & open
self._file = open(self._path, "rb", 0) self._file = open(self._path, "rb", 0)
self._file.seek(0, 2) self._file.seek(0, 2)
self.file_end = self._file.tell() self.file_end = self._file.tell()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment