1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Use monotonic clock for reaping networkDB entries

Signed-off-by: Santhosh Manohar <santhosh@docker.com>
This commit is contained in:
Santhosh Manohar 2016-09-27 16:38:47 -07:00
parent eb02cb999b
commit 0a2537eea3
3 changed files with 35 additions and 25 deletions

View file

@ -270,19 +270,27 @@ func (nDB *NetworkDB) reconnectNode() {
nDB.bulkSync([]string{node.Name}, true) nDB.bulkSync([]string{node.Name}, true)
} }
// For timing the entry deletion in the repaer APIs that doesn't use monotonic clock
// source (time.Now, Sub etc.) should be avoided. Hence we use reapTime in every
// entry which is set initially to reapInterval and decremented by reapPeriod every time
// the reaper runs. NOTE nDB.reapTableEntries updates the reapTime with a readlock. This
// is safe as long as no other concurrent path touches the reapTime field.
func (nDB *NetworkDB) reapState() { func (nDB *NetworkDB) reapState() {
nDB.reapNetworks() nDB.reapNetworks()
nDB.reapTableEntries() nDB.reapTableEntries()
} }
func (nDB *NetworkDB) reapNetworks() { func (nDB *NetworkDB) reapNetworks() {
now := time.Now()
nDB.Lock() nDB.Lock()
for name, nn := range nDB.networks { for name, nn := range nDB.networks {
for id, n := range nn { for id, n := range nn {
if n.leaving && now.Sub(n.leaveTime) > reapInterval { if n.leaving {
delete(nn, id) if n.reapTime <= 0 {
nDB.deleteNetworkNode(id, name) delete(nn, id)
nDB.deleteNetworkNode(id, name)
continue
}
n.reapTime -= reapPeriod
} }
} }
} }
@ -292,8 +300,6 @@ func (nDB *NetworkDB) reapNetworks() {
func (nDB *NetworkDB) reapTableEntries() { func (nDB *NetworkDB) reapTableEntries() {
var paths []string var paths []string
now := time.Now()
nDB.RLock() nDB.RLock()
nDB.indexes[byTable].Walk(func(path string, v interface{}) bool { nDB.indexes[byTable].Walk(func(path string, v interface{}) bool {
entry, ok := v.(*entry) entry, ok := v.(*entry)
@ -301,10 +307,13 @@ func (nDB *NetworkDB) reapTableEntries() {
return false return false
} }
if !entry.deleting || now.Sub(entry.deleteTime) <= reapInterval { if !entry.deleting {
return false
}
if entry.reapTime > 0 {
entry.reapTime -= reapPeriod
return false return false
} }
paths = append(paths, path) paths = append(paths, path)
return false return false
}) })

View file

@ -4,7 +4,6 @@ import (
"fmt" "fmt"
"net" "net"
"strings" "strings"
"time"
"github.com/Sirupsen/logrus" "github.com/Sirupsen/logrus"
"github.com/gogo/protobuf/proto" "github.com/gogo/protobuf/proto"
@ -121,7 +120,7 @@ func (nDB *NetworkDB) handleNetworkEvent(nEvent *NetworkEvent) bool {
n.ltime = nEvent.LTime n.ltime = nEvent.LTime
n.leaving = nEvent.Type == NetworkEventTypeLeave n.leaving = nEvent.Type == NetworkEventTypeLeave
if n.leaving { if n.leaving {
n.leaveTime = time.Now() n.reapTime = reapInterval
} }
nDB.addNetworkNode(nEvent.NetworkID, nEvent.NodeName) nDB.addNetworkNode(nEvent.NetworkID, nEvent.NodeName)
@ -178,7 +177,7 @@ func (nDB *NetworkDB) handleTableEvent(tEvent *TableEvent) bool {
} }
if e.deleting { if e.deleting {
e.deleteTime = time.Now() e.reapTime = reapInterval
} }
nDB.Lock() nDB.Lock()

View file

@ -107,8 +107,9 @@ type network struct {
// Node leave is in progress. // Node leave is in progress.
leaving bool leaving bool
// The time this node knew about the node's network leave. // Number of seconds still left before a deleted network entry gets
leaveTime time.Time // removed from networkDB
reapTime time.Duration
// The broadcast queue for table event gossip. This is only // The broadcast queue for table event gossip. This is only
// initialized for this node's network attachment entries. // initialized for this node's network attachment entries.
@ -153,8 +154,9 @@ type entry struct {
// the cluster for certain amount of time after deletion. // the cluster for certain amount of time after deletion.
deleting bool deleting bool
// The wall clock time when this node learned about this deletion. // Number of seconds still left before a deleted table entry gets
deleteTime time.Time // removed from networkDB
reapTime time.Duration
} }
// New creates a new instance of NetworkDB using the Config passed by // New creates a new instance of NetworkDB using the Config passed by
@ -286,11 +288,11 @@ func (nDB *NetworkDB) DeleteEntry(tname, nid, key string) error {
} }
entry := &entry{ entry := &entry{
ltime: nDB.tableClock.Increment(), ltime: nDB.tableClock.Increment(),
node: nDB.config.NodeName, node: nDB.config.NodeName,
value: value, value: value,
deleting: true, deleting: true,
deleteTime: time.Now(), reapTime: reapInterval,
} }
if err := nDB.sendTableEvent(TableEventTypeDelete, nid, tname, key, entry); err != nil { if err := nDB.sendTableEvent(TableEventTypeDelete, nid, tname, key, entry); err != nil {
@ -339,11 +341,11 @@ func (nDB *NetworkDB) deleteNodeTableEntries(node string) {
key := params[2] key := params[2]
entry := &entry{ entry := &entry{
ltime: oldEntry.ltime, ltime: oldEntry.ltime,
node: node, node: node,
value: oldEntry.value, value: oldEntry.value,
deleting: true, deleting: true,
deleteTime: time.Now(), reapTime: reapInterval,
} }
nDB.indexes[byTable].Insert(fmt.Sprintf("/%s/%s/%s", tname, nid, key), entry) nDB.indexes[byTable].Insert(fmt.Sprintf("/%s/%s/%s", tname, nid, key), entry)