Starting work on server

This commit is contained in:
Brian Buller 2016-02-17 08:30:43 -06:00
parent d569c17220
commit e6fb690fc3
3 changed files with 175 additions and 8 deletions

2
boltrest-server/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
# Server Binary
boltrest-server

53
boltrest-server/main.go Normal file
View File

@ -0,0 +1,53 @@
package main
import (
"errors"
"math/rand"
"os"
"github.com/br0xen/boltrest"
)
var adminDB *boltrest.DB
func main() {
initialize()
adminDB = boltrest.Open("admin.db")
}
func initialize() error {
// Make sure that the necessary files/directories are in place
var tstDir *os.File
var tstDirInfo os.FileInfo
var err error
if tstDir, err = os.Open("dbs"); err != nil {
if err = os.Mkdir("dbs", 0755); err != nil {
return err
}
if tstDir, err = os.Open("dbs"); err != nil {
return err
}
}
if tstDirInfo, err = tstDir.Stat(); err != nil {
return err
}
if !tstDirInfo.IsDir() {
return errors.New("'dbs' exists and is not a directory")
}
// We were able to open the db path and it was a directory
return nil
}
const keyChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
func generateAPIKey() string {
b := make([]byte, 34)
for i := range b {
if i%5 == 4 {
b[i] = '-'
} else {
b[i] = keyChars[rand.Int63()%int64(len(keyChars))]
}
}
return string(b)
}

View File

@ -1,4 +1,4 @@
package boltrest/lib package boltrest
import ( import (
"encoding/json" "encoding/json"
@ -16,9 +16,6 @@ import (
// in a local bolt db and a remote db through a // in a local bolt db and a remote db through a
// rest api. // rest api.
// Custom BoltRest DB keys:
// __BR_LastUpdate: <RFC3339 Timestamp>
// DB is a struct for accomplishing this // DB is a struct for accomplishing this
type DB struct { type DB struct {
localFile string localFile string
@ -68,8 +65,7 @@ func (b *DB) GetValue(path []string, key string) (string, error) {
} }
// SetValue sets the value at path to val // SetValue sets the value at path to val
// path is a '/' separated list of tokens // path is a slice of tokens
// the last token is a key, all others are buckets
func (b *DB) SetValue(path []string, key, val string) error { func (b *DB) SetValue(path []string, key, val string) error {
var err error var err error
b.localDB.Update(func(tx *bolt.Tx) error { b.localDB.Update(func(tx *bolt.Tx) error {
@ -146,12 +142,128 @@ func (b *DB) SetTimestamp(path []string, key string, val time.Time) error {
return b.SetValue(path, key, val.Format(time.RFC3339)) return b.SetValue(path, key, val.Format(time.RFC3339))
} }
// GetBucketList returns a list of all sub-buckets at path
func (b *DB) GetBucketList(path []string) ([]string, error) {
var err error
var ret []string
// TODO: Make sure local db is fresh (or offline)
err = b.localDB.Update(func(tx *bolt.Tx) error {
bkt := tx.Bucket([]byte(path[0]))
if bkt == nil {
return fmt.Errorf("Couldn't find bucket " + path[0])
}
var newBkt *bolt.Bucket
for idx := 1; idx < len(path); idx++ {
newBkt = bkt.Bucket([]byte(path[idx]))
if newBkt == nil {
return fmt.Errorf("Couldn't find bucket " + strings.Join(path[:idx], "/"))
}
}
// newBkt should have the last bucket in the path
berr := newBkt.ForEach(func(k, v []byte) error {
if v == nil {
// Must be a bucket
ret = append(ret, string(k))
}
return nil
})
return berr
})
return ret, err
}
// GetKeyList returns a list of all keys at path
func (b *DB) GetKeyList(path []string) ([]string, error) {
var err error
var ret []string
// TODO: Make sure local db is fresh (or offline)
err = b.localDB.Update(func(tx *bolt.Tx) error {
bkt := tx.Bucket([]byte(path[0]))
if bkt == nil {
return fmt.Errorf("Couldn't find bucket " + path[0])
}
var newBkt *bolt.Bucket
for idx := 1; idx < len(path); idx++ {
newBkt = bkt.Bucket([]byte(path[idx]))
if newBkt == nil {
return fmt.Errorf("Couldn't find bucket " + strings.Join(path[:idx], "/"))
}
}
// newBkt should have the last bucket in the path
berr := newBkt.ForEach(func(k, v []byte) error {
if v != nil {
// Not a bucket
ret = append(ret, string(k))
}
return nil
})
return berr
})
return ret, err
}
// DeletePair deletes the pair with key at path
func (b *DB) DeletePair(path []string, key string) error {
var err error
// TODO: Make sure local db is fresh (or offline)
err = b.localDB.Update(func(tx *bolt.Tx) error {
bkt := tx.Bucket([]byte(path[0]))
if bkt == nil {
return fmt.Errorf("Couldn't find bucket " + path[0])
}
var newBkt *bolt.Bucket
for idx := 1; idx < len(path); idx++ {
newBkt = bkt.Bucket([]byte(path[idx]))
if newBkt == nil {
return fmt.Errorf("Couldn't find bucket " + strings.Join(path[:idx], "/"))
}
}
// newBkt should have the last bucket in the path
// Test to make sure that key is a pair, if so, delete it
if tst := newBkt.Bucket([]byte(key)); tst == nil {
return newBkt.Delete([]byte(key))
}
return nil
})
return err
}
// DeleteBucket deletes the bucket key at path
func (b *DB) DeleteBucket(path []string, key string) error {
var err error
// TODO: Make sure local db is fresh (or offline)
err = b.localDB.Update(func(tx *bolt.Tx) error {
bkt := tx.Bucket([]byte(path[0]))
if bkt == nil {
return fmt.Errorf("Couldn't find bucket " + path[0])
}
var newBkt *bolt.Bucket
for idx := 1; idx < len(path); idx++ {
newBkt = bkt.Bucket([]byte(path[idx]))
if newBkt == nil {
return fmt.Errorf("Couldn't find bucket " + strings.Join(path[:idx], "/"))
}
}
// newBkt should have the last bucket in the path
// Test to make sure that key is a bucket, if so, delete it
if tst := newBkt.Bucket([]byte(key)); tst != nil {
return newBkt.Delete([]byte(key))
}
return nil
})
return err
}
type setURLResponse struct { type setURLResponse struct {
dbMD5 string dbMD5 string
} }
// SetURL sets the DB's remote URL // SetDBURL sets the DB's remote URL
func (b *DB) SetURL(url string) (bool, string) { func (b *DB) SetDBURL(url string) (bool, string) {
resp, err := http.Get(url) resp, err := http.Get(url)
if err != nil { if err != nil {
return false, "" return false, ""