github.com/cockroachdb/pebble@v1.1.1-0.20240513155919-3622ade60459/cmd/pebble/db.go (about) 1 // Copyright 2019 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 main 6 7 import ( 8 "log" 9 10 "github.com/cockroachdb/pebble" 11 "github.com/cockroachdb/pebble/bloom" 12 "github.com/cockroachdb/pebble/internal/bytealloc" 13 "github.com/cockroachdb/pebble/objstorage/remote" 14 "github.com/cockroachdb/pebble/vfs" 15 ) 16 17 // DB specifies the minimal interfaces that need to be implemented to support 18 // the pebble command. 19 type DB interface { 20 NewIter(*pebble.IterOptions) iterator 21 NewBatch() batch 22 Scan(iter iterator, key []byte, count int64, reverse bool) error 23 Metrics() *pebble.Metrics 24 Flush() error 25 } 26 27 type iterator interface { 28 SeekLT(key []byte) bool 29 SeekGE(key []byte) bool 30 Valid() bool 31 Key() []byte 32 Value() []byte 33 First() bool 34 Next() bool 35 Last() bool 36 Prev() bool 37 Close() error 38 } 39 40 type batch interface { 41 Close() error 42 Commit(opts *pebble.WriteOptions) error 43 Set(key, value []byte, opts *pebble.WriteOptions) error 44 Delete(key []byte, opts *pebble.WriteOptions) error 45 LogData(data []byte, opts *pebble.WriteOptions) error 46 } 47 48 // Adapters for Pebble. Since the interfaces above are based on Pebble's 49 // interfaces, it can simply forward calls for everything. 50 type pebbleDB struct { 51 d *pebble.DB 52 ballast []byte 53 } 54 55 func newPebbleDB(dir string) DB { 56 cache := pebble.NewCache(cacheSize) 57 defer cache.Unref() 58 opts := &pebble.Options{ 59 Cache: cache, 60 Comparer: mvccComparer, 61 DisableWAL: disableWAL, 62 FormatMajorVersion: pebble.FormatNewest, 63 L0CompactionThreshold: 2, 64 L0StopWritesThreshold: 1000, 65 LBaseMaxBytes: 64 << 20, // 64 MB 66 Levels: make([]pebble.LevelOptions, 7), 67 MaxOpenFiles: 16384, 68 MemTableSize: 64 << 20, 69 MemTableStopWritesThreshold: 4, 70 Merger: &pebble.Merger{ 71 Name: "cockroach_merge_operator", 72 }, 73 MaxConcurrentCompactions: func() int { 74 return 3 75 }, 76 } 77 78 for i := 0; i < len(opts.Levels); i++ { 79 l := &opts.Levels[i] 80 l.BlockSize = 32 << 10 // 32 KB 81 l.IndexBlockSize = 256 << 10 // 256 KB 82 l.FilterPolicy = bloom.FilterPolicy(10) 83 l.FilterType = pebble.TableFilter 84 if i > 0 { 85 l.TargetFileSize = opts.Levels[i-1].TargetFileSize * 2 86 } 87 l.EnsureDefaults() 88 } 89 opts.Levels[6].FilterPolicy = nil 90 opts.FlushSplitBytes = opts.Levels[0].TargetFileSize 91 92 opts.EnsureDefaults() 93 94 if verbose { 95 lel := pebble.MakeLoggingEventListener(nil) 96 opts.EventListener = &lel 97 opts.EventListener.TableDeleted = nil 98 opts.EventListener.TableIngested = nil 99 opts.EventListener.WALCreated = nil 100 opts.EventListener.WALDeleted = nil 101 } 102 103 if pathToLocalSharedStorage != "" { 104 opts.Experimental.RemoteStorage = remote.MakeSimpleFactory(map[remote.Locator]remote.Storage{ 105 // Store all shared objects on local disk, for convenience. 106 "": remote.NewLocalFS(pathToLocalSharedStorage, vfs.Default), 107 }) 108 opts.Experimental.CreateOnShared = remote.CreateOnSharedAll 109 if secondaryCacheSize != 0 { 110 opts.Experimental.SecondaryCacheSizeBytes = secondaryCacheSize 111 } 112 } 113 114 p, err := pebble.Open(dir, opts) 115 if err != nil { 116 log.Fatal(err) 117 } 118 if pathToLocalSharedStorage != "" { 119 if err := p.SetCreatorID(1); err != nil { 120 log.Fatal(err) 121 } 122 } 123 return pebbleDB{ 124 d: p, 125 ballast: make([]byte, 1<<30), 126 } 127 } 128 129 func (p pebbleDB) Flush() error { 130 return p.d.Flush() 131 } 132 133 func (p pebbleDB) NewIter(opts *pebble.IterOptions) iterator { 134 iter, _ := p.d.NewIter(opts) 135 return iter 136 } 137 138 func (p pebbleDB) NewBatch() batch { 139 return p.d.NewBatch() 140 } 141 142 func (p pebbleDB) Scan(iter iterator, key []byte, count int64, reverse bool) error { 143 var data bytealloc.A 144 if reverse { 145 for i, valid := 0, iter.SeekLT(key); valid; valid = iter.Prev() { 146 data, _ = data.Copy(iter.Key()) 147 data, _ = data.Copy(iter.Value()) 148 i++ 149 if i >= int(count) { 150 break 151 } 152 } 153 } else { 154 for i, valid := 0, iter.SeekGE(key); valid; valid = iter.Next() { 155 data, _ = data.Copy(iter.Key()) 156 data, _ = data.Copy(iter.Value()) 157 i++ 158 if i >= int(count) { 159 break 160 } 161 } 162 } 163 return nil 164 } 165 166 func (p pebbleDB) Metrics() *pebble.Metrics { 167 return p.d.Metrics() 168 }