Skip to content
This repository was archived by the owner on Jun 27, 2023. It is now read-only.

Commit 87d3898

Browse files
authored
create internal and private packages (#108)
* move CreateCompleteHAMT to an internal package * change package name: internal -> private * move hash function to internal pacakge * make link size function internal * make shard width private * add internal * go fmt * fix import order * export DefaultShardWidth back again * move IdHash to private package * move LinkSizeFunction to private * add linksize
1 parent 32ccacd commit 87d3898

File tree

9 files changed

+159
-124
lines changed

9 files changed

+159
-124
lines changed

hamt/hamt.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,23 @@ import (
2525
"fmt"
2626
"os"
2727

28+
format "github.com/ipfs/go-unixfs"
29+
"github.com/ipfs/go-unixfs/internal"
30+
2831
bitfield "github.com/ipfs/go-bitfield"
2932
cid "github.com/ipfs/go-cid"
3033
ipld "github.com/ipfs/go-ipld-format"
3134
dag "github.com/ipfs/go-merkledag"
32-
format "github.com/ipfs/go-unixfs"
3335
)
3436

3537
const (
3638
// HashMurmur3 is the multiformats identifier for Murmur3
3739
HashMurmur3 uint64 = 0x22
3840
)
3941

40-
// Hash function declared as global variable only for testing purposes.
41-
// FIXME: We shoul have a cleaner way to replace this during tests.
42-
var HAMTHashFunction = murmur3Hash
42+
func init() {
43+
internal.HAMTHashFunction = murmur3Hash
44+
}
4345

4446
func (ds *Shard) IsValueNode() bool {
4547
return ds.key != "" && ds.val != nil

hamt/util.go

Lines changed: 6 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
package hamt
22

33
import (
4-
"context"
5-
"encoding/binary"
64
"fmt"
7-
ipld "github.com/ipfs/go-ipld-format"
8-
"github.com/ipfs/go-unixfs"
9-
"github.com/spaolacci/murmur3"
10-
"math"
115
"math/bits"
6+
7+
"github.com/ipfs/go-unixfs/internal"
8+
9+
"github.com/spaolacci/murmur3"
1210
)
1311

1412
// hashBits is a helper that allows the reading of the 'next n bits' as an integer.
@@ -18,11 +16,11 @@ type hashBits struct {
1816
}
1917

2018
func newHashBits(val string) *hashBits {
21-
return &hashBits{b: HAMTHashFunction([]byte(val))}
19+
return &hashBits{b: internal.HAMTHashFunction([]byte(val))}
2220
}
2321

2422
func newConsumedHashBits(val string, consumed int) *hashBits {
25-
hv := &hashBits{b: HAMTHashFunction([]byte(val))}
23+
hv := &hashBits{b: internal.HAMTHashFunction([]byte(val))}
2624
hv.consumed = consumed
2725
return hv
2826
}
@@ -80,66 +78,3 @@ func murmur3Hash(val []byte) []byte {
8078
h.Write(val)
8179
return h.Sum(nil)
8280
}
83-
84-
// ONLY FOR TESTING: Return the same value as the hash.
85-
func IdHash(val []byte) []byte {
86-
return val
87-
}
88-
89-
// CreateCompleteHAMT creates a HAMT the following properties:
90-
// * its height (distance/edges from root to deepest node) is specified by treeHeight.
91-
// * all leaf Shard nodes have the same depth (and have only 'value' links).
92-
// * all internal Shard nodes point only to other Shards (and hence have zero 'value' links).
93-
// * the total number of 'value' links (directory entries) is:
94-
// io.DefaultShardWidth ^ (treeHeight + 1).
95-
// FIXME: HAMTHashFunction needs to be set to IdHash by the caller. We depend on
96-
// this simplification for the current logic to work. (HAMTHashFunction is a
97-
// global setting of the package, it is hard-coded in the serialized Shard node
98-
// and not allowed to be changed on a per HAMT/Shard basis.)
99-
// (If we didn't rehash inside setValue then we could just generate
100-
// the fake hash as in io.SetAndPrevious through `newHashBits()` and pass
101-
// it as an argument making the hash independent of tree manipulation; that
102-
// sounds as the correct way to go in general and we wouldn't need this.)
103-
func CreateCompleteHAMT(ds ipld.DAGService, treeHeight int, childsPerNode int) (ipld.Node, error) {
104-
if treeHeight < 1 {
105-
panic("treeHeight < 1")
106-
}
107-
if treeHeight > 8 {
108-
panic("treeHeight > 8: we don't allow a key larger than what can be enconded in a 64-bit word")
109-
}
110-
//if HAMTHashFunction != IdHash {
111-
// panic("we do not support a hash function other than ID")
112-
//}
113-
// FIXME: Any clean and simple way to do this? Otherwise remove check.
114-
115-
rootShard, err := NewShard(ds, childsPerNode)
116-
if err != nil {
117-
return nil, err
118-
}
119-
// FIXME: Do we need to set the CID builder? Not part of the NewShard
120-
// interface so it shouldn't be mandatory.
121-
122-
// Assuming we are using the ID hash function we can just insert all
123-
// the combinations of a byte slice that will reach the desired height.
124-
totalChildren := int(math.Pow(float64(childsPerNode), float64(treeHeight)))
125-
for i := 0; i < totalChildren; i++ {
126-
var hashbuf [8]byte
127-
binary.LittleEndian.PutUint64(hashbuf[:], uint64(i))
128-
var oldLink *ipld.Link
129-
// FIXME: This is wrong for childsPerNode/DefaultShardWidth different
130-
// than 256 (i.e., one byte of key per level).
131-
oldLink, err = rootShard.SetAndPrevious(context.Background(), string(hashbuf[:treeHeight]), unixfs.EmptyFileNode())
132-
if err != nil {
133-
return nil, err
134-
}
135-
if oldLink != nil {
136-
// We shouldn't be overwriting any value, otherwise the tree
137-
// won't be complete.
138-
return nil, fmt.Errorf("we have overwritten entry %s",
139-
oldLink.Cid)
140-
}
141-
}
142-
// FIXME: Check depth of every Shard to be sure?
143-
144-
return rootShard.Node()
145-
}

hamt/util_test.go

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
package hamt
22

33
import (
4-
"context"
5-
mdtest "github.com/ipfs/go-merkledag/test"
6-
"github.com/stretchr/testify/assert"
7-
"math"
84
"testing"
95
)
106

@@ -66,23 +62,3 @@ func TestHashBitsUneven(t *testing.T) {
6662
t.Fatalf("expected 20269, but got %b (%d)", v, v)
6763
}
6864
}
69-
70-
func TestCreateCompleteShard(t *testing.T) {
71-
ds := mdtest.Mock()
72-
childsPerNode := 256
73-
treeHeight := 2 // This is the limit of what we can fastly generate,
74-
// the default width is too big (256). We may need to refine
75-
// CreateCompleteHAMT encoding of the key to reduce the tableSize.
76-
node, err := CreateCompleteHAMT(ds, treeHeight, 256)
77-
assert.NoError(t, err)
78-
79-
shard, err := NewHamtFromDag(ds, node)
80-
assert.NoError(t, err)
81-
links, err := shard.EnumAll(context.Background())
82-
assert.NoError(t, err)
83-
84-
childNodes := int(math.Pow(float64(childsPerNode), float64(treeHeight)))
85-
//internalNodes := int(math.Pow(float64(childsPerNode), float64(treeHeight-1)))
86-
//totalNodes := childNodes + internalNodes
87-
assert.Equal(t, childNodes, len(links))
88-
}

internal/config.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package internal
2+
3+
var HAMTHashFunction func(val []byte) []byte

io/directory.go

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,16 @@ package io
33
import (
44
"context"
55
"fmt"
6-
mdag "github.com/ipfs/go-merkledag"
7-
format "github.com/ipfs/go-unixfs"
8-
"github.com/ipfs/go-unixfs/hamt"
96
"os"
107

8+
"github.com/ipfs/go-unixfs/hamt"
9+
"github.com/ipfs/go-unixfs/private/linksize"
10+
1111
"github.com/ipfs/go-cid"
1212
ipld "github.com/ipfs/go-ipld-format"
1313
logging "github.com/ipfs/go-log"
14+
mdag "github.com/ipfs/go-merkledag"
15+
format "github.com/ipfs/go-unixfs"
1416
)
1517

1618
var log = logging.Logger("unixfs")
@@ -79,7 +81,9 @@ func productionLinkSize(linkName string, linkCid cid.Cid) int {
7981
return len(linkName) + linkCid.ByteLen()
8082
}
8183

82-
var estimatedLinkSize = productionLinkSize
84+
func init() {
85+
linksize.LinkSizeFunction = productionLinkSize
86+
}
8387

8488
// BasicDirectory is the basic implementation of `Directory`. All the entries
8589
// are stored in a single node.
@@ -191,11 +195,11 @@ func (d *BasicDirectory) computeEstimatedSize() {
191195
}
192196

193197
func (d *BasicDirectory) addToEstimatedSize(name string, linkCid cid.Cid) {
194-
d.estimatedSize += estimatedLinkSize(name, linkCid)
198+
d.estimatedSize += linksize.LinkSizeFunction(name, linkCid)
195199
}
196200

197201
func (d *BasicDirectory) removeFromEstimatedSize(name string, linkCid cid.Cid) {
198-
d.estimatedSize -= estimatedLinkSize(name, linkCid)
202+
d.estimatedSize -= linksize.LinkSizeFunction(name, linkCid)
199203
if d.estimatedSize < 0 {
200204
// Something has gone very wrong. Log an error and recompute the
201205
// size from scratch.
@@ -232,10 +236,10 @@ func (d *BasicDirectory) needsToSwitchToHAMTDir(name string, nodeToAdd ipld.Node
232236
if err != nil {
233237
return false, err
234238
}
235-
operationSizeChange -= estimatedLinkSize(name, entryToRemove.Cid)
239+
operationSizeChange -= linksize.LinkSizeFunction(name, entryToRemove.Cid)
236240
}
237241
if nodeToAdd != nil {
238-
operationSizeChange += estimatedLinkSize(name, nodeToAdd.Cid())
242+
operationSizeChange += linksize.LinkSizeFunction(name, nodeToAdd.Cid())
239243
}
240244

241245
return d.estimatedSize+operationSizeChange >= HAMTShardingSize, nil
@@ -461,11 +465,11 @@ func (d *HAMTDirectory) switchToBasic(ctx context.Context) (*BasicDirectory, err
461465
}
462466

463467
func (d *HAMTDirectory) addToSizeChange(name string, linkCid cid.Cid) {
464-
d.sizeChange += estimatedLinkSize(name, linkCid)
468+
d.sizeChange += linksize.LinkSizeFunction(name, linkCid)
465469
}
466470

467471
func (d *HAMTDirectory) removeFromSizeChange(name string, linkCid cid.Cid) {
468-
d.sizeChange -= estimatedLinkSize(name, linkCid)
472+
d.sizeChange -= linksize.LinkSizeFunction(name, linkCid)
469473
}
470474

471475
// Evaluate a switch from HAMTDirectory to BasicDirectory in case the size will
@@ -488,12 +492,12 @@ func (d *HAMTDirectory) needsToSwitchToBasicDir(ctx context.Context, name string
488492
if err != nil {
489493
return false, err
490494
}
491-
operationSizeChange -= estimatedLinkSize(name, entryToRemove.Cid)
495+
operationSizeChange -= linksize.LinkSizeFunction(name, entryToRemove.Cid)
492496
}
493497

494498
// For the AddEntry case compute the size addition of the new entry.
495499
if nodeToAdd != nil {
496-
operationSizeChange += estimatedLinkSize(name, nodeToAdd.Cid())
500+
operationSizeChange += linksize.LinkSizeFunction(name, nodeToAdd.Cid())
497501
}
498502

499503
if d.sizeChange+operationSizeChange >= 0 {
@@ -530,7 +534,7 @@ func (d *HAMTDirectory) sizeBelowThreshold(ctx context.Context, sizeChange int)
530534
return false, linkResult.Err
531535
}
532536

533-
partialSize += estimatedLinkSize(linkResult.Link.Name, linkResult.Link.Cid)
537+
partialSize += linksize.LinkSizeFunction(linkResult.Link.Name, linkResult.Link.Cid)
534538
if partialSize+sizeChange >= HAMTShardingSize {
535539
// We have already fetched enough shards to assert we are
536540
// above the threshold, so no need to keep fetching.

io/directory_test.go

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ import (
1717
mdtest "github.com/ipfs/go-merkledag/test"
1818

1919
ft "github.com/ipfs/go-unixfs"
20-
"github.com/ipfs/go-unixfs/hamt"
20+
"github.com/ipfs/go-unixfs/internal"
21+
"github.com/ipfs/go-unixfs/private/completehamt"
22+
"github.com/ipfs/go-unixfs/private/linksize"
2123

2224
"github.com/stretchr/testify/assert"
2325
)
@@ -134,15 +136,15 @@ func TestHAMTDirectory_sizeChange(t *testing.T) {
134136
func fullSizeEnumeration(dir Directory) int {
135137
size := 0
136138
dir.ForEachLink(context.Background(), func(l *ipld.Link) error {
137-
size += estimatedLinkSize(l.Name, l.Cid)
139+
size += linksize.LinkSizeFunction(l.Name, l.Cid)
138140
return nil
139141
})
140142
return size
141143
}
142144

143145
func testDirectorySizeEstimation(t *testing.T, dir Directory, ds ipld.DAGService, size func(Directory) int) {
144-
estimatedLinkSize = mockLinkSizeFunc(1)
145-
defer func() { estimatedLinkSize = productionLinkSize }()
146+
linksize.LinkSizeFunction = mockLinkSizeFunc(1)
147+
defer func() { linksize.LinkSizeFunction = productionLinkSize }()
146148

147149
ctx := context.Background()
148150
child := ft.EmptyFileNode()
@@ -241,8 +243,8 @@ func TestUpgradeableDirectorySwitch(t *testing.T) {
241243
oldHamtOption := HAMTShardingSize
242244
defer func() { HAMTShardingSize = oldHamtOption }()
243245
HAMTShardingSize = 0 // Disable automatic switch at the start.
244-
estimatedLinkSize = mockLinkSizeFunc(1)
245-
defer func() { estimatedLinkSize = productionLinkSize }()
246+
linksize.LinkSizeFunction = mockLinkSizeFunc(1)
247+
defer func() { linksize.LinkSizeFunction = productionLinkSize }()
246248

247249
ds := mdtest.Mock()
248250
dir := NewDirectory(ds)
@@ -327,15 +329,15 @@ func TestHAMTEnumerationWhenComputingSize(t *testing.T) {
327329
// Set all link sizes to a uniform 1 so the estimated directory size
328330
// is just the count of its entry links (in HAMT/Shard terminology these
329331
// are the "value" links pointing to anything that is *not* another Shard).
330-
estimatedLinkSize = mockLinkSizeFunc(1)
331-
defer func() { estimatedLinkSize = productionLinkSize }()
332+
linksize.LinkSizeFunction = mockLinkSizeFunc(1)
333+
defer func() { linksize.LinkSizeFunction = productionLinkSize }()
332334

333335
// Use an identity hash function to ease the construction of "complete" HAMTs
334336
// (see CreateCompleteHAMT below for more details). (Ideally this should be
335337
// a parameter we pass and not a global option we modify in the caller.)
336-
oldHashFunc := hamt.HAMTHashFunction
337-
defer func() { hamt.HAMTHashFunction = oldHashFunc }()
338-
hamt.HAMTHashFunction = hamt.IdHash
338+
oldHashFunc := internal.HAMTHashFunction
339+
defer func() { internal.HAMTHashFunction = oldHashFunc }()
340+
internal.HAMTHashFunction = completehamt.IdHash
339341

340342
oldHamtOption := HAMTShardingSize
341343
defer func() { HAMTShardingSize = oldHamtOption }()
@@ -358,7 +360,7 @@ func TestHAMTEnumerationWhenComputingSize(t *testing.T) {
358360
// will need to fetch in order to reach the HAMTShardingSize threshold in
359361
// sizeBelowThreshold (assuming a sequential DAG walk function).
360362
ds := mdtest.Mock()
361-
completeHAMTRoot, err := hamt.CreateCompleteHAMT(ds, treeHeight, shardWidth)
363+
completeHAMTRoot, err := completehamt.CreateCompleteHAMT(ds, treeHeight, shardWidth)
362364
assert.NoError(t, err)
363365

364366
// With this structure and a BFS traversal (from `parallelWalkDepth`) then

0 commit comments

Comments
 (0)