diff options
Diffstat (limited to 'store/store.go')
-rw-r--r-- | store/store.go | 66 |
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) |