pkg/index: check for deletions in EdgesTo

Also introduced and used kvEdgeBackward

http://camlistore.org/issue/191

Change-Id: Ifdca9f2453ec0c7db55afc40cf0b5f1441b83158
This commit is contained in:
mpl 2013-11-28 17:46:36 +01:00
parent 2095a2c913
commit fa32346860
3 changed files with 80 additions and 27 deletions

View File

@ -952,43 +952,61 @@ func (x *Index) GetImageInfo(fileRef blob.Ref) (camtypes.ImageInfo, error) {
func (x *Index) EdgesTo(ref blob.Ref, opts *camtypes.EdgesToOpts) (edges []*camtypes.Edge, err error) { func (x *Index) EdgesTo(ref blob.Ref, opts *camtypes.EdgesToOpts) (edges []*camtypes.Edge, err error) {
it := x.queryPrefix(keyEdgeBackward, ref) it := x.queryPrefix(keyEdgeBackward, ref)
defer closeIterator(it, &err) defer closeIterator(it, &err)
permanodeParents := map[string]blob.Ref{} // blobref key => blobref set permanodeParents := make(map[string]*camtypes.Edge)
for it.Next() { for it.Next() {
keyPart := strings.Split(it.Key(), "|")[1:] edge, ok := kvEdgeBackward(it.Key(), it.Value())
if len(keyPart) < 2 {
continue
}
parent := keyPart[1]
parentRef, ok := blob.Parse(parent)
if !ok { if !ok {
continue continue
} }
valPart := strings.Split(it.Value(), "|") if x.IsDeleted(edge.From) {
if len(valPart) < 2 {
continue continue
} }
parentType, parentName := valPart[0], valPart[1] if x.IsDeleted(edge.BlobRef) {
if parentType == "permanode" { continue
permanodeParents[parent] = parentRef }
edge.To = ref
if edge.FromType == "permanode" {
permanodeParents[edge.From.String()] = edge
} else { } else {
edges = append(edges, &camtypes.Edge{ edges = append(edges, edge)
From: parentRef,
FromType: parentType,
FromTitle: parentName,
To: ref,
})
} }
} }
for _, parentRef := range permanodeParents { for _, e := range permanodeParents {
edges = append(edges, &camtypes.Edge{ edges = append(edges, e)
From: parentRef,
FromType: "permanode",
To: ref,
})
} }
return edges, nil return edges, nil
} }
func kvEdgeBackward(k, v string) (edge *camtypes.Edge, ok bool) {
// TODO(bradfitz): garbage
keyPart := strings.Split(k, "|")
valPart := strings.Split(v, "|")
if len(keyPart) != 4 || len(valPart) != 2 {
// TODO(mpl): use glog
log.Printf("bogus keyEdgeBackward index entry: %q = %q", k, v)
return
}
if keyPart[0] != "edgeback" {
return
}
parentRef, ok := blob.Parse(keyPart[2])
if !ok {
log.Printf("bogus parent in keyEdgeBackward index entry: %q", keyPart[2])
return
}
blobRef, ok := blob.Parse(keyPart[3])
if !ok {
log.Printf("bogus blobref in keyEdgeBackward index entry: %q", keyPart[3])
return
}
return &camtypes.Edge{
From: parentRef,
FromType: valPart[0],
FromTitle: valPart[1],
BlobRef: blobRef,
}, true
}
// GetDirMembers sends on dest the children of the static directory dir. // GetDirMembers sends on dest the children of the static directory dir.
func (x *Index) GetDirMembers(dir blob.Ref, dest chan<- blob.Ref, limit int) (err error) { func (x *Index) GetDirMembers(dir blob.Ref, dest chan<- blob.Ref, limit int) (err error) {
defer close(dest) defer close(dest)

View File

@ -825,16 +825,15 @@ func EdgesTo(t *testing.T, initIdx func() *index.Index) {
idx := initIdx() idx := initIdx()
id := NewIndexDeps(idx) id := NewIndexDeps(idx)
id.Fataler = t id.Fataler = t
defer id.DumpIndex(t)
// pn1 ---member---> pn2 // pn1 ---member---> pn2
pn1 := id.NewPermanode() pn1 := id.NewPermanode()
pn2 := id.NewPermanode() pn2 := id.NewPermanode()
id.AddAttribute(pn1, "camliMember", pn2.String()) claim1 := id.AddAttribute(pn1, "camliMember", pn2.String())
t.Logf("edge %s --> %s", pn1, pn2) t.Logf("edge %s --> %s", pn1, pn2)
id.DumpIndex(t)
// Look for pn1 // Look for pn1
{ {
edges, err := idx.EdgesTo(pn2, nil) edges, err := idx.EdgesTo(pn2, nil)
@ -853,6 +852,41 @@ func EdgesTo(t *testing.T, initIdx func() *index.Index) {
t.Errorf("Wrong edge.\n GOT: %v\nWANT: %v", got, want) t.Errorf("Wrong edge.\n GOT: %v\nWANT: %v", got, want)
} }
} }
// Delete claim -> break edge relationship.
del1 := id.Delete(claim1)
t.Logf("del claim %q deletes claim %q, breaks link between p1 and p2", del1, claim1)
// test that we can't find anymore pn1 from pn2
{
edges, err := idx.EdgesTo(pn2, nil)
if err != nil {
t.Fatal(err)
}
if len(edges) != 0 {
t.Fatalf("num edges = %d; want 0", len(edges))
}
}
// Undelete, should restore the link.
del2 := id.Delete(del1)
t.Logf("del claim %q deletes del claim %q, restores link between p1 and p2", del2, del1)
{
edges, err := idx.EdgesTo(pn2, nil)
if err != nil {
t.Fatal(err)
}
if len(edges) != 1 {
t.Fatalf("num edges = %d; want 1", len(edges))
}
wantEdge := &camtypes.Edge{
From: pn1,
To: pn2,
FromType: "permanode",
}
if got, want := edges[0].String(), wantEdge.String(); got != want {
t.Errorf("Wrong edge.\n GOT: %v\nWANT: %v", got, want)
}
}
} }
func Delete(t *testing.T, initIdx func() *index.Index) { func Delete(t *testing.T, initIdx func() *index.Index) {

View File

@ -157,6 +157,7 @@ type Edge struct {
FromType string // "permanode", "directory", etc FromType string // "permanode", "directory", etc
FromTitle string // name of source permanode or directory FromTitle string // name of source permanode or directory
To blob.Ref To blob.Ref
BlobRef blob.Ref // the blob responsible for the edge relationship
} }
func (e *Edge) String() string { func (e *Edge) String() string {