Skip to content

Commit e0493f9

Browse files
authored
Copy WAL frames through temp file to shadow (#474)
1 parent 016546a commit e0493f9

File tree

1 file changed

+41
-10
lines changed

1 file changed

+41
-10
lines changed

db.go

+41-10
Original file line numberDiff line numberDiff line change
@@ -1024,6 +1024,16 @@ func (db *DB) copyToShadowWAL(filename string) (newSize int64, err error) {
10241024
return 0, fmt.Errorf("last checksum: %w", err)
10251025
}
10261026

1027+
// Write to a temporary shadow file.
1028+
tempFilename := filename + ".tmp"
1029+
defer os.Remove(tempFilename)
1030+
1031+
f, err := internal.CreateFile(tempFilename, db.fileInfo)
1032+
if err != nil {
1033+
return 0, fmt.Errorf("create temp file: %w", err)
1034+
}
1035+
defer f.Close()
1036+
10271037
// Seek to correct position on real wal.
10281038
if _, err := r.Seek(origSize, io.SeekStart); err != nil {
10291039
return 0, fmt.Errorf("real wal seek: %w", err)
@@ -1034,7 +1044,6 @@ func (db *DB) copyToShadowWAL(filename string) (newSize int64, err error) {
10341044
// Read through WAL from last position to find the page of the last
10351045
// committed transaction.
10361046
frame := make([]byte, db.pageSize+WALFrameHeaderSize)
1037-
var buf bytes.Buffer
10381047
offset := origSize
10391048
lastCommitSize := origSize
10401049
for {
@@ -1064,32 +1073,54 @@ func (db *DB) copyToShadowWAL(filename string) (newSize int64, err error) {
10641073
break
10651074
}
10661075

1067-
// Add page to the new size of the shadow WAL.
1068-
buf.Write(frame)
1076+
// Write page to temporary WAL file.
1077+
if _, err := f.Write(frame); err != nil {
1078+
return 0, fmt.Errorf("write temp shadow wal: %w", err)
1079+
}
10691080

10701081
Tracef("%s: copy-shadow: ok %s offset=%d salt=%x %x", db.path, filename, offset, salt0, salt1)
10711082
offset += int64(len(frame))
10721083

1073-
// Flush to shadow WAL if commit record.
1084+
// Update new size if written frame was a commit record.
10741085
newDBSize := binary.BigEndian.Uint32(frame[4:])
10751086
if newDBSize != 0 {
1076-
if _, err := buf.WriteTo(w); err != nil {
1077-
return 0, fmt.Errorf("write shadow wal: %w", err)
1078-
}
1079-
buf.Reset()
10801087
lastCommitSize = offset
10811088
}
10821089
}
10831090

1084-
// Sync & close.
1091+
// If no WAL writes found, exit.
1092+
if origSize == lastCommitSize {
1093+
return origSize, nil
1094+
}
1095+
1096+
walByteN := lastCommitSize - origSize
1097+
1098+
// Move to beginning of temporary file.
1099+
if _, err := f.Seek(0, io.SeekStart); err != nil {
1100+
return 0, fmt.Errorf("temp file seek: %w", err)
1101+
}
1102+
1103+
// Copy from temporary file to shadow WAL.
1104+
if _, err := io.Copy(w, &io.LimitedReader{R: f, N: walByteN}); err != nil {
1105+
return 0, fmt.Errorf("write shadow file: %w", err)
1106+
}
1107+
1108+
// Close & remove temporary file.
1109+
if err := f.Close(); err != nil {
1110+
return 0, err
1111+
} else if err := os.Remove(tempFilename); err != nil {
1112+
return 0, err
1113+
}
1114+
1115+
// Sync & close shadow WAL.
10851116
if err := w.Sync(); err != nil {
10861117
return 0, err
10871118
} else if err := w.Close(); err != nil {
10881119
return 0, err
10891120
}
10901121

10911122
// Track total number of bytes written to WAL.
1092-
db.totalWALBytesCounter.Add(float64(lastCommitSize - origSize))
1123+
db.totalWALBytesCounter.Add(float64(walByteN))
10931124

10941125
return lastCommitSize, nil
10951126
}

0 commit comments

Comments
 (0)