Commit fbde45ad authored by Jim Fulton's avatar Jim Fulton

On systems where the fsync system call is available, we now call

fsync when commiting transactions to make sure that transaction
data are written to physical storage immediately. There is circumstantial
evidence that database corruption has been caused due to problems with
delayed write of data after Zope has flushed transaction data.

Added logic to avoid writing empty transactions. It's imaginable that
some future application might want to write empty transactions to
capture transaction meta data. If this ever becomes an issue, then
this feature would have to be made optional.
parent 8bff3c4e
...@@ -184,7 +184,7 @@ ...@@ -184,7 +184,7 @@
# may have a back pointer to a version record or to a non-version # may have a back pointer to a version record or to a non-version
# record. # record.
# #
__version__='$Revision: 1.32 $'[11:-2] __version__='$Revision: 1.33 $'[11:-2]
import struct, time, os, bpthread, string, base64, sys import struct, time, os, bpthread, string, base64, sys
from struct import pack, unpack from struct import pack, unpack
...@@ -198,6 +198,9 @@ register_subsystem('ZODB FS') ...@@ -198,6 +198,9 @@ register_subsystem('ZODB FS')
import BaseStorage import BaseStorage
from cPickle import Pickler, Unpickler from cPickle import Pickler, Unpickler
try: from posix import fsync
except: fsync=None
z64='\0'*8 z64='\0'*8
def warn(message, *data): def warn(message, *data):
...@@ -667,10 +670,11 @@ class FileStorage(BaseStorage.BaseStorage): ...@@ -667,10 +670,11 @@ class FileStorage(BaseStorage.BaseStorage):
self._thl=23+len(u)+len(d)+len(e) self._thl=23+len(u)+len(d)+len(e)
def _finish(self, tid, u, d, e): def _finish(self, tid, u, d, e):
file=self._file
write=file.write
tfile=self._tfile tfile=self._tfile
dlen=tfile.tell() dlen=tfile.tell()
if not dlen: return # No data in this trans
file=self._file
write=file.write
tfile.seek(0) tfile.seek(0)
id=self._serial id=self._serial
user, desc, ext = self._ude user, desc, ext = self._ude
...@@ -701,6 +705,10 @@ class FileStorage(BaseStorage.BaseStorage): ...@@ -701,6 +705,10 @@ class FileStorage(BaseStorage.BaseStorage):
file.seek(pos+16) file.seek(pos+16)
write(' ') write(' ')
file.flush() file.flush()
if fsync is not None:
fsync(file.fileno())
except: except:
# Hm, an error occured writing out the data. Maybe the # Hm, an error occured writing out the data. Maybe the
# disk is full. We don't want any turd at the end. # disk is full. We don't want any turd at the end.
...@@ -713,6 +721,7 @@ class FileStorage(BaseStorage.BaseStorage): ...@@ -713,6 +721,7 @@ class FileStorage(BaseStorage.BaseStorage):
self._vindex.update(self._tvindex) self._vindex.update(self._tvindex)
def undo(self, transaction_id): def undo(self, transaction_id):
self._lock_acquire() self._lock_acquire()
try: try:
......
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