github.com/docker/docker@v299999999.0.0-20200612211812-aaf470eca7b5+incompatible/builder/builder-next/adapters/snapshot/layer.go (about)

     1  package snapshot
     2  
     3  import (
     4  	"context"
     5  	"os"
     6  	"path/filepath"
     7  
     8  	"github.com/docker/docker/layer"
     9  	"github.com/docker/docker/pkg/ioutils"
    10  	"github.com/pkg/errors"
    11  	bolt "go.etcd.io/bbolt"
    12  	"golang.org/x/sync/errgroup"
    13  )
    14  
    15  func (s *snapshotter) GetDiffIDs(ctx context.Context, key string) ([]layer.DiffID, error) {
    16  	if l, err := s.getLayer(key, true); err != nil {
    17  		return nil, err
    18  	} else if l != nil {
    19  		return getDiffChain(l), nil
    20  	}
    21  	return nil, nil
    22  }
    23  
    24  func (s *snapshotter) EnsureLayer(ctx context.Context, key string) ([]layer.DiffID, error) {
    25  	diffIDs, err := s.GetDiffIDs(ctx, key)
    26  	if err != nil {
    27  		return nil, err
    28  	} else if diffIDs != nil {
    29  		return diffIDs, nil
    30  	}
    31  
    32  	id, committed := s.getGraphDriverID(key)
    33  	if !committed {
    34  		return nil, errors.Errorf("can not convert active %s to layer", key)
    35  	}
    36  
    37  	info, err := s.Stat(ctx, key)
    38  	if err != nil {
    39  		return nil, err
    40  	}
    41  
    42  	eg, gctx := errgroup.WithContext(ctx)
    43  
    44  	// TODO: add flightcontrol
    45  
    46  	var parentChainID layer.ChainID
    47  	if info.Parent != "" {
    48  		eg.Go(func() error {
    49  			diffIDs, err := s.EnsureLayer(gctx, info.Parent)
    50  			if err != nil {
    51  				return err
    52  			}
    53  			parentChainID = layer.CreateChainID(diffIDs)
    54  			return nil
    55  		})
    56  	}
    57  
    58  	tmpDir, err := ioutils.TempDir("", "docker-tarsplit")
    59  	if err != nil {
    60  		return nil, err
    61  	}
    62  	defer os.RemoveAll(tmpDir)
    63  	tarSplitPath := filepath.Join(tmpDir, "tar-split")
    64  
    65  	var diffID layer.DiffID
    66  	var size int64
    67  	eg.Go(func() error {
    68  		parent := ""
    69  		if p := info.Parent; p != "" {
    70  			if l, err := s.getLayer(p, true); err != nil {
    71  				return err
    72  			} else if l != nil {
    73  				parent, err = getGraphID(l)
    74  				if err != nil {
    75  					return err
    76  				}
    77  			} else {
    78  				parent, _ = s.getGraphDriverID(info.Parent)
    79  			}
    80  		}
    81  		diffID, size, err = s.reg.ChecksumForGraphID(id, parent, "", tarSplitPath)
    82  		return err
    83  	})
    84  
    85  	if err := eg.Wait(); err != nil {
    86  		return nil, err
    87  	}
    88  
    89  	l, err := s.reg.RegisterByGraphID(id, parentChainID, diffID, tarSplitPath, size)
    90  	if err != nil {
    91  		return nil, err
    92  	}
    93  
    94  	if err := s.db.Update(func(tx *bolt.Tx) error {
    95  		b := tx.Bucket([]byte(key))
    96  		b.Put(keyChainID, []byte(l.ChainID()))
    97  		return nil
    98  	}); err != nil {
    99  		return nil, err
   100  	}
   101  
   102  	s.mu.Lock()
   103  	s.refs[key] = l
   104  	s.mu.Unlock()
   105  
   106  	return getDiffChain(l), nil
   107  }
   108  
   109  func getDiffChain(l layer.Layer) []layer.DiffID {
   110  	if p := l.Parent(); p != nil {
   111  		return append(getDiffChain(p), l.DiffID())
   112  	}
   113  	return []layer.DiffID{l.DiffID()}
   114  }
   115  
   116  func getGraphID(l layer.Layer) (string, error) {
   117  	if l, ok := l.(interface {
   118  		CacheID() string
   119  	}); ok {
   120  		return l.CacheID(), nil
   121  	}
   122  	return "", errors.Errorf("couldn't access cacheID for %s", l.ChainID())
   123  }