database/bitcask/bitcask.go

157 lines
3.4 KiB
Go
Raw Normal View History

2022-01-09 00:59:10 +00:00
package bitcask
import (
"strings"
"sync"
"git.tcp.direct/Mirrors/bitcask-mirror"
2022-01-09 03:01:15 +00:00
"git.tcp.direct/kayos/database"
)
2022-01-09 03:01:15 +00:00
// Store is an implmentation of a Filer and a Searcher using Bitcask.
type Store struct {
2022-01-01 22:22:08 +00:00
*bitcask.Bitcask
2022-01-09 03:01:15 +00:00
database.Searcher
2022-01-01 22:22:08 +00:00
}
// DB is a mapper of a Filer and Searcher implementation using Bitcask.
type DB struct {
2022-01-09 03:01:15 +00:00
store map[string]Store
2022-01-01 21:08:59 +00:00
path string
2022-01-01 20:06:56 +00:00
mu *sync.RWMutex
}
2022-01-01 22:22:08 +00:00
// OpenDB will either open an existing set of bitcask datastores at the given directory, or it will create a new one.
func OpenDB(path string) *DB {
2022-01-01 21:08:59 +00:00
return &DB{
2022-01-09 03:01:15 +00:00
store: make(map[string]Store),
2022-01-01 21:08:59 +00:00
path: path,
mu: &sync.RWMutex{},
}
}
2022-01-19 09:46:51 +00:00
// Path returns the base path where we store our bitcask "stores".
2022-01-01 21:08:59 +00:00
func (db *DB) Path() string {
return db.path
}
2022-01-19 09:46:51 +00:00
// Init opens a bitcask store at the given path to be referenced by storeName.
func (db *DB) Init(storeName string, bitcaskopts ...bitcask.Option) error {
db.mu.Lock()
defer db.mu.Unlock()
2022-01-19 09:46:51 +00:00
if _, ok := db.store[storeName]; ok {
return errStoreExists
}
2022-01-01 21:08:59 +00:00
path := db.Path()
if !strings.HasSuffix("/", db.Path()) {
path = db.Path() + "/"
}
c, e := bitcask.Open(path+storeName, bitcaskopts...)
if e != nil {
return e
}
2022-01-19 09:46:51 +00:00
db.store[storeName] = Store{Bitcask: c}
return nil
}
// With calls the given underlying bitcask instance.
2022-01-19 09:46:51 +00:00
func (db *DB) With(storeName string) Store {
db.mu.RLock()
defer db.mu.RUnlock()
2022-01-19 09:46:51 +00:00
d, ok := db.store[storeName]
2022-01-01 21:08:59 +00:00
if !ok {
2022-01-09 03:01:15 +00:00
return Store{Bitcask: nil}
2022-01-01 21:08:59 +00:00
}
return d
}
// Close is a simple shim for bitcask's Close function.
2022-01-19 09:46:51 +00:00
func (db *DB) Close(storeName string) error {
db.mu.Lock()
defer db.mu.Unlock()
2022-01-19 09:46:51 +00:00
st, ok := db.store[storeName]
if !ok {
return errBogusStore
}
err := st.Close()
if err != nil {
return err
}
2022-01-19 09:46:51 +00:00
delete(db.store, storeName)
return nil
}
// Sync is a simple shim for bitcask's Sync function.
2022-01-19 09:46:51 +00:00
func (db *DB) Sync(storeName string) error {
db.mu.RLock()
defer db.mu.RUnlock()
2022-01-19 09:46:51 +00:00
return db.store[storeName].Sync()
}
2022-01-01 22:22:08 +00:00
// withAllAction
type withAllAction uint8
const (
2022-01-01 22:22:08 +00:00
// dclose
2022-01-01 21:08:59 +00:00
dclose withAllAction = iota
2022-01-01 22:22:08 +00:00
// dsync
2022-01-01 21:08:59 +00:00
dsync
)
// withAll performs an action on all bitcask stores that we have open.
// In the case of an error, withAll will continue and return a compound form of any errors that occurred.
// For now this is just for Close and Sync, thusly it does a hard lock on the Keeper.
func (db *DB) withAll(action withAllAction) error {
2022-02-12 07:52:42 +00:00
var errs = make([]error, len(db.store))
if len(db.store) < 1 {
return errNoStores
}
for name, store := range db.store {
var err error
2022-01-01 22:22:08 +00:00
if store.Bitcask == nil {
2022-01-01 21:08:59 +00:00
errs = append(errs, namedErr(name, errBogusStore))
continue
}
switch action {
2022-01-01 21:08:59 +00:00
case dclose:
err = namedErr(name, db.Close(name))
2022-01-01 21:08:59 +00:00
case dsync:
err = namedErr(name, db.Sync(name))
default:
2022-01-01 20:06:56 +00:00
return errUnknownAction
}
if err == nil {
continue
}
errs = append(errs, err)
}
return compoundErrors(errs)
}
2022-01-01 22:22:08 +00:00
// SyncAndCloseAll implements the method from Keeper.
func (db *DB) SyncAndCloseAll() error {
2022-02-12 07:52:42 +00:00
var errs = make([]error, len(db.store))
2022-01-01 22:22:08 +00:00
errSync := namedErr("sync", db.SyncAll())
if errSync != nil {
errs = append(errs, errSync)
}
errClose := namedErr("close", db.CloseAll())
if errClose != nil {
errs = append(errs, errClose)
}
return compoundErrors(errs)
}
// CloseAll closes all bitcask datastores.
func (db *DB) CloseAll() error {
return db.withAll(dclose)
}
2022-01-01 22:22:08 +00:00
// SyncAll syncs all bitcask datastores.
func (db *DB) SyncAll() error {
return db.withAll(dsync)
}