Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

swarm/storage: fix HashExplore concurrency bug ethersphere#1211 #19028

Merged
merged 5 commits into from
Feb 12, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 17 additions & 9 deletions swarm/storage/filestore.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"context"
"io"
"sort"
"sync"
)

/*
Expand Down Expand Up @@ -101,38 +102,45 @@ func (f *FileStore) HashSize() int {
// GetAllReferences is a public API. This endpoint returns all chunk hashes (only) for a given file
func (f *FileStore) GetAllReferences(ctx context.Context, data io.Reader, toEncrypt bool) (addrs AddressCollection, err error) {
// create a special kind of putter, which only will store the references
putter := &HashExplorer{
putter := &hashExplorer{
hasherStore: NewHasherStore(f.ChunkStore, f.hashFunc, toEncrypt),
References: make([]Reference, 0),
}
// do the actual splitting anyway, no way around it
_, _, err = PyramidSplit(ctx, data, putter, putter)
_, wait, err := PyramidSplit(ctx, data, putter, putter)
if err != nil {
return nil, err
}
// wait for splitting to be complete and all chunks processed
err = wait(ctx)
if err != nil {
return nil, err
}
// collect all references
addrs = NewAddressCollection(0)
for _, ref := range putter.References {
for _, ref := range putter.references {
addrs = append(addrs, Address(ref))
}
sort.Sort(addrs)
return addrs, nil
}

// HashExplorer is a special kind of putter which will only store chunk references
type HashExplorer struct {
// hashExplorer is a special kind of putter which will only store chunk references
type hashExplorer struct {
*hasherStore
References []Reference
references []Reference
lock sync.Mutex
}

// HashExplorer's Put will add just the chunk hashes to its `References`
func (he *HashExplorer) Put(ctx context.Context, chunkData ChunkData) (Reference, error) {
func (he *hashExplorer) Put(ctx context.Context, chunkData ChunkData) (Reference, error) {
// Need to do the actual Put, which returns the references
ref, err := he.hasherStore.Put(ctx, chunkData)
if err != nil {
return nil, err
}
// internally store the reference
he.References = append(he.References, ref)
he.lock.Lock()
he.references = append(he.references, ref)
he.lock.Unlock()
return ref, nil
}