github.com/MetalBlockchain/metalgo@v1.11.9/database/batch.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  // For ease of implementation, our database's interface matches Ethereum's
     5  // database implementation. This was to allow us to use Geth code as is for the
     6  // EVM chain.
     7  
     8  package database
     9  
    10  import "slices"
    11  
    12  // Batch is a write-only database that commits changes to its host database
    13  // when Write is called. A batch cannot be used concurrently.
    14  type Batch interface {
    15  	KeyValueWriterDeleter
    16  
    17  	// Size retrieves the amount of data queued up for writing, this includes
    18  	// the keys, values, and deleted keys.
    19  	Size() int
    20  
    21  	// Write flushes any accumulated data to disk.
    22  	Write() error
    23  
    24  	// Reset resets the batch for reuse.
    25  	Reset()
    26  
    27  	// Replay replays the batch contents in the same order they were written
    28  	// to the batch.
    29  	Replay(w KeyValueWriterDeleter) error
    30  
    31  	// Inner returns a Batch writing to the inner database, if one exists. If
    32  	// this batch is already writing to the base DB, then itself should be
    33  	// returned.
    34  	Inner() Batch
    35  }
    36  
    37  // Batcher wraps the NewBatch method of a backing data store.
    38  type Batcher interface {
    39  	// NewBatch creates a write-only database that buffers changes to its host db
    40  	// until a final write is called.
    41  	NewBatch() Batch
    42  }
    43  
    44  type BatchOp struct {
    45  	Key    []byte
    46  	Value  []byte
    47  	Delete bool
    48  }
    49  
    50  type BatchOps struct {
    51  	Ops  []BatchOp
    52  	size int
    53  }
    54  
    55  func (b *BatchOps) Put(key, value []byte) error {
    56  	b.Ops = append(b.Ops, BatchOp{
    57  		Key:   slices.Clone(key),
    58  		Value: slices.Clone(value),
    59  	})
    60  	b.size += len(key) + len(value)
    61  	return nil
    62  }
    63  
    64  func (b *BatchOps) Delete(key []byte) error {
    65  	b.Ops = append(b.Ops, BatchOp{
    66  		Key:    slices.Clone(key),
    67  		Delete: true,
    68  	})
    69  	b.size += len(key)
    70  	return nil
    71  }
    72  
    73  func (b *BatchOps) Size() int {
    74  	return b.size
    75  }
    76  
    77  func (b *BatchOps) Reset() {
    78  	b.Ops = b.Ops[:0]
    79  	b.size = 0
    80  }
    81  
    82  func (b *BatchOps) Replay(w KeyValueWriterDeleter) error {
    83  	for _, op := range b.Ops {
    84  		if op.Delete {
    85  			if err := w.Delete(op.Key); err != nil {
    86  				return err
    87  			}
    88  		} else if err := w.Put(op.Key, op.Value); err != nil {
    89  			return err
    90  		}
    91  	}
    92  	return nil
    93  }