github.com/jiasir/docker@v1.3.3-0.20170609024000-252e610103e7/image/store.go (about) 1 package image 2 3 import ( 4 "encoding/json" 5 "errors" 6 "fmt" 7 "sync" 8 9 "github.com/Sirupsen/logrus" 10 "github.com/docker/distribution/digestset" 11 "github.com/docker/docker/layer" 12 "github.com/opencontainers/go-digest" 13 ) 14 15 // Store is an interface for creating and accessing images 16 type Store interface { 17 Create(config []byte) (ID, error) 18 Get(id ID) (*Image, error) 19 Delete(id ID) ([]layer.Metadata, error) 20 Search(partialID string) (ID, error) 21 SetParent(id ID, parent ID) error 22 GetParent(id ID) (ID, error) 23 Children(id ID) []ID 24 Map() map[ID]*Image 25 Heads() map[ID]*Image 26 } 27 28 // LayerGetReleaser is a minimal interface for getting and releasing images. 29 type LayerGetReleaser interface { 30 Get(layer.ChainID) (layer.Layer, error) 31 Release(layer.Layer) ([]layer.Metadata, error) 32 } 33 34 type imageMeta struct { 35 layer layer.Layer 36 children map[ID]struct{} 37 } 38 39 type store struct { 40 sync.Mutex 41 ls LayerGetReleaser 42 images map[ID]*imageMeta 43 fs StoreBackend 44 digestSet *digestset.Set 45 } 46 47 // NewImageStore returns new store object for given layer store 48 func NewImageStore(fs StoreBackend, ls LayerGetReleaser) (Store, error) { 49 is := &store{ 50 ls: ls, 51 images: make(map[ID]*imageMeta), 52 fs: fs, 53 digestSet: digestset.NewSet(), 54 } 55 56 // load all current images and retain layers 57 if err := is.restore(); err != nil { 58 return nil, err 59 } 60 61 return is, nil 62 } 63 64 func (is *store) restore() error { 65 err := is.fs.Walk(func(dgst digest.Digest) error { 66 img, err := is.Get(IDFromDigest(dgst)) 67 if err != nil { 68 logrus.Errorf("invalid image %v, %v", dgst, err) 69 return nil 70 } 71 var l layer.Layer 72 if chainID := img.RootFS.ChainID(); chainID != "" { 73 l, err = is.ls.Get(chainID) 74 if err != nil { 75 return err 76 } 77 } 78 if err := is.digestSet.Add(dgst); err != nil { 79 return err 80 } 81 82 imageMeta := &imageMeta{ 83 layer: l, 84 children: make(map[ID]struct{}), 85 } 86 87 is.images[IDFromDigest(dgst)] = imageMeta 88 89 return nil 90 }) 91 if err != nil { 92 return err 93 } 94 95 // Second pass to fill in children maps 96 for id := range is.images { 97 if parent, err := is.GetParent(id); err == nil { 98 if parentMeta := is.images[parent]; parentMeta != nil { 99 parentMeta.children[id] = struct{}{} 100 } 101 } 102 } 103 104 return nil 105 } 106 107 func (is *store) Create(config []byte) (ID, error) { 108 var img Image 109 err := json.Unmarshal(config, &img) 110 if err != nil { 111 return "", err 112 } 113 114 // Must reject any config that references diffIDs from the history 115 // which aren't among the rootfs layers. 116 rootFSLayers := make(map[layer.DiffID]struct{}) 117 for _, diffID := range img.RootFS.DiffIDs { 118 rootFSLayers[diffID] = struct{}{} 119 } 120 121 layerCounter := 0 122 for _, h := range img.History { 123 if !h.EmptyLayer { 124 layerCounter++ 125 } 126 } 127 if layerCounter > len(img.RootFS.DiffIDs) { 128 return "", errors.New("too many non-empty layers in History section") 129 } 130 131 dgst, err := is.fs.Set(config) 132 if err != nil { 133 return "", err 134 } 135 imageID := IDFromDigest(dgst) 136 137 is.Lock() 138 defer is.Unlock() 139 140 if _, exists := is.images[imageID]; exists { 141 return imageID, nil 142 } 143 144 layerID := img.RootFS.ChainID() 145 146 var l layer.Layer 147 if layerID != "" { 148 l, err = is.ls.Get(layerID) 149 if err != nil { 150 return "", err 151 } 152 } 153 154 imageMeta := &imageMeta{ 155 layer: l, 156 children: make(map[ID]struct{}), 157 } 158 159 is.images[imageID] = imageMeta 160 if err := is.digestSet.Add(imageID.Digest()); err != nil { 161 delete(is.images, imageID) 162 return "", err 163 } 164 165 return imageID, nil 166 } 167 168 func (is *store) Search(term string) (ID, error) { 169 is.Lock() 170 defer is.Unlock() 171 172 dgst, err := is.digestSet.Lookup(term) 173 if err != nil { 174 if err == digestset.ErrDigestNotFound { 175 err = fmt.Errorf("No such image: %s", term) 176 } 177 return "", err 178 } 179 return IDFromDigest(dgst), nil 180 } 181 182 func (is *store) Get(id ID) (*Image, error) { 183 // todo: Check if image is in images 184 // todo: Detect manual insertions and start using them 185 config, err := is.fs.Get(id.Digest()) 186 if err != nil { 187 return nil, err 188 } 189 190 img, err := NewFromJSON(config) 191 if err != nil { 192 return nil, err 193 } 194 img.computedID = id 195 196 img.Parent, err = is.GetParent(id) 197 if err != nil { 198 img.Parent = "" 199 } 200 201 return img, nil 202 } 203 204 func (is *store) Delete(id ID) ([]layer.Metadata, error) { 205 is.Lock() 206 defer is.Unlock() 207 208 imageMeta := is.images[id] 209 if imageMeta == nil { 210 return nil, fmt.Errorf("unrecognized image ID %s", id.String()) 211 } 212 for id := range imageMeta.children { 213 is.fs.DeleteMetadata(id.Digest(), "parent") 214 } 215 if parent, err := is.GetParent(id); err == nil && is.images[parent] != nil { 216 delete(is.images[parent].children, id) 217 } 218 219 if err := is.digestSet.Remove(id.Digest()); err != nil { 220 logrus.Errorf("error removing %s from digest set: %q", id, err) 221 } 222 delete(is.images, id) 223 is.fs.Delete(id.Digest()) 224 225 if imageMeta.layer != nil { 226 return is.ls.Release(imageMeta.layer) 227 } 228 return nil, nil 229 } 230 231 func (is *store) SetParent(id, parent ID) error { 232 is.Lock() 233 defer is.Unlock() 234 parentMeta := is.images[parent] 235 if parentMeta == nil { 236 return fmt.Errorf("unknown parent image ID %s", parent.String()) 237 } 238 if parent, err := is.GetParent(id); err == nil && is.images[parent] != nil { 239 delete(is.images[parent].children, id) 240 } 241 parentMeta.children[id] = struct{}{} 242 return is.fs.SetMetadata(id.Digest(), "parent", []byte(parent)) 243 } 244 245 func (is *store) GetParent(id ID) (ID, error) { 246 d, err := is.fs.GetMetadata(id.Digest(), "parent") 247 if err != nil { 248 return "", err 249 } 250 return ID(d), nil // todo: validate? 251 } 252 253 func (is *store) Children(id ID) []ID { 254 is.Lock() 255 defer is.Unlock() 256 257 return is.children(id) 258 } 259 260 func (is *store) children(id ID) []ID { 261 var ids []ID 262 if is.images[id] != nil { 263 for id := range is.images[id].children { 264 ids = append(ids, id) 265 } 266 } 267 return ids 268 } 269 270 func (is *store) Heads() map[ID]*Image { 271 return is.imagesMap(false) 272 } 273 274 func (is *store) Map() map[ID]*Image { 275 return is.imagesMap(true) 276 } 277 278 func (is *store) imagesMap(all bool) map[ID]*Image { 279 is.Lock() 280 defer is.Unlock() 281 282 images := make(map[ID]*Image) 283 284 for id := range is.images { 285 if !all && len(is.children(id)) > 0 { 286 continue 287 } 288 img, err := is.Get(id) 289 if err != nil { 290 logrus.Errorf("invalid image access: %q, error: %q", id, err) 291 continue 292 } 293 images[id] = img 294 } 295 return images 296 }