Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
p2p
go-p2p-kad-dht
Commits
36578e2b
Commit
36578e2b
authored
Jul 23, 2019
by
Aarsh Shah
Committed by
Steven Allen
Jul 22, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Striped locks for atomic Dht updates (#374)
Implement striped locking for datastore puts.
parent
3c72a7c6
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
95 additions
and
8 deletions
+95
-8
dht.go
dht.go
+2
-0
dht_test.go
dht_test.go
+79
-5
handlers.go
handlers.go
+14
-3
No files found.
dht.go
View file @
36578e2b
...
...
@@ -65,6 +65,8 @@ type IpfsDHT struct {
plk
sync
.
Mutex
stripedPutLocks
[
256
]
sync
.
Mutex
protocols
[]
protocol
.
ID
// DHT protocols
}
...
...
dht_test.go
View file @
36578e2b
...
...
@@ -15,8 +15,7 @@ import (
"github.com/libp2p/go-libp2p-core/peer"
"github.com/libp2p/go-libp2p-core/peerstore"
"github.com/libp2p/go-libp2p-core/routing"
multistream
"github.com/multiformats/go-multistream"
"github.com/multiformats/go-multistream"
"golang.org/x/xerrors"
...
...
@@ -26,12 +25,12 @@ import (
opts
"github.com/libp2p/go-libp2p-kad-dht/opts"
pb
"github.com/libp2p/go-libp2p-kad-dht/pb"
cid
"github.com/ipfs/go-cid"
"github.com/ipfs/go-cid"
u
"github.com/ipfs/go-ipfs-util"
kb
"github.com/libp2p/go-libp2p-kbucket"
record
"github.com/libp2p/go-libp2p-record"
"github.com/libp2p/go-libp2p-record"
swarmt
"github.com/libp2p/go-libp2p-swarm/testing"
ci
"github.com/libp2p/go-libp2p-testing/ci"
"github.com/libp2p/go-libp2p-testing/ci"
travisci
"github.com/libp2p/go-libp2p-testing/ci/travis"
bhost
"github.com/libp2p/go-libp2p/p2p/host/basic"
ma
"github.com/multiformats/go-multiaddr"
...
...
@@ -78,6 +77,36 @@ func (testValidator) Validate(_ string, b []byte) error {
return
nil
}
type
testAtomicPutValidator
struct
{
testValidator
}
// selects the entry with the 'highest' last byte
func
(
testAtomicPutValidator
)
Select
(
_
string
,
bs
[][]
byte
)
(
int
,
error
)
{
index
:=
-
1
max
:=
uint8
(
0
)
for
i
,
b
:=
range
bs
{
if
bytes
.
Equal
(
b
,
[]
byte
(
"valid"
))
{
if
index
==
-
1
{
index
=
i
}
continue
}
str
:=
string
(
b
)
n
:=
str
[
len
(
str
)
-
1
]
if
n
>
max
{
max
=
n
index
=
i
}
}
if
index
==
-
1
{
return
-
1
,
errors
.
New
(
"no rec found"
)
}
return
index
,
nil
}
func
setupDHT
(
ctx
context
.
Context
,
t
*
testing
.
T
,
client
bool
)
*
IpfsDHT
{
d
,
err
:=
New
(
ctx
,
...
...
@@ -1107,6 +1136,51 @@ func TestBadProtoMessages(t *testing.T) {
}
}
func
TestAtomicPut
(
t
*
testing
.
T
)
{
ctx
,
cancel
:=
context
.
WithCancel
(
context
.
Background
())
defer
cancel
()
d
:=
setupDHT
(
ctx
,
t
,
false
)
d
.
Validator
=
testAtomicPutValidator
{}
// fnc to put a record
key
:=
"testkey"
putRecord
:=
func
(
value
[]
byte
)
error
{
rec
:=
record
.
MakePutRecord
(
key
,
value
)
pmes
:=
pb
.
NewMessage
(
pb
.
Message_PUT_VALUE
,
rec
.
Key
,
0
)
pmes
.
Record
=
rec
_
,
err
:=
d
.
handlePutValue
(
ctx
,
"testpeer"
,
pmes
)
return
err
}
// put a valid record
if
err
:=
putRecord
([]
byte
(
"valid"
));
err
!=
nil
{
t
.
Fatal
(
"should not have errored on a valid record"
)
}
// simultaneous puts for old & new values
values
:=
[][]
byte
{[]
byte
(
"newer1"
),
[]
byte
(
"newer7"
),
[]
byte
(
"newer3"
),
[]
byte
(
"newer5"
)}
var
wg
sync
.
WaitGroup
for
_
,
v
:=
range
values
{
wg
.
Add
(
1
)
go
func
(
v
[]
byte
)
{
defer
wg
.
Done
()
putRecord
(
v
)
}(
v
)
}
wg
.
Wait
()
// get should return the newest value
pmes
:=
pb
.
NewMessage
(
pb
.
Message_GET_VALUE
,
[]
byte
(
key
),
0
)
msg
,
err
:=
d
.
handleGetValue
(
ctx
,
"testkey"
,
pmes
)
if
err
!=
nil
{
t
.
Fatalf
(
"should not have errored on final get, but got %+v"
,
err
)
}
if
string
(
msg
.
GetRecord
()
.
Value
)
!=
"newer7"
{
t
.
Fatalf
(
"Expected 'newer7' got '%s'"
,
string
(
msg
.
GetRecord
()
.
Value
))
}
}
func
TestClientModeConnect
(
t
*
testing
.
T
)
{
ctx
,
cancel
:=
context
.
WithCancel
(
context
.
Background
())
defer
cancel
()
...
...
handlers.go
View file @
36578e2b
...
...
@@ -12,13 +12,13 @@ import (
"github.com/libp2p/go-libp2p-core/peerstore"
pstore
"github.com/libp2p/go-libp2p-peerstore"
proto
"github.com/gogo/protobuf/proto"
cid
"github.com/ipfs/go-cid"
"github.com/gogo/protobuf/proto"
"github.com/ipfs/go-cid"
ds
"github.com/ipfs/go-datastore"
u
"github.com/ipfs/go-ipfs-util"
pb
"github.com/libp2p/go-libp2p-kad-dht/pb"
recpb
"github.com/libp2p/go-libp2p-record/pb"
base32
"github.com/whyrusleeping/base32"
"github.com/whyrusleeping/base32"
)
// The number of closer peers to send on requests.
...
...
@@ -173,6 +173,17 @@ func (dht *IpfsDHT) handlePutValue(ctx context.Context, p peer.ID, pmes *pb.Mess
dskey
:=
convertToDsKey
(
rec
.
GetKey
())
// fetch the striped lock for this key
var
indexForLock
byte
if
len
(
rec
.
GetKey
())
==
0
{
indexForLock
=
0
}
else
{
indexForLock
=
rec
.
GetKey
()[
len
(
rec
.
GetKey
())
-
1
]
}
lk
:=
&
dht
.
stripedPutLocks
[
indexForLock
]
lk
.
Lock
()
defer
lk
.
Unlock
()
// Make sure the new record is "better" than the record we have locally.
// This prevents a record with for example a lower sequence number from
// overwriting a record with a higher sequence number.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment