Пример #1
0
/**
 * 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);
		}
	}
}
Пример #2
0
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);
}
Пример #3
0
/**
 * 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);
			}
		}
	}
}
Пример #4
0
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);
}
Пример #5
0
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
}
Пример #6
0
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();
}
Пример #7
0
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());
}
Пример #8
0
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();
}
Пример #9
0
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();
}
Пример #10
0
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
			}
		}
	}
}