// Copyright 2014 by Sascha L. Teichmann // Use of this source code is governed by the MIT license // that can be found in the LICENSE file. package main import ( leveldb "github.com/jmhodges/levigo" ) type LevelDBBackend struct { cache *leveldb.Cache db *leveldb.DB tx *leveldb.WriteBatch } func NewLeveDBBackend(path string, cacheSize int) (ldb *LevelDBBackend, err error) { cache := leveldb.NewLRUCache(cacheSize * 1024 * 1024) opts := leveldb.NewOptions() opts.SetCache(cache) opts.SetCreateIfMissing(true) var db *leveldb.DB if db, err = leveldb.Open(path, opts); err != nil { cache.Close() return } ldb = &LevelDBBackend{ cache: cache, db: db} return } func (ldb *LevelDBBackend) Shutdown() error { tx := ldb.tx if tx != nil { ldb.tx = nil tx.Close() } ldb.db.Close() ldb.cache.Close() return nil } func (ldb *LevelDBBackend) Fetch(hash, key []byte) ([]byte, error) { ro := leveldb.NewReadOptions() defer ro.Close() return ldb.db.Get(ro, key) } func (ldb *LevelDBBackend) InTransaction() bool { return ldb.tx != nil } func (ldb *LevelDBBackend) keyExists(key []byte) (exists bool, err error) { ro := leveldb.NewReadOptions() defer ro.Close() var data []byte if data, err = ldb.db.Get(ro, key); err != nil { return } exists = data != nil return } func (ldb *LevelDBBackend) Store(hash, key, value []byte) (exists bool, err error) { if exists, err = ldb.keyExists(key); err != nil { return } if ldb.tx != nil { ldb.tx.Put(key, value) return } wo := leveldb.NewWriteOptions() defer wo.Close() if err = ldb.db.Put(wo, key, value); err != nil { return } return } func (ldb *LevelDBBackend) BeginTransaction() error { ldb.tx = leveldb.NewWriteBatch() return nil } func (ldb *LevelDBBackend) CommitTransaction() error { tx := ldb.tx ldb.tx = nil wo := leveldb.NewWriteOptions() defer wo.Close() return ldb.db.Write(wo, tx) }