github.com/walkingsparrow/docker@v1.4.2-0.20151218153551-b708a2249bfa/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  	// ErrActiveMount is used when an operation on a
    35  	// mount is attempted but the layer is still
    36  	// mounted and the operation cannot be performed.
    37  	ErrActiveMount = errors.New("mount still active")
    38  
    39  	// ErrNotMounted is used when requesting an active
    40  	// mount but the layer is not mounted.
    41  	ErrNotMounted = errors.New("not mounted")
    42  
    43  	// ErrMaxDepthExceeded is used when a layer is attempted
    44  	// to be created which would result in a layer depth
    45  	// greater than the 125 max.
    46  	ErrMaxDepthExceeded = errors.New("max depth exceeded")
    47  )
    48  
    49  // ChainID is the content-addressable ID of a layer.
    50  type ChainID digest.Digest
    51  
    52  // String returns a string rendition of a layer ID
    53  func (id ChainID) String() string {
    54  	return string(id)
    55  }
    56  
    57  // DiffID is the hash of an individual layer tar.
    58  type DiffID digest.Digest
    59  
    60  // String returns a string rendition of a layer DiffID
    61  func (diffID DiffID) String() string {
    62  	return string(diffID)
    63  }
    64  
    65  // TarStreamer represents an object which may
    66  // have its contents exported as a tar stream.
    67  type TarStreamer interface {
    68  	// TarStream returns a tar archive stream
    69  	// for the contents of a layer.
    70  	TarStream() (io.ReadCloser, error)
    71  }
    72  
    73  // Layer represents a read only layer
    74  type Layer interface {
    75  	TarStreamer
    76  
    77  	// ChainID returns the content hash of the entire layer chain. The hash
    78  	// chain is made up of DiffID of top layer and all of its parents.
    79  	ChainID() ChainID
    80  
    81  	// DiffID returns the content hash of the layer
    82  	// tar stream used to create this layer.
    83  	DiffID() DiffID
    84  
    85  	// Parent returns the next layer in the layer chain.
    86  	Parent() Layer
    87  
    88  	// Size returns the size of the entire layer chain. The size
    89  	// is calculated from the total size of all files in the layers.
    90  	Size() (int64, error)
    91  
    92  	// DiffSize returns the size difference of the top layer
    93  	// from parent layer.
    94  	DiffSize() (int64, error)
    95  
    96  	// Metadata returns the low level storage metadata associated
    97  	// with layer.
    98  	Metadata() (map[string]string, error)
    99  }
   100  
   101  // RWLayer represents a layer which is
   102  // read and writable
   103  type RWLayer interface {
   104  	TarStreamer
   105  
   106  	// Path returns the filesystem path to the writable
   107  	// layer.
   108  	Path() (string, error)
   109  
   110  	// Parent returns the layer which the writable
   111  	// layer was created from.
   112  	Parent() Layer
   113  
   114  	// Size represents the size of the writable layer
   115  	// as calculated by the total size of the files
   116  	// changed in the mutable layer.
   117  	Size() (int64, error)
   118  }
   119  
   120  // Metadata holds information about a
   121  // read only layer
   122  type Metadata struct {
   123  	// ChainID is the content hash of the layer
   124  	ChainID ChainID
   125  
   126  	// DiffID is the hash of the tar data used to
   127  	// create the layer
   128  	DiffID DiffID
   129  
   130  	// Size is the size of the layer and all parents
   131  	Size int64
   132  
   133  	// DiffSize is the size of the top layer
   134  	DiffSize int64
   135  }
   136  
   137  // MountInit is a function to initialize a
   138  // writable mount. Changes made here will
   139  // not be included in the Tar stream of the
   140  // RWLayer.
   141  type MountInit func(root string) error
   142  
   143  // Store represents a backend for managing both
   144  // read-only and read-write layers.
   145  type Store interface {
   146  	Register(io.Reader, ChainID) (Layer, error)
   147  	Get(ChainID) (Layer, error)
   148  	Release(Layer) ([]Metadata, error)
   149  
   150  	Mount(id string, parent ChainID, label string, init MountInit) (RWLayer, error)
   151  	Unmount(id string) error
   152  	DeleteMount(id string) ([]Metadata, error)
   153  	Changes(id string) ([]archive.Change, error)
   154  	Metadata(id string) (map[string]string, error)
   155  }
   156  
   157  // MetadataTransaction represents functions for setting layer metadata
   158  // with a single transaction.
   159  type MetadataTransaction interface {
   160  	SetSize(int64) error
   161  	SetParent(parent ChainID) error
   162  	SetDiffID(DiffID) error
   163  	SetCacheID(string) error
   164  	TarSplitWriter() (io.WriteCloser, error)
   165  
   166  	Commit(ChainID) error
   167  	Cancel() error
   168  	String() string
   169  }
   170  
   171  // MetadataStore represents a backend for persisting
   172  // metadata about layers and providing the metadata
   173  // for restoring a Store.
   174  type MetadataStore interface {
   175  	// StartTransaction starts an update for new metadata
   176  	// which will be used to represent an ID on commit.
   177  	StartTransaction() (MetadataTransaction, error)
   178  
   179  	GetSize(ChainID) (int64, error)
   180  	GetParent(ChainID) (ChainID, error)
   181  	GetDiffID(ChainID) (DiffID, error)
   182  	GetCacheID(ChainID) (string, error)
   183  	TarSplitReader(ChainID) (io.ReadCloser, error)
   184  
   185  	SetMountID(string, string) error
   186  	SetInitID(string, string) error
   187  	SetMountParent(string, ChainID) error
   188  
   189  	GetMountID(string) (string, error)
   190  	GetInitID(string) (string, error)
   191  	GetMountParent(string) (ChainID, error)
   192  
   193  	// List returns the full list of referenced
   194  	// read-only and read-write layers
   195  	List() ([]ChainID, []string, error)
   196  
   197  	Remove(ChainID) error
   198  	RemoveMount(string) error
   199  }
   200  
   201  // CreateChainID returns ID for a layerDigest slice
   202  func CreateChainID(dgsts []DiffID) ChainID {
   203  	return createChainIDFromParent("", dgsts...)
   204  }
   205  
   206  func createChainIDFromParent(parent ChainID, dgsts ...DiffID) ChainID {
   207  	if len(dgsts) == 0 {
   208  		return parent
   209  	}
   210  	if parent == "" {
   211  		return createChainIDFromParent(ChainID(dgsts[0]), dgsts[1:]...)
   212  	}
   213  	// H = "H(n-1) SHA256(n)"
   214  	dgst, err := digest.FromBytes([]byte(string(parent) + " " + string(dgsts[0])))
   215  	if err != nil {
   216  		// Digest calculation is not expected to throw an error,
   217  		// any error at this point is a program error
   218  		panic(err)
   219  	}
   220  	return createChainIDFromParent(ChainID(dgst), dgsts[1:]...)
   221  }
   222  
   223  // ReleaseAndLog releases the provided layer from the given layer
   224  // store, logging any error and release metadata
   225  func ReleaseAndLog(ls Store, l Layer) {
   226  	metadata, err := ls.Release(l)
   227  	if err != nil {
   228  		logrus.Errorf("Error releasing layer %s: %v", l.ChainID(), err)
   229  	}
   230  	LogReleaseMetadata(metadata)
   231  }
   232  
   233  // LogReleaseMetadata logs a metadata array, use this to
   234  // ensure consistent logging for release metadata
   235  func LogReleaseMetadata(metadatas []Metadata) {
   236  	for _, metadata := range metadatas {
   237  		logrus.Infof("Layer %s cleaned up", metadata.ChainID)
   238  	}
   239  }