ListMissingDestinationBlobs reads from 'srcch' and 'dstch' (sorted enumerations of blobs from two blob servers) and sends to 'destMissing' any blobs which appear on the source but not at the destination. destMissing is closed at the end. If an invalid (zero) blob from srcch or dstch arrives, ListM
(destMissing chan<- blob.SizedRef, sizeMismatch func(blob.Ref), srcch, dstch <-chan blob.SizedRef)
| 28 | // If an invalid (zero) blob from srcch or dstch arrives, |
| 29 | // ListMissingDestinationBlobs stops. |
| 30 | func ListMissingDestinationBlobs(destMissing chan<- blob.SizedRef, sizeMismatch func(blob.Ref), srcch, dstch <-chan blob.SizedRef) { |
| 31 | defer close(destMissing) |
| 32 | |
| 33 | src := &blob.ChanPeeker{Ch: srcch} |
| 34 | dst := &blob.ChanPeeker{Ch: dstch} |
| 35 | |
| 36 | for { |
| 37 | srcSized, ok := src.Peek() |
| 38 | if !ok { |
| 39 | break |
| 40 | } |
| 41 | if !srcSized.Ref.Valid() { |
| 42 | return |
| 43 | } |
| 44 | |
| 45 | // If the destination has reached its end, anything |
| 46 | // remaining in the source is needed. |
| 47 | if _, ok := dst.Peek(); !ok { |
| 48 | destMissing <- src.MustTake() |
| 49 | continue |
| 50 | } |
| 51 | |
| 52 | srcBlob := src.MustPeek().Ref |
| 53 | dstRef := dst.MustPeek().Ref |
| 54 | if !dstRef.Valid() { |
| 55 | return |
| 56 | } |
| 57 | |
| 58 | switch { |
| 59 | case srcBlob == dstRef: |
| 60 | // Skip both |
| 61 | sb := src.MustTake() |
| 62 | db := dst.MustTake() |
| 63 | if sb.Size != db.Size { |
| 64 | sizeMismatch(sb.Ref) |
| 65 | } |
| 66 | case srcBlob.Less(dstRef): |
| 67 | destMissing <- src.MustTake() |
| 68 | case dstRef.Less(srcBlob): |
| 69 | dst.Take() |
| 70 | } |
| 71 | } |
| 72 | } |