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 }