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  }