@@ -853,13 +853,18 @@ func (vlog *valueLog) open(db *DB, ptr valuePointer, replayFn logEntry) error {
853853 flags |= y .Sync
854854 }
855855
856+ // We cannot mmap the files upfront here. Windows does not like mmapped files to be
857+ // truncated. We might need to truncate files during a replay.
856858 if err := lf .open (vlog .fpath (fid ), flags ); err != nil {
857859 return err
858860 }
859-
860861 // This file is before the value head pointer. So, we don't need to
861862 // replay it, and can just open it in readonly mode.
862863 if fid < ptr .Fid {
864+ // Mmap the file here, we don't need to replay it.
865+ if err := lf .mmap (int64 (lf .size )); err != nil {
866+ return err
867+ }
863868 continue
864869 }
865870
@@ -888,6 +893,13 @@ func (vlog *valueLog) open(db *DB, ptr valuePointer, replayFn logEntry) error {
888893 return err
889894 }
890895 vlog .db .opt .Infof ("Replay took: %s\n " , time .Since (now ))
896+ if fid < vlog .maxFid {
897+ // This file has been replayed. It can now be mmapped.
898+ // For maxFid, the mmap would be done by the specially written code below.
899+ if err := lf .mmap (int64 (lf .size )); err != nil {
900+ return err
901+ }
902+ }
891903 }
892904
893905 // Seek to the end to start writing.
@@ -916,26 +928,23 @@ func (vlog *valueLog) open(db *DB, ptr valuePointer, replayFn logEntry) error {
916928 return nil
917929}
918930
919- func (lf * logFile ) open (filename string , flags uint32 ) error {
931+ func (lf * logFile ) open (path string , flags uint32 ) error {
920932 var err error
921- if lf .fd , err = y .OpenExistingFile (filename , flags ); err != nil {
922- return errors .Wrapf (err , "Open existing file: %q " , lf . path )
933+ if lf .fd , err = y .OpenExistingFile (path , flags ); err != nil {
934+ return y .Wrapf (err , "Error while opening file in logfile %s " , path )
923935 }
924- fstat , err := lf .fd .Stat ()
936+
937+ fi , err := lf .fd .Stat ()
925938 if err != nil {
926- return errors .Wrapf (err , "Unable to check stat for %q" , lf .path )
927- }
928- sz := fstat .Size ()
929- if sz == 0 {
930- // File is empty. We don't need to mmap it. Return.
931- return nil
939+ return errFile (err , lf .path , "Unable to run file.Stat" )
932940 }
933- y .AssertTrue (sz <= math .MaxUint32 )
941+ sz := fi .Size ()
942+ y .AssertTruef (
943+ sz <= math .MaxUint32 ,
944+ "file size: %d greater than %d" ,
945+ uint32 (sz ), uint32 (math .MaxUint32 ),
946+ )
934947 lf .size = uint32 (sz )
935- if err = lf .mmap (sz ); err != nil {
936- _ = lf .fd .Close ()
937- return errors .Wrapf (err , "Unable to map file: %q" , fstat .Name ())
938- }
939948 return nil
940949}
941950
0 commit comments