github.com/turingchain2020/turingchain@v1.1.21/common/db/localdb.go (about) 1 package db 2 3 import ( 4 "sync" 5 ) 6 7 // LocalDB local db for store key value in local 8 type LocalDB struct { 9 txcache DB 10 cache DB 11 maindb DB 12 intx bool 13 mu sync.RWMutex 14 readOnly bool 15 } 16 17 func newMemDB() DB { 18 memdb, err := NewGoMemDB("", "", 0) 19 if err != nil { 20 panic(err) 21 } 22 return memdb 23 } 24 25 // NewLocalDB new local db 26 func NewLocalDB(maindb DB, readOnly bool) KVDB { 27 if readOnly { 28 //只读模式不需要memdb,比如交易检查,可以使用该localdb,减少memdb内存开销 29 return &LocalDB{ 30 maindb: maindb, 31 readOnly: true, 32 } 33 } 34 return &LocalDB{ 35 cache: newMemDB(), 36 txcache: newMemDB(), 37 maindb: maindb, 38 } 39 } 40 41 // Get get value from local db 42 func (l *LocalDB) Get(key []byte) ([]byte, error) { 43 l.mu.RLock() 44 defer l.mu.RUnlock() 45 value, err := l.get(key) 46 if isdeleted(value) { 47 //表示已经删除了(空值要用内部定义的 emptyvalue) 48 return nil, ErrNotFoundInDb 49 } 50 return value, err 51 } 52 53 func (l *LocalDB) get(key []byte) ([]byte, error) { 54 if l.intx && l.txcache != nil { 55 if value, err := l.txcache.Get(key); err == nil { 56 return value, nil 57 } 58 } 59 if l.cache != nil { 60 if value, err := l.cache.Get(key); err == nil { 61 return value, nil 62 } 63 } 64 value, err := l.maindb.Get(key) 65 if err != nil { 66 return nil, err 67 } 68 if l.cache != nil { 69 err = l.cache.Set(key, value) 70 if err != nil { 71 panic(err) 72 } 73 } 74 return value, nil 75 } 76 77 // Set set key value to local db 78 func (l *LocalDB) Set(key []byte, value []byte) error { 79 l.mu.Lock() 80 defer l.mu.Unlock() 81 if l.readOnly { 82 panic("set local db in read only mode") 83 } 84 if l.intx { 85 if l.txcache == nil { 86 l.txcache = newMemDB() 87 } 88 setdb2(l.txcache, key, value) 89 } else if l.cache != nil { 90 setdb2(l.cache, key, value) 91 } 92 return nil 93 } 94 95 // List 从数据库中查询数据列表,set 中的cache 更新不会影响这个list 96 func (l *LocalDB) List(prefix, key []byte, count, direction int32) ([][]byte, error) { 97 l.mu.RLock() 98 defer l.mu.RUnlock() 99 dblist := make([]IteratorDB, 0) 100 if l.txcache != nil { 101 dblist = append(dblist, l.txcache) 102 } 103 if l.cache != nil { 104 dblist = append(dblist, l.cache) 105 } 106 if l.maindb != nil { 107 dblist = append(dblist, l.maindb) 108 } 109 mergedb := NewMergedIteratorDB(dblist) 110 it := NewListHelper(mergedb) 111 return it.List(prefix, key, count, direction), nil 112 } 113 114 // PrefixCount 从数据库中查询指定前缀的key的数量 115 func (l *LocalDB) PrefixCount(prefix []byte) (count int64) { 116 l.mu.RLock() 117 defer l.mu.RUnlock() 118 dblist := make([]IteratorDB, 0) 119 if l.txcache != nil { 120 dblist = append(dblist, l.txcache) 121 } 122 if l.cache != nil { 123 dblist = append(dblist, l.cache) 124 } 125 if l.maindb != nil { 126 dblist = append(dblist, l.maindb) 127 } 128 mergedb := NewMergedIteratorDB(dblist) 129 it := NewListHelper(mergedb) 130 return it.PrefixCount(prefix) 131 } 132 133 //Begin 开启内存事务处理 134 func (l *LocalDB) Begin() { 135 l.mu.Lock() 136 defer l.mu.Unlock() 137 l.intx = true 138 l.txcache = nil 139 } 140 141 // Rollback reset tx 142 func (l *LocalDB) Rollback() { 143 l.mu.Lock() 144 defer l.mu.Unlock() 145 l.resetTx() 146 } 147 148 // Commit canche tx 149 func (l *LocalDB) Commit() error { 150 l.mu.Lock() 151 defer l.mu.Unlock() 152 if l.txcache == nil { 153 l.resetTx() 154 return nil 155 } 156 it := l.txcache.Iterator(nil, nil, false) 157 for it.Next() { 158 err := l.cache.Set(it.Key(), it.Value()) 159 if err != nil { 160 panic(err) 161 } 162 } 163 l.resetTx() 164 return nil 165 } 166 167 func (l *LocalDB) resetTx() { 168 l.intx = false 169 l.txcache = nil 170 } 171 172 func setdb2(d DB, key []byte, value []byte) { 173 //value == nil 特殊标记key,代表key已经删除了 174 err := d.Set(key, value) 175 if err != nil { 176 panic(err) 177 } 178 }