2015-10-22 12:31:02 -07:00
|
|
|
package db
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2017-12-12 20:06:50 -05:00
|
|
|
"sort"
|
2016-11-29 16:06:36 -08:00
|
|
|
"sync"
|
2015-10-22 12:31:02 -07:00
|
|
|
)
|
|
|
|
|
2016-11-30 20:15:29 -08:00
|
|
|
func init() {
|
2018-01-24 15:55:31 -08:00
|
|
|
registerDBCreator(MemDBBackend, func(name string, dir string) (DB, error) {
|
2016-11-30 20:15:29 -08:00
|
|
|
return NewMemDB(), nil
|
|
|
|
}, false)
|
|
|
|
}
|
|
|
|
|
2017-12-12 20:06:50 -05:00
|
|
|
var _ DB = (*MemDB)(nil)
|
|
|
|
|
2015-10-22 12:31:02 -07:00
|
|
|
type MemDB struct {
|
2016-11-29 16:06:36 -08:00
|
|
|
mtx sync.Mutex
|
|
|
|
db map[string][]byte
|
2015-10-22 12:31:02 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewMemDB() *MemDB {
|
2017-11-09 17:42:32 -05:00
|
|
|
database := &MemDB{
|
2017-12-12 14:00:03 -08:00
|
|
|
db: make(map[string][]byte),
|
2017-11-09 17:42:32 -05:00
|
|
|
}
|
2015-10-22 12:31:02 -07:00
|
|
|
return database
|
|
|
|
}
|
|
|
|
|
2018-03-15 09:43:23 -07:00
|
|
|
// Implements atomicSetDeleter.
|
|
|
|
func (db *MemDB) Mutex() *sync.Mutex {
|
|
|
|
return &(db.mtx)
|
|
|
|
}
|
|
|
|
|
2017-12-28 18:30:56 -08:00
|
|
|
// Implements DB.
|
2015-10-22 12:31:02 -07:00
|
|
|
func (db *MemDB) Get(key []byte) []byte {
|
2016-11-29 16:06:36 -08:00
|
|
|
db.mtx.Lock()
|
|
|
|
defer db.mtx.Unlock()
|
2017-12-17 13:11:28 -08:00
|
|
|
key = nonNilBytes(key)
|
2017-12-28 18:30:56 -08:00
|
|
|
|
2015-10-22 12:31:02 -07:00
|
|
|
return db.db[string(key)]
|
|
|
|
}
|
|
|
|
|
2017-12-28 18:30:56 -08:00
|
|
|
// Implements DB.
|
2017-12-12 14:00:03 -08:00
|
|
|
func (db *MemDB) Has(key []byte) bool {
|
|
|
|
db.mtx.Lock()
|
|
|
|
defer db.mtx.Unlock()
|
2017-12-17 13:11:28 -08:00
|
|
|
key = nonNilBytes(key)
|
|
|
|
|
2017-12-12 14:00:03 -08:00
|
|
|
_, ok := db.db[string(key)]
|
|
|
|
return ok
|
|
|
|
}
|
|
|
|
|
2017-12-28 18:30:56 -08:00
|
|
|
// Implements DB.
|
2015-10-22 12:31:02 -07:00
|
|
|
func (db *MemDB) Set(key []byte, value []byte) {
|
2016-11-29 16:06:36 -08:00
|
|
|
db.mtx.Lock()
|
|
|
|
defer db.mtx.Unlock()
|
2017-12-17 13:11:28 -08:00
|
|
|
|
2017-11-09 17:42:32 -05:00
|
|
|
db.SetNoLock(key, value)
|
2015-10-22 12:31:02 -07:00
|
|
|
}
|
|
|
|
|
2017-12-28 18:30:56 -08:00
|
|
|
// Implements DB.
|
2015-10-22 12:31:02 -07:00
|
|
|
func (db *MemDB) SetSync(key []byte, value []byte) {
|
2016-11-29 16:06:36 -08:00
|
|
|
db.mtx.Lock()
|
|
|
|
defer db.mtx.Unlock()
|
2017-12-17 13:11:28 -08:00
|
|
|
|
2017-11-09 17:42:32 -05:00
|
|
|
db.SetNoLock(key, value)
|
|
|
|
}
|
|
|
|
|
2017-12-28 18:30:56 -08:00
|
|
|
// Implements atomicSetDeleter.
|
2017-11-09 17:42:32 -05:00
|
|
|
func (db *MemDB) SetNoLock(key []byte, value []byte) {
|
2018-03-15 09:43:23 -07:00
|
|
|
db.SetNoLockSync(key, value)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Implements atomicSetDeleter.
|
|
|
|
func (db *MemDB) SetNoLockSync(key []byte, value []byte) {
|
2017-12-17 13:11:28 -08:00
|
|
|
key = nonNilBytes(key)
|
|
|
|
value = nonNilBytes(value)
|
|
|
|
|
2015-10-22 12:31:02 -07:00
|
|
|
db.db[string(key)] = value
|
|
|
|
}
|
|
|
|
|
2017-12-28 18:30:56 -08:00
|
|
|
// Implements DB.
|
2015-10-22 12:31:02 -07:00
|
|
|
func (db *MemDB) Delete(key []byte) {
|
2016-11-29 16:06:36 -08:00
|
|
|
db.mtx.Lock()
|
|
|
|
defer db.mtx.Unlock()
|
2017-12-17 13:11:28 -08:00
|
|
|
|
|
|
|
db.DeleteNoLock(key)
|
2015-10-22 12:31:02 -07:00
|
|
|
}
|
|
|
|
|
2017-12-28 18:30:56 -08:00
|
|
|
// Implements DB.
|
2015-10-22 12:31:02 -07:00
|
|
|
func (db *MemDB) DeleteSync(key []byte) {
|
2016-11-29 16:06:36 -08:00
|
|
|
db.mtx.Lock()
|
|
|
|
defer db.mtx.Unlock()
|
2017-12-17 13:11:28 -08:00
|
|
|
|
|
|
|
db.DeleteNoLock(key)
|
2017-11-09 17:42:32 -05:00
|
|
|
}
|
|
|
|
|
2017-12-28 18:30:56 -08:00
|
|
|
// Implements atomicSetDeleter.
|
2017-11-09 17:42:32 -05:00
|
|
|
func (db *MemDB) DeleteNoLock(key []byte) {
|
2018-03-15 09:43:23 -07:00
|
|
|
db.DeleteNoLockSync(key)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Implements atomicSetDeleter.
|
|
|
|
func (db *MemDB) DeleteNoLockSync(key []byte) {
|
2017-12-17 13:11:28 -08:00
|
|
|
key = nonNilBytes(key)
|
|
|
|
|
2015-10-22 12:31:02 -07:00
|
|
|
delete(db.db, string(key))
|
|
|
|
}
|
|
|
|
|
2017-12-28 18:30:56 -08:00
|
|
|
// Implements DB.
|
2015-10-22 12:31:02 -07:00
|
|
|
func (db *MemDB) Close() {
|
2017-09-24 20:00:42 -06:00
|
|
|
// Close is a noop since for an in-memory
|
|
|
|
// database, we don't have a destination
|
|
|
|
// to flush contents to nor do we want
|
|
|
|
// any data loss on invoking Close()
|
|
|
|
// See the discussion in https://github.com/tendermint/tmlibs/pull/56
|
2015-10-22 12:31:02 -07:00
|
|
|
}
|
|
|
|
|
2017-12-28 18:30:56 -08:00
|
|
|
// Implements DB.
|
2015-10-22 12:31:02 -07:00
|
|
|
func (db *MemDB) Print() {
|
2016-11-29 16:06:36 -08:00
|
|
|
db.mtx.Lock()
|
|
|
|
defer db.mtx.Unlock()
|
2017-11-09 17:42:32 -05:00
|
|
|
|
2015-10-22 12:31:02 -07:00
|
|
|
for key, value := range db.db {
|
|
|
|
fmt.Printf("[%X]:\t[%X]\n", []byte(key), value)
|
|
|
|
}
|
|
|
|
}
|
2016-11-29 16:06:36 -08:00
|
|
|
|
2017-12-28 18:30:56 -08:00
|
|
|
// Implements DB.
|
2017-03-23 11:37:46 -04:00
|
|
|
func (db *MemDB) Stats() map[string]string {
|
2017-11-09 17:42:32 -05:00
|
|
|
db.mtx.Lock()
|
|
|
|
defer db.mtx.Unlock()
|
|
|
|
|
2017-03-23 11:37:46 -04:00
|
|
|
stats := make(map[string]string)
|
|
|
|
stats["database.type"] = "memDB"
|
2017-11-09 17:42:32 -05:00
|
|
|
stats["database.size"] = fmt.Sprintf("%d", len(db.db))
|
2017-03-23 11:37:46 -04:00
|
|
|
return stats
|
|
|
|
}
|
|
|
|
|
2017-12-28 18:30:56 -08:00
|
|
|
// Implements DB.
|
2017-11-09 17:42:32 -05:00
|
|
|
func (db *MemDB) NewBatch() Batch {
|
|
|
|
db.mtx.Lock()
|
|
|
|
defer db.mtx.Unlock()
|
2017-03-23 11:37:46 -04:00
|
|
|
|
2017-11-09 17:42:32 -05:00
|
|
|
return &memBatch{db, nil}
|
2017-03-23 11:37:46 -04:00
|
|
|
}
|
|
|
|
|
2017-11-09 17:42:32 -05:00
|
|
|
//----------------------------------------
|
2017-12-28 18:30:56 -08:00
|
|
|
// Iterator
|
2017-09-28 17:26:24 +02:00
|
|
|
|
2017-12-28 18:30:56 -08:00
|
|
|
// Implements DB.
|
2017-12-12 14:00:03 -08:00
|
|
|
func (db *MemDB) Iterator(start, end []byte) Iterator {
|
2017-12-12 20:06:50 -05:00
|
|
|
db.mtx.Lock()
|
|
|
|
defer db.mtx.Unlock()
|
|
|
|
|
2017-12-17 13:11:28 -08:00
|
|
|
keys := db.getSortedKeys(start, end, false)
|
|
|
|
return newMemDBIterator(db, keys, start, end)
|
2017-12-12 14:00:03 -08:00
|
|
|
}
|
|
|
|
|
2017-12-28 18:30:56 -08:00
|
|
|
// Implements DB.
|
2017-12-12 14:00:03 -08:00
|
|
|
func (db *MemDB) ReverseIterator(start, end []byte) Iterator {
|
2017-12-12 20:06:50 -05:00
|
|
|
db.mtx.Lock()
|
|
|
|
defer db.mtx.Unlock()
|
|
|
|
|
2017-12-17 13:11:28 -08:00
|
|
|
keys := db.getSortedKeys(end, start, true)
|
|
|
|
return newMemDBIterator(db, keys, start, end)
|
2017-03-17 13:27:20 -04:00
|
|
|
}
|
|
|
|
|
2017-12-17 13:11:28 -08:00
|
|
|
// We need a copy of all of the keys.
|
|
|
|
// Not the best, but probably not a bottleneck depending.
|
2017-12-12 20:06:50 -05:00
|
|
|
type memDBIterator struct {
|
2017-12-17 13:11:28 -08:00
|
|
|
db DB
|
|
|
|
cur int
|
|
|
|
keys []string
|
|
|
|
start []byte
|
|
|
|
end []byte
|
2016-11-29 16:06:36 -08:00
|
|
|
}
|
|
|
|
|
2017-12-28 18:30:56 -08:00
|
|
|
var _ Iterator = (*memDBIterator)(nil)
|
|
|
|
|
2017-12-17 13:11:28 -08:00
|
|
|
// Keys is expected to be in reverse order for reverse iterators.
|
|
|
|
func newMemDBIterator(db DB, keys []string, start, end []byte) *memDBIterator {
|
2017-12-12 20:06:50 -05:00
|
|
|
return &memDBIterator{
|
|
|
|
db: db,
|
2017-12-17 13:11:28 -08:00
|
|
|
cur: 0,
|
|
|
|
keys: keys,
|
2017-12-12 20:06:50 -05:00
|
|
|
start: start,
|
|
|
|
end: end,
|
2017-11-09 17:42:32 -05:00
|
|
|
}
|
2017-12-12 20:06:50 -05:00
|
|
|
}
|
|
|
|
|
2017-12-28 18:30:56 -08:00
|
|
|
// Implements Iterator.
|
2017-12-17 13:11:28 -08:00
|
|
|
func (itr *memDBIterator) Domain() ([]byte, []byte) {
|
|
|
|
return itr.start, itr.end
|
2017-11-09 17:42:32 -05:00
|
|
|
}
|
2016-11-29 16:06:36 -08:00
|
|
|
|
2017-12-28 18:30:56 -08:00
|
|
|
// Implements Iterator.
|
2017-12-17 13:11:28 -08:00
|
|
|
func (itr *memDBIterator) Valid() bool {
|
|
|
|
return 0 <= itr.cur && itr.cur < len(itr.keys)
|
2016-11-29 16:06:36 -08:00
|
|
|
}
|
|
|
|
|
2017-12-28 18:30:56 -08:00
|
|
|
// Implements Iterator.
|
2017-12-17 13:11:28 -08:00
|
|
|
func (itr *memDBIterator) Next() {
|
|
|
|
itr.assertIsValid()
|
|
|
|
itr.cur++
|
2016-11-29 16:06:36 -08:00
|
|
|
}
|
|
|
|
|
2017-12-28 18:30:56 -08:00
|
|
|
// Implements Iterator.
|
2017-12-17 13:11:28 -08:00
|
|
|
func (itr *memDBIterator) Key() []byte {
|
|
|
|
itr.assertIsValid()
|
|
|
|
return []byte(itr.keys[itr.cur])
|
2016-11-29 16:06:36 -08:00
|
|
|
}
|
|
|
|
|
2017-12-28 18:30:56 -08:00
|
|
|
// Implements Iterator.
|
2017-12-17 13:11:28 -08:00
|
|
|
func (itr *memDBIterator) Value() []byte {
|
|
|
|
itr.assertIsValid()
|
|
|
|
key := []byte(itr.keys[itr.cur])
|
|
|
|
return itr.db.Get(key)
|
2017-11-09 17:42:32 -05:00
|
|
|
}
|
2016-11-29 16:06:36 -08:00
|
|
|
|
2017-12-28 18:30:56 -08:00
|
|
|
// Implements Iterator.
|
2017-12-17 13:11:28 -08:00
|
|
|
func (itr *memDBIterator) Close() {
|
|
|
|
itr.keys = nil
|
|
|
|
itr.db = nil
|
2017-11-09 17:42:32 -05:00
|
|
|
}
|
|
|
|
|
2017-12-17 13:11:28 -08:00
|
|
|
func (itr *memDBIterator) assertIsValid() {
|
|
|
|
if !itr.Valid() {
|
|
|
|
panic("memDBIterator is invalid")
|
|
|
|
}
|
2017-12-28 18:30:56 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------
|
|
|
|
// Misc.
|
|
|
|
|
|
|
|
func (db *MemDB) getSortedKeys(start, end []byte, reverse bool) []string {
|
|
|
|
keys := []string{}
|
|
|
|
for key, _ := range db.db {
|
|
|
|
if IsKeyInDomain([]byte(key), start, end, false) {
|
|
|
|
keys = append(keys, key)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sort.Strings(keys)
|
|
|
|
if reverse {
|
|
|
|
nkeys := len(keys)
|
|
|
|
for i := 0; i < nkeys/2; i++ {
|
|
|
|
keys[i] = keys[nkeys-i-1]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return keys
|
|
|
|
}
|