summaryrefslogtreecommitdiff
path: root/store/store.go
diff options
context:
space:
mode:
Diffstat (limited to 'store/store.go')
-rw-r--r--store/store.go66
1 files changed, 36 insertions, 30 deletions
diff --git a/store/store.go b/store/store.go
index f7420aa..619eff4 100644
--- a/store/store.go
+++ b/store/store.go
@@ -2,15 +2,17 @@ package store
import (
"encoding/json"
+ "fmt"
"github.com/bwmarrin/snowflake"
log "github.com/sirupsen/logrus"
+ "github.com/syndtr/goleveldb/leveldb"
"os"
"runtime"
"strconv"
"sync"
)
-const revision = -6
+const revision = -7
var (
imageNode *snowflake.Node
@@ -37,6 +39,7 @@ type Store struct {
InitialUser string
PermissionDir os.FileMode
PermissionFile os.FileMode
+ pageldb map[string]*leveldb.DB
mutex map[string]*sync.RWMutex
sync.RWMutex
}
@@ -50,8 +53,7 @@ func init() {
imageNode, err = snowflake.NewNode(9)
userNode, err = snowflake.NewNode(7)
if err != nil {
- log.Fatalf("Error while creating snowflake generation node, %s", err)
- os.Exit(1)
+ log.Fatalf("Error creating snowflake generation node, %s", err)
}
}
@@ -69,17 +71,16 @@ func New(path string, single bool) *Store {
Register: false,
PermissionDir: 0700,
PermissionFile: 0600,
+ pageldb: make(map[string]*leveldb.DB),
mutex: make(map[string]*sync.RWMutex),
}
if err = store.create(); err != nil {
log.Fatalf("Error creating store, %s", err)
- os.Exit(1)
}
} else {
// Exit if store is not a directory.
if !stat.IsDir() {
log.Fatal("Store is not a directory.")
- os.Exit(1)
}
// Load and parse store info.
@@ -87,16 +88,13 @@ func New(path string, single bool) *Store {
var payload []byte
if payload, err = os.ReadFile(path + "/" + infoJson); err != nil {
log.Fatalf("Error reading store information, %s", err)
- os.Exit(1)
} else {
if err = json.Unmarshal(payload, &info); err != nil {
log.Fatalf("Error parsing store information, %s", err)
- os.Exit(1)
}
}
if info.Revision != revision {
log.Fatalf("Store format revision %v, expecting revision %v.", info.Revision, revision)
- os.Exit(1)
}
// Create store instance.
@@ -109,34 +107,50 @@ func New(path string, single bool) *Store {
InitialUser: info.InitialUser,
PermissionDir: info.PermissionDir,
PermissionFile: info.PermissionFile,
+ pageldb: make(map[string]*leveldb.DB),
mutex: make(map[string]*sync.RWMutex),
}
}
+
+ // Handle store locking
if store.file(store.LockPath()) {
if pid, err := os.ReadFile(store.LockPath()); err != nil {
log.Fatalf("Store locked, lock file unreadable, %s", err)
- log.Exit(1)
} else {
log.Fatalf("Store locked by process %s.", string(pid))
- log.Exit(1)
}
}
if err := os.WriteFile(store.LockPath(), []byte(strconv.Itoa(os.Getpid())), store.PermissionFile); err != nil {
log.Fatalf("Error locking store, %s", err)
- log.Exit(1)
}
+
return store
}
// Close closes the store.
func (s *Store) Close() {
+ // Close all leveldb
+ for variant, ldb := range s.pageldb {
+ if err := ldb.Close(); err != nil {
+ log.Errorf("Error closing leveldb variant %s, %s", variant, err)
+ }
+ log.Infof("Page variant %s closed.", variant)
+ }
+
+ // Unlock store
if err := os.Remove(s.LockPath()); err != nil {
- log.Fatalf("Error unlocking store, %s", err)
- log.Exit(1)
+ log.Errorf("Error unlocking store, %s", err)
}
+
log.Info("Store closed.")
}
+// fatalClose closes the store and as cleanly as possible and exits with a fatal message.
+func (s *Store) fatalClose(message string) {
+ s.Close()
+ log.Fatal(message)
+}
+
// create sets up the store directory if it does not exist.
func (s *Store) create() error {
// Check if exists
@@ -163,18 +177,17 @@ func (s *Store) create() error {
if err := os.Mkdir(s.SecretsDir(), s.PermissionDir); err != nil {
return err
}
- if err := os.Mkdir(s.PageBaseDir(), s.PermissionDir); err != nil {
+ if err := os.Mkdir(s.UsernamesDir(), s.PermissionDir); err != nil {
return err
}
- if err := os.Mkdir(s.UsernamesDir(), s.PermissionDir); err != nil {
+ if err := os.Mkdir(s.PageBaseDir(), s.PermissionDir); err != nil {
return err
}
// Create initial user
info := s.UserAdd("root", true, "initial")
if info.Snowflake == "" {
- log.Fatalf("Error creating initial user.")
- os.Exit(1)
+ log.Fatal("Error creating initial user.")
} else {
log.Infof("Created initial user with username root and password initial.")
}
@@ -219,8 +232,7 @@ func (s *Store) file(path string) bool {
if os.IsNotExist(err) {
return false
} else {
- log.Fatalf("Error while stat %s, %s", path, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error stat %s, %s", path, err))
}
}
return true
@@ -232,13 +244,11 @@ func (s *Store) dir(path string) bool {
if os.IsNotExist(err) {
return false
} else {
- log.Fatalf("Error while stat %s, %s", path, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error stat %s, %s", path, err))
}
} else {
if !stat.IsDir() {
- log.Fatalf("Path %s is not a directory.", path)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Path %s is not a directory.", path))
}
}
return true
@@ -257,13 +267,11 @@ func (s *Store) flake(flake string) bool {
func (s *Store) link(old, new string) {
if !s.Compat {
if err := os.Symlink(old, new); err != nil {
- log.Fatalf("Error while linking %s to %s, %s", old, new, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error linking %s to %s, %s", old, new, err))
}
} else {
if err := os.WriteFile(new, []byte(old), s.PermissionFile); err != nil {
- log.Fatalf("Error while writing associate file for %s to %s, %s", old, new, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error writing associate file for %s to %s, %s", old, new, err))
}
}
}
@@ -276,7 +284,6 @@ func (s *Store) readlink(path string) string {
// return ""
// } else {
// log.Fatalf("Error reading symlink %s, %s.", path, err)
- // os.Exit(1)
// }
//} else {
// return final
@@ -287,8 +294,7 @@ func (s *Store) readlink(path string) string {
if os.IsNotExist(err) {
return ""
} else {
- log.Fatalf("Error reading association file %s, %s.", path, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error reading association file %s, %s.", path, err))
}
} else {
return string(final)