github.com/tendermint/tmlibs@v0.9.0/db/remotedb/remotedb.go (about) 1 package remotedb 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/tendermint/tmlibs/db" 8 "github.com/tendermint/tmlibs/db/remotedb/grpcdb" 9 protodb "github.com/tendermint/tmlibs/db/remotedb/proto" 10 ) 11 12 type RemoteDB struct { 13 ctx context.Context 14 dc protodb.DBClient 15 } 16 17 func NewRemoteDB(serverAddr string, serverKey string) (*RemoteDB, error) { 18 return newRemoteDB(grpcdb.NewClient(serverAddr, serverKey)) 19 } 20 21 func newRemoteDB(gdc protodb.DBClient, err error) (*RemoteDB, error) { 22 if err != nil { 23 return nil, err 24 } 25 return &RemoteDB{dc: gdc, ctx: context.Background()}, nil 26 } 27 28 type Init struct { 29 Dir string 30 Name string 31 Type string 32 } 33 34 func (rd *RemoteDB) InitRemote(in *Init) error { 35 _, err := rd.dc.Init(rd.ctx, &protodb.Init{Dir: in.Dir, Type: in.Type, Name: in.Name}) 36 return err 37 } 38 39 var _ db.DB = (*RemoteDB)(nil) 40 41 // Close is a noop currently 42 func (rd *RemoteDB) Close() { 43 } 44 45 func (rd *RemoteDB) Delete(key []byte) { 46 if _, err := rd.dc.Delete(rd.ctx, &protodb.Entity{Key: key}); err != nil { 47 panic(fmt.Sprintf("RemoteDB.Delete: %v", err)) 48 } 49 } 50 51 func (rd *RemoteDB) DeleteSync(key []byte) { 52 if _, err := rd.dc.DeleteSync(rd.ctx, &protodb.Entity{Key: key}); err != nil { 53 panic(fmt.Sprintf("RemoteDB.DeleteSync: %v", err)) 54 } 55 } 56 57 func (rd *RemoteDB) Set(key, value []byte) { 58 if _, err := rd.dc.Set(rd.ctx, &protodb.Entity{Key: key, Value: value}); err != nil { 59 panic(fmt.Sprintf("RemoteDB.Set: %v", err)) 60 } 61 } 62 63 func (rd *RemoteDB) SetSync(key, value []byte) { 64 if _, err := rd.dc.SetSync(rd.ctx, &protodb.Entity{Key: key, Value: value}); err != nil { 65 panic(fmt.Sprintf("RemoteDB.SetSync: %v", err)) 66 } 67 } 68 69 func (rd *RemoteDB) Get(key []byte) []byte { 70 res, err := rd.dc.Get(rd.ctx, &protodb.Entity{Key: key}) 71 if err != nil { 72 panic(fmt.Sprintf("RemoteDB.Get error: %v", err)) 73 } 74 return res.Value 75 } 76 77 func (rd *RemoteDB) Has(key []byte) bool { 78 res, err := rd.dc.Has(rd.ctx, &protodb.Entity{Key: key}) 79 if err != nil { 80 panic(fmt.Sprintf("RemoteDB.Has error: %v", err)) 81 } 82 return res.Exists 83 } 84 85 func (rd *RemoteDB) ReverseIterator(start, end []byte) db.Iterator { 86 dic, err := rd.dc.ReverseIterator(rd.ctx, &protodb.Entity{Start: start, End: end}) 87 if err != nil { 88 panic(fmt.Sprintf("RemoteDB.Iterator error: %v", err)) 89 } 90 return makeReverseIterator(dic) 91 } 92 93 func (rd *RemoteDB) NewBatch() db.Batch { 94 return &batch{ 95 db: rd, 96 ops: nil, 97 } 98 } 99 100 // TODO: Implement Print when db.DB implements a method 101 // to print to a string and not db.Print to stdout. 102 func (rd *RemoteDB) Print() { 103 panic("Unimplemented") 104 } 105 106 func (rd *RemoteDB) Stats() map[string]string { 107 stats, err := rd.dc.Stats(rd.ctx, &protodb.Nothing{}) 108 if err != nil { 109 panic(fmt.Sprintf("RemoteDB.Stats error: %v", err)) 110 } 111 if stats == nil { 112 return nil 113 } 114 return stats.Data 115 } 116 117 func (rd *RemoteDB) Iterator(start, end []byte) db.Iterator { 118 dic, err := rd.dc.Iterator(rd.ctx, &protodb.Entity{Start: start, End: end}) 119 if err != nil { 120 panic(fmt.Sprintf("RemoteDB.Iterator error: %v", err)) 121 } 122 return makeIterator(dic) 123 } 124 125 func makeIterator(dic protodb.DB_IteratorClient) db.Iterator { 126 return &iterator{dic: dic} 127 } 128 129 func makeReverseIterator(dric protodb.DB_ReverseIteratorClient) db.Iterator { 130 return &reverseIterator{dric: dric} 131 } 132 133 type reverseIterator struct { 134 dric protodb.DB_ReverseIteratorClient 135 cur *protodb.Iterator 136 } 137 138 var _ db.Iterator = (*iterator)(nil) 139 140 func (rItr *reverseIterator) Valid() bool { 141 return rItr.cur != nil && rItr.cur.Valid 142 } 143 144 func (rItr *reverseIterator) Domain() (start, end []byte) { 145 if rItr.cur == nil || rItr.cur.Domain == nil { 146 return nil, nil 147 } 148 return rItr.cur.Domain.Start, rItr.cur.Domain.End 149 } 150 151 // Next advances the current reverseIterator 152 func (rItr *reverseIterator) Next() { 153 var err error 154 rItr.cur, err = rItr.dric.Recv() 155 if err != nil { 156 panic(fmt.Sprintf("RemoteDB.ReverseIterator.Next error: %v", err)) 157 } 158 } 159 160 func (rItr *reverseIterator) Key() []byte { 161 if rItr.cur == nil { 162 return nil 163 } 164 return rItr.cur.Key 165 } 166 167 func (rItr *reverseIterator) Value() []byte { 168 if rItr.cur == nil { 169 return nil 170 } 171 return rItr.cur.Value 172 } 173 174 func (rItr *reverseIterator) Close() { 175 } 176 177 // iterator implements the db.Iterator by retrieving 178 // streamed iterators from the remote backend as 179 // needed. It is NOT safe for concurrent usage, 180 // matching the behavior of other iterators. 181 type iterator struct { 182 dic protodb.DB_IteratorClient 183 cur *protodb.Iterator 184 } 185 186 var _ db.Iterator = (*iterator)(nil) 187 188 func (itr *iterator) Valid() bool { 189 return itr.cur != nil && itr.cur.Valid 190 } 191 192 func (itr *iterator) Domain() (start, end []byte) { 193 if itr.cur == nil || itr.cur.Domain == nil { 194 return nil, nil 195 } 196 return itr.cur.Domain.Start, itr.cur.Domain.End 197 } 198 199 // Next advances the current iterator 200 func (itr *iterator) Next() { 201 var err error 202 itr.cur, err = itr.dic.Recv() 203 if err != nil { 204 panic(fmt.Sprintf("RemoteDB.Iterator.Next error: %v", err)) 205 } 206 } 207 208 func (itr *iterator) Key() []byte { 209 if itr.cur == nil { 210 return nil 211 } 212 return itr.cur.Key 213 } 214 215 func (itr *iterator) Value() []byte { 216 if itr.cur == nil { 217 return nil 218 } 219 return itr.cur.Value 220 } 221 222 func (itr *iterator) Close() { 223 err := itr.dic.CloseSend() 224 if err != nil { 225 panic(fmt.Sprintf("Error closing iterator: %v", err)) 226 } 227 } 228 229 type batch struct { 230 db *RemoteDB 231 ops []*protodb.Operation 232 } 233 234 var _ db.Batch = (*batch)(nil) 235 236 func (bat *batch) Set(key, value []byte) { 237 op := &protodb.Operation{ 238 Entity: &protodb.Entity{Key: key, Value: value}, 239 Type: protodb.Operation_SET, 240 } 241 bat.ops = append(bat.ops, op) 242 } 243 244 func (bat *batch) Delete(key []byte) { 245 op := &protodb.Operation{ 246 Entity: &protodb.Entity{Key: key}, 247 Type: protodb.Operation_DELETE, 248 } 249 bat.ops = append(bat.ops, op) 250 } 251 252 func (bat *batch) Write() { 253 if _, err := bat.db.dc.BatchWrite(bat.db.ctx, &protodb.Batch{Ops: bat.ops}); err != nil { 254 panic(fmt.Sprintf("RemoteDB.BatchWrite: %v", err)) 255 } 256 } 257 258 func (bat *batch) WriteSync() { 259 if _, err := bat.db.dc.BatchWriteSync(bat.db.ctx, &protodb.Batch{Ops: bat.ops}); err != nil { 260 panic(fmt.Sprintf("RemoteDB.BatchWriteSync: %v", err)) 261 } 262 }