History

fix: wal tail could be corrupted

HuangYi committed 3 years ago

Commit 55001931 parent 4b09f951 file · +23 −18Browse files

Unified · Split

wal.go+23−18
@@ -97,18 +97,20 @@ type Options struct { · 96 unmodified lines
97 // Perms represents the datafiles modes and permission bits97 // Perms represents the datafiles modes and permission bits
98 DirPerms os.FileMode98 DirPerms os.FileMode
99 FilePerms os.FileMode99 FilePerms os.FileMode
100 // RecoverCorruptedTail will attempt to recover a corrupted tail in the last segment automatically.
101 RecoverCorruptedTail bool
100}102}
101 103
102// DefaultOptions for Open().104// DefaultOptions for Open().
103var DefaultOptions = &Options{105var DefaultOptions = &Options{
104 NoSync: false, // Fsync after every write106 NoSync: false, // Fsync after every write
105 SegmentSize: 20971520, // 20 MB log segment files107 SegmentSize: 20971520, // 20 MB log segment files.
106 LogFormat: Binary, // Binary format is small and fast108 LogFormat: Binary, // Binary format is small and fast.
107 SegmentCacheSize: 2, // Number of cached in-memory segments109 SegmentCacheSize: 2, // Number of cached in-memory segments
108 NoCopy: false, // Make a new copy of data for every Read call110 NoCopy: false, // Make a new copy of data for every Read call.
109 AllowEmpty: false, // Do not allow empty log. 1+ entries required111 DirPerms: 0750, // Permissions for the created directories
110 DirPerms: 0750, // Permissions for the created directories112 FilePerms: 0640, // Permissions for the created data files
111 FilePerms: 0640, // Permissions for the created data files113 RecoverCorruptedTail: false, // Don't recover corrupted tail.
112}114}
113 115
114// Log represents a write ahead log116// Log represents a write ahead log
@@ -282,15 +284,15 @@ func (l *Log) load() error { · 167 unmodified lines
282 l.firstIndex = l.segments[0].index284 l.firstIndex = l.segments[0].index
283 // Open the last segment for appending285 // Open the last segment for appending
284 lseg := l.segments[len(l.segments)-1]286 lseg := l.segments[len(l.segments)-1]
285 l.sfile, err = os.OpenFile(lseg.path, os.O_WRONLY, l.opts.FilePerms)287 // Load the last segment entries
286 if err != nil {288 if err := l.loadSegmentEntries(lseg, l.opts.RecoverCorruptedTail); err != nil {
287 return err289 return err
288 }290 }
289 if _, err := l.sfile.Seek(0, 2); err != nil {291 l.sfile, err = os.OpenFile(lseg.path, os.O_WRONLY, l.opts.FilePerms)
292 if err != nil {
290 return err293 return err
291 }294 }
292 // Load the last segment entries295 if _, err := l.sfile.Seek(int64(len(lseg.ebuf)), 0); err != nil {
293 if err := l.loadSegmentEntries(lseg); err != nil {
294 return err296 return err
295 }297 }
296 l.lastIndex = lseg.index + uint64(len(lseg.epos)) - 1298 l.lastIndex = lseg.index + uint64(len(lseg.epos)) - 1
@@ -555,7 +557,7 @@ func (l *Log) findSegment(index uint64) int { · 258 unmodified lines
555 return i - 1557 return i - 1
556}558}
557 559
558func (l *Log) loadSegmentEntries(s *segment) error {560func (l *Log) loadSegmentEntries(s *segment, ignoreCorruptedTail bool) error {
559 data, err := ioutil.ReadFile(s.path)561 data, err := ioutil.ReadFile(s.path)
560 if err != nil {562 if err != nil {
561 return err563 return err
@@ -570,6 +572,9 @@ func (l *Log) loadSegmentEntries(s *segment) error { · 8 unmodified lines
570 } else {572 } else {
571 n, err = loadNextBinaryEntry(data)573 n, err = loadNextBinaryEntry(data)
572 }574 }
575 if err == ErrCorrupt && ignoreCorruptedTail {
576 break
577 }
573 if err != nil {578 if err != nil {
574 return err579 return err
575 }580 }
@@ -577,7 +582,7 @@ func (l *Log) loadSegmentEntries(s *segment) error { · 1 unmodified line
577 epos = append(epos, bpos{pos, pos + n})582 epos = append(epos, bpos{pos, pos + n})
578 pos += n583 pos += n
579 }584 }
580 s.ebuf = ebuf585 s.ebuf = ebuf[:pos]
581 s.epos = epos586 s.epos = epos
582 return nil587 return nil
583}588}
@@ -633,7 +638,7 @@ func (l *Log) loadSegment(index uint64) (*segment, error) { · 49 unmodified lines
633 s := l.segments[idx]638 s := l.segments[idx]
634 if len(s.epos) == 0 {639 if len(s.epos) == 0 {
635 // load the entries from cache640 // load the entries from cache
636 if err := l.loadSegmentEntries(s); err != nil {641 if err := l.loadSegmentEntries(s, false); err != nil {
637 return nil, err642 return nil, err
638 }643 }
639 }644 }
@@ -850,7 +855,7 @@ func (l *Log) truncateFront(index uint64) (err error) { · 210 unmodified lines
850 return err855 return err
851 }856 }
852 // Load the last segment entries857 // Load the last segment entries
853 if err = l.loadSegmentEntries(s); err != nil {858 if err = l.loadSegmentEntries(s, false); err != nil {
854 return err859 return err
855 }860 }
856 }861 }
@@ -958,7 +963,7 @@ func (l *Log) truncateBack(index uint64) (err error) { · 101 unmodified lines
958 l.segments = append([]*segment{}, l.segments[:segIdx+1]...)963 l.segments = append([]*segment{}, l.segments[:segIdx+1]...)
959 l.lastIndex = index964 l.lastIndex = index
960 l.clearCache()965 l.clearCache()
961 if err = l.loadSegmentEntries(s); err != nil {966 if err = l.loadSegmentEntries(s, false); err != nil {
962 return err967 return err
963 }968 }
964 return nil969 return nil

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t