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  }