package mdb /* Copyright (c) 2022, John David Lee All rights reserved. This source code is licensed under the BSD-style license found in the LICENSE file in the root directory of this source tree. */ import ( "net" "os" "path/filepath" "sync" "git.crumpington.com/public/mdb/kvstore" "golang.org/x/sys/unix" ) type LogInfo = kvstore.LogInfo type Database struct { root string lock *os.File kv *kvstore.KV collections map[string]dbCollection } func NewPrimary(root string) *Database { return newDB(root, true) } func NewSecondary(root string) *Database { return newDB(root, false) } func newDB(root string, primary bool) *Database { must(os.MkdirAll(root, 0700)) 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)) db := &Database{ root: root, collections: map[string]dbCollection{}, lock: lock, } if primary { db.kv = kvstore.NewPrimary(root) } else { db.kv = kvstore.NewSecondary(root, db.onStore, db.onDelete) } 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) MaxSeqNum() uint64 { return db.kv.MaxSeqNum() } func (db *Database) LogInfo() LogInfo { return db.kv.LogInfo() } func (db *Database) Close() { if db.kv != nil { db.kv.Close() db.kv = nil } if db.lock != nil { db.lock.Close() db.lock = nil } } // ---------------------------------------------------------------------------- func (db *Database) onStore(collection string, id uint64, data []byte) { if c, ok := db.collections[collection]; ok { c.onStore(id, data) } } func (db *Database) onDelete(collection string, id uint64) { if c, ok := db.collections[collection]; ok { c.onDelete(id) } } // ---------------------------------------------------------------------------- func (db *Database) SyncSend(conn net.Conn) { db.kv.SyncSend(conn) } func (db *Database) SyncRecv(conn net.Conn) { db.kv.SyncRecv(conn) } // ---------------------------------------------------------------------------- // CleanBefore deletes log entries that are more than the given number of // seconds old. func (db *Database) CleanBefore(seconds int64) { db.kv.CleanBefore(seconds) }