| 191 | } |
| 192 | |
| 193 | func (sto *Storage) StatBlobs(ctx context.Context, blobs []blob.Ref, fn func(blob.SizedRef) error) error { |
| 194 | need := map[blob.Ref]bool{} |
| 195 | for _, br := range blobs { |
| 196 | need[br] = true |
| 197 | } |
| 198 | err := sto.cache.StatBlobs(ctx, blobs, func(sb blob.SizedRef) error { |
| 199 | sto.touch(sb) |
| 200 | delete(need, sb.Ref) |
| 201 | return fn(sb) |
| 202 | }) |
| 203 | if err != nil { |
| 204 | return err |
| 205 | } |
| 206 | if len(need) == 0 { |
| 207 | // Cache had them all. |
| 208 | return nil |
| 209 | } |
| 210 | // And now any missing ones: |
| 211 | blobs = make([]blob.Ref, 0, len(need)) |
| 212 | for br := range need { |
| 213 | blobs = append(blobs, br) |
| 214 | } |
| 215 | return sto.origin.StatBlobs(ctx, blobs, func(sb blob.SizedRef) error { |
| 216 | sto.touch(sb) |
| 217 | return fn(sb) |
| 218 | }) |
| 219 | } |
| 220 | |
| 221 | func (sto *Storage) ReceiveBlob(ctx context.Context, br blob.Ref, src io.Reader) (blob.SizedRef, error) { |
| 222 | // Slurp the whole blob before replicating. Bounded by 16 MB anyway. |