- package db
-
- import (
- "fmt"
- "sort"
- "sync"
- )
-
- func init() {
- registerDBCreator(MemDBBackendStr, func(name string, dir string) (DB, error) {
- return NewMemDB(), nil
- }, false)
- }
-
- var _ DB = (*MemDB)(nil)
-
- type MemDB struct {
- mtx sync.Mutex
- db map[string][]byte
- }
-
- func NewMemDB() *MemDB {
- database := &MemDB{
- db: make(map[string][]byte),
- }
- return database
- }
-
- func (db *MemDB) Get(key []byte) []byte {
- db.mtx.Lock()
- defer db.mtx.Unlock()
- panicNilKey(key)
- return db.db[string(key)]
- }
-
- func (db *MemDB) Has(key []byte) bool {
- db.mtx.Lock()
- defer db.mtx.Unlock()
- panicNilKey(key)
- _, ok := db.db[string(key)]
- return ok
- }
-
- func (db *MemDB) Set(key []byte, value []byte) {
- db.mtx.Lock()
- defer db.mtx.Unlock()
- panicNilKey(key)
- db.SetNoLock(key, value)
- }
-
- func (db *MemDB) SetSync(key []byte, value []byte) {
- db.mtx.Lock()
- defer db.mtx.Unlock()
- panicNilKey(key)
- db.SetNoLock(key, value)
- }
-
- // NOTE: Implements atomicSetDeleter
- func (db *MemDB) SetNoLock(key []byte, value []byte) {
- if value == nil {
- value = []byte{}
- }
- panicNilKey(key)
- db.db[string(key)] = value
- }
-
- func (db *MemDB) Delete(key []byte) {
- db.mtx.Lock()
- defer db.mtx.Unlock()
- panicNilKey(key)
- delete(db.db, string(key))
- }
-
- func (db *MemDB) DeleteSync(key []byte) {
- db.mtx.Lock()
- defer db.mtx.Unlock()
- panicNilKey(key)
- delete(db.db, string(key))
- }
-
- // NOTE: Implements atomicSetDeleter
- func (db *MemDB) DeleteNoLock(key []byte) {
- panicNilKey(key)
- delete(db.db, string(key))
- }
-
- func (db *MemDB) Close() {
- // 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
- }
-
- func (db *MemDB) Print() {
- db.mtx.Lock()
- defer db.mtx.Unlock()
-
- for key, value := range db.db {
- fmt.Printf("[%X]:\t[%X]\n", []byte(key), value)
- }
- }
-
- func (db *MemDB) Stats() map[string]string {
- db.mtx.Lock()
- defer db.mtx.Unlock()
-
- stats := make(map[string]string)
- stats["database.type"] = "memDB"
- stats["database.size"] = fmt.Sprintf("%d", len(db.db))
- return stats
- }
-
- func (db *MemDB) NewBatch() Batch {
- db.mtx.Lock()
- defer db.mtx.Unlock()
-
- return &memBatch{db, nil}
- }
-
- func (db *MemDB) Mutex() *sync.Mutex {
- return &(db.mtx)
- }
-
- //----------------------------------------
-
- func (db *MemDB) Iterator(start, end []byte) Iterator {
- it := newMemDBIterator(db, start, end)
-
- db.mtx.Lock()
- defer db.mtx.Unlock()
-
- // We need a copy of all of the keys.
- // Not the best, but probably not a bottleneck depending.
- it.keys = db.getSortedKeys(start, end)
- return it
- }
-
- func (db *MemDB) ReverseIterator(start, end []byte) Iterator {
- it := newMemDBIterator(db, start, end)
-
- db.mtx.Lock()
- defer db.mtx.Unlock()
-
- // We need a copy of all of the keys.
- // Not the best, but probably not a bottleneck depending.
- it.keys = db.getSortedKeys(end, start)
- // reverse the order
- l := len(it.keys) - 1
- for i, v := range it.keys {
- it.keys[i] = it.keys[l-i]
- it.keys[l-i] = v
- }
- return nil
- }
-
- func (db *MemDB) getSortedKeys(start, end []byte) []string {
- keys := []string{}
- for key, _ := range db.db {
- if IsKeyInDomain(key, start, end) {
- keys = append(keys, key)
- }
- }
- sort.Strings(keys)
- return keys
- }
-
- var _ Iterator = (*memDBIterator)(nil)
-
- type memDBIterator struct {
- cur int
- keys []string
- db DB
- start, end []byte
- }
-
- func newMemDBIterator(db DB, start, end []byte) *memDBIterator {
- return &memDBIterator{
- db: db,
- start: start,
- end: end,
- }
- }
-
- func (it *memDBIterator) Domain() ([]byte, []byte) {
- return it.start, it.end
- }
-
- func (it *memDBIterator) Valid() bool {
- return 0 <= it.cur && it.cur < len(it.keys)
- }
-
- func (it *memDBIterator) Next() {
- if !it.Valid() {
- panic("memDBIterator Next() called when invalid")
- }
- it.cur++
- }
-
- func (it *memDBIterator) Prev() {
- if !it.Valid() {
- panic("memDBIterator Next() called when invalid")
- }
- it.cur--
- }
-
- func (it *memDBIterator) Key() []byte {
- if !it.Valid() {
- panic("memDBIterator Key() called when invalid")
- }
- return []byte(it.keys[it.cur])
- }
-
- func (it *memDBIterator) Value() []byte {
- if !it.Valid() {
- panic("memDBIterator Value() called when invalid")
- }
- return it.db.Get(it.Key())
- }
-
- func (it *memDBIterator) Close() {
- it.db = nil
- it.keys = nil
- }
-
- func (it *memDBIterator) Release() {}
|