github.com/zuoyebang/bitalostable@v1.0.1-0.20240229032404-e3b99a834294/flushable.go (about) 1 // Copyright 2020 The LevelDB-Go and Pebble and Bitalostored 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 bitalostable 6 7 import ( 8 "fmt" 9 "sync/atomic" 10 "time" 11 12 "github.com/zuoyebang/bitalostable/internal/keyspan" 13 "github.com/zuoyebang/bitalostable/internal/manual" 14 ) 15 16 // flushable defines the interface for immutable memtables. 17 type flushable interface { 18 newIter(o *IterOptions) internalIterator 19 newFlushIter(o *IterOptions, bytesFlushed *uint64) internalIterator 20 newRangeDelIter(o *IterOptions) keyspan.FragmentIterator 21 newRangeKeyIter(o *IterOptions) keyspan.FragmentIterator 22 containsRangeKeys() bool 23 // inuseBytes returns the number of inuse bytes by the flushable. 24 inuseBytes() uint64 25 // totalBytes returns the total number of bytes allocated by the flushable. 26 totalBytes() uint64 27 // readyForFlush returns true when the flushable is ready for flushing. See 28 // memTable.readyForFlush for one implementation which needs to check whether 29 // there are any outstanding write references. 30 readyForFlush() bool 31 release() 32 } 33 34 // flushableEntry wraps a flushable and adds additional metadata and 35 // functionality that is common to all flushables. 36 type flushableEntry struct { 37 flushable 38 // Channel which is closed when the flushable has been flushed. 39 flushed chan struct{} 40 // flushForced indicates whether a flush was forced on this memtable (either 41 // manual, or due to ingestion). Protected by DB.mu. 42 flushForced bool 43 // delayedFlushForcedAt indicates whether a timer has been set to force a 44 // flush on this memtable at some point in the future. Protected by DB.mu. 45 // Holds the timestamp of when the flush will be issued. 46 delayedFlushForcedAt time.Time 47 // logNum corresponds to the WAL that contains the records present in the 48 // receiver. 49 logNum FileNum 50 // logSize is the size in bytes of the associated WAL. Protected by DB.mu. 51 logSize uint64 52 // The current logSeqNum at the time the memtable was created. This is 53 // guaranteed to be less than or equal to any seqnum stored in the memtable. 54 logSeqNum uint64 55 // readerRefs tracks the read references on the flushable. The two sources of 56 // reader references are DB.mu.mem.queue and readState.memtables. The memory 57 // reserved by the flushable in the cache is released when the reader refs 58 // drop to zero. If the flushable is a memTable, when the reader refs drops 59 // to zero, the writer refs will already be zero because the memtable will 60 // have been flushed and that only occurs once the writer refs drops to zero. 61 readerRefs int32 62 // Closure to invoke to release memory accounting. 63 releaseMemAccounting func() 64 65 alloc []byte 66 } 67 68 func (e *flushableEntry) readerRef() { 69 switch v := atomic.AddInt32(&e.readerRefs, 1); { 70 case v <= 1: 71 panic(fmt.Sprintf("bitalostable: inconsistent reference count: %d", v)) 72 } 73 } 74 75 func (e *flushableEntry) readerUnref() { 76 switch v := atomic.AddInt32(&e.readerRefs, -1); { 77 case v < 0: 78 panic(fmt.Sprintf("bitalostable: inconsistent reference count: %d", v)) 79 case v == 0: 80 if e.releaseMemAccounting == nil { 81 panic("bitalostable: memtable reservation already released") 82 } 83 e.releaseMemAccounting() 84 e.releaseMemAccounting = nil 85 if e.alloc != nil { 86 manual.Free(e.alloc) 87 e.alloc = nil 88 } 89 e.release() 90 e.flushable = nil 91 } 92 } 93 94 type flushableList []*flushableEntry