graph: add parent img refcount for faster rmi

also fix a typo in pkg/truncindex package comment

Signed-off-by: Antonio Murdaca <amurdaca@redhat.com>
This commit is contained in:
Antonio Murdaca 2015-10-06 01:50:45 +02:00
parent 0137e3eda2
commit 292a1564dc
2 changed files with 41 additions and 10 deletions

View File

@ -82,6 +82,9 @@ type Graph struct {
imageMutex imageMutex // protect images in driver. imageMutex imageMutex // protect images in driver.
retained *retainedLayers retained *retainedLayers
tarSplitDisabled bool tarSplitDisabled bool
parentRefs map[string]int
parentRefsMutex sync.Mutex
} }
// file names for ./graph/<ID>/ // file names for ./graph/<ID>/
@ -116,6 +119,7 @@ func NewGraph(root string, driver graphdriver.Driver) (*Graph, error) {
idIndex: truncindex.NewTruncIndex([]string{}), idIndex: truncindex.NewTruncIndex([]string{}),
driver: driver, driver: driver,
retained: &retainedLayers{layerHolders: make(map[string]map[string]struct{})}, retained: &retainedLayers{layerHolders: make(map[string]map[string]struct{})},
parentRefs: make(map[string]int),
} }
// Windows does not currently support tarsplit functionality. // Windows does not currently support tarsplit functionality.
@ -283,6 +287,13 @@ func (graph *Graph) Register(img *image.Image, layerData io.Reader) (err error)
return err return err
} }
graph.idIndex.Add(img.ID) graph.idIndex.Add(img.ID)
graph.parentRefsMutex.Lock()
if img.Parent != "" {
graph.parentRefs[img.Parent]++
}
graph.parentRefsMutex.Unlock()
return nil return nil
} }
@ -345,6 +356,10 @@ func (graph *Graph) Delete(name string) error {
if err != nil { if err != nil {
return err return err
} }
img, err := graph.Get(id)
if err != nil {
return err
}
tmp, err := graph.mktemp() tmp, err := graph.mktemp()
graph.idIndex.Delete(id) graph.idIndex.Delete(id)
if err == nil { if err == nil {
@ -359,6 +374,16 @@ func (graph *Graph) Delete(name string) error {
} }
// Remove rootfs data from the driver // Remove rootfs data from the driver
graph.driver.Remove(id) graph.driver.Remove(id)
graph.parentRefsMutex.Lock()
if img.Parent != "" {
graph.parentRefs[img.Parent]--
if graph.parentRefs[img.Parent] == 0 {
delete(graph.parentRefs, img.Parent)
}
}
graph.parentRefsMutex.Unlock()
// Remove the trashed image directory // Remove the trashed image directory
return os.RemoveAll(tmp) return os.RemoveAll(tmp)
} }
@ -376,9 +401,11 @@ func (graph *Graph) Map() map[string]*image.Image {
// The walking order is undetermined. // The walking order is undetermined.
func (graph *Graph) walkAll(handler func(*image.Image)) { func (graph *Graph) walkAll(handler func(*image.Image)) {
graph.idIndex.Iterate(func(id string) { graph.idIndex.Iterate(func(id string) {
if img, err := graph.Get(id); err != nil { img, err := graph.Get(id)
if err != nil {
return return
} else if handler != nil { }
if handler != nil {
handler(img) handler(img)
} }
}) })
@ -406,7 +433,10 @@ func (graph *Graph) ByParent() map[string][]*image.Image {
// HasChildren returns whether the given image has any child images. // HasChildren returns whether the given image has any child images.
func (graph *Graph) HasChildren(img *image.Image) bool { func (graph *Graph) HasChildren(img *image.Image) bool {
return len(graph.ByParent()[img.ID]) > 0 graph.parentRefsMutex.Lock()
refCount := graph.parentRefs[img.ID]
graph.parentRefsMutex.Unlock()
return refCount > 0
} }
// Retain keeps the images and layers that are in the pulling chain so that // Retain keeps the images and layers that are in the pulling chain so that
@ -424,13 +454,14 @@ func (graph *Graph) Release(sessionID string, layerIDs ...string) {
// A head is an image which is not the parent of another image in the graph. // A head is an image which is not the parent of another image in the graph.
func (graph *Graph) Heads() map[string]*image.Image { func (graph *Graph) Heads() map[string]*image.Image {
heads := make(map[string]*image.Image) heads := make(map[string]*image.Image)
byParent := graph.ByParent()
graph.walkAll(func(image *image.Image) { graph.walkAll(func(image *image.Image) {
// If it's not in the byParent lookup table, then // If it's not in the byParent lookup table, then
// it's not a parent -> so it's a head! // it's not a parent -> so it's a head!
if _, exists := byParent[image.ID]; !exists { graph.parentRefsMutex.Lock()
if _, exists := graph.parentRefs[image.ID]; !exists {
heads[image.ID] = image heads[image.ID] = image
} }
graph.parentRefsMutex.Unlock()
}) })
return heads return heads
} }

View File

@ -1,4 +1,4 @@
// Package truncindex package provides a general 'index tree', used by Docker // Package truncindex provides a general 'index tree', used by Docker
// in order to be able to reference containers by only a few unambiguous // in order to be able to reference containers by only a few unambiguous
// characters of their id. // characters of their id.
package truncindex package truncindex