github.com/zhouyu0/docker-note@v0.0.0-20190722021225-b8d3825084db/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) EnsureLayer(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  
    22  	id, committed := s.getGraphDriverID(key)
    23  	if !committed {
    24  		return nil, errors.Errorf("can not convert active %s to layer", key)
    25  	}
    26  
    27  	info, err := s.Stat(ctx, key)
    28  	if err != nil {
    29  		return nil, err
    30  	}
    31  
    32  	eg, gctx := errgroup.WithContext(ctx)
    33  
    34  	// TODO: add flightcontrol
    35  
    36  	var parentChainID layer.ChainID
    37  	if info.Parent != "" {
    38  		eg.Go(func() error {
    39  			diffIDs, err := s.EnsureLayer(gctx, info.Parent)
    40  			if err != nil {
    41  				return err
    42  			}
    43  			parentChainID = layer.CreateChainID(diffIDs)
    44  			return nil
    45  		})
    46  	}
    47  
    48  	tmpDir, err := ioutils.TempDir("", "docker-tarsplit")
    49  	if err != nil {
    50  		return nil, err
    51  	}
    52  	defer os.RemoveAll(tmpDir)
    53  	tarSplitPath := filepath.Join(tmpDir, "tar-split")
    54  
    55  	var diffID layer.DiffID
    56  	var size int64
    57  	eg.Go(func() error {
    58  		parent := ""
    59  		if p := info.Parent; p != "" {
    60  			if l, err := s.getLayer(p, true); err != nil {
    61  				return err
    62  			} else if l != nil {
    63  				parent, err = getGraphID(l)
    64  				if err != nil {
    65  					return err
    66  				}
    67  			} else {
    68  				parent, _ = s.getGraphDriverID(info.Parent)
    69  			}
    70  		}
    71  		diffID, size, err = s.reg.ChecksumForGraphID(id, parent, "", tarSplitPath)
    72  		return err
    73  	})
    74  
    75  	if err := eg.Wait(); err != nil {
    76  		return nil, err
    77  	}
    78  
    79  	l, err := s.reg.RegisterByGraphID(id, parentChainID, diffID, tarSplitPath, size)
    80  	if err != nil {
    81  		return nil, err
    82  	}
    83  
    84  	if err := s.db.Update(func(tx *bolt.Tx) error {
    85  		b := tx.Bucket([]byte(key))
    86  		b.Put(keyChainID, []byte(l.ChainID()))
    87  		return nil
    88  	}); err != nil {
    89  		return nil, err
    90  	}
    91  
    92  	s.mu.Lock()
    93  	s.refs[key] = l
    94  	s.mu.Unlock()
    95  
    96  	return getDiffChain(l), nil
    97  }
    98  
    99  func getDiffChain(l layer.Layer) []layer.DiffID {
   100  	if p := l.Parent(); p != nil {
   101  		return append(getDiffChain(p), l.DiffID())
   102  	}
   103  	return []layer.DiffID{l.DiffID()}
   104  }
   105  
   106  func getGraphID(l layer.Layer) (string, error) {
   107  	if l, ok := l.(interface {
   108  		CacheID() string
   109  	}); ok {
   110  		return l.CacheID(), nil
   111  	}
   112  	return "", errors.Errorf("couldn't access cacheID for %s", l.ChainID())
   113  }