Skip to content

Commit

Permalink
fix: Key function
Browse files Browse the repository at this point in the history
- Merge only last layer onto `currentImage`.
  • Loading branch information
gabyx committed May 17, 2022
1 parent 62747f6 commit 11bab2f
Showing 1 changed file with 45 additions and 28 deletions.
73 changes: 45 additions & 28 deletions pkg/snapshot/layered_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type LayeredMap struct {
cacheHasher func(string) (string, error)
}

// NewLayeredMap creates a new layered map which keeps track of adds and deletes.
func NewLayeredMap(h func(string) (string, error), c func(string) (string, error)) *LayeredMap {
l := LayeredMap{
hasher: h,
Expand All @@ -49,69 +50,85 @@ func NewLayeredMap(h func(string) (string, error), c func(string) (string, error
return &l
}

// Snapshot creates a new layer.
func (l *LayeredMap) Snapshot() {

// Save current state of image
l.UpdateCurrentImage()
l.updateCurrentImage()

l.whiteouts = append(l.whiteouts, map[string]struct{}{})
l.layers = append(l.layers, map[string]string{})
l.layerHashCache = map[string]string{} // Erase the hash cache for this new layer.
}

// Key returns a hash for added files
// Key returns a hash for added and delted files.
func (l *LayeredMap) Key() (string, error) {
c := bytes.NewBuffer([]byte{})
enc := json.NewEncoder(c)
err := enc.Encode(l.layers)
err := enc.Encode(l.layers[len(l.layers)-1])
if err != nil {
return "", err
}
err = enc.Encode(l.whiteouts[len(l.whiteouts)-1])
if err != nil {
return "", err
}
return util.SHA256(c)
}

// UpdateCurrentImage computes the current image by
// flattening all layers and stores the result in currentImage.
func (l *LayeredMap) UpdateCurrentImage() {
// getCurrentImage returns the current image by merging the latest
// adds and deletes on to the current image (if its not yet valid.)
func (l *LayeredMap) getCurrentImage() map[string]string {
if l.isCurrentImageValid {
return
return l.currentImage
}

l.currentImage = map[string]string{}
current := map[string]string{}

// Adding and deleting files over all layers.
for i := 0; i < len(l.layers); i++ {
addedFiles := l.layers[i]
deletedFiles := l.whiteouts[i]
// Copy current image paths/hashes.
for p, h := range l.currentImage {
current[p] = h
}

for add, hash := range addedFiles {
l.currentImage[add] = hash
}
// Add the last layer on top.
addedFiles := l.layers[len(l.layers)-1]
deletedFiles := l.whiteouts[len(l.whiteouts)-1]

for del := range deletedFiles {
delete(l.currentImage, del)
}
for add, hash := range addedFiles {
current[add] = hash
}

l.isCurrentImageValid = true
for del := range deletedFiles {
delete(current, del)
}

return current
}

func (l *LayeredMap) Get(s string) (string, bool) {
for i := len(l.layers) - 1; i >= 0; i-- {
if v, ok := l.layers[i][s]; ok {
return v, ok
}
// updateCurrentImage update the internal current image by merging the
// top adds and deletes onto the current image.
func (l *LayeredMap) updateCurrentImage() {
if l.isCurrentImageValid {
return
}
return "", false

l.currentImage = l.getCurrentImage()
l.isCurrentImageValid = true
}

// get returns the current hash in the current image `l.currentImage`.
func (l *LayeredMap) get(s string) (string, bool) {
h, ok := l.currentImage[s]
return h, ok
}

// GetCurrentPaths returns all existing paths in the actual current image
// cached by FlattenLayers.
func (l *LayeredMap) GetCurrentPaths() map[string]struct{} {
l.UpdateCurrentImage()
current := l.getCurrentImage()

paths := map[string]struct{}{}
for f := range l.currentImage {
for f := range current {
paths[f] = struct{}{}
}
return paths
Expand Down Expand Up @@ -162,7 +179,7 @@ func (l *LayeredMap) CheckFileChange(s string) (bool, error) {
// adding the file.
l.layerHashCache[s] = newV

oldV, ok := l.currentImage[s]
oldV, ok := l.get(s)
if ok && newV == oldV {
// File hash did not change => Unchanged.
return false, nil
Expand Down

0 comments on commit 11bab2f

Please sign in to comment.