diff --git a/config/database.go b/config/database.go index 460aa01..109e575 100644 --- a/config/database.go +++ b/config/database.go @@ -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. diff --git a/config/option.go b/config/option.go index 4d79560..b4e928e 100644 --- a/config/option.go +++ b/config/option.go @@ -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 } diff --git a/database/controller.go b/database/controller.go index a9f9d48..e5e94fc 100644 --- a/database/controller.go +++ b/database/controller.go @@ -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 { diff --git a/database/storage/badger/badger.go b/database/storage/badger/badger.go index 8f473cd..82283d4 100644 --- a/database/storage/badger/badger.go +++ b/database/storage/badger/badger.go @@ -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. diff --git a/database/storage/badger/badger_test.go b/database/storage/badger/badger_test.go index 47e10b6..8cfae5a 100644 --- a/database/storage/badger/badger_test.go +++ b/database/storage/badger/badger_test.go @@ -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) } diff --git a/database/storage/bbolt/bbolt.go b/database/storage/bbolt/bbolt.go index bb049a9..26666d9 100644 --- a/database/storage/bbolt/bbolt.go +++ b/database/storage/bbolt/bbolt.go @@ -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. diff --git a/database/storage/bbolt/bbolt_test.go b/database/storage/bbolt/bbolt_test.go index e5cdd3e..84586a3 100644 --- a/database/storage/bbolt/bbolt_test.go +++ b/database/storage/bbolt/bbolt_test.go @@ -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) diff --git a/database/storage/fstree/fstree.go b/database/storage/fstree/fstree.go index fa160de..34fc9f3 100644 --- a/database/storage/fstree/fstree.go +++ b/database/storage/fstree/fstree.go @@ -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. diff --git a/database/storage/hashmap/map.go b/database/storage/hashmap/map.go index d9fa3df..ba6afd6 100644 --- a/database/storage/hashmap/map.go +++ b/database/storage/hashmap/map.go @@ -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. diff --git a/database/storage/hashmap/map_test.go b/database/storage/hashmap/map_test.go index 911dc5b..a546809 100644 --- a/database/storage/hashmap/map_test.go +++ b/database/storage/hashmap/map_test.go @@ -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) diff --git a/database/storage/injectbase.go b/database/storage/injectbase.go index 2596820..182291c 100644 --- a/database/storage/injectbase.go +++ b/database/storage/injectbase.go @@ -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. diff --git a/database/storage/interface.go b/database/storage/interface.go index 484f852..bdf12e4 100644 --- a/database/storage/interface.go +++ b/database/storage/interface.go @@ -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) diff --git a/database/storage/sinkhole/sinkhole.go b/database/storage/sinkhole/sinkhole.go index e26eaa5..dd3b065 100644 --- a/database/storage/sinkhole/sinkhole.go +++ b/database/storage/sinkhole/sinkhole.go @@ -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. diff --git a/log/output.go b/log/output.go index 28bde37..0b5c799 100644 --- a/log/output.go +++ b/log/output.go @@ -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 } } diff --git a/notifications/database.go b/notifications/database.go index debeffc..58b455c 100644 --- a/notifications/database.go +++ b/notifications/database.go @@ -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.