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 }