(ctx context.Context, h backend.Handle)
| 93 | } |
| 94 | |
| 95 | func (b *Backend) cacheFile(ctx context.Context, h backend.Handle) error { |
| 96 | finish := make(chan struct{}) |
| 97 | |
| 98 | b.inProgressMutex.Lock() |
| 99 | other, alreadyDownloading := b.inProgress[h] |
| 100 | if !alreadyDownloading { |
| 101 | b.inProgress[h] = finish |
| 102 | } |
| 103 | b.inProgressMutex.Unlock() |
| 104 | |
| 105 | if alreadyDownloading { |
| 106 | debug.Log("readahead %v is already performed by somebody else, delegating...", h) |
| 107 | <-other |
| 108 | debug.Log("download %v finished", h) |
| 109 | return nil |
| 110 | } |
| 111 | |
| 112 | defer func() { |
| 113 | // signal other waiting goroutines that the file may now be cached |
| 114 | close(finish) |
| 115 | |
| 116 | // remove the finish channel from the map |
| 117 | b.inProgressMutex.Lock() |
| 118 | delete(b.inProgress, h) |
| 119 | b.inProgressMutex.Unlock() |
| 120 | }() |
| 121 | |
| 122 | // test again, maybe the file was cached in the meantime |
| 123 | if !b.Cache.Has(h) { |
| 124 | // nope, it's still not in the cache, pull it from the repo and save it |
| 125 | err := b.Backend.Load(ctx, h, 0, 0, func(rd io.Reader) error { |
| 126 | return b.Cache.save(h, rd) |
| 127 | }) |
| 128 | if err != nil { |
| 129 | // try to remove from the cache, ignore errors |
| 130 | _, _ = b.Cache.remove(h) |
| 131 | } |
| 132 | return err |
| 133 | } |
| 134 | |
| 135 | return nil |
| 136 | } |
| 137 | |
| 138 | // loadFromCache will try to load the file from the cache. |
| 139 | func (b *Backend) loadFromCache(h backend.Handle, length int, offset int64, consumer func(rd io.Reader) error) (bool, error) { |
no test coverage detected