diff --git a/ratel/graph/main.go b/ratel/graph/main.go index 24c5cff..99206cf 100644 --- a/ratel/graph/main.go +++ b/ratel/graph/main.go @@ -209,6 +209,66 @@ func ToPath[V st | by](path []V) (b by) { return } +func Read[V by | st](g *T, path V) (b by, err er) { + log.I.F("Read %s %s", path, b) + pb := by(path) + if !bytes.HasPrefix(pb, by{'/'}) { + err = errorf.E("path must begin with the root /, '%s'", path) + return + } + split := bytes.Split(pb, by{'/'})[1:] + parent := serial.Make(0) + var found bo + for i, v := range split { + log.I.F("%s", v) + if err = g.DB.View(func(txn *badger.Txn) (err er) { + it := txn.NewIterator(badger.DefaultIteratorOptions) + defer it.Close() + prf := prefixes.Node.Key(parent) + for it.Rewind(); it.Valid(); it.Next() { + item := it.Item() + var val by + if val, err = item.ValueCopy(nil); chk.E(err) { + return + } + k := item.KeyCopy(nil) + if !bytes.HasPrefix(k, prf) { + continue + } + log.I.F("%d %s == %s", i, val, v) + if equals(v, val) { + parent = serial.FromKey(k) + found = true + return + } + } + return + }); chk.E(err) { + return + } + } + if found { + valKey := prefixes.Value.Key(parent) + if err = g.DB.View(func(txn *badger.Txn) (err er) { + it := txn.NewIterator(badger.DefaultIteratorOptions) + defer it.Close() + it.Seek(valKey) + if it.Valid() { + b, err = it.Item().ValueCopy(nil) + return + } + return + }); chk.E(err) { + return + } + // the value should now be returned + return + } else { + // if there is no value it's as though there is no value + } + return +} + func Write[V by | st](g *T, path, b V) (err er) { log.I.F("Write %s %s", path, b) pb := by(path) diff --git a/ratel/graph/main_test.go b/ratel/graph/main_test.go index 1cae1c8..3092bd9 100644 --- a/ratel/graph/main_test.go +++ b/ratel/graph/main_test.go @@ -26,30 +26,47 @@ func TestWrite(t *testing.T) { LogLevel: "trace", Compression: "zstd", }); chk.E(err) { - return + t.Fatal(err) } if err = g.Init(); chk.E(err) { - return + t.Fatal(err) } interrupt.AddHandler(func() { cancel() }) if err = Write(g, "/path/to/one", "1"); chk.E(err) { - return + t.Fatal(err) } fmt.Fprintln(os.Stderr) if err = Write(g, "/path/to/other/two", "2"); chk.E(err) { - return + t.Fatal(err) } fmt.Fprintln(os.Stderr) if err = Write(g, "/path/four", "4"); chk.E(err) { - return + t.Fatal(err) + } + fmt.Fprintln(os.Stderr) + var b by + if b, err = Read(g, "/path/four"); chk.E(err) { + t.Fatal(err) + } + log.I.F("/path/four = '%s'", b) + fmt.Fprintln(os.Stderr) + if b, err = Read(g, "/path/to/one"); chk.E(err) { + t.Fatal(err) + } + log.I.F("/path/to/one = '%s'", b) + fmt.Fprintln(os.Stderr) + if b, err = Read(g, "/path/to/other/two"); chk.E(err) { + t.Fatal(err) } + log.I.F("/path/to/other/two = '%s'", b) fmt.Fprintln(os.Stderr) g.DB.View(func(txn *badger.Txn) (err er) { it := txn.NewIterator(badger.DefaultIteratorOptions) defer it.Close() + log.I.F("content of db:") for it.Rewind(); it.Valid(); it.Next() { v, _ := it.Item().ValueCopy(nil) - log.I.F("%0x %0x %s", it.Item().Key(), v, v) + log.I.F("%0x [%s] %s", it.Item().Key(), it.Item().Key(), v) } return })