void JobManager::DoSchedule(InternalJob::Pointer job, Poco::Timestamp::TimeDiff delay) { Poco::ScopedLock<Poco::Mutex> managerLock(m_mutex); //job may have been canceled already int state = job->InternalGetState(); if (state != InternalJob::ABOUT_TO_SCHEDULE && state != Job::SLEEPING) return; //if it's a decoration job with no rule, don't run it right now if the system is busy if (job->GetPriority() == Job::DECORATE && job->GetRule() == 0) { Poco::Timestamp::TimeDiff tmp_minDelay = m_running.size() * 100; delay = std::max(delay, tmp_minDelay); } if (delay > 0) { job->SetStartTime(Poco::Timestamp() + delay * 100); InternalJob::Pointer sptr_job(job); ChangeState(sptr_job, Job::SLEEPING); } else { job->SetStartTime(Poco::Timestamp() + DelayFor(job->GetPriority()) * 100); job->SetWaitQueueStamp(m_waitQueueCounter++); InternalJob::Pointer sptr_job(job); ChangeState(sptr_job, Job::WAITING); } }
void JobManager::ChangeState(InternalJob::Pointer sptr_job, int newState) { bool blockedJobs = false; { Poco::ScopedLock<Poco::Mutex> m_managerLock(m_mutex); int tmp_oldState = sptr_job->InternalGetState(); switch (tmp_oldState) { case Job::NONE: case InternalJob::ABOUT_TO_SCHEDULE: break; case InternalJob::BLOCKED: //remove this job from the linked list of blocked jobs sptr_job->Remove(); break; case Job::WAITING: m_JobQueueWaiting.Remove(sptr_job); // assert(false, "Tried to remove a job that wasn't in the queue"); break; case Job::SLEEPING: m_JobQueueSleeping.Remove(sptr_job); // assert(false, "Tried to remove a job that wasn't in the queue"); case Job::RUNNING: case InternalJob::ABOUT_TO_RUN: m_running.remove(sptr_job); //add any blocked jobs back to the wait queue InternalJob::Pointer sptr_blocked(sptr_job->Previous()); sptr_job->Remove(); blockedJobs = sptr_blocked != 0; while (sptr_blocked != 0) { InternalJob::Pointer previous = sptr_blocked->Previous(); ChangeState(sptr_blocked, Job::WAITING); sptr_blocked = previous; } break; // default : // Assert.isLegal(false, "Invalid job state: " + job + ", state: " + oldState); } sptr_job->InternalSetState(newState); switch (newState) { case Job::NONE: sptr_job->SetStartTime(InternalJob::T_NONE); sptr_job->SetWaitQueueStamp(InternalJob::T_NONE); case InternalJob::BLOCKED: break; case Job::WAITING: m_JobQueueWaiting.Enqueue(sptr_job); break; case Job::SLEEPING: //try { m_JobQueueSleeping.Enqueue(sptr_job); //} catch (RuntimeException e) { // throw new RuntimeException("Error changing from state: " + oldState); //} break; case Job::RUNNING: case InternalJob::ABOUT_TO_RUN: sptr_job->SetStartTime(InternalJob::T_NONE); sptr_job->SetWaitQueueStamp(InternalJob::T_NONE); m_running.insert(sptr_job); break; case InternalJob::ABOUT_TO_SCHEDULE: break; // default : // Assert.isLegal(false, "Invalid job state: " + job + ", state: " + newState); } } //notify queue outside sync block if (blockedJobs) m_Pool->JobQueued(); }