package steam import ( "sync" "time" ) // JobStatus provides specific information about an individual job type Job struct { action string target *Game running bool start *time.Time errors []error // If applicablle size *int64 transferred *int64 eta *time.Duration m sync.Mutex } // Action is a short string describing the action, i.e. "packaging", "deleting" func (j *Job) Action() string { j.m.Lock() defer j.m.Unlock() return j.action } // Target returns the game that is the target of the action func (j *Job) Target() *Game { j.m.Lock() defer j.m.Unlock() return j.target } // IsRunning returns true if the job is currently running, otherwise false func (j *Job) IsRunning() bool { j.m.Lock() defer j.m.Unlock() return j.running } // StartTime returns the time in which the job started func (j *Job) StartTime() *time.Time { j.m.Lock() defer j.m.Unlock() return j.start } func (j *Job) Errors() []error { j.m.Lock() defer j.m.Unlock() return j.errors } // newJob sets up a job of action for the target Game func newJob(action string, target *Game) *Job { t := time.Now() return &Job{ action: action, target: target, running: true, start: &t, } } func (j *Job) setSize(size int64) { j.m.Lock() defer j.m.Unlock() j.size = &size } // GetSize returns the size set if applicable for the operation func (j *Job) GetSize() *int64 { j.m.Lock() defer j.m.Unlock() return j.size } func (j *Job) setTransferred(transferred int64) { j.m.Lock() defer j.m.Unlock() j.transferred = &transferred } // GetTransferred returns the transferred set if applicable for the operation func (j *Job) GetTransferred() *int64 { j.m.Lock() defer j.m.Unlock() return j.transferred } // setETA sets the eta to the speicifed duration func (j *Job) setETA(d time.Duration) { j.m.Lock() defer j.m.Unlock() j.eta = &d } // GetETA returns the ETA to completion as a *time.Duration. nil represents // when func (j *Job) GetETA() *time.Duration { j.m.Lock() defer j.m.Unlock() return j.eta } // done sets running to false func (j *Job) done() { j.m.Lock() defer j.m.Unlock() j.running = false } // addError appends an error to the internal slice of errors func (j *Job) addError(err error) { j.m.Lock() defer j.m.Unlock() j.errors = append(j.errors, err) } // Jobs is by the Library to determine whether or not we currently have any // jobs running on this library, as well as to give some history as to // what jobs have been run previously type Jobs struct { running []*Job previous []*Job m sync.Mutex } func (jobs *Jobs) scan() { jobs.m.Lock() defer jobs.m.Unlock() running := []*Job{} notrunning := []*Job{} for _, job := range jobs.running { if job == nil { continue } if job.IsRunning() == true { running = append(running, job) } else { notrunning = append(notrunning, job) } } if len(notrunning) > 0 { jobs.previous = append(jobs.previous, notrunning...) } jobs.running = running } // Running returns true if any job is currently running, otherwise false func (jobs *Jobs) Running() bool { jobs.scan() jobs.m.Lock() defer jobs.m.Unlock() if len(jobs.running) == 0 { return false } return true } // GetJobs returns all of the jobs regardless of their state func (jobs *Jobs) GetJobs() []*Job { jobs.scan() jobs.m.Lock() defer jobs.m.Unlock() return append(jobs.running, jobs.previous...) } // GetRunningJobs returns all of the running jobs func (jobs *Jobs) GetRunningJobs() []*Job { jobs.scan() jobs.m.Lock() defer jobs.m.Unlock() return jobs.running } // GetStoppedJobs returns all of the stopped jobs func (jobs *Jobs) GetStoppedJobs() []*Job { jobs.scan() jobs.m.Lock() defer jobs.m.Unlock() return jobs.previous } // addJob adds a job to the internal slice func (jobs *Jobs) addJob(j *Job) { jobs.m.Lock() jobs.running = append(jobs.running, j) jobs.m.Unlock() jobs.scan() }