diff --git a/wal.go b/wal.go index ab5eac8..8735995 100644 --- a/wal.go +++ b/wal.go @@ -915,3 +915,27 @@ func (l *Log) Sync() error { } return l.sfile.Sync() } + +// Clear empties the log, removing all entries and resetting +// the index back to its default value +func (l *Log) Clear() error { + l.mu.Lock() + defer l.mu.Unlock() + + // Clean up segment files + for _, segment := range l.segments { + if err := os.Remove(segment.path); err != nil { + return err + } + } + + // Clear most state + l.segments = []*segment{} + l.sfile = nil + l.firstIndex = 1 + l.lastIndex = 0 + l.clearCache() + + // Load the log as if it were new again + return l.load() +} diff --git a/wal_test.go b/wal_test.go index b23a002..dabafa1 100644 --- a/wal_test.go +++ b/wal_test.go @@ -837,6 +837,47 @@ func TestSimpleTruncateBack(t *testing.T) { } +func TestClear(t *testing.T) { + os.RemoveAll("testlog") + + l, err := Open("testlog", &Options{ + NoSync: true, + }) + if err != nil { + t.Fatal(err) + } + defer l.Close() + + // Write some entries + for i := 1; i < 50; i++ { + err := l.Write(uint64(i), []byte(dataStr(uint64(i)))) + if err != nil { + t.Fatal(err) + } + } + + // Clear the log + if err := l.Clear(); err != nil { + t.Fatal(err) + } + + // Validate some log information + if i, err := l.FirstIndex(); err != nil || i != 0 { + t.Fatal(fmt.Errorf("expected first index %d but got %d (error: %w)", 0, i, err)) + } + if i, err := l.LastIndex(); err != nil || i != 0 { + t.Fatal(fmt.Errorf("expected last index %d but got %d (error: %w)", 0, i, err)) + } + + // Ensure we can continue to write after a clear + for i := 1; i < 50; i++ { + err := l.Write(uint64(i), []byte(dataStr(uint64(i)))) + if err != nil { + t.Fatal(err) + } + } +} + func TestConcurrency(t *testing.T) { os.RemoveAll("testlog")