Merge pull request #262 from mrjana/cnm_integ

Add support to trigger immediate garbage collection
This commit is contained in:
Madhu Venugopal 2015-06-05 14:21:35 -07:00
commit 48374f367f
4 changed files with 64 additions and 5 deletions

View file

@ -59,6 +59,7 @@ import (
"github.com/docker/libnetwork/datastore"
"github.com/docker/libnetwork/driverapi"
"github.com/docker/libnetwork/hostdiscovery"
"github.com/docker/libnetwork/sandbox"
"github.com/docker/libnetwork/types"
"github.com/docker/swarm/pkg/store"
)
@ -84,6 +85,9 @@ type NetworkController interface {
// NetworkByID returns the Network which has the passed id. If not found, the error ErrNoSuchNetwork is returned.
NetworkByID(id string) (Network, error)
// GC triggers immediate garbage collection of resources which are garbage collected.
GC()
}
// NetworkWalker is a client provided function which will be used to walk the Networks.
@ -394,3 +398,7 @@ func (c *controller) loadDriver(networkType string) (driverapi.Driver, error) {
}
return d, nil
}
func (c *controller) GC() {
sandbox.GC()
}

View file

@ -25,6 +25,7 @@ var (
gpmLock sync.Mutex
gpmWg sync.WaitGroup
gpmCleanupPeriod = 60 * time.Second
gpmChan = make(chan chan struct{})
)
// The networkNamespace type is the linux implementation of the Sandbox
@ -56,7 +57,18 @@ func removeUnusedPaths() {
period := gpmCleanupPeriod
gpmLock.Unlock()
for range time.Tick(period) {
ticker := time.NewTicker(period)
for {
var (
gc chan struct{}
gcOk bool
)
select {
case <-ticker.C:
case gc, gcOk = <-gpmChan:
}
gpmLock.Lock()
pathList := make([]string, 0, len(garbagePathMap))
for path := range garbagePathMap {
@ -71,6 +83,9 @@ func removeUnusedPaths() {
}
gpmWg.Done()
if gcOk {
close(gc)
}
}
}
@ -86,6 +101,18 @@ func removeFromGarbagePaths(path string) {
gpmLock.Unlock()
}
// GC triggers garbage collection of namespace path right away
// and waits for it.
func GC() {
waitGC := make(chan struct{})
// Trigger GC now
gpmChan <- waitGC
// wait for gc to complete
<-waitGC
}
// GenerateKey generates a sandbox key based on the passed
// container id.
func GenerateKey(containerID string) string {

View file

@ -153,9 +153,16 @@ func verifySandbox(t *testing.T, s Sandbox) {
}
}
func verifyCleanup(t *testing.T, s Sandbox) {
time.Sleep(time.Duration(gpmCleanupPeriod * 2))
func verifyCleanup(t *testing.T, s Sandbox, wait bool) {
if wait {
time.Sleep(time.Duration(gpmCleanupPeriod * 2))
}
if _, err := os.Stat(s.Key()); err == nil {
t.Fatalf("The sandbox path %s is not getting cleanup event after twice the cleanup period", s.Key())
if wait {
t.Fatalf("The sandbox path %s is not getting cleaned up even after twice the cleanup period", s.Key())
} else {
t.Fatalf("The sandbox path %s is not cleaned up after running gc", s.Key())
}
}
}

View file

@ -54,7 +54,7 @@ func TestSandboxCreate(t *testing.T) {
verifySandbox(t, s)
s.Destroy()
verifyCleanup(t, s)
verifyCleanup(t, s, true)
}
func TestSandboxCreateTwice(t *testing.T) {
@ -77,6 +77,23 @@ func TestSandboxCreateTwice(t *testing.T) {
s.Destroy()
}
func TestSandboxGC(t *testing.T) {
key, err := newKey(t)
if err != nil {
t.Fatalf("Failed to obtain a key: %v", err)
}
s, err := NewSandbox(key, true)
if err != nil {
t.Fatalf("Failed to create a new sandbox: %v", err)
}
s.Destroy()
GC()
verifyCleanup(t, s, false)
}
func TestAddRemoveInterface(t *testing.T) {
key, err := newKey(t)
if err != nil {