/** * Reset the state of items after reloading from disk and * delete items which could not be resumed. */ void PrePostProcessor::SanitisePostQueue(PostQueue* pPostQueue) { for (PostQueue::iterator it = pPostQueue->begin(); it != pPostQueue->end(); it++) { PostInfo* pPostInfo = *it; if (pPostInfo->GetStage() == PostInfo::ptExecutingScript || !Util::DirectoryExists(pPostInfo->GetNZBInfo()->GetDestDir())) { pPostInfo->SetStage(PostInfo::ptFinished); } else { pPostInfo->SetStage(PostInfo::ptQueued); } } }
void ParCoordinator::UpdateParCheckProgress() { DownloadQueue::Lock(); PostInfo* pPostInfo = m_ParChecker.GetPostInfo(); if (m_ParChecker.GetFileProgress() == 0) { pPostInfo->SetProgressLabel(m_ParChecker.GetProgressLabel()); } pPostInfo->SetFileProgress(m_ParChecker.GetFileProgress()); pPostInfo->SetStageProgress(m_ParChecker.GetStageProgress()); PostInfo::EStage StageKind[] = { PostInfo::ptLoadingPars, PostInfo::ptVerifyingSources, PostInfo::ptRepairing, PostInfo::ptVerifyingRepaired }; PostInfo::EStage eStage = StageKind[m_ParChecker.GetStage()]; time_t tCurrent = time(NULL); if (pPostInfo->GetStage() != eStage) { pPostInfo->SetStage(eStage); pPostInfo->SetStageTime(tCurrent); if (pPostInfo->GetStage() == PostInfo::ptRepairing) { m_ParChecker.SetRepairTime(tCurrent); } else if (pPostInfo->GetStage() == PostInfo::ptVerifyingRepaired) { int iRepairSec = (int)(tCurrent - m_ParChecker.GetRepairTime()); pPostInfo->GetNZBInfo()->SetRepairSec(pPostInfo->GetNZBInfo()->GetRepairSec() + iRepairSec); } } bool bParCancel = false; if (!m_ParChecker.GetCancelled()) { if ((g_pOptions->GetParTimeLimit() > 0) && m_ParChecker.GetStage() == ParChecker::ptRepairing && ((g_pOptions->GetParTimeLimit() > 5 && tCurrent - pPostInfo->GetStageTime() > 5 * 60) || (g_pOptions->GetParTimeLimit() <= 5 && tCurrent - pPostInfo->GetStageTime() > 1 * 60))) { // first five (or one) minutes elapsed, now can check the estimated time int iEstimatedRepairTime = (int)((tCurrent - pPostInfo->GetStartTime()) * 1000 / (pPostInfo->GetStageProgress() > 0 ? pPostInfo->GetStageProgress() : 1)); if (iEstimatedRepairTime > g_pOptions->GetParTimeLimit() * 60) { debug("Estimated repair time %i seconds", iEstimatedRepairTime); m_ParChecker.PrintMessage(Message::mkWarning, "Cancelling par-repair for %s, estimated repair time (%i minutes) exceeds allowed repair time", m_ParChecker.GetInfoName(), iEstimatedRepairTime / 60); bParCancel = true; } } } if (bParCancel) { m_ParChecker.Cancel(); } DownloadQueue::Unlock(); CheckPauseState(pPostInfo); }
/** * Reset the state of items after reloading from disk and * delete items which could not be resumed. * Also count the number of post-jobs. */ void PrePostProcessor::SanitisePostQueue() { GuardedDownloadQueue downloadQueue = DownloadQueue::Guard(); for (NzbInfo* nzbInfo : downloadQueue->GetQueue()) { PostInfo* postInfo = nzbInfo->GetPostInfo(); if (postInfo) { m_jobCount++; if (postInfo->GetStage() == PostInfo::ptExecutingScript || !FileSystem::DirectoryExists(nzbInfo->GetDestDir())) { postInfo->SetStage(PostInfo::ptFinished); } else { postInfo->SetStage(PostInfo::ptQueued); } } } }
void ParCoordinator::UpdateParRenameProgress() { DownloadQueue::Lock(); PostInfo* pPostInfo = m_ParRenamer.GetPostInfo(); pPostInfo->SetProgressLabel(m_ParRenamer.GetProgressLabel()); pPostInfo->SetStageProgress(m_ParRenamer.GetStageProgress()); time_t tCurrent = time(NULL); if (pPostInfo->GetStage() != PostInfo::ptRenaming) { pPostInfo->SetStage(PostInfo::ptRenaming); pPostInfo->SetStageTime(tCurrent); } DownloadQueue::Unlock(); CheckPauseState(pPostInfo); }
void PrePostProcessor::CheckRequestPar(DownloadQueue* downloadQueue) { #ifndef DISABLE_PARCHECK for (NzbInfo* postJob : m_activeJobs) { PostInfo* postInfo = postJob->GetPostInfo(); if (postInfo->GetRequestParCheck() && (postInfo->GetNzbInfo()->GetParStatus() <= NzbInfo::psSkipped || (postInfo->GetForceRepair() && !postInfo->GetNzbInfo()->GetParFull())) && g_Options->GetParCheck() != Options::pcManual) { postInfo->SetForceParFull(postInfo->GetNzbInfo()->GetParStatus() > NzbInfo::psSkipped); postInfo->GetNzbInfo()->SetParStatus(NzbInfo::psNone); postInfo->SetRequestParCheck(false); postInfo->GetNzbInfo()->GetScriptStatuses()->clear(); postInfo->SetWorking(false); } else if (postInfo->GetRequestParCheck() && postInfo->GetNzbInfo()->GetParStatus() <= NzbInfo::psSkipped && g_Options->GetParCheck() == Options::pcManual) { postInfo->SetRequestParCheck(false); postInfo->GetNzbInfo()->SetParStatus(NzbInfo::psManual); if (!postInfo->GetNzbInfo()->GetFileList()->empty()) { postInfo->GetNzbInfo()->PrintMessage(Message::mkInfo, "Downloading all remaining files for manual par-check for %s", postInfo->GetNzbInfo()->GetName()); downloadQueue->EditEntry(postInfo->GetNzbInfo()->GetId(), DownloadQueue::eaGroupResume, nullptr); postInfo->SetStage(PostInfo::ptFinished); } else { postInfo->GetNzbInfo()->PrintMessage(Message::mkInfo, "There are no par-files remain for download for %s", postInfo->GetNzbInfo()->GetName()); } postInfo->SetWorking(false); } } #endif }
void ParCoordinator::ParRenameCompleted() { DownloadQueue* pDownloadQueue = DownloadQueue::Lock(); PostInfo* pPostInfo = m_ParRenamer.GetPostInfo(); pPostInfo->GetNZBInfo()->SetRenameStatus(m_ParRenamer.GetStatus() == ParRenamer::psSuccess ? NZBInfo::rsSuccess : NZBInfo::rsFailure); if (m_ParRenamer.HasMissedFiles() && pPostInfo->GetNZBInfo()->GetParStatus() <= NZBInfo::psSkipped) { m_ParRenamer.PrintMessage(Message::mkInfo, "Requesting par-check/repair for %s to restore missing files ", m_ParRenamer.GetInfoName()); pPostInfo->SetRequestParCheck(true); } pPostInfo->SetWorking(false); pPostInfo->SetStage(PostInfo::ptQueued); pDownloadQueue->Save(); DownloadQueue::Unlock(); }
void PrePostProcessor::CleanupJobs(DownloadQueue* downloadQueue) { m_activeJobs.erase(std::remove_if(m_activeJobs.begin(), m_activeJobs.end(), [processor = this, downloadQueue](NzbInfo* postJob) { PostInfo* postInfo = postJob->GetPostInfo(); if (!postInfo->GetWorking() && !(postInfo->GetPostThread() && postInfo->GetPostThread()->IsRunning())) { delete postInfo->GetPostThread(); postInfo->SetPostThread(nullptr); postInfo->SetStageTime(0); postInfo->SetStageProgress(0); postInfo->SetFileProgress(0); postInfo->SetProgressLabel(""); if (postInfo->GetStartTime() > 0) { postJob->SetPostTotalSec(postJob->GetPostTotalSec() + (int)(Util::CurrentTime() - postInfo->GetStartTime())); postInfo->SetStartTime(0); } if (postInfo->GetStage() == PostInfo::ptFinished || postInfo->GetDeleted()) { processor->JobCompleted(downloadQueue, postInfo); } else { postInfo->SetStage(PostInfo::ptQueued); } return true; } return false; }), m_activeJobs.end()); }
void ParCoordinator::ParCheckCompleted() { DownloadQueue* pDownloadQueue = DownloadQueue::Lock(); PostInfo* pPostInfo = m_ParChecker.GetPostInfo(); // Update ParStatus (accumulate result) if ((m_ParChecker.GetStatus() == ParChecker::psRepaired || m_ParChecker.GetStatus() == ParChecker::psRepairNotNeeded) && pPostInfo->GetNZBInfo()->GetParStatus() <= NZBInfo::psSkipped) { pPostInfo->GetNZBInfo()->SetParStatus(NZBInfo::psSuccess); pPostInfo->SetParRepaired(m_ParChecker.GetStatus() == ParChecker::psRepaired); } else if (m_ParChecker.GetStatus() == ParChecker::psRepairPossible && pPostInfo->GetNZBInfo()->GetParStatus() != NZBInfo::psFailure) { pPostInfo->GetNZBInfo()->SetParStatus(NZBInfo::psRepairPossible); } else { pPostInfo->GetNZBInfo()->SetParStatus(NZBInfo::psFailure); } int iWaitTime = pPostInfo->GetNZBInfo()->GetDownloadSec() - m_ParChecker.GetDownloadSec(); pPostInfo->SetStartTime(pPostInfo->GetStartTime() + (time_t)iWaitTime); int iParSec = (int)(time(NULL) - m_ParChecker.GetParTime()) - iWaitTime; pPostInfo->GetNZBInfo()->SetParSec(pPostInfo->GetNZBInfo()->GetParSec() + iParSec); pPostInfo->GetNZBInfo()->SetParFull(m_ParChecker.GetParFull()); pPostInfo->SetWorking(false); pPostInfo->SetStage(PostInfo::ptQueued); pDownloadQueue->Save(); DownloadQueue::Unlock(); }
void PrePostProcessor::CheckPostQueue() { DownloadQueue* pDownloadQueue = g_pQueueCoordinator->LockQueue(); if (!pDownloadQueue->GetPostQueue()->empty()) { PostInfo* pPostInfo = pDownloadQueue->GetPostQueue()->front(); if (!pPostInfo->GetWorking()) { #ifndef DISABLE_PARCHECK if (pPostInfo->GetRequestParCheck() && pPostInfo->GetNZBInfo()->GetParStatus() <= NZBInfo::psSkipped && g_pOptions->GetParCheck() != Options::pcManual) { pPostInfo->GetNZBInfo()->SetParStatus(NZBInfo::psNone); pPostInfo->SetRequestParCheck(false); pPostInfo->SetStage(PostInfo::ptQueued); pPostInfo->GetNZBInfo()->GetScriptStatuses()->Clear(); DeletePostThread(pPostInfo); } else if (pPostInfo->GetRequestParCheck() && pPostInfo->GetNZBInfo()->GetParStatus() <= NZBInfo::psSkipped && g_pOptions->GetParCheck() == Options::pcManual) { pPostInfo->SetRequestParCheck(false); pPostInfo->GetNZBInfo()->SetParStatus(NZBInfo::psManual); DeletePostThread(pPostInfo); FileInfo* pFileInfo = GetQueueGroup(pDownloadQueue, pPostInfo->GetNZBInfo()); if (pFileInfo) { info("Downloading all remaining files for manual par-check for %s", pPostInfo->GetNZBInfo()->GetName()); g_pQueueCoordinator->GetQueueEditor()->LockedEditEntry(pDownloadQueue, pFileInfo->GetID(), false, QueueEditor::eaGroupResume, 0, NULL); pPostInfo->SetStage(PostInfo::ptFinished); pPostInfo->GetNZBInfo()->SetPostProcess(false); } else { info("There are no par-files remain for download for %s", pPostInfo->GetNZBInfo()->GetName()); pPostInfo->SetStage(PostInfo::ptQueued); } } else if (pPostInfo->GetRequestParRename()) { pPostInfo->GetNZBInfo()->SetRenameStatus(NZBInfo::rsNone); pPostInfo->SetRequestParRename(false); pPostInfo->SetStage(PostInfo::ptQueued); DeletePostThread(pPostInfo); } #endif if (pPostInfo->GetDeleted()) { pPostInfo->SetStage(PostInfo::ptFinished); } if (pPostInfo->GetStage() == PostInfo::ptQueued && !g_pOptions->GetPausePostProcess()) { DeletePostThread(pPostInfo); StartJob(pDownloadQueue, pPostInfo); } else if (pPostInfo->GetStage() == PostInfo::ptFinished) { UpdatePauseState(false, NULL); JobCompleted(pDownloadQueue, pPostInfo); } else if (!g_pOptions->GetPausePostProcess()) { error("Internal error: invalid state in post-processor"); } } } g_pQueueCoordinator->UnlockQueue(); }
void PrePostProcessor::CheckPostQueue() { GuardedDownloadQueue downloadQueue = DownloadQueue::Guard(); if (!m_curJob && m_jobCount > 0) { m_curJob = GetNextJob(downloadQueue); } if (m_curJob) { PostInfo* postInfo = m_curJob->GetPostInfo(); if (!postInfo->GetWorking() && !IsNzbFileDownloading(m_curJob)) { #ifndef DISABLE_PARCHECK if (postInfo->GetRequestParCheck() && (postInfo->GetNzbInfo()->GetParStatus() <= NzbInfo::psSkipped || (postInfo->GetForceRepair() && !postInfo->GetNzbInfo()->GetParFull())) && g_Options->GetParCheck() != Options::pcManual) { postInfo->SetForceParFull(postInfo->GetNzbInfo()->GetParStatus() > NzbInfo::psSkipped); postInfo->GetNzbInfo()->SetParStatus(NzbInfo::psNone); postInfo->SetRequestParCheck(false); postInfo->SetStage(PostInfo::ptQueued); postInfo->GetNzbInfo()->GetScriptStatuses()->clear(); DeletePostThread(postInfo); } else if (postInfo->GetRequestParCheck() && postInfo->GetNzbInfo()->GetParStatus() <= NzbInfo::psSkipped && g_Options->GetParCheck() == Options::pcManual) { postInfo->SetRequestParCheck(false); postInfo->GetNzbInfo()->SetParStatus(NzbInfo::psManual); DeletePostThread(postInfo); if (!postInfo->GetNzbInfo()->GetFileList()->empty()) { postInfo->GetNzbInfo()->PrintMessage(Message::mkInfo, "Downloading all remaining files for manual par-check for %s", postInfo->GetNzbInfo()->GetName()); downloadQueue->EditEntry(postInfo->GetNzbInfo()->GetId(), DownloadQueue::eaGroupResume, 0, nullptr); postInfo->SetStage(PostInfo::ptFinished); } else { postInfo->GetNzbInfo()->PrintMessage(Message::mkInfo, "There are no par-files remain for download for %s", postInfo->GetNzbInfo()->GetName()); postInfo->SetStage(PostInfo::ptQueued); } } #endif if (postInfo->GetDeleted()) { postInfo->SetStage(PostInfo::ptFinished); } if (postInfo->GetStage() == PostInfo::ptQueued && (!g_Options->GetPausePostProcess() || postInfo->GetNzbInfo()->GetForcePriority())) { DeletePostThread(postInfo); StartJob(downloadQueue, postInfo); } else if (postInfo->GetStage() == PostInfo::ptFinished) { UpdatePauseState(false, nullptr); JobCompleted(downloadQueue, postInfo); } else if (!g_Options->GetPausePostProcess()) { error("Internal error: invalid state in post-processor"); // TODO: cancel (delete) current job } } } }