2014-04-18 10:50:29 +04:00
|
|
|
package leveldb
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"github.com/jmhodges/levigo"
|
|
|
|
)
|
|
|
|
|
|
|
|
const defaultFilterBits int = 10
|
|
|
|
|
|
|
|
type Config struct {
|
|
|
|
Path string `json:"path"`
|
|
|
|
|
|
|
|
Compression bool `json:"compression"`
|
|
|
|
|
|
|
|
BlockSize int `json:"block_size"`
|
|
|
|
WriteBufferSize int `json:"write_buffer_size"`
|
|
|
|
CacheSize int `json:"cache_size"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type DB struct {
|
|
|
|
cfg *Config
|
|
|
|
db *levigo.DB
|
|
|
|
|
|
|
|
opts *levigo.Options
|
|
|
|
|
|
|
|
//for default read and write options
|
|
|
|
readOpts *levigo.ReadOptions
|
|
|
|
writeOpts *levigo.WriteOptions
|
|
|
|
iteratorOpts *levigo.ReadOptions
|
|
|
|
|
|
|
|
cache *levigo.Cache
|
|
|
|
|
|
|
|
filter *levigo.FilterPolicy
|
|
|
|
}
|
|
|
|
|
2014-04-30 04:56:51 +04:00
|
|
|
func OpenWithConfig(cfg *Config) (*DB, error) {
|
2014-04-18 10:50:29 +04:00
|
|
|
db := new(DB)
|
|
|
|
db.cfg = cfg
|
|
|
|
|
|
|
|
db.opts = db.initOptions(cfg)
|
|
|
|
|
|
|
|
db.readOpts = levigo.NewReadOptions()
|
|
|
|
db.writeOpts = levigo.NewWriteOptions()
|
|
|
|
db.iteratorOpts = levigo.NewReadOptions()
|
|
|
|
db.iteratorOpts.SetFillCache(false)
|
|
|
|
|
2014-04-30 04:56:51 +04:00
|
|
|
var err error
|
2014-04-18 10:50:29 +04:00
|
|
|
db.db, err = levigo.Open(cfg.Path, db.opts)
|
|
|
|
return db, err
|
|
|
|
}
|
|
|
|
|
2014-04-30 04:56:51 +04:00
|
|
|
func Open(configJson json.RawMessage) (*DB, error) {
|
|
|
|
cfg := new(Config)
|
|
|
|
err := json.Unmarshal(configJson, cfg)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return OpenWithConfig(cfg)
|
|
|
|
}
|
|
|
|
|
2014-04-18 10:50:29 +04:00
|
|
|
func (db *DB) initOptions(cfg *Config) *levigo.Options {
|
|
|
|
opts := levigo.NewOptions()
|
|
|
|
|
|
|
|
opts.SetCreateIfMissing(true)
|
|
|
|
|
|
|
|
if cfg.CacheSize > 0 {
|
|
|
|
db.cache = levigo.NewLRUCache(cfg.CacheSize)
|
|
|
|
opts.SetCache(db.cache)
|
|
|
|
}
|
|
|
|
|
|
|
|
//we must use bloomfilter
|
|
|
|
db.filter = levigo.NewBloomFilter(defaultFilterBits)
|
|
|
|
opts.SetFilterPolicy(db.filter)
|
|
|
|
|
|
|
|
if !cfg.Compression {
|
|
|
|
opts.SetCompression(levigo.NoCompression)
|
|
|
|
}
|
|
|
|
|
2014-04-30 04:56:51 +04:00
|
|
|
if cfg.BlockSize > 0 {
|
|
|
|
opts.SetBlockSize(cfg.BlockSize)
|
2014-04-18 10:50:29 +04:00
|
|
|
}
|
|
|
|
|
2014-04-30 04:56:51 +04:00
|
|
|
if cfg.WriteBufferSize > 0 {
|
|
|
|
opts.SetWriteBufferSize(cfg.WriteBufferSize)
|
2014-04-18 10:50:29 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return opts
|
|
|
|
}
|
|
|
|
|
|
|
|
func (db *DB) Close() {
|
|
|
|
db.opts.Close()
|
|
|
|
|
|
|
|
if db.cache != nil {
|
|
|
|
db.cache.Close()
|
|
|
|
}
|
|
|
|
|
|
|
|
if db.filter != nil {
|
|
|
|
db.filter.Close()
|
|
|
|
}
|
|
|
|
|
|
|
|
db.readOpts.Close()
|
|
|
|
db.writeOpts.Close()
|
|
|
|
db.iteratorOpts.Close()
|
|
|
|
|
|
|
|
db.db.Close()
|
|
|
|
db.db = nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (db *DB) Destroy() {
|
|
|
|
db.Close()
|
|
|
|
opts := levigo.NewOptions()
|
|
|
|
defer opts.Close()
|
|
|
|
|
|
|
|
levigo.DestroyDatabase(db.cfg.Path, opts)
|
|
|
|
}
|
|
|
|
|
2014-05-07 09:40:48 +04:00
|
|
|
func (db *DB) Clear() {
|
2014-05-07 18:53:24 +04:00
|
|
|
it := db.Iterator(nil, nil, 0, 0, -1)
|
2014-05-07 09:40:48 +04:00
|
|
|
for ; it.Valid(); it.Next() {
|
|
|
|
db.Delete(it.Key())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-18 10:50:29 +04:00
|
|
|
func (db *DB) Put(key, value []byte) error {
|
|
|
|
return db.db.Put(db.writeOpts, key, value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (db *DB) Get(key []byte) ([]byte, error) {
|
|
|
|
return db.db.Get(db.readOpts, key)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (db *DB) Delete(key []byte) error {
|
|
|
|
return db.db.Delete(db.writeOpts, key)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (db *DB) NewWriteBatch() *WriteBatch {
|
|
|
|
wb := new(WriteBatch)
|
|
|
|
wb.wb = levigo.NewWriteBatch()
|
|
|
|
wb.db = db
|
|
|
|
return wb
|
|
|
|
}
|
|
|
|
|
2014-05-07 12:44:08 +04:00
|
|
|
//limit < 0, unlimit
|
2014-05-07 18:53:24 +04:00
|
|
|
//offset must >= 0, if < 0, will get nothing
|
|
|
|
func (db *DB) Iterator(min []byte, max []byte, rangeType uint8, offset int, limit int) *Iterator {
|
|
|
|
return newIterator(db, db.iteratorOpts, NewRange(min, max, rangeType), offset, limit, IteratorForward)
|
2014-04-18 10:50:29 +04:00
|
|
|
}
|
|
|
|
|
2014-05-07 12:44:08 +04:00
|
|
|
//limit < 0, unlimit
|
2014-05-07 18:53:24 +04:00
|
|
|
//offset must >= 0, if < 0, will get nothing
|
|
|
|
func (db *DB) RevIterator(min []byte, max []byte, rangeType uint8, offset int, limit int) *Iterator {
|
|
|
|
return newIterator(db, db.iteratorOpts, NewRange(min, max, rangeType), offset, limit, IteratorBackward)
|
2014-04-18 10:50:29 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
func (db *DB) NewSnapshot() *Snapshot {
|
|
|
|
return newSnapshot(db)
|
|
|
|
}
|
2014-05-05 13:00:11 +04:00
|
|
|
|
|
|
|
func (db *DB) GetInt(key []byte) (int64, error) {
|
2014-05-05 13:09:05 +04:00
|
|
|
return Int(db.Get(key))
|
2014-05-05 13:00:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
func (db *DB) GetUInt(key []byte) (uint64, error) {
|
2014-05-05 13:09:05 +04:00
|
|
|
return Uint(db.Get(key))
|
2014-05-05 13:00:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
func (db *DB) GetFloat(key []byte) (float64, error) {
|
2014-05-05 13:09:05 +04:00
|
|
|
return Float(db.Get(key))
|
2014-05-05 13:00:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
func (db *DB) GetString(key []byte) (string, error) {
|
2014-05-05 13:09:05 +04:00
|
|
|
return String(db.Get(key))
|
2014-05-05 13:00:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
func (db *DB) GetSlice(key []byte) ([]byte, error) {
|
2014-05-05 13:09:05 +04:00
|
|
|
return Slice(db.Get(key))
|
2014-05-05 13:00:11 +04:00
|
|
|
}
|