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