github.com/sijibomii/docker@v0.0.0-20231230191044-5cf6ca554647/layer/layer.go (about)

     1  // Package layer is package for managing read-only
     2  // and read-write mounts on the union file system
     3  // driver. Read-only mounts are referenced using a
     4  // content hash and are protected from mutation in
     5  // the exposed interface. The tar format is used
     6  // to create read-only layers and export both
     7  // read-only and writable layers. The exported
     8  // tar data for a read-only layer should match
     9  // the tar used to create the layer.
    10  package layer
    11  
    12  import (
    13  	"errors"
    14  	"io"
    15  
    16  	"github.com/Sirupsen/logrus"
    17  	"github.com/docker/distribution/digest"
    18  	"github.com/docker/docker/pkg/archive"
    19  )
    20  
    21  var (
    22  	// ErrLayerDoesNotExist is used when an operation is
    23  	// attempted on a layer which does not exist.
    24  	ErrLayerDoesNotExist = errors.New("layer does not exist")
    25  
    26  	// ErrLayerNotRetained is used when a release is
    27  	// attempted on a layer which is not retained.
    28  	ErrLayerNotRetained = errors.New("layer not retained")
    29  
    30  	// ErrMountDoesNotExist is used when an operation is
    31  	// attempted on a mount layer which does not exist.
    32  	ErrMountDoesNotExist = errors.New("mount does not exist")
    33  
    34  	// ErrMountNameConflict is used when a mount is attempted
    35  	// to be created but there is already a mount with the name
    36  	// used for creation.
    37  	ErrMountNameConflict = errors.New("mount already exists with name")
    38  
    39  	// ErrActiveMount is used when an operation on a
    40  	// mount is attempted but the layer is still
    41  	// mounted and the operation cannot be performed.
    42  	ErrActiveMount = errors.New("mount still active")
    43  
    44  	// ErrNotMounted is used when requesting an active
    45  	// mount but the layer is not mounted.
    46  	ErrNotMounted = errors.New("not mounted")
    47  
    48  	// ErrMaxDepthExceeded is used when a layer is attempted
    49  	// to be created which would result in a layer depth
    50  	// greater than the 125 max.
    51  	ErrMaxDepthExceeded = errors.New("max depth exceeded")
    52  
    53  	// ErrNotSupported is used when the action is not supppoted
    54  	// on the current platform
    55  	ErrNotSupported = errors.New("not support on this platform")
    56  )
    57  
    58  // ChainID is the content-addressable ID of a layer.
    59  type ChainID digest.Digest
    60  
    61  // String returns a string rendition of a layer ID
    62  func (id ChainID) String() string {
    63  	return string(id)
    64  }
    65  
    66  // DiffID is the hash of an individual layer tar.
    67  type DiffID digest.Digest
    68  
    69  // String returns a string rendition of a layer DiffID
    70  func (diffID DiffID) String() string {
    71  	return string(diffID)
    72  }
    73  
    74  // TarStreamer represents an object which may
    75  // have its contents exported as a tar stream.
    76  type TarStreamer interface {
    77  	// TarStream returns a tar archive stream
    78  	// for the contents of a layer.
    79  	TarStream() (io.ReadCloser, error)
    80  }
    81  
    82  // Layer represents a read-only layer
    83  type Layer interface {
    84  	TarStreamer
    85  
    86  	// ChainID returns the content hash of the entire layer chain. The hash
    87  	// chain is made up of DiffID of top layer and all of its parents.
    88  	ChainID() ChainID
    89  
    90  	// DiffID returns the content hash of the layer
    91  	// tar stream used to create this layer.
    92  	DiffID() DiffID
    93  
    94  	// Parent returns the next layer in the layer chain.
    95  	Parent() Layer
    96  
    97  	// Size returns the size of the entire layer chain. The size
    98  	// is calculated from the total size of all files in the layers.
    99  	Size() (int64, error)
   100  
   101  	// DiffSize returns the size difference of the top layer
   102  	// from parent layer.
   103  	DiffSize() (int64, error)
   104  
   105  	// Metadata returns the low level storage metadata associated
   106  	// with layer.
   107  	Metadata() (map[string]string, error)
   108  }
   109  
   110  // RWLayer represents a layer which is
   111  // read and writable
   112  type RWLayer interface {
   113  	TarStreamer
   114  
   115  	// Name of mounted layer
   116  	Name() string
   117  
   118  	// Parent returns the layer which the writable
   119  	// layer was created from.
   120  	Parent() Layer
   121  
   122  	// Mount mounts the RWLayer and returns the filesystem path
   123  	// the to the writable layer.
   124  	Mount(mountLabel string) (string, error)
   125  
   126  	// Unmount unmounts the RWLayer. This should be called
   127  	// for every mount. If there are multiple mount calls
   128  	// this operation will only decrement the internal mount counter.
   129  	Unmount() error
   130  
   131  	// Size represents the size of the writable layer
   132  	// as calculated by the total size of the files
   133  	// changed in the mutable layer.
   134  	Size() (int64, error)
   135  
   136  	// Changes returns the set of changes for the mutable layer
   137  	// from the base layer.
   138  	Changes() ([]archive.Change, error)
   139  
   140  	// Metadata returns the low level metadata for the mutable layer
   141  	Metadata() (map[string]string, error)
   142  }
   143  
   144  // Metadata holds information about a
   145  // read-only layer
   146  type Metadata struct {
   147  	// ChainID is the content hash of the layer
   148  	ChainID ChainID
   149  
   150  	// DiffID is the hash of the tar data used to
   151  	// create the layer
   152  	DiffID DiffID
   153  
   154  	// Size is the size of the layer and all parents
   155  	Size int64
   156  
   157  	// DiffSize is the size of the top layer
   158  	DiffSize int64
   159  }
   160  
   161  // MountInit is a function to initialize a
   162  // writable mount. Changes made here will
   163  // not be included in the Tar stream of the
   164  // RWLayer.
   165  type MountInit func(root string) error
   166  
   167  // Store represents a backend for managing both
   168  // read-only and read-write layers.
   169  type Store interface {
   170  	Register(io.Reader, ChainID) (Layer, error)
   171  	Get(ChainID) (Layer, error)
   172  	Release(Layer) ([]Metadata, error)
   173  
   174  	CreateRWLayer(id string, parent ChainID, mountLabel string, initFunc MountInit, storageOpt map[string]string) (RWLayer, error)
   175  	GetRWLayer(id string) (RWLayer, error)
   176  	GetMountID(id string) (string, error)
   177  	ReinitRWLayer(l RWLayer) error
   178  	ReleaseRWLayer(RWLayer) ([]Metadata, error)
   179  
   180  	Cleanup() error
   181  	DriverStatus() [][2]string
   182  	DriverName() string
   183  }
   184  
   185  // MetadataTransaction represents functions for setting layer metadata
   186  // with a single transaction.
   187  type MetadataTransaction interface {
   188  	SetSize(int64) error
   189  	SetParent(parent ChainID) error
   190  	SetDiffID(DiffID) error
   191  	SetCacheID(string) error
   192  	TarSplitWriter(compressInput bool) (io.WriteCloser, error)
   193  
   194  	Commit(ChainID) error
   195  	Cancel() error
   196  	String() string
   197  }
   198  
   199  // MetadataStore represents a backend for persisting
   200  // metadata about layers and providing the metadata
   201  // for restoring a Store.
   202  type MetadataStore interface {
   203  	// StartTransaction starts an update for new metadata
   204  	// which will be used to represent an ID on commit.
   205  	StartTransaction() (MetadataTransaction, error)
   206  
   207  	GetSize(ChainID) (int64, error)
   208  	GetParent(ChainID) (ChainID, error)
   209  	GetDiffID(ChainID) (DiffID, error)
   210  	GetCacheID(ChainID) (string, error)
   211  	TarSplitReader(ChainID) (io.ReadCloser, error)
   212  
   213  	SetMountID(string, string) error
   214  	SetInitID(string, string) error
   215  	SetMountParent(string, ChainID) error
   216  
   217  	GetMountID(string) (string, error)
   218  	GetInitID(string) (string, error)
   219  	GetMountParent(string) (ChainID, error)
   220  
   221  	// List returns the full list of referenced
   222  	// read-only and read-write layers
   223  	List() ([]ChainID, []string, error)
   224  
   225  	Remove(ChainID) error
   226  	RemoveMount(string) error
   227  }
   228  
   229  // CreateChainID returns ID for a layerDigest slice
   230  func CreateChainID(dgsts []DiffID) ChainID {
   231  	return createChainIDFromParent("", dgsts...)
   232  }
   233  
   234  func createChainIDFromParent(parent ChainID, dgsts ...DiffID) ChainID {
   235  	if len(dgsts) == 0 {
   236  		return parent
   237  	}
   238  	if parent == "" {
   239  		return createChainIDFromParent(ChainID(dgsts[0]), dgsts[1:]...)
   240  	}
   241  	// H = "H(n-1) SHA256(n)"
   242  	dgst := digest.FromBytes([]byte(string(parent) + " " + string(dgsts[0])))
   243  	return createChainIDFromParent(ChainID(dgst), dgsts[1:]...)
   244  }
   245  
   246  // ReleaseAndLog releases the provided layer from the given layer
   247  // store, logging any error and release metadata
   248  func ReleaseAndLog(ls Store, l Layer) {
   249  	metadata, err := ls.Release(l)
   250  	if err != nil {
   251  		logrus.Errorf("Error releasing layer %s: %v", l.ChainID(), err)
   252  	}
   253  	LogReleaseMetadata(metadata)
   254  }
   255  
   256  // LogReleaseMetadata logs a metadata array, uses this to
   257  // ensure consistent logging for release metadata
   258  func LogReleaseMetadata(metadatas []Metadata) {
   259  	for _, metadata := range metadatas {
   260  		logrus.Infof("Layer %s cleaned up", metadata.ChainID)
   261  	}
   262  }