github.com/n1ghtfa1l/go-vnt@v0.6.4-alpha.6/vntp2p/database.go (about) 1 // Copyright 2019 The go-vnt Authors 2 // This file is part of the go-vnt library. 3 // 4 // The go-vnt library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-vnt library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-vnt library. If not, see <http://www.gnu.org/licenses/>. 16 17 package vntp2p 18 19 import ( 20 "fmt" 21 22 ds "github.com/ipfs/go-datastore" 23 "github.com/ipfs/go-datastore/query" 24 "github.com/syndtr/goleveldb/leveldb" 25 ) 26 27 // LevelDB vntdb object 28 type LevelDB struct { 29 path string 30 db *leveldb.DB 31 } 32 33 // 最好使用单例,因为leveldb只能有一个打开句柄,而且这个句柄是线程安全的。 34 var vntdb *LevelDB 35 36 // GetDatastore singleton design pattern 37 func GetDatastore(path string) (*LevelDB, error) { 38 if vntdb != nil && vntdb.path == path { 39 return vntdb, nil 40 } 41 vntdb, err := newDatastore(path) 42 if err != nil { 43 return nil, err 44 } 45 return vntdb, nil 46 } 47 48 func newDatastore(path string) (*LevelDB, error) { 49 db, err := leveldb.OpenFile(path, nil) 50 if err != nil { 51 return nil, err 52 } 53 return &LevelDB{ 54 path: path, 55 db: db, 56 }, nil 57 } 58 59 // Put implement Put() of ds.Batching interface 60 func (d *LevelDB) Put(key ds.Key, value interface{}) (err error) { 61 byteKey := []byte(key.String()) 62 byteVal, ok := value.([]byte) 63 if !ok { 64 return ds.ErrInvalidType 65 } 66 err = d.db.Put(byteKey, byteVal, nil) 67 if err != nil { 68 fmt.Printf("leveldb put error = %s\n", err) 69 return err 70 } 71 return nil 72 } 73 74 // Get implement Get() of ds.Batching interface 75 func (d *LevelDB) Get(key ds.Key) (value interface{}, err error) { 76 byteKey := []byte(key.String()) 77 byteVal, err := d.db.Get(byteKey, nil) 78 if err == leveldb.ErrNotFound { 79 return nil, ds.ErrNotFound 80 } 81 if err != nil { 82 return nil, err 83 } 84 return byteVal, nil 85 } 86 87 // Has implement Has() of ds.Batching interface 88 func (d *LevelDB) Has(key ds.Key) (exists bool, err error) { 89 byteKey := []byte(key.String()) 90 exists, err = d.db.Has(byteKey, nil) 91 if err != nil { 92 return false, err 93 } 94 return exists, nil 95 } 96 97 // Delete implement Delete() of ds.Batching interface 98 func (d *LevelDB) Delete(key ds.Key) (err error) { 99 byteKey := []byte(key.String()) 100 err = d.db.Delete(byteKey, nil) 101 if err != nil { 102 return err 103 } 104 return nil 105 } 106 107 // Query implement Query() of ds.Batching interface 108 func (d *LevelDB) Query(q query.Query) (query.Results, error) { 109 var re []query.Entry 110 iter := d.db.NewIterator(nil, nil) 111 for iter.Next() { 112 keyByte := iter.Key() 113 valueByte := iter.Value() 114 re = append(re, query.Entry{Key: string(keyByte), Value: valueByte}) 115 } 116 r := query.ResultsWithEntries(q, re) 117 r = query.NaiveQueryApply(q, r) 118 return r, nil 119 } 120 121 // Close implement Close() of ds.Batching interface 122 func (d *LevelDB) Close() error { 123 err := d.db.Close() 124 if err != nil { 125 return err 126 } 127 return nil 128 } 129 130 // Batch implement Batch() of ds.Batching interface 131 func (d *LevelDB) Batch() (ds.Batch, error) { 132 return ds.NewBasicBatch(d), nil 133 }