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