Tizen_4.0 base
[platform/upstream/docker-engine.git] / layer / ro_layer.go
1 package layer
2
3 import (
4         "fmt"
5         "io"
6
7         "github.com/docker/distribution"
8         "github.com/docker/docker/pkg/ioutils"
9         "github.com/opencontainers/go-digest"
10 )
11
12 type roLayer struct {
13         chainID    ChainID
14         diffID     DiffID
15         parent     *roLayer
16         cacheID    string
17         size       int64
18         layerStore *layerStore
19         descriptor distribution.Descriptor
20         platform   Platform
21
22         referenceCount int
23         references     map[Layer]struct{}
24 }
25
26 // TarStream for roLayer guarantees that the data that is produced is the exact
27 // data that the layer was registered with.
28 func (rl *roLayer) TarStream() (io.ReadCloser, error) {
29         rc, err := rl.layerStore.getTarStream(rl)
30         if err != nil {
31                 return nil, err
32         }
33
34         vrc, err := newVerifiedReadCloser(rc, digest.Digest(rl.diffID))
35         if err != nil {
36                 return nil, err
37         }
38         return vrc, nil
39 }
40
41 // TarSeekStream for roLayer guarantees that the data that is produced is the exact
42 // data that the layer was registered with.
43 func (rl *roLayer) TarSeekStream() (ioutils.ReadSeekCloser, error) {
44         return rl.layerStore.getTarSeekStream(rl)
45 }
46
47 // TarStreamFrom does not make any guarantees to the correctness of the produced
48 // data. As such it should not be used when the layer content must be verified
49 // to be an exact match to the registered layer.
50 func (rl *roLayer) TarStreamFrom(parent ChainID) (io.ReadCloser, error) {
51         var parentCacheID string
52         for pl := rl.parent; pl != nil; pl = pl.parent {
53                 if pl.chainID == parent {
54                         parentCacheID = pl.cacheID
55                         break
56                 }
57         }
58
59         if parent != ChainID("") && parentCacheID == "" {
60                 return nil, fmt.Errorf("layer ID '%s' is not a parent of the specified layer: cannot provide diff to non-parent", parent)
61         }
62         return rl.layerStore.driver.Diff(rl.cacheID, parentCacheID)
63 }
64
65 func (rl *roLayer) ChainID() ChainID {
66         return rl.chainID
67 }
68
69 func (rl *roLayer) DiffID() DiffID {
70         return rl.diffID
71 }
72
73 func (rl *roLayer) Parent() Layer {
74         if rl.parent == nil {
75                 return nil
76         }
77         return rl.parent
78 }
79
80 func (rl *roLayer) Size() (size int64, err error) {
81         if rl.parent != nil {
82                 size, err = rl.parent.Size()
83                 if err != nil {
84                         return
85                 }
86         }
87
88         return size + rl.size, nil
89 }
90
91 func (rl *roLayer) DiffSize() (size int64, err error) {
92         return rl.size, nil
93 }
94
95 func (rl *roLayer) Metadata() (map[string]string, error) {
96         return rl.layerStore.driver.GetMetadata(rl.cacheID)
97 }
98
99 type referencedCacheLayer struct {
100         *roLayer
101 }
102
103 func (rl *roLayer) getReference() Layer {
104         ref := &referencedCacheLayer{
105                 roLayer: rl,
106         }
107         rl.references[ref] = struct{}{}
108
109         return ref
110 }
111
112 func (rl *roLayer) hasReference(ref Layer) bool {
113         _, ok := rl.references[ref]
114         return ok
115 }
116
117 func (rl *roLayer) hasReferences() bool {
118         return len(rl.references) > 0
119 }
120
121 func (rl *roLayer) deleteReference(ref Layer) {
122         delete(rl.references, ref)
123 }
124
125 func (rl *roLayer) depth() int {
126         if rl.parent == nil {
127                 return 1
128         }
129         return rl.parent.depth() + 1
130 }
131
132 func storeLayer(tx MetadataTransaction, layer *roLayer) error {
133         if err := tx.SetDiffID(layer.diffID); err != nil {
134                 return err
135         }
136         if err := tx.SetSize(layer.size); err != nil {
137                 return err
138         }
139         if err := tx.SetCacheID(layer.cacheID); err != nil {
140                 return err
141         }
142         // Do not store empty descriptors
143         if layer.descriptor.Digest != "" {
144                 if err := tx.SetDescriptor(layer.descriptor); err != nil {
145                         return err
146                 }
147         }
148         if layer.parent != nil {
149                 if err := tx.SetParent(layer.parent.chainID); err != nil {
150                         return err
151                 }
152         }
153         if err := tx.SetPlatform(layer.platform); err != nil {
154                 return err
155         }
156
157         return nil
158 }
159
160 func newVerifiedReadCloser(rc io.ReadCloser, dgst digest.Digest) (io.ReadCloser, error) {
161         return &verifiedReadCloser{
162                 rc:       rc,
163                 dgst:     dgst,
164                 verifier: dgst.Verifier(),
165         }, nil
166 }
167
168 type verifiedReadCloser struct {
169         rc       io.ReadCloser
170         dgst     digest.Digest
171         verifier digest.Verifier
172 }
173
174 func (vrc *verifiedReadCloser) Read(p []byte) (n int, err error) {
175         n, err = vrc.rc.Read(p)
176         if n > 0 {
177                 if n, err := vrc.verifier.Write(p[:n]); err != nil {
178                         return n, err
179                 }
180         }
181         if err == io.EOF {
182                 if !vrc.verifier.Verified() {
183                         err = fmt.Errorf("could not verify layer data for: %s. This may be because internal files in the layer store were modified. Re-pulling or rebuilding this image may resolve the issue", vrc.dgst)
184                 }
185         }
186         return
187 }
188 func (vrc *verifiedReadCloser) Close() error {
189         return vrc.rc.Close()
190 }