@@ -75,37 +75,34 @@ func (ff *hardlinkingFileFetcher) GetFile(ctx context.Context, blobDigest digest
7575 key += "-x"
7676 }
7777
78- // If the file is present in the cache, hardlink it to the destination.
79- wasMissing , err := ff . tryLinkFromCache ( key , directory , name )
80- if err == nil {
81- return nil
82- } else if ! wasMissing {
83- return err
84- }
78+ for {
79+ // If the file is present in the cache, hardlink it to the destination.
80+ if err := ff . tryLinkFromCache ( key , directory , name ); err == nil {
81+ return nil
82+ } else if ! os . IsNotExist ( err ) {
83+ return err
84+ }
8585
86- // A download is required. Let's see if one is already in progress.
87- ff .downloadsLock .Lock ()
88- wait , ok := ff .downloads [key ]
89- if ok {
90- // A download is already in progress. Wait for it to finish.
91- ff .downloadsLock .Unlock ()
92- select {
93- case <- wait :
94- // Try linking from cache. If missing (download failed or
95- // other issue), retry GetFile which will attempt a new download.
96- wasMissing , err := ff .tryLinkFromCache (key , directory , name )
97- if err == nil {
98- return nil
99- } else if wasMissing {
100- return ff .GetFile (ctx , blobDigest , directory , name , isExecutable )
86+ // A download is required. Let's see if one is already in progress.
87+ ff .downloadsLock .Lock ()
88+ wait , ok := ff .downloads [key ]
89+ if ok {
90+ // A download is already in progress. Wait for it to finish.
91+ ff .downloadsLock .Unlock ()
92+ select {
93+ case <- wait :
94+ // Download finished. Loop back to try linking from
95+ // cache. If missing (download failed or other issue),
96+ // we'll attempt a new download.
97+ continue
98+ case <- ctx .Done ():
99+ return util .StatusFromContext (ctx )
101100 }
102- return err
103- case <- ctx .Done ():
104- return util .StatusFromContext (ctx )
105101 }
106- }
107102
108- // Start a new download.
103+ // Start a new download.
104+ break
105+ }
109106 newWait := make (chan struct {})
110107 ff .downloads [key ] = newWait
111108 ff .downloadsLock .Unlock ()
@@ -119,10 +116,9 @@ func (ff *hardlinkingFileFetcher) GetFile(ctx context.Context, blobDigest digest
119116
120117 // Check cache again in case another download completed between our initial
121118 // tryLinkFromCache() call and acquiring the download lock.
122- wasMissing , err = ff .tryLinkFromCache (key , directory , name )
123- if err == nil {
119+ if err := ff .tryLinkFromCache (key , directory , name ); err == nil {
124120 return nil
125- } else if ! wasMissing {
121+ } else if ! os . IsNotExist ( err ) {
126122 return err
127123 }
128124
@@ -149,7 +145,7 @@ func (ff *hardlinkingFileFetcher) GetFile(ctx context.Context, blobDigest digest
149145 }
150146 }
151147 ff .evictionLock .Unlock ()
152- } else if wasMissing {
148+ } else {
153149 // The file was already part of our bookkeeping,
154150 // but was missing on disk. Repair this by adding
155151 // a link to the newly downloaded file.
@@ -164,15 +160,15 @@ func (ff *hardlinkingFileFetcher) GetFile(ctx context.Context, blobDigest digest
164160}
165161
166162// tryLinkFromCache attempts to create a hardlink from the cache to a
167- // file in the build directory. The first return value indicates whether
168- // a download is needed: true if the file is not in the cache bookkeeping,
169- // or if it was in bookkeeping but missing on disk.
170- func (ff * hardlinkingFileFetcher ) tryLinkFromCache (key string , directory filesystem.Directory , name path.Component ) ( bool , error ) {
163+ // file in the build directory. It returns os.ErrNotExist if the file
164+ // is not in the cache bookkeeping, or if it was in bookkeeping but
165+ // missing on disk.
166+ func (ff * hardlinkingFileFetcher ) tryLinkFromCache (key string , directory filesystem.Directory , name path.Component ) error {
171167 ff .filesLock .RLock ()
172168 _ , ok := ff .filesSize [key ]
173169 ff .filesLock .RUnlock ()
174170 if ! ok {
175- return true , os .ErrNotExist
171+ return os .ErrNotExist
176172 }
177173
178174 ff .evictionLock .Lock ()
@@ -181,13 +177,13 @@ func (ff *hardlinkingFileFetcher) tryLinkFromCache(key string, directory filesys
181177
182178 if err := ff .cacheDirectory .Link (path .MustNewComponent (key ), directory , name ); err == nil {
183179 // Successfully hardlinked the file to its destination.
184- return false , nil
180+ return nil
185181 } else if ! os .IsNotExist (err ) {
186- return false , util .StatusWrapfWithCode (err , codes .Internal , "Failed to create hardlink to cached file %#v" , key )
182+ return util .StatusWrapfWithCode (err , codes .Internal , "Failed to create hardlink to cached file %#v" , key )
187183 }
188184
189185 // The file was part of the cache, even though it did not
190186 // exist on disk. Some other process may have tampered with
191187 // the cache directory's contents.
192- return true , os .ErrNotExist
188+ return os .ErrNotExist
193189}
0 commit comments