diff --git a/README.md b/README.md index a66aee9..8b2217d 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,8 @@ An in-process, in-memory database for Go. ## TO DO -* [ ] kvstore: tests +* [ ] mdb: db exclusive lock +* [ ] mdb: clean up tests ## Structure diff --git a/database.go b/database.go index 25e2ee7..a1c7243 100644 --- a/database.go +++ b/database.go @@ -3,35 +3,49 @@ package mdb import ( "net" "os" + "path/filepath" "sync" "git.crumpington.com/private/mdb/kvstore" + "golang.org/x/sys/unix" ) type Database struct { root string + lock *os.File kv *kvstore.KV collections map[string]dbCollection } func NewPrimary(root string) *Database { - must(os.MkdirAll(root, 0700)) - db := &Database{ - root: root, - collections: map[string]dbCollection{}, - } - db.kv = kvstore.NewPrimary(root) - return db + 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) } - db.kv = kvstore.NewSecondary(root, db.onStore, db.onDelete) return db } @@ -55,9 +69,11 @@ func (db *Database) WALStatus() (ws WALStatus) { func (db *Database) Close() { db.kv.Close() + db.lock.Close() } -// ---------------------------------------------------------------------------- +// ----------------- + db.kv = kvstore.NewSecondary(root)----------------------------------------------------------- func (db *Database) onStore(collection string, id uint64, data []byte) { c, ok := db.collections[collection]