Add simple 'read-only' mode.
It just closes the database as soon as it's done loading it. To refresh, you have to close out and reopen.
This commit is contained in:
parent
6261d4da06
commit
7d7e0bfcd3
@ -364,6 +364,9 @@ func addBucketFromBoltBucket(path []string, bb *BoltBucket) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func deleteKey(path []string) error {
|
func deleteKey(path []string) error {
|
||||||
|
if AppArgs.ReadOnly {
|
||||||
|
return errors.New("DB is in Read-Only Mode")
|
||||||
|
}
|
||||||
err := db.Update(func(tx *bolt.Tx) error {
|
err := db.Update(func(tx *bolt.Tx) error {
|
||||||
// len(b.path)-1 is the key we need to delete,
|
// len(b.path)-1 is the key we need to delete,
|
||||||
// the rest are buckets leading to that key
|
// the rest are buckets leading to that key
|
||||||
@ -469,6 +472,9 @@ func renameBucket(path []string, name string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func updatePairKey(path []string, k string) error {
|
func updatePairKey(path []string, k string) error {
|
||||||
|
if AppArgs.ReadOnly {
|
||||||
|
return errors.New("DB is in Read-Only Mode")
|
||||||
|
}
|
||||||
err := db.Update(func(tx *bolt.Tx) error {
|
err := db.Update(func(tx *bolt.Tx) error {
|
||||||
// len(b.path)-1 is the key for the pair we're updating,
|
// len(b.path)-1 is the key for the pair we're updating,
|
||||||
// the rest are buckets leading to that key
|
// the rest are buckets leading to that key
|
||||||
@ -498,6 +504,9 @@ func updatePairKey(path []string, k string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func updatePairValue(path []string, v string) error {
|
func updatePairValue(path []string, v string) error {
|
||||||
|
if AppArgs.ReadOnly {
|
||||||
|
return errors.New("DB is in Read-Only Mode")
|
||||||
|
}
|
||||||
err := db.Update(func(tx *bolt.Tx) error {
|
err := db.Update(func(tx *bolt.Tx) error {
|
||||||
// len(b.GetPath())-1 is the key for the pair we're updating,
|
// len(b.GetPath())-1 is the key for the pair we're updating,
|
||||||
// the rest are buckets leading to that key
|
// the rest are buckets leading to that key
|
||||||
@ -521,6 +530,9 @@ func updatePairValue(path []string, v string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func insertBucket(path []string, n string) error {
|
func insertBucket(path []string, n string) error {
|
||||||
|
if AppArgs.ReadOnly {
|
||||||
|
return errors.New("DB is in Read-Only Mode")
|
||||||
|
}
|
||||||
// Inserts a new bucket named 'n' at 'path'
|
// Inserts a new bucket named 'n' at 'path'
|
||||||
err := db.Update(func(tx *bolt.Tx) error {
|
err := db.Update(func(tx *bolt.Tx) error {
|
||||||
if len(path) == 0 {
|
if len(path) == 0 {
|
||||||
@ -558,6 +570,9 @@ func insertBucket(path []string, n string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func insertPair(path []string, k string, v string) error {
|
func insertPair(path []string, k string, v string) error {
|
||||||
|
if AppArgs.ReadOnly {
|
||||||
|
return errors.New("DB is in Read-Only Mode")
|
||||||
|
}
|
||||||
// Insert a new pair k => v at path
|
// Insert a new pair k => v at path
|
||||||
err := db.Update(func(tx *bolt.Tx) error {
|
err := db.Update(func(tx *bolt.Tx) error {
|
||||||
if len(path) == 0 {
|
if len(path) == 0 {
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
@ -20,27 +21,79 @@ var currentFilename string
|
|||||||
|
|
||||||
const DefaultDBOpenTimeout = time.Second
|
const DefaultDBOpenTimeout = time.Second
|
||||||
|
|
||||||
var args struct {
|
var AppArgs struct {
|
||||||
DBOpenTimeout time.Duration
|
DBOpenTimeout time.Duration
|
||||||
|
ReadOnly bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
flag.DurationVar(&args.DBOpenTimeout, "timeout", DefaultDBOpenTimeout, "DB file open timeout")
|
AppArgs.DBOpenTimeout = DefaultDBOpenTimeout
|
||||||
flag.Usage = func() {
|
AppArgs.ReadOnly = false
|
||||||
fmt.Fprintf(os.Stderr, "Usage: %s [OPTIONS] <filename(s)>\nOptions:\n", ProgramName)
|
|
||||||
flag.PrintDefaults()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseArgs() {
|
||||||
|
var err error
|
||||||
|
if len(os.Args) == 1 {
|
||||||
|
printUsage(nil)
|
||||||
|
}
|
||||||
|
parms := os.Args[1:]
|
||||||
|
for i := range parms {
|
||||||
|
// All 'option' arguments start with "-"
|
||||||
|
if !strings.HasPrefix(parms[i], "-") {
|
||||||
|
databaseFiles = append(databaseFiles, parms[i])
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings.Contains(parms[i], "=") {
|
||||||
|
// Key/Value pair Arguments
|
||||||
|
pts := strings.Split(parms[i], "=")
|
||||||
|
key, val := pts[0], pts[1]
|
||||||
|
switch key {
|
||||||
|
case "-timeout":
|
||||||
|
AppArgs.DBOpenTimeout, err = time.ParseDuration(val)
|
||||||
|
if err != nil {
|
||||||
|
// See if we can successfully parse by adding a 's'
|
||||||
|
AppArgs.DBOpenTimeout, err = time.ParseDuration(val + "s")
|
||||||
|
}
|
||||||
|
// If err is still not nil, print usage
|
||||||
|
if err != nil {
|
||||||
|
printUsage(err)
|
||||||
|
}
|
||||||
|
case "-readonly", "-ro":
|
||||||
|
if val == "true" {
|
||||||
|
AppArgs.ReadOnly = true
|
||||||
|
}
|
||||||
|
case "-help":
|
||||||
|
printUsage(nil)
|
||||||
|
default:
|
||||||
|
printUsage(errors.New("Invalid option"))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Single-word arguments
|
||||||
|
switch parms[i] {
|
||||||
|
case "-readonly", "-ro":
|
||||||
|
AppArgs.ReadOnly = true
|
||||||
|
case "-help":
|
||||||
|
printUsage(nil)
|
||||||
|
default:
|
||||||
|
printUsage(errors.New("Invalid option"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printUsage(err error) {
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, err.Error())
|
||||||
|
}
|
||||||
|
fmt.Fprintf(os.Stderr, "Usage: %s [OPTIONS] <filename(s)>\nOptions:\n", ProgramName)
|
||||||
|
fmt.Fprintf(os.Stderr, " -timeout=duration\n DB file open timeout (default 1s)\n")
|
||||||
|
fmt.Fprintf(os.Stderr, " -ro, -readonly \n Open the DB in read-only mode\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
flag.Parse()
|
parseArgs()
|
||||||
|
|
||||||
if flag.NArg() == 0 {
|
|
||||||
flag.Usage()
|
|
||||||
os.Exit(2)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = termbox.Init()
|
err = termbox.Init()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -50,10 +103,9 @@ func main() {
|
|||||||
style := defaultStyle()
|
style := defaultStyle()
|
||||||
termbox.SetOutputMode(termbox.Output256)
|
termbox.SetOutputMode(termbox.Output256)
|
||||||
|
|
||||||
databaseFiles := flag.Args()
|
|
||||||
for _, databaseFile := range databaseFiles {
|
for _, databaseFile := range databaseFiles {
|
||||||
currentFilename = databaseFile
|
currentFilename = databaseFile
|
||||||
db, err = bolt.Open(databaseFile, 0600, &bolt.Options{Timeout: args.DBOpenTimeout})
|
db, err = bolt.Open(databaseFile, 0600, &bolt.Options{Timeout: AppArgs.DBOpenTimeout})
|
||||||
if err == bolt.ErrTimeout {
|
if err == bolt.ErrTimeout {
|
||||||
termbox.Close()
|
termbox.Close()
|
||||||
fmt.Printf("File %s is locked. Make sure it's not used by another app and try again\n", databaseFile)
|
fmt.Printf("File %s is locked. Make sure it's not used by another app and try again\n", databaseFile)
|
||||||
@ -65,12 +117,17 @@ func main() {
|
|||||||
} else {
|
} else {
|
||||||
termbox.Close()
|
termbox.Close()
|
||||||
fmt.Printf("Error reading file: %q\n", err.Error())
|
fmt.Printf("Error reading file: %q\n", err.Error())
|
||||||
os.Exit(111)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// First things first, load the database into memory
|
// First things first, load the database into memory
|
||||||
memBolt.refreshDatabase()
|
memBolt.refreshDatabase()
|
||||||
|
if AppArgs.ReadOnly {
|
||||||
|
// If we're opening it in readonly mode, close it now
|
||||||
|
db.Close()
|
||||||
|
}
|
||||||
|
|
||||||
// Kick off the UI loop
|
// Kick off the UI loop
|
||||||
mainLoop(memBolt, style)
|
mainLoop(memBolt, style)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
Loading…
Reference in New Issue
Block a user