// Copyright (C) 2020 Storj Labs, Inc. // See LICENSE for copying information. package piecedeletion import "sync" // LimitedJobs is a finalizable list of deletion jobs with a limit to how many // jobs it can handle. type LimitedJobs struct { maxPiecesPerBatch int mu sync.Mutex // done indicates that no more items will be appended to the queue. done bool // count is the number of piece ids queued here. count int // list is the list of delete jobs. list []Job } // NewLimitedJobs returns a new limited job queue. func NewLimitedJobs(maxPiecesPerBatch int) *LimitedJobs { return &LimitedJobs{ maxPiecesPerBatch: maxPiecesPerBatch, } } // TryPush tries to add a job to the queue. // // maxPiecesPerBatch < 0, means no limit func (jobs *LimitedJobs) TryPush(job Job) bool { return jobs.tryPush(job, jobs.maxPiecesPerBatch) } // tryPush tries to add a job to the queue. // // maxPiecesPerBatch < 0, means no limit func (jobs *LimitedJobs) tryPush(job Job, maxPiecesPerBatch int) bool { jobs.mu.Lock() defer jobs.mu.Unlock() // check whether we have finished work with this jobs queue. if jobs.done { return false } // add to the queue, this can potentially overflow `maxPiecesPerBatch`, // however splitting a single request and promise across multiple batches, is annoying. jobs.count += len(job.Pieces) // check whether the queue is at capacity if maxPiecesPerBatch >= 0 && jobs.count >= maxPiecesPerBatch { jobs.done = true } jobs.list = append(jobs.list, job) return true } // PopAll returns all the jobs in this list. func (jobs *LimitedJobs) PopAll() (_ []Job, ok bool) { jobs.mu.Lock() defer jobs.mu.Unlock() // when we try to pop and the queue is empty, make the queue final. if len(jobs.list) == 0 { jobs.done = true return nil, false } list := jobs.list jobs.list = nil return list, true }