queueOrCommit queues the specified layer to be committed to the storage. If no other goroutine is already committing layers, the layer and all subsequent layers (if already queued) will be committed to the storage.
(index int, info addedLayerInfo)
| 888 | // If no other goroutine is already committing layers, the layer and all |
| 889 | // subsequent layers (if already queued) will be committed to the storage. |
| 890 | func (s *storageImageDestination) queueOrCommit(index int, info addedLayerInfo) error { |
| 891 | // NOTE: whenever the code below is touched, make sure that all code |
| 892 | // paths unlock the lock and to unlock it exactly once. |
| 893 | // |
| 894 | // Conceptually, the code is divided in two stages: |
| 895 | // |
| 896 | // 1) Queue in work by marking the layer as ready to be committed. |
| 897 | // If at least one previous/parent layer with a lower index has |
| 898 | // not yet been committed, return early. |
| 899 | // |
| 900 | // 2) Process the queued-in work by committing the "ready" layers |
| 901 | // in sequence. Make sure that more items can be queued-in |
| 902 | // during the comparatively I/O expensive task of committing a |
| 903 | // layer. |
| 904 | // |
| 905 | // The conceptual benefit of this design is that caller can continue |
| 906 | // pulling layers after an early return. At any given time, only one |
| 907 | // caller is the "worker" routine committing layers. All other routines |
| 908 | // can continue pulling and queuing in layers. |
| 909 | s.lock.Lock() |
| 910 | s.lockProtected.indexToAddedLayerInfo[index] = info |
| 911 | |
| 912 | // We're still waiting for at least one previous/parent layer to be |
| 913 | // committed, so there's nothing to do. |
| 914 | if index != s.lockProtected.currentIndex { |
| 915 | s.lock.Unlock() |
| 916 | return nil |
| 917 | } |
| 918 | |
| 919 | for { |
| 920 | info, ok := s.lockProtected.indexToAddedLayerInfo[index] |
| 921 | if !ok { |
| 922 | break |
| 923 | } |
| 924 | s.lock.Unlock() |
| 925 | // Note: commitLayer locks on-demand. |
| 926 | if stopQueue, err := s.commitLayer(index, info, -1); stopQueue || err != nil { |
| 927 | return err |
| 928 | } |
| 929 | s.lock.Lock() |
| 930 | index++ |
| 931 | } |
| 932 | |
| 933 | // Set the index at the very end to make sure that only one routine |
| 934 | // enters stage 2). |
| 935 | s.lockProtected.currentIndex = index |
| 936 | s.lock.Unlock() |
| 937 | return nil |
| 938 | } |
| 939 | |
| 940 | // commitLayer commits the specified layer with the given index to the storage. |
| 941 | // size can usually be -1; it can be provided if the layer is not known to be already present in blobDiffIDs. |
no test coverage detected