@@ -35,6 +35,7 @@ type ProgressTracker struct {
3535 root string
3636 transferState string
3737 added chan jobUpdate
38+ extraction chan extractionUpdate
3839 waitC chan struct {}
3940
4041 parents map [digest.Digest ][]ocispec.Descriptor
@@ -47,6 +48,8 @@ const (
4748 jobAdded jobState = iota
4849 jobInProgress
4950 jobComplete
51+ jobExtracting
52+ jobExtracted
5053)
5154
5255type jobStatus struct {
@@ -72,12 +75,18 @@ type StatusTracker interface {
7275 Check (context.Context , digest.Digest ) (bool , error )
7376}
7477
78+ type extractionUpdate struct {
79+ desc ocispec.Descriptor
80+ progress int64
81+ }
82+
7583// NewProgressTracker tracks content download progress
7684func NewProgressTracker (root , transferState string ) * ProgressTracker {
7785 return & ProgressTracker {
7886 root : root ,
7987 transferState : transferState ,
8088 added : make (chan jobUpdate , 1 ),
89+ extraction : make (chan extractionUpdate , 1 ),
8190 waitC : make (chan struct {}),
8291 parents : map [digest.Digest ][]ocispec.Descriptor {},
8392 }
@@ -97,7 +106,8 @@ func (j *ProgressTracker) HandleProgress(ctx context.Context, pf transfer.Progre
97106 log .G (ctx ).WithError (err ).Error ("failed to get statuses for progress" )
98107 }
99108 for dgst , job := range jobs {
100- if job .state != jobComplete {
109+ switch job .state {
110+ case jobAdded , jobInProgress :
101111 status , ok := active .Status (job .name )
102112 if ok {
103113 if status .Offset > job .progress {
@@ -130,6 +140,30 @@ func (j *ProgressTracker) HandleProgress(ctx context.Context, pf transfer.Progre
130140 jobs [dgst ] = job
131141 }
132142 }
143+ case jobExtracting :
144+ if job .progress == job .desc .Size {
145+ pf (transfer.Progress {
146+ Event : "extracted" ,
147+ Name : job .name ,
148+ Parents : job .parents ,
149+ Progress : job .desc .Size ,
150+ Total : job .desc .Size ,
151+ Desc : & job .desc ,
152+ })
153+ job .state = jobExtracted
154+ jobs [dgst ] = job
155+ } else {
156+ pf (transfer.Progress {
157+ Event : "extracting" ,
158+ Name : job .name ,
159+ Parents : job .parents ,
160+ Progress : job .progress ,
161+ Total : job .desc .Size ,
162+ Desc : & job .desc ,
163+ })
164+ }
165+ case jobComplete , jobExtracted :
166+ // No progress to send
133167 }
134168 }
135169 }
@@ -161,10 +195,9 @@ func (j *ProgressTracker) HandleProgress(ctx context.Context, pf transfer.Progre
161195 }
162196 jobs [update .desc .Digest ] = job
163197 pf (transfer.Progress {
164- Event : "waiting" ,
165- Name : name ,
166- Parents : parents ,
167- //Digest: desc.Digest.String(),
198+ Event : "waiting" ,
199+ Name : name ,
200+ Parents : parents ,
168201 Progress : 0 ,
169202 Total : update .desc .Size ,
170203 Desc : & job .desc ,
@@ -181,7 +214,37 @@ func (j *ProgressTracker) HandleProgress(ctx context.Context, pf transfer.Progre
181214 job .state = jobComplete
182215 job .progress = job .desc .Size
183216 }
217+ case extraction := <- j .extraction :
218+ job , ok := jobs [extraction .desc .Digest ]
219+ if ! ok {
220+ // Only captures the parents defined before,
221+ // could handle parent updates in same thread
222+ // if there is a synchronization issue
223+ var parents []string
224+ j .parentL .Lock ()
225+ for _ , parent := range j .parents [extraction .desc .Digest ] {
226+ parents = append (parents , remotes .MakeRefKey (ctx , parent ))
227+ }
228+ j .parentL .Unlock ()
229+ if len (parents ) == 0 {
230+ parents = []string {j .root }
231+ }
232+ name := remotes .MakeRefKey (ctx , extraction .desc )
184233
234+ job = & jobStatus {
235+ state : jobExtracting ,
236+ name : name ,
237+ parents : parents ,
238+ progress : extraction .progress ,
239+ desc : extraction .desc ,
240+ }
241+ jobs [extraction .desc .Digest ] = job
242+ } else {
243+ if job .state != jobExtracting {
244+ job .state = jobExtracting
245+ }
246+ job .progress = extraction .progress
247+ }
185248 case <- tc .C :
186249 update ()
187250 // Next timer?
@@ -226,6 +289,16 @@ func (j *ProgressTracker) AddChildren(desc ocispec.Descriptor, children []ocispe
226289
227290}
228291
292+ func (j * ProgressTracker ) ExtractProgress (desc ocispec.Descriptor , progress int64 ) {
293+ if j == nil {
294+ return
295+ }
296+ j .extraction <- extractionUpdate {
297+ desc : desc ,
298+ progress : progress ,
299+ }
300+ }
301+
229302func (j * ProgressTracker ) Wait () {
230303 // timeout rather than rely on cancel
231304 timeout := time .After (10 * time .Second )
0 commit comments