Commit bb801b23 authored by Tommi Virtanen's avatar Tommi Virtanen

Implement flatfs Query, in a dumb way

parent 3ee8720e
......@@ -54,6 +54,18 @@ func (fs *Datastore) encode(key datastore.Key) (dir, file string) {
return dir, file
}
func (fs *Datastore) decode(file string) (key datastore.Key, ok bool) {
if path.Ext(file) != extension {
return datastore.Key{}, false
}
name := file[:len(file)-len(extension)]
k, err := hex.DecodeString(name)
if err != nil {
return datastore.Key{}, false
}
return datastore.NewKey(string(k)), true
}
func (fs *Datastore) Put(key datastore.Key, value interface{}) error {
val, ok := value.([]byte)
if !ok {
......@@ -141,7 +153,54 @@ func (fs *Datastore) Delete(key datastore.Key) error {
}
func (fs *Datastore) Query(q query.Query) (query.Results, error) {
return nil, errors.New("TODO")
if (q.Prefix != "" && q.Prefix != "/") ||
len(q.Filters) > 0 ||
len(q.Orders) > 0 ||
q.Limit > 0 ||
q.Offset > 0 ||
!q.KeysOnly {
// TODO this is overly simplistic, but the only caller is
// `ipfs refs local` for now, and this gets us moving.
return nil, errors.New("flatfs only supports listing all keys in random order")
}
// TODO this dumb implementation gathers all keys into a single slice.
root, err := os.Open(fs.path)
if err != nil {
return nil, err
}
defer root.Close()
var res []query.Entry
prefixes, err := root.Readdir(0)
if err != nil {
return nil, err
}
for _, fi := range prefixes {
if !fi.IsDir() || fi.Name()[0] == '.' {
continue
}
child, err := os.Open(path.Join(fs.path, fi.Name()))
if err != nil {
return nil, err
}
defer child.Close()
objs, err := child.Readdir(0)
if err != nil {
return nil, err
}
for _, fi := range objs {
if !fi.Mode().IsRegular() || fi.Name()[0] == '.' {
continue
}
key, ok := fs.decode(fi.Name())
if !ok {
continue
}
res = append(res, query.Entry{Key: key.String()})
}
}
return query.ResultsWithEntries(q, res), nil
}
var _ datastore.ThreadSafeDatastore = (*Datastore)(nil)
......
......@@ -8,6 +8,7 @@ import (
"github.com/jbenet/go-datastore"
"github.com/jbenet/go-datastore/flatfs"
"github.com/jbenet/go-datastore/query"
)
func tempdir(t testing.TB) (path string, cleanup func()) {
......@@ -276,3 +277,39 @@ func TestDeleteFound(t *testing.T) {
t.Fatalf("expected Get after Delete to give ErrNotFound, got: %v\n", g)
}
}
func TestQuerySimple(t *testing.T) {
temp, cleanup := tempdir(t)
defer cleanup()
fs, err := flatfs.New(temp, 2)
if err != nil {
t.Fatalf("New fail: %v\n", err)
}
const myKey = "quux"
err = fs.Put(datastore.NewKey(myKey), []byte("foobar"))
if err != nil {
t.Fatalf("Put fail: %v\n", err)
}
res, err := fs.Query(query.Query{KeysOnly: true})
if err != nil {
t.Fatalf("Query fail: %v\n", err)
}
entries, err := res.Rest()
if err != nil {
t.Fatalf("Query Results.Rest fail: %v\n", err)
}
seen := false
for _, e := range entries {
switch e.Key {
case datastore.NewKey(myKey).String():
seen = true
default:
t.Errorf("saw unexpected key: %q", e.Key)
}
}
if !seen {
t.Errorf("did not see wanted key %q in %+v", myKey, entries)
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment