@ -1,5 +1,5 @@ |
|||||
# slowlorisdb |
# slowlorisdb |
||||
|
|
||||
Slow and decentralized cryptographically consistent database |
|
||||
|
Slow, decentralized and cryptographically consistent database |
||||
|
|
||||
![slowloris](https://04019a5a-a-62cb3a1a-s-sites.googlegroups.com/site/jchristensensdigitalportfolio/slow-loris/IO-moth-eating-frozen-apple-sauce.jpg "slowloris") |
![slowloris](https://04019a5a-a-62cb3a1a-s-sites.googlegroups.com/site/jchristensensdigitalportfolio/slow-loris/IO-moth-eating-frozen-apple-sauce.jpg "slowloris") |
@ -0,0 +1,55 @@ |
|||||
|
package db |
||||
|
|
||||
|
import ( |
||||
|
"github.com/syndtr/goleveldb/leveldb" |
||||
|
) |
||||
|
|
||||
|
// Db is the database with the specified prefix
|
||||
|
type Db struct { |
||||
|
ldb *leveldb.DB |
||||
|
prefix []byte |
||||
|
} |
||||
|
|
||||
|
// New creates a new Db database
|
||||
|
func New(path string) (*Db, error) { |
||||
|
ldb, err := leveldb.OpenFile(path, nil) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
return &Db{ldb, []byte{}}, nil |
||||
|
} |
||||
|
|
||||
|
// WithPrefix returns a subdatabase with the specified prefix
|
||||
|
func (db *Db) WithPrefix(prefix []byte) *Db { |
||||
|
return &Db{db.ldb, append(db.prefix, prefix...)} |
||||
|
} |
||||
|
|
||||
|
// Put adds the key value to the database
|
||||
|
func (db *Db) Put(key, value []byte) error { |
||||
|
err := db.ldb.Put(append(db.prefix, key[:]...), value, nil) |
||||
|
return err |
||||
|
} |
||||
|
|
||||
|
// Get retreives a value from the database for a given key
|
||||
|
func (db *Db) Get(key []byte) ([]byte, error) { |
||||
|
v, err := db.ldb.Get(append(db.prefix, key[:]...), nil) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
return v, nil |
||||
|
} |
||||
|
|
||||
|
// Iterate iterates over the database
|
||||
|
func (db *Db) Iterate(f func([]byte, []byte)) error { |
||||
|
snapshot, err := db.ldb.GetSnapshot() |
||||
|
if err != nil { |
||||
|
return err |
||||
|
} |
||||
|
iter := snapshot.NewIterator(nil, nil) |
||||
|
for iter.Next() { |
||||
|
f(iter.Key(), iter.Value()) |
||||
|
} |
||||
|
iter.Release() |
||||
|
err = iter.Error() |
||||
|
return err |
||||
|
} |
@ -0,0 +1,53 @@ |
|||||
|
package db |
||||
|
|
||||
|
import ( |
||||
|
"io/ioutil" |
||||
|
"testing" |
||||
|
|
||||
|
"github.com/stretchr/testify/assert" |
||||
|
|
||||
|
"github.com/syndtr/goleveldb/leveldb/errors" |
||||
|
) |
||||
|
|
||||
|
func TestNew(t *testing.T) { |
||||
|
dir, err := ioutil.TempDir("", "db") |
||||
|
assert.Nil(t, err) |
||||
|
_, err = New(dir) |
||||
|
assert.Nil(t, err) |
||||
|
} |
||||
|
func TestPutAndGet(t *testing.T) { |
||||
|
dir, err := ioutil.TempDir("", "db") |
||||
|
assert.Nil(t, err) |
||||
|
db, err := New(dir) |
||||
|
assert.Nil(t, err) |
||||
|
|
||||
|
k := []byte("test key") |
||||
|
v := []byte("test value") |
||||
|
|
||||
|
err = db.Put(k, v) |
||||
|
assert.Nil(t, err) |
||||
|
|
||||
|
vg, err := db.Get(k) |
||||
|
assert.Nil(t, err) |
||||
|
assert.Equal(t, v, vg) |
||||
|
|
||||
|
} |
||||
|
|
||||
|
func TestPrefix(t *testing.T) { |
||||
|
dir, err := ioutil.TempDir("", "db") |
||||
|
assert.Nil(t, err) |
||||
|
db, err := New(dir) |
||||
|
assert.Nil(t, err) |
||||
|
|
||||
|
dbPrefix := db.WithPrefix([]byte("prefix1")) |
||||
|
|
||||
|
err = dbPrefix.Put([]byte("k1"), []byte("v1")) |
||||
|
assert.Nil(t, err) |
||||
|
|
||||
|
_, err = db.Get([]byte("k1")) |
||||
|
assert.Equal(t, err, errors.ErrNotFound) |
||||
|
|
||||
|
v1, err := dbPrefix.Get([]byte("k1")) |
||||
|
assert.Nil(t, err) |
||||
|
assert.Equal(t, []byte("v1"), v1) |
||||
|
} |