github.com/petermattis/pebble@v0.0.0-20190905164901-ab51a2166067/snapshot.go (about) 1 // Copyright 2012 The LevelDB-Go and Pebble Authors. All rights reserved. Use 2 // of this source code is governed by a BSD-style license that can be found in 3 // the LICENSE file. 4 5 package pebble 6 7 // Snapshot provides a read-only point-in-time view of the DB state. 8 type Snapshot struct { 9 // The db the snapshot was created from. 10 db *DB 11 seqNum uint64 12 13 // The list the snapshot is linked into. 14 list *snapshotList 15 16 // The next/prev link for the snapshotList doubly-linked list of snapshots. 17 prev, next *Snapshot 18 } 19 20 var _ Reader = (*Snapshot)(nil) 21 22 // Get gets the value for the given key. It returns ErrNotFound if the DB does 23 // not contain the key. 24 // 25 // The caller should not modify the contents of the returned slice, but it is 26 // safe to modify the contents of the argument after Get returns. 27 func (s *Snapshot) Get(key []byte) ([]byte, error) { 28 if s.db == nil { 29 panic(ErrClosed) 30 } 31 return s.db.getInternal(key, nil /* batch */, s) 32 } 33 34 // NewIter returns an iterator that is unpositioned (Iterator.Valid() will 35 // return false). The iterator can be positioned via a call to SeekGE, 36 // SeekLT, First or Last. 37 func (s *Snapshot) NewIter(o *IterOptions) *Iterator { 38 if s.db == nil { 39 panic(ErrClosed) 40 } 41 return s.db.newIterInternal(nil /* batchIter */, nil /* batchRangeDelIter */, s, o) 42 } 43 44 // Close closes the snapshot, releasing its resources. Close must be 45 // called. Failure to do so while result in a tiny memory leak, and a large 46 // leak of resources on disk due to the entries the snapshot is preventing from 47 // being deleted. 48 func (s *Snapshot) Close() error { 49 if s.db == nil { 50 panic(ErrClosed) 51 } 52 s.db.mu.Lock() 53 s.db.mu.snapshots.remove(s) 54 s.db.mu.Unlock() 55 s.db = nil 56 return nil 57 } 58 59 type snapshotList struct { 60 root Snapshot 61 } 62 63 func (l *snapshotList) init() { 64 l.root.next = &l.root 65 l.root.prev = &l.root 66 } 67 68 func (l *snapshotList) empty() bool { 69 return l.root.next == &l.root 70 } 71 72 func (l *snapshotList) toSlice() []uint64 { 73 if l.empty() { 74 return nil 75 } 76 var results []uint64 77 for i := l.root.next; i != &l.root; i = i.next { 78 results = append(results, i.seqNum) 79 } 80 return results 81 } 82 83 func (l *snapshotList) pushBack(s *Snapshot) { 84 if s.list != nil || s.prev != nil || s.next != nil { 85 panic("pebble: snapshot list is inconsistent") 86 } 87 s.prev = l.root.prev 88 s.prev.next = s 89 s.next = &l.root 90 s.next.prev = s 91 s.list = l 92 } 93 94 func (l *snapshotList) remove(s *Snapshot) { 95 if s == &l.root { 96 panic("pebble: cannot remove snapshot list root node") 97 } 98 if s.list != l { 99 panic("pebble: snapshot list is inconsistent") 100 } 101 s.prev.next = s.next 102 s.next.prev = s.prev 103 s.next = nil // avoid memory leaks 104 s.prev = nil // avoid memory leaks 105 s.list = nil // avoid memory leaks 106 }