mirror of
https://github.com/safing/portbase
synced 2025-09-01 18:19:57 +00:00
Merge pull request #32 from safing/feature/improve-storage-put
Improve database storage put method
This commit is contained in:
commit
c58d6a0f30
15 changed files with 59 additions and 48 deletions
|
@ -36,26 +36,30 @@ func (s *StorageInterface) Get(key string) (record.Record, error) {
|
|||
}
|
||||
|
||||
// Put stores a record in the database.
|
||||
func (s *StorageInterface) Put(r record.Record) error {
|
||||
func (s *StorageInterface) Put(r record.Record) (record.Record, error) {
|
||||
if r.Meta().Deleted > 0 {
|
||||
return setConfigOption(r.DatabaseKey(), nil, false)
|
||||
return r, setConfigOption(r.DatabaseKey(), nil, false)
|
||||
}
|
||||
|
||||
acc := r.GetAccessor(r)
|
||||
if acc == nil {
|
||||
return errors.New("invalid data")
|
||||
return nil, errors.New("invalid data")
|
||||
}
|
||||
|
||||
val, ok := acc.Get("Value")
|
||||
if !ok || val == nil {
|
||||
return setConfigOption(r.DatabaseKey(), nil, false)
|
||||
err := setConfigOption(r.DatabaseKey(), nil, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.Get(r.DatabaseKey())
|
||||
}
|
||||
|
||||
optionsLock.RLock()
|
||||
option, ok := options[r.DatabaseKey()]
|
||||
optionsLock.RUnlock()
|
||||
if !ok {
|
||||
return errors.New("config option does not exist")
|
||||
return nil, errors.New("config option does not exist")
|
||||
}
|
||||
|
||||
var value interface{}
|
||||
|
@ -70,14 +74,14 @@ func (s *StorageInterface) Put(r record.Record) error {
|
|||
value, ok = acc.GetBool("Value")
|
||||
}
|
||||
if !ok {
|
||||
return errors.New("received invalid value in \"Value\"")
|
||||
return nil, errors.New("received invalid value in \"Value\"")
|
||||
}
|
||||
|
||||
err := setConfigOption(r.DatabaseKey(), value, false)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
return nil
|
||||
return option.Export()
|
||||
}
|
||||
|
||||
// Delete deletes a record from the database.
|
||||
|
|
|
@ -70,14 +70,14 @@ func (option *Option) Export() (record.Record, error) {
|
|||
}
|
||||
|
||||
if option.activeValue != nil {
|
||||
data, err = sjson.SetBytes(data, "Value", option.activeValue)
|
||||
data, err = sjson.SetBytes(data, "Value", option.activeValue.getData(option))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if option.activeDefaultValue != nil {
|
||||
data, err = sjson.SetBytes(data, "DefaultValue", option.activeDefaultValue)
|
||||
data, err = sjson.SetBytes(data, "DefaultValue", option.activeDefaultValue.getData(option))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package database
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sync"
|
||||
|
||||
"github.com/tevino/abool"
|
||||
|
@ -119,10 +120,13 @@ func (c *Controller) Put(r record.Record) (err error) {
|
|||
}
|
||||
}
|
||||
|
||||
err = c.storage.Put(r)
|
||||
r, err = c.storage.Put(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if r == nil {
|
||||
return errors.New("storage returned nil record after successful put operation")
|
||||
}
|
||||
|
||||
// process subscriptions
|
||||
for _, sub := range c.subscriptions {
|
||||
|
|
|
@ -82,16 +82,19 @@ func (b *Badger) Get(key string) (record.Record, error) {
|
|||
}
|
||||
|
||||
// Put stores a record in the database.
|
||||
func (b *Badger) Put(r record.Record) error {
|
||||
func (b *Badger) Put(r record.Record) (record.Record, error) {
|
||||
data, err := r.MarshalRecord(r)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = b.db.Update(func(txn *badger.Txn) error {
|
||||
return txn.Set([]byte(r.DatabaseKey()), data)
|
||||
})
|
||||
return err
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// Delete deletes a record from the database.
|
||||
|
|
|
@ -65,7 +65,7 @@ func TestBadger(t *testing.T) {
|
|||
a.SetKey("test:A")
|
||||
|
||||
// put record
|
||||
err = db.Put(a)
|
||||
_, err = db.Put(a)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -86,10 +86,10 @@ func (b *BBolt) Get(key string) (record.Record, error) {
|
|||
}
|
||||
|
||||
// Put stores a record in the database.
|
||||
func (b *BBolt) Put(r record.Record) error {
|
||||
func (b *BBolt) Put(r record.Record) (record.Record, error) {
|
||||
data, err := r.MarshalRecord(r)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = b.db.Update(func(tx *bbolt.Tx) error {
|
||||
|
@ -100,9 +100,9 @@ func (b *BBolt) Put(r record.Record) error {
|
|||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
return nil
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// PutMany stores many records in the database.
|
||||
|
|
|
@ -65,7 +65,7 @@ func TestBBolt(t *testing.T) {
|
|||
a.SetKey("test:A")
|
||||
|
||||
// put record
|
||||
err = db.Put(a)
|
||||
_, err = db.Put(a)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -100,15 +100,15 @@ func TestBBolt(t *testing.T) {
|
|||
qZ.SetKey("test:z")
|
||||
qZ.CreateMeta()
|
||||
// put
|
||||
err = db.Put(qA)
|
||||
_, err = db.Put(qA)
|
||||
if err == nil {
|
||||
err = db.Put(qB)
|
||||
_, err = db.Put(qB)
|
||||
}
|
||||
if err == nil {
|
||||
err = db.Put(qC)
|
||||
_, err = db.Put(qC)
|
||||
}
|
||||
if err == nil {
|
||||
err = db.Put(qZ)
|
||||
_, err = db.Put(qZ)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
|
@ -104,15 +104,15 @@ func (fst *FSTree) Get(key string) (record.Record, error) {
|
|||
}
|
||||
|
||||
// Put stores a record in the database.
|
||||
func (fst *FSTree) Put(r record.Record) error {
|
||||
func (fst *FSTree) Put(r record.Record) (record.Record, error) {
|
||||
dstPath, err := fst.buildFilePath(r.DatabaseKey(), true)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := r.MarshalRecord(r)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = writeFile(dstPath, data, defaultFileMode)
|
||||
|
@ -120,15 +120,15 @@ func (fst *FSTree) Put(r record.Record) error {
|
|||
// create dir and try again
|
||||
err = os.MkdirAll(filepath.Dir(dstPath), defaultDirMode)
|
||||
if err != nil {
|
||||
return fmt.Errorf("fstree: failed to create directory %s: %s", filepath.Dir(dstPath), err)
|
||||
return nil, fmt.Errorf("fstree: failed to create directory %s: %s", filepath.Dir(dstPath), err)
|
||||
}
|
||||
err = writeFile(dstPath, data, defaultFileMode)
|
||||
if err != nil {
|
||||
return fmt.Errorf("fstree: could not write file %s: %s", dstPath, err)
|
||||
return nil, fmt.Errorf("fstree: could not write file %s: %s", dstPath, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// Delete deletes a record from the database.
|
||||
|
|
|
@ -44,12 +44,12 @@ func (hm *HashMap) Get(key string) (record.Record, error) {
|
|||
}
|
||||
|
||||
// Put stores a record in the database.
|
||||
func (hm *HashMap) Put(r record.Record) error {
|
||||
func (hm *HashMap) Put(r record.Record) (record.Record, error) {
|
||||
hm.dbLock.Lock()
|
||||
defer hm.dbLock.Unlock()
|
||||
|
||||
hm.db[r.DatabaseKey()] = r
|
||||
return nil
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// PutMany stores many records in the database.
|
||||
|
|
|
@ -57,7 +57,7 @@ func TestHashMap(t *testing.T) {
|
|||
a.SetKey("test:A")
|
||||
|
||||
// put record
|
||||
err = db.Put(a)
|
||||
_, err = db.Put(a)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -86,15 +86,15 @@ func TestHashMap(t *testing.T) {
|
|||
qZ.SetKey("test:z")
|
||||
qZ.CreateMeta()
|
||||
// put
|
||||
err = db.Put(qA)
|
||||
_, err = db.Put(qA)
|
||||
if err == nil {
|
||||
err = db.Put(qB)
|
||||
_, err = db.Put(qB)
|
||||
}
|
||||
if err == nil {
|
||||
err = db.Put(qC)
|
||||
_, err = db.Put(qC)
|
||||
}
|
||||
if err == nil {
|
||||
err = db.Put(qZ)
|
||||
_, err = db.Put(qZ)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
|
@ -21,8 +21,8 @@ func (i *InjectBase) Get(key string) (record.Record, error) {
|
|||
}
|
||||
|
||||
// Put stores a record in the database.
|
||||
func (i *InjectBase) Put(m record.Record) error {
|
||||
return errNotImplemented
|
||||
func (i *InjectBase) Put(m record.Record) (record.Record, error) {
|
||||
return nil, errNotImplemented
|
||||
}
|
||||
|
||||
// PutMany stores many records in the database.
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
// Interface defines the database storage API.
|
||||
type Interface interface {
|
||||
Get(key string) (record.Record, error)
|
||||
Put(m record.Record) error
|
||||
Put(m record.Record) (record.Record, error)
|
||||
Delete(key string) error
|
||||
Query(q *query.Query, local, internal bool) (*iterator.Iterator, error)
|
||||
|
||||
|
|
|
@ -36,8 +36,8 @@ func (s *Sinkhole) Get(key string) (record.Record, error) {
|
|||
}
|
||||
|
||||
// Put stores a record in the database.
|
||||
func (s *Sinkhole) Put(m record.Record) error {
|
||||
return nil
|
||||
func (s *Sinkhole) Put(r record.Record) (record.Record, error) {
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// PutMany stores many records in the database.
|
||||
|
|
|
@ -41,7 +41,7 @@ func writeLine(line *logLine, duplicates uint64) {
|
|||
}
|
||||
|
||||
func startWriter() {
|
||||
fmt.Println(fmt.Sprintf("%s%s %s BOF%s", InfoLevel.color(), time.Now().Format(timeFormat), rightArrow, endColor()))
|
||||
fmt.Printf("%s%s %s BOF%s\n", InfoLevel.color(), time.Now().Format(timeFormat), rightArrow, endColor())
|
||||
|
||||
shutdownWaitGroup.Add(1)
|
||||
go writerManager()
|
||||
|
@ -168,7 +168,7 @@ func finalizeWriting() {
|
|||
case line := <-logBuffer:
|
||||
writeLine(line, 0)
|
||||
case <-time.After(10 * time.Millisecond):
|
||||
fmt.Println(fmt.Sprintf("%s%s %s EOF%s", InfoLevel.color(), time.Now().Format(timeFormat), leftArrow, endColor()))
|
||||
fmt.Printf("%s%s %s EOF%s\n", InfoLevel.color(), time.Now().Format(timeFormat), leftArrow, endColor())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,26 +111,26 @@ func (s *StorageInterface) processQuery(q *query.Query, it *iterator.Iterator) {
|
|||
}
|
||||
|
||||
// Put stores a record in the database.
|
||||
func (s *StorageInterface) Put(r record.Record) error {
|
||||
func (s *StorageInterface) Put(r record.Record) (record.Record, error) {
|
||||
// record is already locked!
|
||||
key := r.DatabaseKey()
|
||||
n, err := EnsureNotification(r)
|
||||
|
||||
if err != nil {
|
||||
return ErrInvalidData
|
||||
return nil, ErrInvalidData
|
||||
}
|
||||
|
||||
// transform key
|
||||
if strings.HasPrefix(key, "all/") {
|
||||
key = strings.TrimPrefix(key, "all/")
|
||||
} else {
|
||||
return ErrInvalidPath
|
||||
return nil, ErrInvalidPath
|
||||
}
|
||||
|
||||
// continue in goroutine
|
||||
go UpdateNotification(n, key)
|
||||
|
||||
return nil
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// UpdateNotification updates a notification with input from a database action. Notification will not be saved/propagated if there is no valid change.
|
||||
|
|
Loading…
Add table
Reference in a new issue