github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/db/memdb/mem_db.go (about) 1 package memdb 2 3 import ( 4 "fmt" 5 "sort" 6 "sync" 7 8 dbm "github.com/gnolang/gno/tm2/pkg/db" 9 "github.com/gnolang/gno/tm2/pkg/db/internal" 10 "github.com/gnolang/gno/tm2/pkg/strings" 11 ) 12 13 func init() { 14 dbm.InternalRegisterDBCreator(dbm.MemDBBackend, func(name, dir string) (dbm.DB, error) { 15 return NewMemDB(), nil 16 }, false) 17 } 18 19 var _ dbm.DB = (*MemDB)(nil) 20 21 type MemDB struct { 22 mtx sync.Mutex 23 db map[string][]byte 24 } 25 26 func NewMemDB() *MemDB { 27 database := &MemDB{ 28 db: make(map[string][]byte), 29 } 30 return database 31 } 32 33 // Implements internal.AtomicSetDeleter. 34 func (db *MemDB) Mutex() *sync.Mutex { 35 return &(db.mtx) 36 } 37 38 // Implements DB. 39 func (db *MemDB) Get(key []byte) []byte { 40 db.mtx.Lock() 41 defer db.mtx.Unlock() 42 key = internal.NonNilBytes(key) 43 44 value := db.db[string(key)] 45 return value 46 } 47 48 // Implements DB. 49 func (db *MemDB) Has(key []byte) bool { 50 db.mtx.Lock() 51 defer db.mtx.Unlock() 52 key = internal.NonNilBytes(key) 53 54 _, ok := db.db[string(key)] 55 return ok 56 } 57 58 // Implements DB. 59 func (db *MemDB) Set(key []byte, value []byte) { 60 db.mtx.Lock() 61 defer db.mtx.Unlock() 62 63 db.SetNoLock(key, value) 64 } 65 66 // Implements DB. 67 func (db *MemDB) SetSync(key []byte, value []byte) { 68 db.mtx.Lock() 69 defer db.mtx.Unlock() 70 71 db.SetNoLock(key, value) 72 } 73 74 // Implements internal.AtomicSetDeleter. 75 func (db *MemDB) SetNoLock(key []byte, value []byte) { 76 db.SetNoLockSync(key, value) 77 } 78 79 // Implements internal.AtomicSetDeleter. 80 func (db *MemDB) SetNoLockSync(key []byte, value []byte) { 81 key = internal.NonNilBytes(key) 82 value = internal.NonNilBytes(value) 83 84 db.db[string(key)] = value 85 } 86 87 // Implements DB. 88 func (db *MemDB) Delete(key []byte) { 89 db.mtx.Lock() 90 defer db.mtx.Unlock() 91 92 db.DeleteNoLock(key) 93 } 94 95 // Implements DB. 96 func (db *MemDB) DeleteSync(key []byte) { 97 db.mtx.Lock() 98 defer db.mtx.Unlock() 99 100 db.DeleteNoLock(key) 101 } 102 103 // Implements internal.AtomicSetDeleter. 104 func (db *MemDB) DeleteNoLock(key []byte) { 105 db.DeleteNoLockSync(key) 106 } 107 108 // Implements internal.AtomicSetDeleter. 109 func (db *MemDB) DeleteNoLockSync(key []byte) { 110 key = internal.NonNilBytes(key) 111 112 delete(db.db, string(key)) 113 } 114 115 // Implements DB. 116 func (db *MemDB) Close() { 117 // Close is a noop since for an in-memory 118 // database, we don't have a destination 119 // to flush contents to nor do we want 120 // any data loss on invoking Close() 121 // See the discussion in https://github.com/tendermint/classic/libs/pull/56 122 } 123 124 // Implements DB. 125 func (db *MemDB) Print() { 126 db.mtx.Lock() 127 defer db.mtx.Unlock() 128 129 for key, value := range db.db { 130 var keystr, valstr string 131 if strings.IsASCIIText(key) { 132 keystr = key 133 } else { 134 keystr = fmt.Sprintf("0x%X", []byte(key)) 135 } 136 if strings.IsASCIIText(string(value)) { 137 valstr = string(value) 138 } else { 139 valstr = fmt.Sprintf("0x%X", value) 140 } 141 fmt.Printf("%s:\t%s\n", keystr, valstr) 142 } 143 } 144 145 // Implements DB. 146 func (db *MemDB) Stats() map[string]string { 147 db.mtx.Lock() 148 defer db.mtx.Unlock() 149 150 stats := make(map[string]string) 151 stats["database.type"] = "memDB" 152 stats["database.size"] = fmt.Sprintf("%d", len(db.db)) 153 return stats 154 } 155 156 // Implements DB. 157 func (db *MemDB) NewBatch() dbm.Batch { 158 db.mtx.Lock() 159 defer db.mtx.Unlock() 160 161 return &internal.MemBatch{db, nil} 162 } 163 164 // ---------------------------------------- 165 // Iterator 166 167 // Implements DB. 168 func (db *MemDB) Iterator(start, end []byte) dbm.Iterator { 169 db.mtx.Lock() 170 defer db.mtx.Unlock() 171 172 keys := db.getSortedKeys(start, end, false) 173 return internal.NewMemIterator(db, keys, start, end) 174 } 175 176 // Implements DB. 177 func (db *MemDB) ReverseIterator(start, end []byte) dbm.Iterator { 178 db.mtx.Lock() 179 defer db.mtx.Unlock() 180 181 keys := db.getSortedKeys(start, end, true) 182 return internal.NewMemIterator(db, keys, start, end) 183 } 184 185 // ---------------------------------------- 186 // Misc. 187 188 func (db *MemDB) getSortedKeys(start, end []byte, reverse bool) []string { 189 keys := []string{} 190 for key := range db.db { 191 inDomain := dbm.IsKeyInDomain([]byte(key), start, end) 192 if inDomain { 193 keys = append(keys, key) 194 } 195 } 196 sort.Strings(keys) 197 if reverse { 198 nkeys := len(keys) 199 for i := 0; i < nkeys/2; i++ { 200 temp := keys[i] 201 keys[i] = keys[nkeys-i-1] 202 keys[nkeys-i-1] = temp 203 } 204 } 205 return keys 206 }