plugeth/ethdb/database.go

146 lines
2.6 KiB
Go
Raw Normal View History

2014-02-14 22:56:09 +00:00
package ethdb
import (
"sync"
"time"
2014-08-23 09:00:33 +00:00
2015-02-12 16:06:15 +00:00
"github.com/ethereum/go-ethereum/compression/rle"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
2014-02-14 22:56:09 +00:00
"github.com/syndtr/goleveldb/leveldb"
2014-11-02 23:31:15 +00:00
"github.com/syndtr/goleveldb/leveldb/iterator"
2014-02-14 22:56:09 +00:00
)
type LDBDatabase struct {
fn string
mu sync.Mutex
db *leveldb.DB
queue map[string][]byte
quit chan struct{}
2014-02-14 22:56:09 +00:00
}
func NewLDBDatabase(file string) (*LDBDatabase, error) {
2014-02-14 22:56:09 +00:00
// Open the db
db, err := leveldb.OpenFile(file, nil)
2014-02-14 22:56:09 +00:00
if err != nil {
return nil, err
}
database := &LDBDatabase{
fn: file,
db: db,
quit: make(chan struct{}),
}
database.makeQueue()
go database.update()
2014-02-14 22:56:09 +00:00
return database, nil
}
func (self *LDBDatabase) makeQueue() {
self.queue = make(map[string][]byte)
}
2014-11-02 23:31:15 +00:00
func (self *LDBDatabase) Put(key []byte, value []byte) {
self.mu.Lock()
defer self.mu.Unlock()
self.queue[string(key)] = value
/*
2014-11-02 23:31:15 +00:00
value = rle.Compress(value)
err := self.db.Put(key, value, nil)
if err != nil {
fmt.Println("Error put", err)
}
*/
2014-02-14 22:56:09 +00:00
}
2014-11-02 23:31:15 +00:00
func (self *LDBDatabase) Get(key []byte) ([]byte, error) {
self.mu.Lock()
defer self.mu.Unlock()
// Check queue first
if dat, ok := self.queue[string(key)]; ok {
return dat, nil
}
2014-11-02 23:31:15 +00:00
dat, err := self.db.Get(key, nil)
if err != nil {
return nil, err
}
return rle.Decompress(dat)
2014-02-24 11:12:01 +00:00
}
2014-11-02 23:31:15 +00:00
func (self *LDBDatabase) Delete(key []byte) error {
self.mu.Lock()
defer self.mu.Unlock()
// make sure it's not in the queue
delete(self.queue, string(key))
2014-11-02 23:31:15 +00:00
return self.db.Delete(key, nil)
2014-02-25 10:21:03 +00:00
}
2014-11-02 23:31:15 +00:00
func (self *LDBDatabase) LastKnownTD() []byte {
data, _ := self.Get([]byte("LTD"))
2014-02-14 22:56:09 +00:00
if len(data) == 0 {
data = []byte{0x0}
}
return data
}
2014-11-02 23:31:15 +00:00
func (self *LDBDatabase) NewIterator() iterator.Iterator {
return self.db.NewIterator(nil, nil)
}
func (self *LDBDatabase) Flush() error {
self.mu.Lock()
defer self.mu.Unlock()
batch := new(leveldb.Batch)
for key, value := range self.queue {
batch.Put([]byte(key), rle.Compress(value))
}
self.makeQueue() // reset the queue
2014-12-23 14:18:48 +00:00
return self.db.Write(batch, nil)
}
2014-11-02 23:31:15 +00:00
func (self *LDBDatabase) Close() {
self.quit <- struct{}{}
<-self.quit
glog.V(logger.Info).Infoln("flushed and closed db:", self.fn)
2014-02-14 22:56:09 +00:00
}
func (self *LDBDatabase) update() {
ticker := time.NewTicker(1 * time.Minute)
done:
for {
select {
case <-ticker.C:
if err := self.Flush(); err != nil {
glog.V(logger.Error).Infof("error: flush '%s': %v\n", self.fn, err)
}
case <-self.quit:
break done
}
}
2014-02-14 22:56:09 +00:00
if err := self.Flush(); err != nil {
glog.V(logger.Error).Infof("error: flush '%s': %v\n", self.fn, err)
2014-02-14 22:56:09 +00:00
}
// Close the leveldb database
self.db.Close()
self.quit <- struct{}{}
2014-02-14 22:56:09 +00:00
}