commit 927cb8b75a97c335f16894d3ba1ffe8cefe76e3c
parent 2492d80a6a8448c46fbacb8562a84ceac36d222b
Author: lash <dev@holbrook.no>
Date: Tue, 14 Jan 2025 19:59:28 +0000
Add fs db dumper
Diffstat:
5 files changed, 134 insertions(+), 2 deletions(-)
diff --git a/db/db.go b/db/db.go
@@ -209,5 +209,6 @@ func(bd *DbBase) ToKey(ctx context.Context, key []byte) (LookupKey, error) {
lk.Translation = ToDbKey(db.pfx, b, ln)
}
}
+ logg.TraceCtxf(ctx, "made key", "lk", lk.Default, "pfx", db.pfx)
return lk, nil
}
diff --git a/db/fs/dump.go b/db/fs/dump.go
@@ -1,12 +1,72 @@
package fs
import (
+ "bytes"
"context"
- "errors"
+ "os"
"git.defalsify.org/vise.git/db"
)
func(fdb *fsDb) Dump(ctx context.Context, key []byte) (*db.Dumper, error) {
- return nil, errors.New("unimplemented")
+ var err error
+ key = append([]byte{db.DATATYPE_USERDATA}, key...)
+ fdb.matchPrefix = key
+ fdb.elements, err = os.ReadDir(fdb.dir)
+ if err != nil {
+ return nil, err
+ }
+
+ if len(fdb.elements) > 0 {
+ if len(key) == 0 {
+ v := fdb.elements[0]
+ fdb.elements = fdb.elements[1:]
+ s := v.Name()
+ k := []byte(s)
+ k[0] -= 0x30
+ vv, err := fdb.Get(ctx, k)
+ if err != nil {
+ return nil, err
+ }
+ return db.NewDumper(fdb.dumpFunc).WithFirst(k, vv), nil
+ }
+ }
+ for len(fdb.elements) > 0 {
+ v := fdb.elements[0]
+ fdb.elements = fdb.elements[1:]
+ s := v.Name()
+ k := []byte(s)
+ if len(key) > len(k) {
+ continue
+ }
+ k[0] -= 0x30
+ if bytes.HasPrefix(k, key) {
+ vv, err := fdb.Get(ctx, k[1:])
+ if err != nil {
+ return nil, err
+ }
+ return db.NewDumper(fdb.dumpFunc).WithFirst(k, vv), nil
+ }
+ }
+ return nil, db.NewErrNotFound(key)
+}
+
+func(fdb *fsDb) dumpFunc(ctx context.Context) ([]byte, []byte) {
+ if len(fdb.elements) == 0 {
+ return nil, nil
+ }
+ v := fdb.elements[0]
+ fdb.elements = fdb.elements[1:]
+ s := v.Name()
+ k := []byte(s)
+ k[0] -= 0x30
+ if bytes.HasPrefix(k, fdb.matchPrefix) {
+ vv, err := fdb.Get(ctx, k[1:])
+ if err != nil {
+ logg.ErrorCtxf(ctx, "failed to get entry", "key", k)
+ return nil, nil
+ }
+ return k, vv
+ }
+ return nil, nil
}
diff --git a/db/fs/dump_test.go b/db/fs/dump_test.go
@@ -0,0 +1,68 @@
+package fs
+
+import (
+ "bytes"
+ "context"
+ "io/ioutil"
+ "testing"
+
+ "git.defalsify.org/vise.git/db"
+)
+
+func TestDumpFs(t *testing.T) {
+ ctx := context.Background()
+
+ store := NewFsDb()
+ d, err := ioutil.TempDir("", "vise-db-fs-*")
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = store.Connect(ctx, d)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ store.SetPrefix(db.DATATYPE_USERDATA)
+ err = store.Put(ctx, []byte("bar"), []byte("inky"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = store.Put(ctx, []byte("foobar"), []byte("pinky"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = store.Put(ctx, []byte("foobarbaz"), []byte("blinky"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = store.Put(ctx, []byte("xyzzy"), []byte("clyde"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ o, err := store.Dump(ctx, []byte("foo"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ k, v := o.Next(ctx)
+ if !bytes.Equal(k, append([]byte{db.DATATYPE_USERDATA}, []byte("foobar")...)) {
+ t.Fatalf("expected key 'foobar', got %s", k)
+ }
+ if !bytes.Equal(v, []byte("pinky")) {
+ t.Fatalf("expected val 'pinky', got %s", v)
+ }
+ k, v = o.Next(ctx)
+ if !bytes.Equal(k, append([]byte{db.DATATYPE_USERDATA}, []byte("foobarbaz")...)) {
+ t.Fatalf("expected key 'foobarbaz', got %s", k)
+ }
+ if !bytes.Equal(v, []byte("blinky")) {
+ t.Fatalf("expected val 'blinky', got %s", v)
+ }
+ k, v = o.Next(ctx)
+ if k != nil {
+ t.Fatalf("expected nil, got %s", k)
+ }
+}
+func TestDump(t *testing.T) {
+
+}
diff --git a/db/fs/fs.go b/db/fs/fs.go
@@ -21,6 +21,8 @@ type fsLookupKey struct {
type fsDb struct {
*db.DbBase
dir string
+ elements []os.DirEntry
+ matchPrefix []byte
}
diff --git a/db/gdbm/dump.go b/db/gdbm/dump.go
@@ -10,6 +10,7 @@ import (
"git.defalsify.org/vise.git/db"
)
+// TODO: userdata is hardcoded here, should not be
func(gdb *gdbmDb) Dump(ctx context.Context, key []byte) (*db.Dumper, error) {
key = append([]byte{db.DATATYPE_USERDATA}, key...)
gdb.it = gdb.conn.Iterator()