2022-07-26 12:02:32 +00:00
|
|
|
package mdb
|
|
|
|
|
|
|
|
import (
|
|
|
|
"net"
|
|
|
|
"os"
|
2022-07-26 12:10:41 +00:00
|
|
|
"path/filepath"
|
2022-07-26 12:02:32 +00:00
|
|
|
"sync"
|
|
|
|
|
|
|
|
"git.crumpington.com/private/mdb/kvstore"
|
2022-07-26 12:10:41 +00:00
|
|
|
"golang.org/x/sys/unix"
|
2022-07-26 12:02:32 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type Database struct {
|
|
|
|
root string
|
2022-07-26 12:10:41 +00:00
|
|
|
lock *os.File
|
2022-07-26 12:02:32 +00:00
|
|
|
kv *kvstore.KV
|
|
|
|
|
|
|
|
collections map[string]dbCollection
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewPrimary(root string) *Database {
|
2022-07-26 12:10:41 +00:00
|
|
|
return newDB(root, true)
|
2022-07-26 12:02:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewSecondary(root string) *Database {
|
2022-07-26 12:10:41 +00:00
|
|
|
return newDB(root, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
func newDB(root string, primary bool) *Database {
|
2022-07-26 12:02:32 +00:00
|
|
|
must(os.MkdirAll(root, 0700))
|
2022-07-26 12:10:41 +00:00
|
|
|
|
|
|
|
lockPath := filepath.Join(root, "lock")
|
|
|
|
|
|
|
|
// Acquire the lock.
|
|
|
|
lock, err := os.OpenFile(lockPath, os.O_RDWR|os.O_CREATE, 0600)
|
|
|
|
must(err)
|
|
|
|
must(unix.Flock(int(lock.Fd()), unix.LOCK_EX))
|
|
|
|
|
2022-07-26 12:02:32 +00:00
|
|
|
db := &Database{
|
|
|
|
root: root,
|
|
|
|
collections: map[string]dbCollection{},
|
2022-07-26 12:10:41 +00:00
|
|
|
lock: lock,
|
|
|
|
}
|
|
|
|
if primary {
|
|
|
|
db.kv = kvstore.NewPrimary(root)
|
|
|
|
} else {
|
|
|
|
db.kv = kvstore.NewSecondary(root, db.onStore, db.onDelete)
|
2022-07-26 12:02:32 +00:00
|
|
|
}
|
|
|
|
return db
|
|
|
|
}
|
|
|
|
|
|
|
|
func (db *Database) Start() {
|
|
|
|
wg := sync.WaitGroup{}
|
|
|
|
for _, c := range db.collections {
|
|
|
|
wg.Add(1)
|
|
|
|
go func(c dbCollection) {
|
|
|
|
defer wg.Done()
|
|
|
|
c.loadData()
|
|
|
|
}(c)
|
|
|
|
}
|
|
|
|
wg.Wait()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (db *Database) WALStatus() (ws WALStatus) {
|
2022-07-26 12:13:41 +00:00
|
|
|
ws.MaxSeqNumKV = db.kv.WALMaxSeqNum()
|
|
|
|
ws.MaxSeqNumWAL = db.kv.MaxSeqNum()
|
2022-07-26 12:02:32 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (db *Database) Close() {
|
2022-07-26 12:13:41 +00:00
|
|
|
if db.kv != nil {
|
|
|
|
db.kv.Close()
|
|
|
|
db.kv = nil
|
|
|
|
}
|
|
|
|
if db.lock != nil {
|
|
|
|
db.lock.Close()
|
|
|
|
db.lock = nil
|
|
|
|
}
|
2022-07-26 12:02:32 +00:00
|
|
|
}
|
|
|
|
|
2022-07-26 12:13:41 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
2022-07-26 12:02:32 +00:00
|
|
|
|
|
|
|
func (db *Database) onStore(collection string, id uint64, data []byte) {
|
|
|
|
c, ok := db.collections[collection]
|
|
|
|
if ok {
|
|
|
|
c.onStore(collection, id, data)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (db *Database) onDelete(collection string, id uint64) {
|
|
|
|
c, ok := db.collections[collection]
|
|
|
|
if ok {
|
|
|
|
c.onDelete(collection, id)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
func (db *Database) SyncSend(conn net.Conn) {
|
|
|
|
db.kv.SyncSend(conn)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (db *Database) SyncRecv(conn net.Conn) {
|
|
|
|
db.kv.SyncRecv(conn)
|
|
|
|
}
|