Skip to content

Commit 5cab8cd

Browse files
holisticodedshulyak
authored andcommitted
swarm/storage: fix HashExplore concurrency bug ethersphere#1211 (ethereum#19028)
* swarm/storage: fix HashExplore concurrency bug ethersphere#1211 * swarm/storage: lock as value not pointer * swarm/storage: wait for to complete * swarm/storage: fix linter problems * swarm/storage: append to nil slice (cherry picked from commit 3d22a46)
1 parent a05ae88 commit 5cab8cd

File tree

1 file changed

+17
-9
lines changed

1 file changed

+17
-9
lines changed

swarm/storage/filestore.go

+17-9
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"context"
2121
"io"
2222
"sort"
23+
"sync"
2324
)
2425

2526
/*
@@ -101,38 +102,45 @@ func (f *FileStore) HashSize() int {
101102
// GetAllReferences is a public API. This endpoint returns all chunk hashes (only) for a given file
102103
func (f *FileStore) GetAllReferences(ctx context.Context, data io.Reader, toEncrypt bool) (addrs AddressCollection, err error) {
103104
// create a special kind of putter, which only will store the references
104-
putter := &HashExplorer{
105+
putter := &hashExplorer{
105106
hasherStore: NewHasherStore(f.ChunkStore, f.hashFunc, toEncrypt),
106-
References: make([]Reference, 0),
107107
}
108108
// do the actual splitting anyway, no way around it
109-
_, _, err = PyramidSplit(ctx, data, putter, putter)
109+
_, wait, err := PyramidSplit(ctx, data, putter, putter)
110+
if err != nil {
111+
return nil, err
112+
}
113+
// wait for splitting to be complete and all chunks processed
114+
err = wait(ctx)
110115
if err != nil {
111116
return nil, err
112117
}
113118
// collect all references
114119
addrs = NewAddressCollection(0)
115-
for _, ref := range putter.References {
120+
for _, ref := range putter.references {
116121
addrs = append(addrs, Address(ref))
117122
}
118123
sort.Sort(addrs)
119124
return addrs, nil
120125
}
121126

122-
// HashExplorer is a special kind of putter which will only store chunk references
123-
type HashExplorer struct {
127+
// hashExplorer is a special kind of putter which will only store chunk references
128+
type hashExplorer struct {
124129
*hasherStore
125-
References []Reference
130+
references []Reference
131+
lock sync.Mutex
126132
}
127133

128134
// HashExplorer's Put will add just the chunk hashes to its `References`
129-
func (he *HashExplorer) Put(ctx context.Context, chunkData ChunkData) (Reference, error) {
135+
func (he *hashExplorer) Put(ctx context.Context, chunkData ChunkData) (Reference, error) {
130136
// Need to do the actual Put, which returns the references
131137
ref, err := he.hasherStore.Put(ctx, chunkData)
132138
if err != nil {
133139
return nil, err
134140
}
135141
// internally store the reference
136-
he.References = append(he.References, ref)
142+
he.lock.Lock()
143+
he.references = append(he.references, ref)
144+
he.lock.Unlock()
137145
return ref, nil
138146
}

0 commit comments

Comments
 (0)