Files
nzbget/daemon/queue/DownloadInfo.cpp
Andrey Prygunkov f5daf39bb8 fixed #67: mark as bad may return items to queue
… if multiple duplicate-items were marked at once
2015-08-20 21:23:37 +02:00

1465 lines
30 KiB
C++

/*
* This file is part of nzbget
*
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
* Copyright (C) 2007-2015 Andrey Prygunkov <hugbug@users.sourceforge.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $Revision$
* $Date$
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef WIN32
#include "win32.h"
#endif
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <ctype.h>
#include <sys/stat.h>
#include <algorithm>
#include "nzbget.h"
#include "DownloadInfo.h"
#include "ArticleWriter.h"
#include "DiskState.h"
#include "Options.h"
#include "Util.h"
int FileInfo::m_iIDGen = 0;
int FileInfo::m_iIDMax = 0;
int NZBInfo::m_iIDGen = 0;
int NZBInfo::m_iIDMax = 0;
DownloadQueue* DownloadQueue::g_pDownloadQueue = NULL;
bool DownloadQueue::g_bLoaded = false;
NZBParameter::NZBParameter(const char* szName)
{
m_szName = strdup(szName);
m_szValue = NULL;
}
NZBParameter::~NZBParameter()
{
free(m_szName);
free(m_szValue);
}
void NZBParameter::SetValue(const char* szValue)
{
free(m_szValue);
m_szValue = strdup(szValue);
}
NZBParameterList::~NZBParameterList()
{
Clear();
}
void NZBParameterList::Clear()
{
for (iterator it = begin(); it != end(); it++)
{
delete *it;
}
clear();
}
void NZBParameterList::SetParameter(const char* szName, const char* szValue)
{
NZBParameter* pParameter = NULL;
bool bDelete = !szValue || !*szValue;
for (iterator it = begin(); it != end(); it++)
{
NZBParameter* pLookupParameter = *it;
if (!strcmp(pLookupParameter->GetName(), szName))
{
if (bDelete)
{
delete pLookupParameter;
erase(it);
return;
}
pParameter = pLookupParameter;
break;
}
}
if (bDelete)
{
return;
}
if (!pParameter)
{
pParameter = new NZBParameter(szName);
push_back(pParameter);
}
pParameter->SetValue(szValue);
}
NZBParameter* NZBParameterList::Find(const char* szName, bool bCaseSensitive)
{
for (iterator it = begin(); it != end(); it++)
{
NZBParameter* pParameter = *it;
if ((bCaseSensitive && !strcmp(pParameter->GetName(), szName)) ||
(!bCaseSensitive && !strcasecmp(pParameter->GetName(), szName)))
{
return pParameter;
}
}
return NULL;
}
void NZBParameterList::CopyFrom(NZBParameterList* pSourceParameters)
{
for (iterator it = pSourceParameters->begin(); it != pSourceParameters->end(); it++)
{
NZBParameter* pParameter = *it;
SetParameter(pParameter->GetName(), pParameter->GetValue());
}
}
ScriptStatus::ScriptStatus(const char* szName, EStatus eStatus)
{
m_szName = strdup(szName);
m_eStatus = eStatus;
}
ScriptStatus::~ScriptStatus()
{
free(m_szName);
}
ScriptStatusList::~ScriptStatusList()
{
Clear();
}
void ScriptStatusList::Clear()
{
for (iterator it = begin(); it != end(); it++)
{
delete *it;
}
clear();
}
void ScriptStatusList::Add(const char* szScriptName, ScriptStatus::EStatus eStatus)
{
push_back(new ScriptStatus(szScriptName, eStatus));
}
ScriptStatus::EStatus ScriptStatusList::CalcTotalStatus()
{
ScriptStatus::EStatus eStatus = ScriptStatus::srNone;
for (iterator it = begin(); it != end(); it++)
{
ScriptStatus* pScriptStatus = *it;
// Failure-Status overrides Success-Status
if ((pScriptStatus->GetStatus() == ScriptStatus::srSuccess && eStatus == ScriptStatus::srNone) ||
(pScriptStatus->GetStatus() == ScriptStatus::srFailure))
{
eStatus = pScriptStatus->GetStatus();
}
}
return eStatus;
}
ServerStat::ServerStat(int iServerID)
{
m_iServerID = iServerID;
m_iSuccessArticles = 0;
m_iFailedArticles = 0;
}
ServerStatList::~ServerStatList()
{
Clear();
}
void ServerStatList::Clear()
{
for (iterator it = begin(); it != end(); it++)
{
delete *it;
}
clear();
}
void ServerStatList::StatOp(int iServerID, int iSuccessArticles, int iFailedArticles, EStatOperation eStatOperation)
{
ServerStat* pServerStat = NULL;
for (iterator it = begin(); it != end(); it++)
{
ServerStat* pServerStat1 = *it;
if (pServerStat1->GetServerID() == iServerID)
{
pServerStat = pServerStat1;
break;
}
}
if (!pServerStat)
{
pServerStat = new ServerStat(iServerID);
push_back(pServerStat);
}
switch (eStatOperation)
{
case soSet:
pServerStat->SetSuccessArticles(iSuccessArticles);
pServerStat->SetFailedArticles(iFailedArticles);
break;
case soAdd:
pServerStat->SetSuccessArticles(pServerStat->GetSuccessArticles() + iSuccessArticles);
pServerStat->SetFailedArticles(pServerStat->GetFailedArticles() + iFailedArticles);
break;
case soSubtract:
pServerStat->SetSuccessArticles(pServerStat->GetSuccessArticles() - iSuccessArticles);
pServerStat->SetFailedArticles(pServerStat->GetFailedArticles() - iFailedArticles);
break;
}
}
void ServerStatList::ListOp(ServerStatList* pServerStats, EStatOperation eStatOperation)
{
for (iterator it = pServerStats->begin(); it != pServerStats->end(); it++)
{
ServerStat* pServerStat = *it;
StatOp(pServerStat->GetServerID(), pServerStat->GetSuccessArticles(), pServerStat->GetFailedArticles(), eStatOperation);
}
}
NZBInfo::NZBInfo() : m_FileList(true)
{
debug("Creating NZBInfo");
m_eKind = nkNzb;
m_szURL = strdup("");
m_szFilename = strdup("");
m_szDestDir = strdup("");
m_szFinalDir = strdup("");
m_szCategory = strdup("");
m_szName = NULL;
m_iFileCount = 0;
m_iParkedFileCount = 0;
m_lSize = 0;
m_lSuccessSize = 0;
m_lFailedSize = 0;
m_lCurrentSuccessSize = 0;
m_lCurrentFailedSize = 0;
m_lParSize = 0;
m_lParSuccessSize = 0;
m_lParFailedSize = 0;
m_lParCurrentSuccessSize = 0;
m_lParCurrentFailedSize = 0;
m_iTotalArticles = 0;
m_iSuccessArticles = 0;
m_iFailedArticles = 0;
m_iCurrentSuccessArticles = 0;
m_iCurrentFailedArticles = 0;
m_eRenameStatus = rsNone;
m_eParStatus = psNone;
m_eUnpackStatus = usNone;
m_eCleanupStatus = csNone;
m_eMoveStatus = msNone;
m_eDeleteStatus = dsNone;
m_eMarkStatus = ksNone;
m_eUrlStatus = lsNone;
m_iExtraParBlocks = 0;
m_bAddUrlPaused = false;
m_bDeleting = false;
m_bDeletePaused = false;
m_bManyDupeFiles = false;
m_bAvoidHistory = false;
m_bHealthPaused = false;
m_bParCleanup = false;
m_bCleanupDisk = false;
m_bUnpackCleanedUpDisk = false;
m_szQueuedFilename = strdup("");
m_szDupeKey = strdup("");
m_iDupeScore = 0;
m_eDupeMode = dmScore;
m_iFullContentHash = 0;
m_iFilteredContentHash = 0;
m_iPausedFileCount = 0;
m_lRemainingSize = 0;
m_lPausedSize = 0;
m_iRemainingParCount = 0;
m_tMinTime = 0;
m_tMaxTime = 0;
m_iPriority = 0;
m_iActiveDownloads = 0;
m_Messages.clear();
m_pPostInfo = NULL;
m_iIDMessageGen = 0;
m_iID = ++m_iIDGen;
m_lDownloadedSize = 0;
m_iDownloadSec = 0;
m_iPostTotalSec = 0;
m_iParSec = 0;
m_iRepairSec = 0;
m_iUnpackSec = 0;
m_tDownloadStartTime = 0;
m_bReprocess = false;
m_tQueueScriptTime = 0;
m_bParFull = false;
m_iMessageCount = 0;
m_iCachedMessageCount = 0;
m_iFeedID = 0;
}
NZBInfo::~NZBInfo()
{
debug("Destroying NZBInfo");
free(m_szURL);
free(m_szFilename);
free(m_szDestDir);
free(m_szFinalDir);
free(m_szCategory);
free(m_szName);
free(m_szQueuedFilename);
free(m_szDupeKey);
delete m_pPostInfo;
ClearCompletedFiles();
m_FileList.Clear();
}
void NZBInfo::SetID(int iID)
{
m_iID = iID;
if (m_iIDMax < m_iID)
{
m_iIDMax = m_iID;
}
}
void NZBInfo::ResetGenID(bool bMax)
{
if (bMax)
{
m_iIDGen = m_iIDMax;
}
else
{
m_iIDGen = 0;
m_iIDMax = 0;
}
}
int NZBInfo::GenerateID()
{
return ++m_iIDGen;
}
void NZBInfo::ClearCompletedFiles()
{
for (CompletedFiles::iterator it = m_completedFiles.begin(); it != m_completedFiles.end(); it++)
{
delete *it;
}
m_completedFiles.clear();
}
void NZBInfo::SetDestDir(const char* szDestDir)
{
free(m_szDestDir);
m_szDestDir = strdup(szDestDir);
}
void NZBInfo::SetFinalDir(const char* szFinalDir)
{
free(m_szFinalDir);
m_szFinalDir = strdup(szFinalDir);
}
void NZBInfo::SetURL(const char* szURL)
{
free(m_szURL);
m_szURL = strdup(szURL);
if (!m_szName)
{
char szNZBNicename[1024];
MakeNiceUrlName(szURL, m_szFilename, szNZBNicename, sizeof(szNZBNicename));
szNZBNicename[1024-1] = '\0';
#ifdef WIN32
WebUtil::AnsiToUtf8(szNZBNicename, 1024);
#endif
SetName(szNZBNicename);
}
}
void NZBInfo::SetFilename(const char* szFilename)
{
bool bHadFilename = !Util::EmptyStr(m_szFilename);
free(m_szFilename);
m_szFilename = strdup(szFilename);
if ((!m_szName || !bHadFilename) && !Util::EmptyStr(szFilename))
{
char szNZBNicename[1024];
MakeNiceNZBName(m_szFilename, szNZBNicename, sizeof(szNZBNicename), true);
szNZBNicename[1024-1] = '\0';
#ifdef WIN32
WebUtil::AnsiToUtf8(szNZBNicename, 1024);
#endif
SetName(szNZBNicename);
}
}
void NZBInfo::SetName(const char* szName)
{
free(m_szName);
m_szName = szName ? strdup(szName) : NULL;
}
void NZBInfo::SetCategory(const char* szCategory)
{
free(m_szCategory);
m_szCategory = strdup(szCategory);
}
void NZBInfo::SetQueuedFilename(const char * szQueuedFilename)
{
free(m_szQueuedFilename);
m_szQueuedFilename = strdup(szQueuedFilename);
}
void NZBInfo::SetDupeKey(const char* szDupeKey)
{
free(m_szDupeKey);
m_szDupeKey = strdup(szDupeKey ? szDupeKey : "");
}
void NZBInfo::MakeNiceNZBName(const char * szNZBFilename, char * szBuffer, int iSize, bool bRemoveExt)
{
char postname[1024];
const char* szBaseName = Util::BaseFileName(szNZBFilename);
strncpy(postname, szBaseName, 1024);
postname[1024-1] = '\0';
if (bRemoveExt)
{
// wipe out ".nzb"
char* p = strrchr(postname, '.');
if (p && !strcasecmp(p, ".nzb")) *p = '\0';
}
Util::MakeValidFilename(postname, '_', false);
strncpy(szBuffer, postname, iSize);
szBuffer[iSize-1] = '\0';
}
void NZBInfo::MakeNiceUrlName(const char* szURL, const char* szNZBFilename, char* szBuffer, int iSize)
{
URL url(szURL);
if (!Util::EmptyStr(szNZBFilename))
{
char szNZBNicename[1024];
MakeNiceNZBName(szNZBFilename, szNZBNicename, sizeof(szNZBNicename), true);
snprintf(szBuffer, iSize, "%s @ %s", szNZBNicename, url.GetHost());
}
else if (url.IsValid())
{
snprintf(szBuffer, iSize, "%s%s", url.GetHost(), url.GetResource());
}
else
{
snprintf(szBuffer, iSize, "%s", szURL);
}
szBuffer[iSize-1] = '\0';
}
void NZBInfo::BuildDestDirName()
{
char szDestDir[1024];
if (Util::EmptyStr(g_pOptions->GetInterDir()))
{
BuildFinalDirName(szDestDir, 1024);
}
else
{
snprintf(szDestDir, 1024, "%s%s.#%i", g_pOptions->GetInterDir(), GetName(), GetID());
szDestDir[1024-1] = '\0';
}
#ifdef WIN32
WebUtil::Utf8ToAnsi(szDestDir, 1024);
#endif
SetDestDir(szDestDir);
}
void NZBInfo::BuildFinalDirName(char* szFinalDirBuf, int iBufSize)
{
char szBuffer[1024];
bool bUseCategory = m_szCategory && m_szCategory[0] != '\0';
snprintf(szFinalDirBuf, iBufSize, "%s", g_pOptions->GetDestDir());
szFinalDirBuf[iBufSize-1] = '\0';
if (bUseCategory)
{
Options::Category *pCategory = g_pOptions->FindCategory(m_szCategory, false);
if (pCategory && pCategory->GetDestDir() && pCategory->GetDestDir()[0] != '\0')
{
snprintf(szFinalDirBuf, iBufSize, "%s", pCategory->GetDestDir());
szFinalDirBuf[iBufSize-1] = '\0';
bUseCategory = false;
}
}
if (g_pOptions->GetAppendCategoryDir() && bUseCategory)
{
char szCategoryDir[1024];
strncpy(szCategoryDir, m_szCategory, 1024);
szCategoryDir[1024 - 1] = '\0';
Util::MakeValidFilename(szCategoryDir, '_', true);
snprintf(szBuffer, 1024, "%s%s%c", szFinalDirBuf, szCategoryDir, PATH_SEPARATOR);
szBuffer[1024-1] = '\0';
strncpy(szFinalDirBuf, szBuffer, iBufSize);
}
snprintf(szBuffer, 1024, "%s%s", szFinalDirBuf, GetName());
szBuffer[1024-1] = '\0';
strncpy(szFinalDirBuf, szBuffer, iBufSize);
#ifdef WIN32
WebUtil::Utf8ToAnsi(szFinalDirBuf, iBufSize);
#endif
}
int NZBInfo::CalcHealth()
{
if (m_lCurrentFailedSize == 0 || m_lSize == m_lParSize)
{
return 1000;
}
int iHealth = (int)((m_lSize - m_lParSize -
(m_lCurrentFailedSize - m_lParCurrentFailedSize)) * 1000 / (m_lSize - m_lParSize));
if (iHealth == 1000 && m_lCurrentFailedSize - m_lParCurrentFailedSize > 0)
{
iHealth = 999;
}
return iHealth;
}
int NZBInfo::CalcCriticalHealth(bool bAllowEstimation)
{
if (m_lSize == 0)
{
return 1000;
}
if (m_lSize == m_lParSize)
{
return 0;
}
long long lGoodParSize = m_lParSize - m_lParCurrentFailedSize;
int iCriticalHealth = (int)((m_lSize - lGoodParSize*2) * 1000 / (m_lSize - lGoodParSize));
if (lGoodParSize*2 > m_lSize)
{
iCriticalHealth = 0;
}
else if (iCriticalHealth == 1000 && m_lParSize > 0)
{
iCriticalHealth = 999;
}
if (iCriticalHealth == 1000 && bAllowEstimation)
{
// using empirical critical health 85%, to avoid false alarms for downloads with renamed par-files
iCriticalHealth = 850;
}
return iCriticalHealth;
}
void NZBInfo::UpdateMinMaxTime()
{
m_tMinTime = 0;
m_tMaxTime = 0;
bool bFirst = true;
for (FileList::iterator it = m_FileList.begin(); it != m_FileList.end(); it++)
{
FileInfo* pFileInfo = *it;
if (bFirst)
{
m_tMinTime = pFileInfo->GetTime();
m_tMaxTime = pFileInfo->GetTime();
bFirst = false;
}
if (pFileInfo->GetTime() > 0)
{
if (pFileInfo->GetTime() < m_tMinTime)
{
m_tMinTime = pFileInfo->GetTime();
}
if (pFileInfo->GetTime() > m_tMaxTime)
{
m_tMaxTime = pFileInfo->GetTime();
}
}
}
}
MessageList* NZBInfo::LockCachedMessages()
{
m_mutexLog.Lock();
return &m_Messages;
}
void NZBInfo::UnlockCachedMessages()
{
m_mutexLog.Unlock();
}
void NZBInfo::AddMessage(Message::EKind eKind, const char * szText)
{
switch (eKind)
{
case Message::mkDetail:
detail("%s", szText);
break;
case Message::mkInfo:
info("%s", szText);
break;
case Message::mkWarning:
warn("%s", szText);
break;
case Message::mkError:
error("%s", szText);
break;
case Message::mkDebug:
debug("%s", szText);
break;
}
m_mutexLog.Lock();
Message* pMessage = new Message(++m_iIDMessageGen, eKind, time(NULL), szText);
m_Messages.push_back(pMessage);
if (g_pOptions->GetSaveQueue() && g_pOptions->GetServerMode() && g_pOptions->GetNzbLog())
{
g_pDiskState->AppendNZBMessage(m_iID, eKind, szText);
m_iMessageCount++;
}
while (m_Messages.size() > (unsigned int)g_pOptions->GetLogBufferSize())
{
Message* pMessage = m_Messages.front();
delete pMessage;
m_Messages.pop_front();
}
m_iCachedMessageCount = m_Messages.size();
m_mutexLog.Unlock();
}
void NZBInfo::PrintMessage(Message::EKind eKind, const char* szFormat, ...)
{
char tmp2[1024];
va_list ap;
va_start(ap, szFormat);
vsnprintf(tmp2, 1024, szFormat, ap);
tmp2[1024-1] = '\0';
va_end(ap);
AddMessage(eKind, tmp2);
}
void NZBInfo::ClearMessages()
{
m_mutexLog.Lock();
m_Messages.Clear();
m_iCachedMessageCount = 0;
m_mutexLog.Unlock();
}
void NZBInfo::CopyFileList(NZBInfo* pSrcNZBInfo)
{
m_FileList.Clear();
for (FileList::iterator it = pSrcNZBInfo->GetFileList()->begin(); it != pSrcNZBInfo->GetFileList()->end(); it++)
{
FileInfo* pFileInfo = *it;
pFileInfo->SetNZBInfo(this);
m_FileList.push_back(pFileInfo);
}
pSrcNZBInfo->GetFileList()->clear(); // only remove references
SetFullContentHash(pSrcNZBInfo->GetFullContentHash());
SetFilteredContentHash(pSrcNZBInfo->GetFilteredContentHash());
SetFileCount(pSrcNZBInfo->GetFileCount());
SetPausedFileCount(pSrcNZBInfo->GetPausedFileCount());
SetRemainingParCount(pSrcNZBInfo->GetRemainingParCount());
SetSize(pSrcNZBInfo->GetSize());
SetRemainingSize(pSrcNZBInfo->GetRemainingSize());
SetPausedSize(pSrcNZBInfo->GetPausedSize());
SetSuccessSize(pSrcNZBInfo->GetSuccessSize());
SetCurrentSuccessSize(pSrcNZBInfo->GetCurrentSuccessSize());
SetFailedSize(pSrcNZBInfo->GetFailedSize());
SetCurrentFailedSize(pSrcNZBInfo->GetCurrentFailedSize());
SetParSize(pSrcNZBInfo->GetParSize());
SetParSuccessSize(pSrcNZBInfo->GetParSuccessSize());
SetParCurrentSuccessSize(pSrcNZBInfo->GetParCurrentSuccessSize());
SetParFailedSize(pSrcNZBInfo->GetParFailedSize());
SetParCurrentFailedSize(pSrcNZBInfo->GetParCurrentFailedSize());
SetTotalArticles(pSrcNZBInfo->GetTotalArticles());
SetSuccessArticles(pSrcNZBInfo->GetSuccessArticles());
SetFailedArticles(pSrcNZBInfo->GetFailedArticles());
SetCurrentSuccessArticles(pSrcNZBInfo->GetSuccessArticles());
SetCurrentFailedArticles(pSrcNZBInfo->GetFailedArticles());
SetMinTime(pSrcNZBInfo->GetMinTime());
SetMaxTime(pSrcNZBInfo->GetMaxTime());
}
void NZBInfo::EnterPostProcess()
{
m_pPostInfo = new PostInfo();
m_pPostInfo->SetNZBInfo(this);
}
void NZBInfo::LeavePostProcess()
{
delete m_pPostInfo;
m_pPostInfo = NULL;
ClearMessages();
}
void NZBInfo::SetActiveDownloads(int iActiveDownloads)
{
if (((m_iActiveDownloads == 0 && iActiveDownloads > 0) ||
(m_iActiveDownloads > 0 && iActiveDownloads == 0)) &&
m_eKind == NZBInfo::nkNzb)
{
if (iActiveDownloads > 0)
{
m_tDownloadStartTime = time(NULL);
}
else
{
m_iDownloadSec += time(NULL) - m_tDownloadStartTime;
m_tDownloadStartTime = 0;
}
}
m_iActiveDownloads = iActiveDownloads;
}
bool NZBInfo::IsDupeSuccess()
{
bool bFailure =
m_eMarkStatus != NZBInfo::ksSuccess &&
m_eMarkStatus != NZBInfo::ksGood &&
(m_eDeleteStatus != NZBInfo::dsNone ||
m_eMarkStatus == NZBInfo::ksBad ||
m_eParStatus == NZBInfo::psFailure ||
m_eUnpackStatus == NZBInfo::usFailure ||
m_eUnpackStatus == NZBInfo::usPassword ||
(m_eParStatus == NZBInfo::psSkipped &&
m_eUnpackStatus == NZBInfo::usSkipped &&
CalcHealth() < CalcCriticalHealth(true)));
return !bFailure;
}
const char* NZBInfo::MakeTextStatus(bool bIgnoreScriptStatus)
{
const char* szStatus = "FAILURE/INTERNAL_ERROR";
if (m_eKind == NZBInfo::nkNzb)
{
int iHealth = CalcHealth();
int iCriticalHealth = CalcCriticalHealth(false);
ScriptStatus::EStatus eScriptStatus = bIgnoreScriptStatus ? ScriptStatus::srSuccess : m_scriptStatuses.CalcTotalStatus();
if (m_eMarkStatus == NZBInfo::ksBad)
{
szStatus = "FAILURE/BAD";
}
else if (m_eMarkStatus == NZBInfo::ksGood)
{
szStatus = "SUCCESS/GOOD";
}
else if (m_eMarkStatus == NZBInfo::ksSuccess)
{
szStatus = "SUCCESS/MARK";
}
else if (m_eDeleteStatus == NZBInfo::dsHealth)
{
szStatus = "FAILURE/HEALTH";
}
else if (m_eDeleteStatus == NZBInfo::dsManual)
{
szStatus = "DELETED/MANUAL";
}
else if (m_eDeleteStatus == NZBInfo::dsDupe)
{
szStatus = "DELETED/DUPE";
}
else if (m_eDeleteStatus == NZBInfo::dsBad)
{
szStatus = "FAILURE/BAD";
}
else if (m_eDeleteStatus == NZBInfo::dsGood)
{
szStatus = "DELETED/GOOD";
}
else if (m_eDeleteStatus == NZBInfo::dsCopy)
{
szStatus = "DELETED/COPY";
}
else if (m_eDeleteStatus == NZBInfo::dsScan)
{
szStatus = "FAILURE/SCAN";
}
else if (m_eParStatus == NZBInfo::psFailure)
{
szStatus = "FAILURE/PAR";
}
else if (m_eUnpackStatus == NZBInfo::usFailure)
{
szStatus = "FAILURE/UNPACK";
}
else if (m_eMoveStatus == NZBInfo::msFailure)
{
szStatus = "FAILURE/MOVE";
}
else if (m_eParStatus == NZBInfo::psManual)
{
szStatus = "WARNING/DAMAGED";
}
else if (m_eParStatus == NZBInfo::psRepairPossible)
{
szStatus = "WARNING/REPAIRABLE";
}
else if ((m_eParStatus == NZBInfo::psNone || m_eParStatus == NZBInfo::psSkipped) &&
(m_eUnpackStatus == NZBInfo::usNone || m_eUnpackStatus == NZBInfo::usSkipped) &&
iHealth < iCriticalHealth)
{
szStatus = "FAILURE/HEALTH";
}
else if ((m_eParStatus == NZBInfo::psNone || m_eParStatus == NZBInfo::psSkipped) &&
(m_eUnpackStatus == NZBInfo::usNone || m_eUnpackStatus == NZBInfo::usSkipped) &&
iHealth < 1000 && iHealth >= iCriticalHealth)
{
szStatus = "WARNING/HEALTH";
}
else if ((m_eParStatus == NZBInfo::psNone || m_eParStatus == NZBInfo::psSkipped) &&
(m_eUnpackStatus == NZBInfo::usNone || m_eUnpackStatus == NZBInfo::usSkipped) &&
eScriptStatus != ScriptStatus::srFailure && iHealth == 1000)
{
szStatus = "SUCCESS/HEALTH";
}
else if (m_eUnpackStatus == NZBInfo::usSpace)
{
szStatus = "WARNING/SPACE";
}
else if (m_eUnpackStatus == NZBInfo::usPassword)
{
szStatus = "WARNING/PASSWORD";
}
else if ((m_eUnpackStatus == NZBInfo::usSuccess ||
((m_eUnpackStatus == NZBInfo::usNone || m_eUnpackStatus == NZBInfo::usSkipped) &&
m_eParStatus == NZBInfo::psSuccess)) &&
eScriptStatus == ScriptStatus::srSuccess)
{
szStatus = "SUCCESS/ALL";
}
else if (m_eUnpackStatus == NZBInfo::usSuccess && eScriptStatus == ScriptStatus::srNone)
{
szStatus = "SUCCESS/UNPACK";
}
else if (m_eParStatus == NZBInfo::psSuccess && eScriptStatus == ScriptStatus::srNone)
{
szStatus = "SUCCESS/PAR";
}
else if (eScriptStatus == ScriptStatus::srFailure)
{
szStatus = "WARNING/SCRIPT";
}
}
else if (m_eKind == NZBInfo::nkUrl)
{
if (m_eDeleteStatus == NZBInfo::dsManual)
{
szStatus = "DELETED/MANUAL";
}
else if (m_eDeleteStatus == NZBInfo::dsDupe)
{
szStatus = "DELETED/DUPE";
}
else
{
const char* szUrlStatusName[] = { "FAILURE/INTERNAL_ERROR", "FAILURE/INTERNAL_ERROR", "FAILURE/INTERNAL_ERROR",
"FAILURE/FETCH", "FAILURE/INTERNAL_ERROR", "WARNING/SKIPPED", "FAILURE/SCAN" };
szStatus = szUrlStatusName[m_eUrlStatus];
}
}
return szStatus;
}
NZBList::~NZBList()
{
if (m_bOwnObjects)
{
Clear();
}
}
void NZBList::Clear()
{
for (iterator it = begin(); it != end(); it++)
{
delete *it;
}
clear();
}
void NZBList::Add(NZBInfo* pNZBInfo, bool bAddTop)
{
if (bAddTop)
{
push_front(pNZBInfo);
}
else
{
push_back(pNZBInfo);
}
}
void NZBList::Remove(NZBInfo* pNZBInfo)
{
iterator it = std::find(begin(), end(), pNZBInfo);
if (it != end())
{
erase(it);
}
}
NZBInfo* NZBList::Find(int iID)
{
for (iterator it = begin(); it != end(); it++)
{
NZBInfo* pNZBInfo = *it;
if (pNZBInfo->GetID() == iID)
{
return pNZBInfo;
}
}
return NULL;
}
ArticleInfo::ArticleInfo()
{
//debug("Creating ArticleInfo");
m_szMessageID = NULL;
m_iSize = 0;
m_pSegmentContent = NULL;
m_iSegmentOffset = 0;
m_iSegmentSize = 0;
m_eStatus = aiUndefined;
m_szResultFilename = NULL;
m_lCrc = 0;
}
ArticleInfo::~ ArticleInfo()
{
//debug("Destroying ArticleInfo");
DiscardSegment();
free(m_szMessageID);
free(m_szResultFilename);
}
void ArticleInfo::SetMessageID(const char * szMessageID)
{
free(m_szMessageID);
m_szMessageID = strdup(szMessageID);
}
void ArticleInfo::SetResultFilename(const char * v)
{
free(m_szResultFilename);
m_szResultFilename = strdup(v);
}
void ArticleInfo::AttachSegment(char* pContent, long long iOffset, int iSize)
{
DiscardSegment();
m_pSegmentContent = pContent;
m_iSegmentOffset = iOffset;
m_iSegmentSize = iSize;
}
void ArticleInfo::DiscardSegment()
{
if (m_pSegmentContent)
{
free(m_pSegmentContent);
m_pSegmentContent = NULL;
g_pArticleCache->Free(m_iSegmentSize);
}
}
FileInfo::FileInfo(int iID)
{
debug("Creating FileInfo");
m_Articles.clear();
m_Groups.clear();
m_szSubject = NULL;
m_szFilename = NULL;
m_szOutputFilename = NULL;
m_pMutexOutputFile = NULL;
m_bFilenameConfirmed = false;
m_lSize = 0;
m_lRemainingSize = 0;
m_lMissedSize = 0;
m_lSuccessSize = 0;
m_lFailedSize = 0;
m_iTotalArticles = 0;
m_iMissedArticles = 0;
m_iFailedArticles = 0;
m_iSuccessArticles = 0;
m_tTime = 0;
m_bPaused = false;
m_bDeleted = false;
m_iCompletedArticles = 0;
m_bParFile = false;
m_bOutputInitialized = false;
m_pNZBInfo = NULL;
m_bExtraPriority = false;
m_iActiveDownloads = 0;
m_bAutoDeleted = false;
m_iCachedArticles = 0;
m_bPartialChanged = false;
m_iID = iID ? iID : ++m_iIDGen;
}
FileInfo::~ FileInfo()
{
debug("Destroying FileInfo");
free(m_szSubject);
free(m_szFilename);
free(m_szOutputFilename);
delete m_pMutexOutputFile;
for (Groups::iterator it = m_Groups.begin(); it != m_Groups.end() ;it++)
{
free(*it);
}
m_Groups.clear();
ClearArticles();
}
void FileInfo::ClearArticles()
{
for (Articles::iterator it = m_Articles.begin(); it != m_Articles.end() ;it++)
{
delete *it;
}
m_Articles.clear();
}
void FileInfo::SetID(int iID)
{
m_iID = iID;
if (m_iIDMax < m_iID)
{
m_iIDMax = m_iID;
}
}
void FileInfo::ResetGenID(bool bMax)
{
if (bMax)
{
m_iIDGen = m_iIDMax;
}
else
{
m_iIDGen = 0;
m_iIDMax = 0;
}
}
void FileInfo::SetPaused(bool bPaused)
{
if (m_bPaused != bPaused && m_pNZBInfo)
{
m_pNZBInfo->SetPausedFileCount(m_pNZBInfo->GetPausedFileCount() + (bPaused ? 1 : -1));
m_pNZBInfo->SetPausedSize(m_pNZBInfo->GetPausedSize() + (bPaused ? m_lRemainingSize : - m_lRemainingSize));
}
m_bPaused = bPaused;
}
void FileInfo::SetSubject(const char* szSubject)
{
m_szSubject = strdup(szSubject);
}
void FileInfo::SetFilename(const char* szFilename)
{
free(m_szFilename);
m_szFilename = strdup(szFilename);
}
void FileInfo::MakeValidFilename()
{
Util::MakeValidFilename(m_szFilename, '_', false);
}
void FileInfo::LockOutputFile()
{
m_pMutexOutputFile->Lock();
}
void FileInfo::UnlockOutputFile()
{
m_pMutexOutputFile->Unlock();
}
void FileInfo::SetOutputFilename(const char* szOutputFilename)
{
free(m_szOutputFilename);
m_szOutputFilename = strdup(szOutputFilename);
}
void FileInfo::SetActiveDownloads(int iActiveDownloads)
{
m_iActiveDownloads = iActiveDownloads;
if (m_iActiveDownloads > 0 && !m_pMutexOutputFile)
{
m_pMutexOutputFile = new Mutex();
}
else if (m_iActiveDownloads == 0 && m_pMutexOutputFile)
{
delete m_pMutexOutputFile;
m_pMutexOutputFile = NULL;
}
}
FileList::~FileList()
{
if (m_bOwnObjects)
{
Clear();
}
}
void FileList::Clear()
{
for (iterator it = begin(); it != end(); it++)
{
delete *it;
}
clear();
}
void FileList::Remove(FileInfo* pFileInfo)
{
erase(std::find(begin(), end(), pFileInfo));
}
CompletedFile::CompletedFile(int iID, const char* szFileName, EStatus eStatus, unsigned long lCrc)
{
m_iID = iID;
if (FileInfo::m_iIDMax < m_iID)
{
FileInfo::m_iIDMax = m_iID;
}
m_szFileName = strdup(szFileName);
m_eStatus = eStatus;
m_lCrc = lCrc;
}
void CompletedFile::SetFileName(const char* szFileName)
{
free(m_szFileName);
m_szFileName = strdup(szFileName);
}
CompletedFile::~CompletedFile()
{
free(m_szFileName);
}
PostInfo::PostInfo()
{
debug("Creating PostInfo");
m_pNZBInfo = NULL;
m_bWorking = false;
m_bDeleted = false;
m_bRequestParCheck = false;
m_bForceParFull = false;
m_bForceRepair = false;
m_bParRepaired = false;
m_bUnpackTried = false;
m_bPassListTried = false;
m_eLastUnpackStatus = 0;
m_szProgressLabel = strdup("");
m_iFileProgress = 0;
m_iStageProgress = 0;
m_tStartTime = 0;
m_tStageTime = 0;
m_eStage = ptQueued;
m_pPostThread = NULL;
}
PostInfo::~ PostInfo()
{
debug("Destroying PostInfo");
free(m_szProgressLabel);
for (ParredFiles::iterator it = m_ParredFiles.begin(); it != m_ParredFiles.end(); it++)
{
free(*it);
}
}
void PostInfo::SetProgressLabel(const char* szProgressLabel)
{
free(m_szProgressLabel);
m_szProgressLabel = strdup(szProgressLabel);
}
DupInfo::DupInfo()
{
m_iID = 0;
m_szName = NULL;
m_szDupeKey = NULL;
m_iDupeScore = 0;
m_eDupeMode = dmScore;
m_lSize = 0;
m_iFullContentHash = 0;
m_iFilteredContentHash = 0;
m_eStatus = dsUndefined;
}
DupInfo::~DupInfo()
{
free(m_szName);
free(m_szDupeKey);
}
void DupInfo::SetID(int iID)
{
m_iID = iID;
if (NZBInfo::m_iIDMax < m_iID)
{
NZBInfo::m_iIDMax = m_iID;
}
}
void DupInfo::SetName(const char* szName)
{
free(m_szName);
m_szName = strdup(szName);
}
void DupInfo::SetDupeKey(const char* szDupeKey)
{
free(m_szDupeKey);
m_szDupeKey = strdup(szDupeKey);
}
HistoryInfo::HistoryInfo(NZBInfo* pNZBInfo)
{
m_eKind = pNZBInfo->GetKind() == NZBInfo::nkNzb ? hkNzb : hkUrl;
m_pInfo = pNZBInfo;
m_tTime = 0;
}
HistoryInfo::HistoryInfo(DupInfo* pDupInfo)
{
m_eKind = hkDup;
m_pInfo = pDupInfo;
m_tTime = 0;
}
HistoryInfo::~HistoryInfo()
{
if ((m_eKind == hkNzb || m_eKind == hkUrl) && m_pInfo)
{
delete (NZBInfo*)m_pInfo;
}
else if (m_eKind == hkDup && m_pInfo)
{
delete (DupInfo*)m_pInfo;
}
}
int HistoryInfo::GetID()
{
if ((m_eKind == hkNzb || m_eKind == hkUrl))
{
return ((NZBInfo*)m_pInfo)->GetID();
}
else // if (m_eKind == hkDup)
{
return ((DupInfo*)m_pInfo)->GetID();
}
}
void HistoryInfo::GetName(char* szBuffer, int iSize)
{
if (m_eKind == hkNzb || m_eKind == hkUrl)
{
strncpy(szBuffer, GetNZBInfo()->GetName(), iSize);
szBuffer[iSize-1] = '\0';
}
else if (m_eKind == hkDup)
{
strncpy(szBuffer, GetDupInfo()->GetName(), iSize);
szBuffer[iSize-1] = '\0';
}
else
{
strncpy(szBuffer, "<unknown>", iSize);
}
}
HistoryList::~HistoryList()
{
for (iterator it = begin(); it != end(); it++)
{
delete *it;
}
}
HistoryInfo* HistoryList::Find(int iID)
{
for (iterator it = begin(); it != end(); it++)
{
HistoryInfo* pHistoryInfo = *it;
if (pHistoryInfo->GetID() == iID)
{
return pHistoryInfo;
}
}
return NULL;
}
DownloadQueue* DownloadQueue::Lock()
{
g_pDownloadQueue->m_LockMutex.Lock();
return g_pDownloadQueue;
}
void DownloadQueue::Unlock()
{
g_pDownloadQueue->m_LockMutex.Unlock();
}
void DownloadQueue::CalcRemainingSize(long long* pRemaining, long long* pRemainingForced)
{
long long lRemainingSize = 0;
long long lRemainingForced = 0;
for (NZBList::iterator it = m_Queue.begin(); it != m_Queue.end(); it++)
{
NZBInfo* pNZBInfo = *it;
for (FileList::iterator it2 = pNZBInfo->GetFileList()->begin(); it2 != pNZBInfo->GetFileList()->end(); it2++)
{
FileInfo* pFileInfo = *it2;
if (!pFileInfo->GetPaused() && !pFileInfo->GetDeleted())
{
lRemainingSize += pFileInfo->GetRemainingSize();
if (pNZBInfo->GetForcePriority())
{
lRemainingForced += pFileInfo->GetRemainingSize();
}
}
}
}
*pRemaining = lRemainingSize;
if (pRemainingForced)
{
*pRemainingForced = lRemainingForced;
}
}