mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Add support to trigger immediate garbage collection
Right now the namespace paths are cleaned up every garbage collection period. But if the daemon is restarted before all the namespace paths of removed containers are garbage collected they will remain there forever. The fix is to provide a GC() api so that garbage collection can be triggered immediately. Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
This commit is contained in:
parent
dbc025117d
commit
15ddc3717a
4 changed files with 64 additions and 5 deletions
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -153,9 +153,16 @@ func verifySandbox(t *testing.T, s Sandbox) {
|
|||
}
|
||||
}
|
||||
|
||||
func verifyCleanup(t *testing.T, s Sandbox) {
|
||||
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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Add table
Reference in a new issue