github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/storage/sst_writer.go (about) 1 // Copyright 2019 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package storage 12 13 import ( 14 "bytes" 15 "io" 16 17 "github.com/cockroachdb/cockroach/pkg/roachpb" 18 "github.com/cockroachdb/errors" 19 "github.com/cockroachdb/pebble/sstable" 20 ) 21 22 // SSTWriter writes SSTables. 23 type SSTWriter struct { 24 fw *sstable.Writer 25 f writeCloseSyncer 26 // DataSize tracks the total key and value bytes added so far. 27 DataSize int64 28 scratch []byte 29 } 30 31 // writeCloseSyncer interface copied from pebble.sstable. 32 type writeCloseSyncer interface { 33 io.WriteCloser 34 Sync() error 35 } 36 37 // MakeBackupSSTWriter creates a new SSTWriter tailored for backup SSTs. These 38 // SSTs have bloom filters disabled and format set to LevelDB. 39 func MakeBackupSSTWriter(f writeCloseSyncer) SSTWriter { 40 opts := DefaultPebbleOptions().MakeWriterOptions(0) 41 opts.TableFormat = sstable.TableFormatLevelDB 42 // Disable bloom filters to produce SSTs matching those from 43 // RocksDBSstFileWriter. 44 opts.FilterPolicy = nil 45 opts.MergerName = "nullptr" 46 sst := sstable.NewWriter(f, opts) 47 return SSTWriter{fw: sst, f: f} 48 } 49 50 // MakeIngestionSSTWriter creates a new SSTWriter tailored for ingestion SSTs. 51 // These SSTs have bloom filters enabled (as set in DefaultPebbleOptions) and 52 // format set to RocksDBv2. 53 func MakeIngestionSSTWriter(f writeCloseSyncer) SSTWriter { 54 opts := DefaultPebbleOptions().MakeWriterOptions(0) 55 opts.TableFormat = sstable.TableFormatRocksDBv2 56 opts.MergerName = "nullptr" 57 sst := sstable.NewWriter(f, opts) 58 return SSTWriter{fw: sst, f: f} 59 } 60 61 // Finish finalizes the writer and returns the constructed file's contents, 62 // since the last call to Truncate (if any). At least one kv entry must have been added. 63 func (fw *SSTWriter) Finish() error { 64 if fw.fw == nil { 65 return errors.New("cannot call Finish on a closed writer") 66 } 67 if err := fw.fw.Close(); err != nil { 68 return err 69 } 70 fw.fw = nil 71 return nil 72 } 73 74 // ClearRange implements the Writer interface. 75 func (fw *SSTWriter) ClearRange(start, end MVCCKey) error { 76 if fw.fw == nil { 77 return errors.New("cannot call ClearRange on a closed writer") 78 } 79 fw.DataSize += int64(len(start.Key)) + int64(len(end.Key)) 80 fw.scratch = EncodeKeyToBuf(fw.scratch[:0], start) 81 return fw.fw.DeleteRange(fw.scratch, EncodeKey(end)) 82 } 83 84 // Put puts a kv entry into the sstable being built. An error is returned if it 85 // is not greater than any previously added entry (according to the comparator 86 // configured during writer creation). `Close` cannot have been called. 87 func (fw *SSTWriter) Put(key MVCCKey, value []byte) error { 88 if fw.fw == nil { 89 return errors.New("cannot call Put on a closed writer") 90 } 91 fw.DataSize += int64(len(key.Key)) + int64(len(value)) 92 fw.scratch = EncodeKeyToBuf(fw.scratch[:0], key) 93 return fw.fw.Set(fw.scratch, value) 94 } 95 96 // ApplyBatchRepr implements the Writer interface. 97 func (fw *SSTWriter) ApplyBatchRepr(repr []byte, sync bool) error { 98 panic("unimplemented") 99 } 100 101 // Clear implements the Writer interface. 102 func (fw *SSTWriter) Clear(key MVCCKey) error { 103 if fw.fw == nil { 104 return errors.New("cannot call Clear on a closed writer") 105 } 106 fw.scratch = EncodeKeyToBuf(fw.scratch[:0], key) 107 fw.DataSize += int64(len(key.Key)) 108 return fw.fw.Delete(fw.scratch) 109 } 110 111 // SingleClear implements the Writer interface. 112 func (fw *SSTWriter) SingleClear(key MVCCKey) error { 113 panic("unimplemented") 114 } 115 116 // ClearIterRange implements the Writer interface. 117 func (fw *SSTWriter) ClearIterRange(iter Iterator, start, end roachpb.Key) error { 118 if fw.fw == nil { 119 return errors.New("cannot call ClearIterRange on a closed writer") 120 } 121 122 // Set an upper bound on the iterator. This is okay because all calls to 123 // ClearIterRange are with throwaway iterators, so there should be no new 124 // side effects. 125 iter.SetUpperBound(end) 126 iter.SeekGE(MakeMVCCMetadataKey(start)) 127 128 valid, err := iter.Valid() 129 for valid && err == nil { 130 key := iter.UnsafeKey() 131 fw.scratch = EncodeKeyToBuf(fw.scratch[:0], key) 132 fw.DataSize += int64(len(key.Key)) 133 if err := fw.fw.Delete(fw.scratch); err != nil { 134 return err 135 } 136 137 iter.Next() 138 valid, err = iter.Valid() 139 } 140 return err 141 } 142 143 // Merge implements the Writer interface. 144 func (fw *SSTWriter) Merge(key MVCCKey, value []byte) error { 145 if fw.fw == nil { 146 return errors.New("cannot call Merge on a closed writer") 147 } 148 fw.DataSize += int64(len(key.Key)) + int64(len(value)) 149 fw.scratch = EncodeKeyToBuf(fw.scratch[:0], key) 150 return fw.fw.Merge(fw.scratch, value) 151 } 152 153 // LogData implements the Writer interface. 154 func (fw *SSTWriter) LogData(data []byte) error { 155 // No-op. 156 return nil 157 } 158 159 // LogLogicalOp implements the Writer interface. 160 func (fw *SSTWriter) LogLogicalOp(op MVCCLogicalOpType, details MVCCLogicalOpDetails) { 161 // No-op. 162 } 163 164 // Close finishes and frees memory and other resources. Close is idempotent. 165 func (fw *SSTWriter) Close() { 166 if fw.fw == nil { 167 return 168 } 169 // pebble.Writer *does* return interesting errors from Close... but normally 170 // we already called its Close() in Finish() and we no-op here. Thus the only 171 // time we expect to be here is in a deferred Close(), in which case the caller 172 // probably is already returning some other error, so returning one from this 173 // method just makes for messy defers. 174 _ = fw.fw.Close() 175 fw.fw = nil 176 } 177 178 // MemFile is a file-like struct that buffers all data written to it in memory. 179 // Implements the writeCloseSyncer interface and is intended for use with 180 // SSTWriter. 181 type MemFile struct { 182 bytes.Buffer 183 } 184 185 // Close implements the writeCloseSyncer interface. 186 func (*MemFile) Close() error { 187 return nil 188 } 189 190 // Sync implements the writeCloseSyncer interface. 191 func (*MemFile) Sync() error { 192 return nil 193 } 194 195 // Data returns the in-memory buffer behind this MemFile. 196 func (f *MemFile) Data() []byte { 197 return f.Bytes() 198 }