Skip to content

Commit bbdbd0a

Browse files
Merge pull request #4398 from ipfs/fix/hamt-bug
fix hamt delete issue
2 parents 715bd16 + 76e4dcf commit bbdbd0a

File tree

10 files changed

+58
-53
lines changed

10 files changed

+58
-53
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ os:
1010
language: go
1111

1212
go:
13-
- 1.8
13+
- 1.9
1414

1515
env:
1616
- TEST_NO_FUSE=1 TEST_VERBOSE=1 TEST_SUITE=test_go_expensive

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ With snap, in any of the [supported Linux distributions](https://snapcraft.io/do
104104

105105
#### Install Go
106106

107-
The build process for ipfs requires Go 1.8 or higher. If you don't have it: [Download Go 1.8+](https://golang.org/dl/).
107+
The build process for ipfs requires Go 1.9 or higher. If you don't have it: [Download Go 1.9+](https://golang.org/dl/).
108108

109109

110110
You'll need to add Go's bin directories to your `$PATH` environment variable e.g., by adding these lines to your `/etc/profile` (for a system-wide installation) or `$HOME/.profile`:
@@ -148,7 +148,7 @@ mismatched APIs.
148148
* Also, [instructions for OpenBSD](docs/openbsd.md).
149149
* `git` is required in order for `go get` to fetch all dependencies.
150150
* Package managers often contain out-of-date `golang` packages.
151-
Ensure that `go version` reports at least 1.8. See above for how to install go.
151+
Ensure that `go version` reports at least 1.9. See above for how to install go.
152152
* If you are interested in development, please install the development
153153
dependencies as well.
154154
* *WARNING: Older versions of OSX FUSE (for Mac OS X) can cause kernel panics when mounting!*

bin/Rules.mk

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
include mk/header.mk
22

3-
dist_root_$(d)=/ipfs/QmR27Do9gqx9VmuQTEX1UGXETSWYJTQzPzxS5FNUnySCv1
3+
dist_root_$(d)=/ipfs/QmT3CLJKJzWPuN4NAN4LLy69UpKskMF3AuYhXstKdn8V43
44

5-
$(d)/gx: $(d)/gx-v0.12.0
6-
$(d)/gx-go: $(d)/gx-go-v1.5.0
5+
$(d)/gx: $(d)/gx-v0.12.1
6+
$(d)/gx-go: $(d)/gx-go-v1.6.0
77

88
TGTS_$(d) := $(d)/gx $(d)/gx-go
99
DISTCLEAN += $(wildcard $(d)/gx-v*) $(wildcard $(d)/gx-go-v*) $(d)/tmp

ci/Dockerfile.buildenv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM golang:1.8
1+
FROM golang:1.9
22
MAINTAINER Jakub Sztandera <[email protected]>
33

44

circle.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ machine:
1212

1313
post:
1414
- sudo rm -rf /usr/local/go
15-
- if [ ! -e go1.8.3.linux-amd64.tar.gz ]; then curl -o go1.8.3.linux-amd64.tar.gz https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz; fi
16-
- sudo tar -C /usr/local -xzf go1.8.3.linux-amd64.tar.gz
15+
- if [ ! -e go1.9.2.linux-amd64.tar.gz ]; then curl -o go1.9.2.linux-amd64.tar.gz https://storage.googleapis.com/golang/go1.9.2.linux-amd64.tar.gz; fi
16+
- sudo tar -C /usr/local -xzf go1.9.2.linux-amd64.tar.gz
1717

1818
services:
1919
- docker
@@ -30,7 +30,7 @@ dependencies:
3030
- cd "$HOME/.go_workspace/src/$IMPORT_PATH" && make deps
3131

3232
cache_directories:
33-
- ~/go1.8.3.linux-amd64.tar.gz
33+
- ~/go1.9.2.linux-amd64.tar.gz
3434
- "$HOME/.go_workspace/src/gx/ipfs"
3535

3636
test:

mk/golang.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# golang utilities
2-
GO_MIN_VERSION = 1.8
2+
GO_MIN_VERSION = 1.9
33

44
# pre-definitions
55
GOCC ?= go

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
},
55
"gx": {
66
"dvcsimport": "github.com/ipfs/go-ipfs",
7-
"goversion": "1.8"
7+
"goversion": "1.9"
88
},
99
"gxDependencies": [
1010
{

unixfs/hamt/hamt.go

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -492,39 +492,44 @@ func (ds *HamtShard) modifyValue(ctx context.Context, hv *hashBits, key string,
492492

493493
return nil
494494
case *shardValue:
495-
switch {
496-
case val == nil: // passing a nil value signifies a 'delete'
497-
ds.bitfield.SetBit(ds.bitfield, idx, 0)
498-
return ds.rmChild(cindex)
495+
if child.key == key {
496+
// value modification
497+
if val == nil {
498+
ds.bitfield.SetBit(ds.bitfield, idx, 0)
499+
return ds.rmChild(cindex)
500+
}
499501

500-
case child.key == key: // value modification
501502
child.val = val
502503
return nil
504+
}
503505

504-
default: // replace value with another shard, one level deeper
505-
ns, err := NewHamtShard(ds.dserv, ds.tableSize)
506-
if err != nil {
507-
return err
508-
}
509-
ns.prefix = ds.prefix
510-
chhv := &hashBits{
511-
b: hash([]byte(child.key)),
512-
consumed: hv.consumed,
513-
}
506+
if val == nil {
507+
return os.ErrNotExist
508+
}
514509

515-
err = ns.modifyValue(ctx, hv, key, val)
516-
if err != nil {
517-
return err
518-
}
510+
// replace value with another shard, one level deeper
511+
ns, err := NewHamtShard(ds.dserv, ds.tableSize)
512+
if err != nil {
513+
return err
514+
}
515+
ns.prefix = ds.prefix
516+
chhv := &hashBits{
517+
b: hash([]byte(child.key)),
518+
consumed: hv.consumed,
519+
}
519520

520-
err = ns.modifyValue(ctx, chhv, child.key, child.val)
521-
if err != nil {
522-
return err
523-
}
521+
err = ns.modifyValue(ctx, hv, key, val)
522+
if err != nil {
523+
return err
524+
}
524525

525-
ds.setChild(cindex, ns)
526-
return nil
526+
err = ns.modifyValue(ctx, chhv, child.key, child.val)
527+
if err != nil {
528+
return err
527529
}
530+
531+
ds.setChild(cindex, ns)
532+
return nil
528533
default:
529534
return fmt.Errorf("unexpected type for child: %#v", child)
530535
}

unixfs/hamt/hamt_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,20 @@ func TestRemoveElems(t *testing.T) {
222222
}
223223
ctx := context.Background()
224224

225+
for i := 0; i < 100; i++ {
226+
err := s.Remove(ctx, fmt.Sprintf("NOTEXIST%d", rand.Int()))
227+
if err != os.ErrNotExist {
228+
t.Fatal("shouldnt be able to remove things that don't exist")
229+
}
230+
}
231+
232+
for _, d := range dirs {
233+
_, err := s.Find(ctx, d)
234+
if err != nil {
235+
t.Fatal(err)
236+
}
237+
}
238+
225239
shuffle(time.Now().UnixNano(), dirs)
226240

227241
for _, d := range dirs {

unixfs/hamt/util.go

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package hamt
22

33
import (
44
"math/big"
5+
"math/bits"
56
)
67

78
// hashBits is a helper that allows the reading of the 'next n bits' as an integer.
@@ -39,25 +40,10 @@ func (hb *hashBits) Next(i int) int {
3940
}
4041
}
4142

42-
const (
43-
m1 = 0x5555555555555555 //binary: 0101...
44-
m2 = 0x3333333333333333 //binary: 00110011..
45-
m4 = 0x0f0f0f0f0f0f0f0f //binary: 4 zeros, 4 ones ...
46-
h01 = 0x0101010101010101 //the sum of 256 to the power of 0,1,2,3...
47-
)
48-
49-
// from https://en.wikipedia.org/wiki/Hamming_weight
50-
func popCountUint64(x uint64) int {
51-
x -= (x >> 1) & m1 //put count of each 2 bits into those 2 bits
52-
x = (x & m2) + ((x >> 2) & m2) //put count of each 4 bits into those 4 bits
53-
x = (x + (x >> 4)) & m4 //put count of each 8 bits into those 8 bits
54-
return int((x * h01) >> 56)
55-
}
56-
5743
func popCount(i *big.Int) int {
5844
var n int
5945
for _, v := range i.Bits() {
60-
n += popCountUint64(uint64(v))
46+
n += bits.OnesCount64(uint64(v))
6147
}
6248
return n
6349
}

0 commit comments

Comments
 (0)