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