good morning!!!!
Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
B
bor
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container registry
Harbor Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
open
bor
Commits
cbd3ae69
Commit
cbd3ae69
authored
May 21, 2015
by
Péter Szilágyi
Browse files
Options
Downloads
Patches
Plain Diff
p2p/discover: fix #838, evacuate self entries from the node db
parent
af24c271
No related branches found
No related tags found
No related merge requests found
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
p2p/discover/database.go
+32
-15
32 additions, 15 deletions
p2p/discover/database.go
p2p/discover/database_test.go
+65
-8
65 additions, 8 deletions
p2p/discover/database_test.go
p2p/discover/table.go
+2
-2
2 additions, 2 deletions
p2p/discover/table.go
with
99 additions
and
25 deletions
p2p/discover/database.go
+
32
−
15
View file @
cbd3ae69
...
...
@@ -33,6 +33,8 @@ type nodeDB struct {
lvl
*
leveldb
.
DB
// Interface to the database itself
seeder
iterator
.
Iterator
// Iterator for fetching possible seed nodes
self
NodeID
// Own node id to prevent adding it into the database
runner
sync
.
Once
// Ensures we can start at most one expirer
quit
chan
struct
{}
// Channel to signal the expiring thread to stop
}
...
...
@@ -50,29 +52,30 @@ var (
// newNodeDB creates a new node database for storing and retrieving infos about
// known peers in the network. If no path is given, an in-memory, temporary
// database is constructed.
func
newNodeDB
(
path
string
,
version
int
)
(
*
nodeDB
,
error
)
{
func
newNodeDB
(
path
string
,
version
int
,
self
NodeID
)
(
*
nodeDB
,
error
)
{
if
path
==
""
{
return
newMemoryNodeDB
()
return
newMemoryNodeDB
(
self
)
}
return
newPersistentNodeDB
(
path
,
version
)
return
newPersistentNodeDB
(
path
,
version
,
self
)
}
// newMemoryNodeDB creates a new in-memory node database without a persistent
// backend.
func
newMemoryNodeDB
()
(
*
nodeDB
,
error
)
{
func
newMemoryNodeDB
(
self
NodeID
)
(
*
nodeDB
,
error
)
{
db
,
err
:=
leveldb
.
Open
(
storage
.
NewMemStorage
(),
nil
)
if
err
!=
nil
{
return
nil
,
err
}
return
&
nodeDB
{
lvl
:
db
,
self
:
self
,
quit
:
make
(
chan
struct
{}),
},
nil
}
// newPersistentNodeDB creates/opens a leveldb backed persistent node database,
// also flushing its contents in case of a version mismatch.
func
newPersistentNodeDB
(
path
string
,
version
int
)
(
*
nodeDB
,
error
)
{
func
newPersistentNodeDB
(
path
string
,
version
int
,
self
NodeID
)
(
*
nodeDB
,
error
)
{
opts
:=
&
opt
.
Options
{
OpenFilesCacheCapacity
:
5
}
db
,
err
:=
leveldb
.
OpenFile
(
path
,
opts
)
if
_
,
iscorrupted
:=
err
.
(
*
errors
.
ErrCorrupted
);
iscorrupted
{
...
...
@@ -102,11 +105,12 @@ func newPersistentNodeDB(path string, version int) (*nodeDB, error) {
if
err
=
os
.
RemoveAll
(
path
);
err
!=
nil
{
return
nil
,
err
}
return
newPersistentNodeDB
(
path
,
version
)
return
newPersistentNodeDB
(
path
,
version
,
self
)
}
}
return
&
nodeDB
{
lvl
:
db
,
self
:
self
,
quit
:
make
(
chan
struct
{}),
},
nil
}
...
...
@@ -182,6 +186,17 @@ func (db *nodeDB) updateNode(node *Node) error {
return
db
.
lvl
.
Put
(
makeKey
(
node
.
ID
,
nodeDBDiscoverRoot
),
blob
,
nil
)
}
// deleteNode deletes all information/keys associated with a node.
func
(
db
*
nodeDB
)
deleteNode
(
id
NodeID
)
error
{
deleter
:=
db
.
lvl
.
NewIterator
(
util
.
BytesPrefix
(
makeKey
(
id
,
""
)),
nil
)
for
deleter
.
Next
()
{
if
err
:=
db
.
lvl
.
Delete
(
deleter
.
Key
(),
nil
);
err
!=
nil
{
return
err
}
}
return
nil
}
// ensureExpirer is a small helper method ensuring that the data expiration
// mechanism is running. If the expiration goroutine is already running, this
// method simply returns.
...
...
@@ -227,17 +242,14 @@ func (db *nodeDB) expireNodes() error {
if
field
!=
nodeDBDiscoverRoot
{
continue
}
// Skip the node if not expired yet
// Skip the node if not expired yet (and not self)
if
bytes
.
Compare
(
id
[
:
],
db
.
self
[
:
])
!=
0
{
if
seen
:=
db
.
lastPong
(
id
);
seen
.
After
(
threshold
)
{
continue
}
// Otherwise delete all associated information
deleter
:=
db
.
lvl
.
NewIterator
(
util
.
BytesPrefix
(
makeKey
(
id
,
""
)),
nil
)
for
deleter
.
Next
()
{
if
err
:=
db
.
lvl
.
Delete
(
deleter
.
Key
(),
nil
);
err
!=
nil
{
return
err
}
}
// Otherwise delete all associated information
db
.
deleteNode
(
id
)
}
return
nil
}
...
...
@@ -286,6 +298,11 @@ func (db *nodeDB) querySeeds(n int) []*Node {
if
field
!=
nodeDBDiscoverRoot
{
continue
}
// Dump it if its a self reference
if
bytes
.
Compare
(
id
[
:
],
db
.
self
[
:
])
==
0
{
db
.
deleteNode
(
id
)
continue
}
// Load it as a potential seed
if
node
:=
db
.
node
(
id
);
node
!=
nil
{
nodes
=
append
(
nodes
,
node
)
...
...
This diff is collapsed.
Click to expand it.
p2p/discover/database_test.go
+
65
−
8
View file @
cbd3ae69
...
...
@@ -63,7 +63,7 @@ var nodeDBInt64Tests = []struct {
}
func
TestNodeDBInt64
(
t
*
testing
.
T
)
{
db
,
_
:=
newNodeDB
(
""
,
Version
)
db
,
_
:=
newNodeDB
(
""
,
Version
,
NodeID
{}
)
defer
db
.
close
()
tests
:=
nodeDBInt64Tests
...
...
@@ -94,7 +94,7 @@ func TestNodeDBFetchStore(t *testing.T) {
)
inst
:=
time
.
Now
()
db
,
_
:=
newNodeDB
(
""
,
Version
)
db
,
_
:=
newNodeDB
(
""
,
Version
,
NodeID
{}
)
defer
db
.
close
()
// Check fetch/store operations on a node ping object
...
...
@@ -165,7 +165,7 @@ var nodeDBSeedQueryNodes = []struct {
}
func
TestNodeDBSeedQuery
(
t
*
testing
.
T
)
{
db
,
_
:=
newNodeDB
(
""
,
Version
)
db
,
_
:=
newNodeDB
(
""
,
Version
,
NodeID
{}
)
defer
db
.
close
()
// Insert a batch of nodes for querying
...
...
@@ -205,7 +205,7 @@ func TestNodeDBSeedQuery(t *testing.T) {
}
func
TestNodeDBSeedQueryContinuation
(
t
*
testing
.
T
)
{
db
,
_
:=
newNodeDB
(
""
,
Version
)
db
,
_
:=
newNodeDB
(
""
,
Version
,
NodeID
{}
)
defer
db
.
close
()
// Insert a batch of nodes for querying
...
...
@@ -230,6 +230,32 @@ func TestNodeDBSeedQueryContinuation(t *testing.T) {
}
}
func
TestNodeDBSelfSeedQuery
(
t
*
testing
.
T
)
{
// Assign a node as self to verify evacuation
self
:=
nodeDBSeedQueryNodes
[
0
]
.
node
.
ID
db
,
_
:=
newNodeDB
(
""
,
Version
,
self
)
defer
db
.
close
()
// Insert a batch of nodes for querying
for
i
,
seed
:=
range
nodeDBSeedQueryNodes
{
if
err
:=
db
.
updateNode
(
seed
.
node
);
err
!=
nil
{
t
.
Fatalf
(
"node %d: failed to insert: %v"
,
i
,
err
)
}
}
// Retrieve the entire batch and check that self was evacuated
seeds
:=
db
.
querySeeds
(
2
*
len
(
nodeDBSeedQueryNodes
))
if
len
(
seeds
)
!=
len
(
nodeDBSeedQueryNodes
)
-
1
{
t
.
Errorf
(
"seed count mismatch: have %v, want %v"
,
len
(
seeds
),
len
(
nodeDBSeedQueryNodes
)
-
1
)
}
have
:=
make
(
map
[
NodeID
]
struct
{})
for
_
,
seed
:=
range
seeds
{
have
[
seed
.
ID
]
=
struct
{}{}
}
if
_
,
ok
:=
have
[
self
];
ok
{
t
.
Errorf
(
"self not evacuated"
)
}
}
func
TestNodeDBPersistency
(
t
*
testing
.
T
)
{
root
,
err
:=
ioutil
.
TempDir
(
""
,
"nodedb-"
)
if
err
!=
nil
{
...
...
@@ -243,7 +269,7 @@ func TestNodeDBPersistency(t *testing.T) {
)
// Create a persistent database and store some values
db
,
err
:=
newNodeDB
(
filepath
.
Join
(
root
,
"database"
),
Version
)
db
,
err
:=
newNodeDB
(
filepath
.
Join
(
root
,
"database"
),
Version
,
NodeID
{}
)
if
err
!=
nil
{
t
.
Fatalf
(
"failed to create persistent database: %v"
,
err
)
}
...
...
@@ -253,7 +279,7 @@ func TestNodeDBPersistency(t *testing.T) {
db
.
close
()
// Reopen the database and check the value
db
,
err
=
newNodeDB
(
filepath
.
Join
(
root
,
"database"
),
Version
)
db
,
err
=
newNodeDB
(
filepath
.
Join
(
root
,
"database"
),
Version
,
NodeID
{}
)
if
err
!=
nil
{
t
.
Fatalf
(
"failed to open persistent database: %v"
,
err
)
}
...
...
@@ -263,7 +289,7 @@ func TestNodeDBPersistency(t *testing.T) {
db
.
close
()
// Change the database version and check flush
db
,
err
=
newNodeDB
(
filepath
.
Join
(
root
,
"database"
),
Version
+
1
)
db
,
err
=
newNodeDB
(
filepath
.
Join
(
root
,
"database"
),
Version
+
1
,
NodeID
{}
)
if
err
!=
nil
{
t
.
Fatalf
(
"failed to open persistent database: %v"
,
err
)
}
...
...
@@ -300,7 +326,7 @@ var nodeDBExpirationNodes = []struct {
}
func
TestNodeDBExpiration
(
t
*
testing
.
T
)
{
db
,
_
:=
newNodeDB
(
""
,
Version
)
db
,
_
:=
newNodeDB
(
""
,
Version
,
NodeID
{}
)
defer
db
.
close
()
// Add all the test nodes and set their last pong time
...
...
@@ -323,3 +349,34 @@ func TestNodeDBExpiration(t *testing.T) {
}
}
}
func
TestNodeDBSelfExpiration
(
t
*
testing
.
T
)
{
// Find a node in the tests that shouldn't expire, and assign it as self
var
self
NodeID
for
_
,
node
:=
range
nodeDBExpirationNodes
{
if
!
node
.
exp
{
self
=
node
.
node
.
ID
break
}
}
db
,
_
:=
newNodeDB
(
""
,
Version
,
self
)
defer
db
.
close
()
// Add all the test nodes and set their last pong time
for
i
,
seed
:=
range
nodeDBExpirationNodes
{
if
err
:=
db
.
updateNode
(
seed
.
node
);
err
!=
nil
{
t
.
Fatalf
(
"node %d: failed to insert: %v"
,
i
,
err
)
}
if
err
:=
db
.
updateLastPong
(
seed
.
node
.
ID
,
seed
.
pong
);
err
!=
nil
{
t
.
Fatalf
(
"node %d: failed to update pong: %v"
,
i
,
err
)
}
}
// Expire the nodes and make sure self has been evacuated too
if
err
:=
db
.
expireNodes
();
err
!=
nil
{
t
.
Fatalf
(
"failed to expire nodes: %v"
,
err
)
}
node
:=
db
.
node
(
self
)
if
node
!=
nil
{
t
.
Errorf
(
"self not evacuated"
)
}
}
This diff is collapsed.
Click to expand it.
p2p/discover/table.go
+
2
−
2
View file @
cbd3ae69
...
...
@@ -68,10 +68,10 @@ type bucket struct {
func
newTable
(
t
transport
,
ourID
NodeID
,
ourAddr
*
net
.
UDPAddr
,
nodeDBPath
string
)
*
Table
{
// If no node database was given, use an in-memory one
db
,
err
:=
newNodeDB
(
nodeDBPath
,
Version
)
db
,
err
:=
newNodeDB
(
nodeDBPath
,
Version
,
ourID
)
if
err
!=
nil
{
glog
.
V
(
logger
.
Warn
)
.
Infoln
(
"Failed to open node database:"
,
err
)
db
,
_
=
newNodeDB
(
""
,
Version
)
db
,
_
=
newNodeDB
(
""
,
Version
,
ourID
)
}
tab
:=
&
Table
{
net
:
t
,
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment