Unverified Commit f1728295 authored by Steven Allen's avatar Steven Allen Committed by GitHub

Merge pull request #81 from ipfs/fix/panic-on-delete

fix: fix a panic when deleting
parents da35b26a af8709db
...@@ -489,10 +489,28 @@ func (ds *Shard) modifyValue(ctx context.Context, hv *hashBits, key string, val ...@@ -489,10 +489,28 @@ func (ds *Shard) modifyValue(ctx context.Context, hv *hashBits, key string, val
// structures, this will help to normalize them. // structures, this will help to normalize them.
return ds.childer.rm(idx) return ds.childer.rm(idx)
case 1: case 1:
nchild := child.childer.children[0] // The single child _should_ be a value by
if nchild.isValueNode() { // induction. However, we allow for it to be a
// shard in case an implementation is broken.
// Have we loaded the child? Prefer that.
schild := child.childer.child(0)
if schild != nil {
if schild.isValueNode() {
ds.childer.set(schild, i)
}
return nil
}
// Otherwise, work with the link.
slnk := child.childer.link(0)
lnkType, err := child.childer.sd.childLinkType(slnk)
if err != nil {
return err
}
if lnkType == shardValueLink {
// sub-shard with a single value element, collapse it // sub-shard with a single value element, collapse it
ds.childer.set(nchild, i) ds.childer.setLink(slnk, i)
} }
return nil return nil
} }
...@@ -517,6 +535,8 @@ type childer struct { ...@@ -517,6 +535,8 @@ type childer struct {
sd *Shard sd *Shard
dserv ipld.DAGService dserv ipld.DAGService
bitfield bitfield.Bitfield bitfield bitfield.Bitfield
// Only one of links/children will be non-nil for every child/link.
links []*ipld.Link links []*ipld.Link
children []*Shard children []*Shard
} }
...@@ -572,6 +592,12 @@ func (s *childer) insert(key string, lnk *ipld.Link, idx int) error { ...@@ -572,6 +592,12 @@ func (s *childer) insert(key string, lnk *ipld.Link, idx int) error {
func (s *childer) set(sd *Shard, i int) { func (s *childer) set(sd *Shard, i int) {
s.children[i] = sd s.children[i] = sd
s.links[i] = nil
}
func (s *childer) setLink(lnk *ipld.Link, i int) {
s.children[i] = nil
s.links[i] = lnk
} }
func (s *childer) rm(childIndex int) error { func (s *childer) rm(childIndex int) error {
......
...@@ -268,6 +268,45 @@ func TestRemoveElems(t *testing.T) { ...@@ -268,6 +268,45 @@ func TestRemoveElems(t *testing.T) {
} }
} }
func TestRemoveAfterMarshal(t *testing.T) {
ds := mdtest.Mock()
dirs, s, err := makeDir(ds, 500)
if err != nil {
t.Fatal(err)
}
nd, err := s.Node()
if err != nil {
t.Fatal(err)
}
s, err = NewHamtFromDag(ds, nd)
ctx := context.Background()
shuffle(time.Now().UnixNano(), dirs)
for i, d := range dirs {
err := s.Remove(ctx, d)
if err != nil {
t.Fatalf("%d/%d: %s", i, len(dirs), err)
}
}
nd, err = s.Node()
if err != nil {
t.Fatal(err)
}
if len(nd.Links()) > 0 {
t.Fatal("shouldnt have any links here")
}
err = s.Remove(ctx, "doesnt exist")
if err != os.ErrNotExist {
t.Fatal("expected error does not exist")
}
}
func TestSetAfterMarshal(t *testing.T) { func TestSetAfterMarshal(t *testing.T) {
ds := mdtest.Mock() ds := mdtest.Mock()
_, s, err := makeDir(ds, 300) _, s, err := makeDir(ds, 300)
......
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