github.com/cockroachdb/pebble@v1.1.2/internal/base/merger.go (about) 1 // Copyright 2018 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 base 6 7 import "io" 8 9 // Merge creates a ValueMerger for the specified key initialized with the value 10 // of one merge operand. 11 type Merge func(key, value []byte) (ValueMerger, error) 12 13 // ValueMerger receives merge operands one by one. The operand received is either 14 // newer or older than all operands received so far as indicated by the function 15 // names, `MergeNewer()` and `MergeOlder()`. Once all operands have been received, 16 // the client will invoke `Finish()` to obtain the final result. The order of 17 // a merge is not changed after the first call to `MergeNewer()` or 18 // `MergeOlder()`, i.e. the same method is used to submit all operands. 19 // 20 // The implementation may choose to merge values into the result immediately upon 21 // receiving each operand, or buffer operands until Finish() is called. For example, 22 // buffering may be useful to avoid (de)serializing partial merge results. 23 // 24 // The merge operation must be associative. That is, for the values A, B, C: 25 // 26 // Merge(A).MergeOlder(B).MergeOlder(C) == Merge(C).MergeNewer(B).MergeNewer(A) 27 // 28 // Examples of merge operators are integer addition, list append, and string 29 // concatenation. 30 type ValueMerger interface { 31 // MergeNewer adds an operand that is newer than all existing operands. 32 // The caller retains ownership of value. 33 // 34 // If an error is returned the merge is aborted and no other methods must 35 // be called. 36 MergeNewer(value []byte) error 37 38 // MergeOlder adds an operand that is older than all existing operands. 39 // The caller retains ownership of value. 40 // 41 // If an error is returned the merge is aborted and no other methods must 42 // be called. 43 MergeOlder(value []byte) error 44 45 // Finish does any final processing of the added operands and returns a 46 // result. The caller can assume the returned byte slice will not be mutated. 47 // 48 // Finish must be the last function called on the ValueMerger. The caller 49 // must not call any other ValueMerger functions after calling Finish. 50 // 51 // If `includesBase` is true, the oldest merge operand was part of the 52 // merge. This will always be the true during normal iteration, but may be 53 // false during compaction when only a subset of operands may be 54 // available. Note that `includesBase` is set to true conservatively: a false 55 // value means that we could not definitely determine that the base merge 56 // operand was included. 57 // 58 // If a Closer is returned, the returned slice will remain valid until it is 59 // closed. The caller must arrange for the closer to be eventually closed. 60 Finish(includesBase bool) ([]byte, io.Closer, error) 61 } 62 63 // DeletableValueMerger is an extension to ValueMerger which allows indicating that the 64 // result of a merge operation is non-existent. Such non-existent entries will eventually 65 // be deleted during compaction. Note that during compaction, non-existence of the result 66 // of a merge means that the merge operands will not result in any record being output. 67 // This is not the same as transforming the merge operands into a deletion tombstone, as 68 // older merge operands will still be visible during iteration. Deletion of the merge operands 69 // in this way is akin to the way a SingleDelete+Set combine into non-existence while leaving 70 // older records for the same key unaffected. 71 type DeletableValueMerger interface { 72 ValueMerger 73 74 // DeletableFinish enables a value merger to indicate that the result of a merge operation 75 // is non-existent. See Finish for a description of includesBase. 76 DeletableFinish(includesBase bool) (value []byte, delete bool, closer io.Closer, err error) 77 } 78 79 // Merger defines an associative merge operation. The merge operation merges 80 // two or more values for a single key. A merge operation is requested by 81 // writing a value using {Batch,DB}.Merge(). The value at that key is merged 82 // with any existing value. It is valid to Set a value at a key and then Merge 83 // a new value. Similar to non-merged values, a merged value can be deleted by 84 // either Delete or DeleteRange. 85 // 86 // The merge operation is invoked when a merge value is encountered during a 87 // read, either during a compaction or during iteration. 88 type Merger struct { 89 Merge Merge 90 91 // Name is the name of the merger. 92 // 93 // Pebble stores the merger name on disk, and opening a database with a 94 // different merger from the one it was created with will result in an error. 95 Name string 96 } 97 98 // AppendValueMerger concatenates merge operands in order from oldest to newest. 99 type AppendValueMerger struct { 100 buf []byte 101 } 102 103 // MergeNewer appends value to the result. 104 func (a *AppendValueMerger) MergeNewer(value []byte) error { 105 a.buf = append(a.buf, value...) 106 return nil 107 } 108 109 // MergeOlder prepends value to the result, which involves allocating a new buffer. 110 func (a *AppendValueMerger) MergeOlder(value []byte) error { 111 buf := make([]byte, len(a.buf)+len(value)) 112 copy(buf, value) 113 copy(buf[len(value):], a.buf) 114 a.buf = buf 115 return nil 116 } 117 118 // Finish returns the buffer that was constructed on-demand in `Merge{OlderNewer}()` calls. 119 func (a *AppendValueMerger) Finish(includesBase bool) ([]byte, io.Closer, error) { 120 return a.buf, nil, nil 121 } 122 123 // DefaultMerger is the default implementation of the Merger interface. It 124 // concatenates the two values to merge. 125 var DefaultMerger = &Merger{ 126 Merge: func(key, value []byte) (ValueMerger, error) { 127 res := &AppendValueMerger{} 128 res.buf = append(res.buf, value...) 129 return res, nil 130 }, 131 132 Name: "pebble.concatenate", 133 }