diff --git a/libnetwork/controller.go b/libnetwork/controller.go index 225f7fa609..fe9c4ddf97 100644 --- a/libnetwork/controller.go +++ b/libnetwork/controller.go @@ -44,7 +44,6 @@ create network namespaces and allocate interfaces for containers to use. package libnetwork import ( - "container/heap" "fmt" "net" "path/filepath" @@ -1085,7 +1084,7 @@ func (c *controller) NewSandbox(containerID string, options ...SandboxOption) (S sb = &sandbox{ id: sandboxID, containerID: containerID, - endpoints: epHeap{}, + endpoints: []*endpoint{}, epPriority: map[string]int{}, populatedEndpoints: map[string]struct{}{}, config: containerConfig{}, @@ -1094,8 +1093,6 @@ func (c *controller) NewSandbox(containerID string, options ...SandboxOption) (S } } - heap.Init(&sb.endpoints) - sb.processOptions(options...) c.Lock() diff --git a/libnetwork/endpoint.go b/libnetwork/endpoint.go index 1e1b6a1675..822b9fe173 100644 --- a/libnetwork/endpoint.go +++ b/libnetwork/endpoint.go @@ -1,7 +1,6 @@ package libnetwork import ( - "container/heap" "encoding/json" "fmt" "net" @@ -514,9 +513,7 @@ func (ep *endpoint) sbJoin(sb *sandbox, options ...EndpointOption) (err error) { // Current endpoint providing external connectivity for the sandbox extEp := sb.getGatewayEndpoint() - sb.Lock() - heap.Push(&sb.endpoints, ep) - sb.Unlock() + sb.addEndpoint(ep) defer func() { if err != nil { sb.removeEndpoint(ep) diff --git a/libnetwork/sandbox.go b/libnetwork/sandbox.go index 423066c128..41e8d01c5d 100644 --- a/libnetwork/sandbox.go +++ b/libnetwork/sandbox.go @@ -1,10 +1,10 @@ package libnetwork import ( - "container/heap" "encoding/json" "fmt" "net" + "sort" "strings" "sync" "time" @@ -63,8 +63,6 @@ func (sb *sandbox) processOptions(options ...SandboxOption) { } } -type epHeap []*endpoint - type sandbox struct { id string containerID string @@ -75,7 +73,7 @@ type sandbox struct { resolver Resolver resolverOnce sync.Once refCnt int - endpoints epHeap + endpoints []*endpoint epPriority map[string]int populatedEndpoints map[string]struct{} joinLeaveDone chan struct{} @@ -360,13 +358,31 @@ func (sb *sandbox) getConnectedEndpoints() []*endpoint { return eps } +func (sb *sandbox) addEndpoint(ep *endpoint) { + sb.Lock() + defer sb.Unlock() + + l := len(sb.endpoints) + i := sort.Search(l, func(j int) bool { + return ep.Less(sb.endpoints[j]) + }) + + sb.endpoints = append(sb.endpoints, nil) + copy(sb.endpoints[i+1:], sb.endpoints[i:]) + sb.endpoints[i] = ep +} + func (sb *sandbox) removeEndpoint(ep *endpoint) { sb.Lock() defer sb.Unlock() + sb.removeEndpointRaw(ep) +} + +func (sb *sandbox) removeEndpointRaw(ep *endpoint) { for i, e := range sb.endpoints { if e == ep { - heap.Remove(&sb.endpoints, i) + sb.endpoints = append(sb.endpoints[:i], sb.endpoints[i+1:]...) return } } @@ -940,7 +956,7 @@ func (sb *sandbox) clearNetworkResources(origEp *endpoint) error { return nil } - heap.Remove(&sb.endpoints, index) + sb.removeEndpointRaw(ep) for _, e := range sb.endpoints { if len(e.Gateway()) > 0 { gwepAfter = e @@ -1165,19 +1181,14 @@ func OptionIngress() SandboxOption { } } -func (eh epHeap) Len() int { return len(eh) } - -func (eh epHeap) Less(i, j int) bool { +func (epi *endpoint) Less(epj *endpoint) bool { var ( cip, cjp int ok bool ) - ci, _ := eh[i].getSandbox() - cj, _ := eh[j].getSandbox() - - epi := eh[i] - epj := eh[j] + ci, _ := epi.getSandbox() + cj, _ := epj.getSandbox() if epi.endpointInGWNetwork() { return false @@ -1207,40 +1218,26 @@ func (eh epHeap) Less(i, j int) bool { } if ci != nil { - cip, ok = ci.epPriority[eh[i].ID()] + cip, ok = ci.epPriority[epi.ID()] if !ok { cip = 0 } } if cj != nil { - cjp, ok = cj.epPriority[eh[j].ID()] + cjp, ok = cj.epPriority[epj.ID()] if !ok { cjp = 0 } } if cip == cjp { - return eh[i].network.Name() < eh[j].network.Name() + return epi.network.Name() < epj.network.Name() } return cip > cjp } -func (eh epHeap) Swap(i, j int) { eh[i], eh[j] = eh[j], eh[i] } - -func (eh *epHeap) Push(x interface{}) { - *eh = append(*eh, x.(*endpoint)) -} - -func (eh *epHeap) Pop() interface{} { - old := *eh - n := len(old) - x := old[n-1] - *eh = old[0 : n-1] - return x -} - func (sb *sandbox) NdotsSet() bool { return sb.ndotsSet } diff --git a/libnetwork/sandbox_store.go b/libnetwork/sandbox_store.go index a083644598..ebc884e6f0 100644 --- a/libnetwork/sandbox_store.go +++ b/libnetwork/sandbox_store.go @@ -1,7 +1,6 @@ package libnetwork import ( - "container/heap" "encoding/json" "sync" @@ -215,7 +214,7 @@ func (c *controller) sandboxCleanup(activeSandboxes map[string]interface{}) { id: sbs.ID, controller: sbs.c, containerID: sbs.Cid, - endpoints: epHeap{}, + endpoints: []*endpoint{}, populatedEndpoints: map[string]struct{}{}, dbIndex: sbs.dbIndex, isStub: true, @@ -242,7 +241,6 @@ func (c *controller) sandboxCleanup(activeSandboxes map[string]interface{}) { sb.processOptions(opts...) sb.restorePath() create = !sb.config.useDefaultSandBox - heap.Init(&sb.endpoints) } sb.osSbox, err = osl.NewSandbox(sb.Key(), create, isRestore) if err != nil { @@ -272,7 +270,7 @@ func (c *controller) sandboxCleanup(activeSandboxes map[string]interface{}) { logrus.Errorf("failed to restore endpoint %s in %s for container %s due to %v", eps.Eid, eps.Nid, sb.ContainerID(), err) continue } - heap.Push(&sb.endpoints, ep) + sb.addEndpoint(ep) } if _, ok := activeSandboxes[sb.ID()]; !ok {