Files
nzbget/daemon/queue/DownloadInfo.cpp
Andrey Prygunkov f3f7fbd0de #176: updated copyright notice in source files
- added link to http://nzbget.net;
- replaced FSF Post address with a web link;
- removed unusable subversion-tags;
- updated year.
2016-03-01 19:45:07 +01:00

1034 lines
21 KiB
C++

/*
* This file is part of nzbget. See <http://nzbget.net>.
*
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
* Copyright (C) 2007-2016 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, see <http://www.gnu.org/licenses/>.
*/
#include "nzbget.h"
#include "DownloadInfo.h"
#include "DiskState.h"
#include "Options.h"
#include "Util.h"
#include "FileSystem.h"
int FileInfo::m_idGen = 0;
int FileInfo::m_idMax = 0;
int NzbInfo::m_idGen = 0;
int NzbInfo::m_idMax = 0;
DownloadQueue* DownloadQueue::g_DownloadQueue = nullptr;
bool DownloadQueue::g_Loaded = false;
void NzbParameterList::SetParameter(const char* name, const char* value)
{
bool emptyVal = Util::EmptyStr(value);
iterator pos = std::find_if(begin(), end(),
[name](NzbParameter& parameter)
{
return !strcmp(parameter.GetName(), name);
});
if (emptyVal && pos != end())
{
erase(pos);
}
else if (pos != end())
{
pos->SetValue(value);
}
else if (!emptyVal)
{
emplace_back(name, value);
}
}
NzbParameter* NzbParameterList::Find(const char* name, bool caseSensitive)
{
for (NzbParameter& parameter : this)
{
if ((caseSensitive && !strcmp(parameter.GetName(), name)) ||
(!caseSensitive && !strcasecmp(parameter.GetName(), name)))
{
return &parameter;
}
}
return nullptr;
}
void NzbParameterList::CopyFrom(NzbParameterList* sourceParameters)
{
for (NzbParameter& parameter : sourceParameters)
{
SetParameter(parameter.GetName(), parameter.GetValue());
}
}
ScriptStatus::EStatus ScriptStatusList::CalcTotalStatus()
{
ScriptStatus::EStatus status = ScriptStatus::srNone;
for (ScriptStatus& scriptStatus : this)
{
// Failure-Status overrides Success-Status
if ((scriptStatus.GetStatus() == ScriptStatus::srSuccess && status == ScriptStatus::srNone) ||
(scriptStatus.GetStatus() == ScriptStatus::srFailure))
{
status = scriptStatus.GetStatus();
}
}
return status;
}
void ServerStatList::StatOp(int serverId, int successArticles, int failedArticles, EStatOperation statOperation)
{
ServerStat* serverStat = nullptr;
for (ServerStat& serverStat1 : this)
{
if (serverStat1.GetServerId() == serverId)
{
serverStat = &serverStat1;
break;
}
}
if (!serverStat)
{
emplace_back(serverId);
serverStat = &back();
}
switch (statOperation)
{
case soSet:
serverStat->SetSuccessArticles(successArticles);
serverStat->SetFailedArticles(failedArticles);
break;
case soAdd:
serverStat->SetSuccessArticles(serverStat->GetSuccessArticles() + successArticles);
serverStat->SetFailedArticles(serverStat->GetFailedArticles() + failedArticles);
break;
case soSubtract:
serverStat->SetSuccessArticles(serverStat->GetSuccessArticles() - successArticles);
serverStat->SetFailedArticles(serverStat->GetFailedArticles() - failedArticles);
break;
}
}
void ServerStatList::ListOp(ServerStatList* serverStats, EStatOperation statOperation)
{
for (ServerStat& serverStat : serverStats)
{
StatOp(serverStat.GetServerId(), serverStat.GetSuccessArticles(), serverStat.GetFailedArticles(), statOperation);
}
}
NzbInfo::NzbInfo() : m_fileList(true)
{
debug("Creating NZBInfo");
m_kind = nkNzb;
m_url = "";
m_filename = "";
m_destDir = "";
m_finalDir = "";
m_category = "";
m_name = nullptr;
m_fileCount = 0;
m_parkedFileCount = 0;
m_size = 0;
m_successSize = 0;
m_failedSize = 0;
m_currentSuccessSize = 0;
m_currentFailedSize = 0;
m_parSize = 0;
m_parSuccessSize = 0;
m_parFailedSize = 0;
m_parCurrentSuccessSize = 0;
m_parCurrentFailedSize = 0;
m_totalArticles = 0;
m_successArticles = 0;
m_failedArticles = 0;
m_currentSuccessArticles = 0;
m_currentFailedArticles = 0;
m_renameStatus = rsNone;
m_parStatus = psNone;
m_unpackStatus = usNone;
m_cleanupStatus = csNone;
m_moveStatus = msNone;
m_deleteStatus = dsNone;
m_markStatus = ksNone;
m_urlStatus = lsNone;
m_extraParBlocks = 0;
m_addUrlPaused = false;
m_deleting = false;
m_deletePaused = false;
m_manyDupeFiles = false;
m_avoidHistory = false;
m_healthPaused = false;
m_parCleanup = false;
m_cleanupDisk = false;
m_unpackCleanedUpDisk = false;
m_queuedFilename = "";
m_dupeKey = "";
m_dupeScore = 0;
m_dupeMode = dmScore;
m_fullContentHash = 0;
m_filteredContentHash = 0;
m_pausedFileCount = 0;
m_remainingSize = 0;
m_pausedSize = 0;
m_remainingParCount = 0;
m_minTime = 0;
m_maxTime = 0;
m_priority = 0;
m_activeDownloads = 0;
m_messages.clear();
m_postInfo = nullptr;
m_idMessageGen = 0;
m_id = ++m_idGen;
m_downloadedSize = 0;
m_downloadSec = 0;
m_postTotalSec = 0;
m_parSec = 0;
m_repairSec = 0;
m_unpackSec = 0;
m_downloadStartTime = 0;
m_reprocess = false;
m_queueScriptTime = 0;
m_parFull = false;
m_messageCount = 0;
m_cachedMessageCount = 0;
m_feedId = 0;
}
NzbInfo::~NzbInfo()
{
debug("Destroying NZBInfo");
delete m_postInfo;
m_fileList.Clear();
}
void NzbInfo::SetId(int id)
{
m_id = id;
if (m_idMax < m_id)
{
m_idMax = m_id;
}
}
void NzbInfo::ResetGenId(bool max)
{
if (max)
{
m_idGen = m_idMax;
}
else
{
m_idGen = 0;
m_idMax = 0;
}
}
int NzbInfo::GenerateId()
{
return ++m_idGen;
}
void NzbInfo::SetUrl(const char* url)
{
m_url = url;
if (!m_name)
{
CString nzbNicename = MakeNiceUrlName(url, m_filename);
SetName(nzbNicename);
}
}
void NzbInfo::SetFilename(const char* filename)
{
bool hadFilename = !Util::EmptyStr(m_filename);
m_filename = filename;
if ((!m_name || !hadFilename) && !Util::EmptyStr(filename))
{
CString nzbNicename = MakeNiceNzbName(m_filename, true);
SetName(nzbNicename);
}
}
CString NzbInfo::MakeNiceNzbName(const char * nzbFilename, bool removeExt)
{
CString nicename = FileSystem::BaseFileName(nzbFilename);
if (removeExt)
{
// wipe out ".nzb"
char* p = strrchr(nicename, '.');
if (p && !strcasecmp(p, ".nzb")) *p = '\0';
}
FileSystem::MakeValidFilename(nicename, '_', false);
return nicename;
}
CString NzbInfo::MakeNiceUrlName(const char* urlStr, const char* nzbFilename)
{
CString urlNicename;
URL url(urlStr);
if (!Util::EmptyStr(nzbFilename))
{
CString nzbNicename = MakeNiceNzbName(nzbFilename, true);
urlNicename.Format("%s @ %s", *nzbNicename, url.GetHost());
}
else if (url.IsValid())
{
urlNicename.Format("%s%s", url.GetHost(), url.GetResource());
}
else
{
urlNicename = urlStr;
}
return urlNicename;
}
void NzbInfo::BuildDestDirName()
{
if (Util::EmptyStr(g_Options->GetInterDir()))
{
m_destDir = BuildFinalDirName();
}
else
{
m_destDir.Format("%s%c%s.#%i", g_Options->GetInterDir(), PATH_SEPARATOR, GetName(), GetId());
}
}
CString NzbInfo::BuildFinalDirName()
{
CString finalDir = g_Options->GetDestDir();
bool useCategory = !m_category.Empty();
if (useCategory)
{
Options::Category* category = g_Options->FindCategory(m_category, false);
if (category && !Util::EmptyStr(category->GetDestDir()))
{
finalDir = category->GetDestDir();
useCategory = false;
}
}
if (g_Options->GetAppendCategoryDir() && useCategory)
{
BString<1024> categoryDir;
categoryDir = m_category;
FileSystem::MakeValidFilename(categoryDir, '_', true);
// we can't format with "finalDir.Format" because one of the parameter is "finalDir" itself.
finalDir = CString::FormatStr("%s%c%s", *finalDir, PATH_SEPARATOR, *categoryDir);
}
finalDir.AppendFmt("%c%s", PATH_SEPARATOR, GetName());
return finalDir;
}
int NzbInfo::CalcHealth()
{
if (m_currentFailedSize == 0 || m_size == m_parSize)
{
return 1000;
}
int health = (int)((m_size - m_parSize -
(m_currentFailedSize - m_parCurrentFailedSize)) * 1000 / (m_size - m_parSize));
if (health == 1000 && m_currentFailedSize - m_parCurrentFailedSize > 0)
{
health = 999;
}
return health;
}
int NzbInfo::CalcCriticalHealth(bool allowEstimation)
{
if (m_size == 0)
{
return 1000;
}
if (m_size == m_parSize)
{
return 0;
}
int64 goodParSize = m_parSize - m_parCurrentFailedSize;
int criticalHealth = (int)((m_size - goodParSize*2) * 1000 / (m_size - goodParSize));
if (goodParSize*2 > m_size)
{
criticalHealth = 0;
}
else if (criticalHealth == 1000 && m_parSize > 0)
{
criticalHealth = 999;
}
if (criticalHealth == 1000 && allowEstimation)
{
// using empirical critical health 85%, to avoid false alarms for downloads with renamed par-files
criticalHealth = 850;
}
return criticalHealth;
}
void NzbInfo::UpdateMinMaxTime()
{
m_minTime = 0;
m_maxTime = 0;
bool first = true;
for (FileInfo* fileInfo : m_fileList)
{
if (first)
{
m_minTime = fileInfo->GetTime();
m_maxTime = fileInfo->GetTime();
first = false;
}
if (fileInfo->GetTime() > 0)
{
if (fileInfo->GetTime() < m_minTime)
{
m_minTime = fileInfo->GetTime();
}
if (fileInfo->GetTime() > m_maxTime)
{
m_maxTime = fileInfo->GetTime();
}
}
}
}
MessageList* NzbInfo::LockCachedMessages()
{
m_logMutex.Lock();
return &m_messages;
}
void NzbInfo::UnlockCachedMessages()
{
m_logMutex.Unlock();
}
void NzbInfo::AddMessage(Message::EKind kind, const char * text)
{
switch (kind)
{
case Message::mkDetail:
detail("%s", text);
break;
case Message::mkInfo:
info("%s", text);
break;
case Message::mkWarning:
warn("%s", text);
break;
case Message::mkError:
error("%s", text);
break;
case Message::mkDebug:
debug("%s", text);
break;
}
m_logMutex.Lock();
m_messages.emplace_back(++m_idMessageGen, kind, Util::CurrentTime(), text);
if (g_Options->GetSaveQueue() && g_Options->GetServerMode() && g_Options->GetNzbLog())
{
g_DiskState->AppendNzbMessage(m_id, kind, text);
m_messageCount++;
}
while (m_messages.size() > (uint32)g_Options->GetLogBufferSize())
{
m_messages.pop_front();
}
m_cachedMessageCount = m_messages.size();
m_logMutex.Unlock();
}
void NzbInfo::PrintMessage(Message::EKind kind, const char* format, ...)
{
char tmp2[1024];
va_list ap;
va_start(ap, format);
vsnprintf(tmp2, 1024, format, ap);
tmp2[1024-1] = '\0';
va_end(ap);
AddMessage(kind, tmp2);
}
void NzbInfo::ClearMessages()
{
m_logMutex.Lock();
m_messages.clear();
m_cachedMessageCount = 0;
m_logMutex.Unlock();
}
void NzbInfo::CopyFileList(NzbInfo* srcNzbInfo)
{
m_fileList.Clear();
for (FileInfo* fileInfo : srcNzbInfo->GetFileList())
{
fileInfo->SetNzbInfo(this);
m_fileList.push_back(fileInfo);
}
srcNzbInfo->GetFileList()->clear(); // only remove references
SetFullContentHash(srcNzbInfo->GetFullContentHash());
SetFilteredContentHash(srcNzbInfo->GetFilteredContentHash());
SetFileCount(srcNzbInfo->GetFileCount());
SetPausedFileCount(srcNzbInfo->GetPausedFileCount());
SetRemainingParCount(srcNzbInfo->GetRemainingParCount());
SetSize(srcNzbInfo->GetSize());
SetRemainingSize(srcNzbInfo->GetRemainingSize());
SetPausedSize(srcNzbInfo->GetPausedSize());
SetSuccessSize(srcNzbInfo->GetSuccessSize());
SetCurrentSuccessSize(srcNzbInfo->GetCurrentSuccessSize());
SetFailedSize(srcNzbInfo->GetFailedSize());
SetCurrentFailedSize(srcNzbInfo->GetCurrentFailedSize());
SetParSize(srcNzbInfo->GetParSize());
SetParSuccessSize(srcNzbInfo->GetParSuccessSize());
SetParCurrentSuccessSize(srcNzbInfo->GetParCurrentSuccessSize());
SetParFailedSize(srcNzbInfo->GetParFailedSize());
SetParCurrentFailedSize(srcNzbInfo->GetParCurrentFailedSize());
SetTotalArticles(srcNzbInfo->GetTotalArticles());
SetSuccessArticles(srcNzbInfo->GetSuccessArticles());
SetFailedArticles(srcNzbInfo->GetFailedArticles());
SetCurrentSuccessArticles(srcNzbInfo->GetSuccessArticles());
SetCurrentFailedArticles(srcNzbInfo->GetFailedArticles());
SetMinTime(srcNzbInfo->GetMinTime());
SetMaxTime(srcNzbInfo->GetMaxTime());
}
void NzbInfo::EnterPostProcess()
{
m_postInfo = new PostInfo();
m_postInfo->SetNzbInfo(this);
}
void NzbInfo::LeavePostProcess()
{
delete m_postInfo;
m_postInfo = nullptr;
ClearMessages();
}
void NzbInfo::SetActiveDownloads(int activeDownloads)
{
if (((m_activeDownloads == 0 && activeDownloads > 0) ||
(m_activeDownloads > 0 && activeDownloads == 0)) &&
m_kind == NzbInfo::nkNzb)
{
if (activeDownloads > 0)
{
m_downloadStartTime = Util::CurrentTime();
}
else
{
m_downloadSec += Util::CurrentTime() - m_downloadStartTime;
m_downloadStartTime = 0;
}
}
m_activeDownloads = activeDownloads;
}
bool NzbInfo::IsDupeSuccess()
{
bool failure =
m_markStatus != NzbInfo::ksSuccess &&
m_markStatus != NzbInfo::ksGood &&
(m_deleteStatus != NzbInfo::dsNone ||
m_markStatus == NzbInfo::ksBad ||
m_parStatus == NzbInfo::psFailure ||
m_unpackStatus == NzbInfo::usFailure ||
m_unpackStatus == NzbInfo::usPassword ||
(m_parStatus == NzbInfo::psSkipped &&
m_unpackStatus == NzbInfo::usSkipped &&
CalcHealth() < CalcCriticalHealth(true)));
return !failure;
}
const char* NzbInfo::MakeTextStatus(bool ignoreScriptStatus)
{
const char* status = "FAILURE/INTERNAL_ERROR";
if (m_kind == NzbInfo::nkNzb)
{
int health = CalcHealth();
int criticalHealth = CalcCriticalHealth(false);
ScriptStatus::EStatus scriptStatus = ignoreScriptStatus ? ScriptStatus::srSuccess : m_scriptStatuses.CalcTotalStatus();
if (m_markStatus == NzbInfo::ksBad)
{
status = "FAILURE/BAD";
}
else if (m_markStatus == NzbInfo::ksGood)
{
status = "SUCCESS/GOOD";
}
else if (m_markStatus == NzbInfo::ksSuccess)
{
status = "SUCCESS/MARK";
}
else if (m_deleteStatus == NzbInfo::dsHealth)
{
status = "FAILURE/HEALTH";
}
else if (m_deleteStatus == NzbInfo::dsManual)
{
status = "DELETED/MANUAL";
}
else if (m_deleteStatus == NzbInfo::dsDupe)
{
status = "DELETED/DUPE";
}
else if (m_deleteStatus == NzbInfo::dsBad)
{
status = "FAILURE/BAD";
}
else if (m_deleteStatus == NzbInfo::dsGood)
{
status = "DELETED/GOOD";
}
else if (m_deleteStatus == NzbInfo::dsCopy)
{
status = "DELETED/COPY";
}
else if (m_deleteStatus == NzbInfo::dsScan)
{
status = "FAILURE/SCAN";
}
else if (m_parStatus == NzbInfo::psFailure)
{
status = "FAILURE/PAR";
}
else if (m_unpackStatus == NzbInfo::usFailure)
{
status = "FAILURE/UNPACK";
}
else if (m_moveStatus == NzbInfo::msFailure)
{
status = "FAILURE/MOVE";
}
else if (m_parStatus == NzbInfo::psManual)
{
status = "WARNING/DAMAGED";
}
else if (m_parStatus == NzbInfo::psRepairPossible)
{
status = "WARNING/REPAIRABLE";
}
else if ((m_parStatus == NzbInfo::psNone || m_parStatus == NzbInfo::psSkipped) &&
(m_unpackStatus == NzbInfo::usNone || m_unpackStatus == NzbInfo::usSkipped) &&
health < criticalHealth)
{
status = "FAILURE/HEALTH";
}
else if ((m_parStatus == NzbInfo::psNone || m_parStatus == NzbInfo::psSkipped) &&
(m_unpackStatus == NzbInfo::usNone || m_unpackStatus == NzbInfo::usSkipped) &&
health < 1000 && health >= criticalHealth)
{
status = "WARNING/HEALTH";
}
else if ((m_parStatus == NzbInfo::psNone || m_parStatus == NzbInfo::psSkipped) &&
(m_unpackStatus == NzbInfo::usNone || m_unpackStatus == NzbInfo::usSkipped) &&
scriptStatus != ScriptStatus::srFailure && health == 1000)
{
status = "SUCCESS/HEALTH";
}
else if (m_unpackStatus == NzbInfo::usSpace)
{
status = "WARNING/SPACE";
}
else if (m_unpackStatus == NzbInfo::usPassword)
{
status = "WARNING/PASSWORD";
}
else if ((m_unpackStatus == NzbInfo::usSuccess ||
((m_unpackStatus == NzbInfo::usNone || m_unpackStatus == NzbInfo::usSkipped) &&
m_parStatus == NzbInfo::psSuccess)) &&
scriptStatus == ScriptStatus::srSuccess)
{
status = "SUCCESS/ALL";
}
else if (m_unpackStatus == NzbInfo::usSuccess && scriptStatus == ScriptStatus::srNone)
{
status = "SUCCESS/UNPACK";
}
else if (m_parStatus == NzbInfo::psSuccess && scriptStatus == ScriptStatus::srNone)
{
status = "SUCCESS/PAR";
}
else if (scriptStatus == ScriptStatus::srFailure)
{
status = "WARNING/SCRIPT";
}
}
else if (m_kind == NzbInfo::nkUrl)
{
if (m_deleteStatus == NzbInfo::dsManual)
{
status = "DELETED/MANUAL";
}
else if (m_deleteStatus == NzbInfo::dsDupe)
{
status = "DELETED/DUPE";
}
else
{
const char* urlStatusName[] = { "FAILURE/INTERNAL_ERROR", "FAILURE/INTERNAL_ERROR", "FAILURE/INTERNAL_ERROR",
"FAILURE/FETCH", "FAILURE/INTERNAL_ERROR", "WARNING/SKIPPED", "FAILURE/SCAN" };
status = urlStatusName[m_urlStatus];
}
}
return status;
}
NzbList::~NzbList()
{
if (m_ownObjects)
{
Clear();
}
}
void NzbList::Clear()
{
for (NzbInfo* nzbInfo : this)
{
delete nzbInfo;
}
clear();
}
void NzbList::Add(NzbInfo* nzbInfo, bool addTop)
{
if (addTop)
{
push_front(nzbInfo);
}
else
{
push_back(nzbInfo);
}
}
void NzbList::Remove(NzbInfo* nzbInfo)
{
iterator it = std::find(begin(), end(), nzbInfo);
if (it != end())
{
erase(it);
}
}
NzbInfo* NzbList::Find(int id)
{
for (NzbInfo* nzbInfo : this)
{
if (nzbInfo->GetId() == id)
{
return nzbInfo;
}
}
return nullptr;
}
void ArticleInfo::AttachSegment(std::unique_ptr<SegmentData> content, int64 offset, int size)
{
m_segmentContent = std::move(content);
m_segmentOffset = offset;
m_segmentSize = size;
}
void ArticleInfo::DiscardSegment()
{
m_segmentContent.reset();
}
FileInfo::~ FileInfo()
{
debug("Destroying FileInfo");
delete m_mutexOutputFile;
ClearArticles();
}
void FileInfo::ClearArticles()
{
for (ArticleInfo* articleInfo : m_articles)
{
delete articleInfo;
}
m_articles.clear();
}
void FileInfo::SetId(int id)
{
m_id = id;
if (m_idMax < m_id)
{
m_idMax = m_id;
}
}
void FileInfo::ResetGenId(bool max)
{
if (max)
{
m_idGen = m_idMax;
}
else
{
m_idGen = 0;
m_idMax = 0;
}
}
void FileInfo::SetPaused(bool paused)
{
if (m_paused != paused && m_nzbInfo)
{
m_nzbInfo->SetPausedFileCount(m_nzbInfo->GetPausedFileCount() + (paused ? 1 : -1));
m_nzbInfo->SetPausedSize(m_nzbInfo->GetPausedSize() + (paused ? m_remainingSize : - m_remainingSize));
}
m_paused = paused;
}
void FileInfo::MakeValidFilename()
{
FileSystem::MakeValidFilename(m_filename, '_', false);
}
void FileInfo::LockOutputFile()
{
m_mutexOutputFile->Lock();
}
void FileInfo::UnlockOutputFile()
{
m_mutexOutputFile->Unlock();
}
void FileInfo::SetActiveDownloads(int activeDownloads)
{
m_activeDownloads = activeDownloads;
if (m_activeDownloads > 0 && !m_mutexOutputFile)
{
m_mutexOutputFile = new Mutex();
}
else if (m_activeDownloads == 0 && m_mutexOutputFile)
{
delete m_mutexOutputFile;
m_mutexOutputFile = nullptr;
}
}
FileList::~FileList()
{
if (m_ownObjects)
{
Clear();
}
}
void FileList::Clear()
{
for (FileInfo* fileInfo : this)
{
delete fileInfo;
}
clear();
}
void FileList::Remove(FileInfo* fileInfo)
{
erase(std::find(begin(), end(), fileInfo));
}
CompletedFile::CompletedFile(int id, const char* fileName, EStatus status, uint32 crc) :
m_id(id), m_fileName(fileName), m_status(status), m_crc(crc)
{
if (FileInfo::m_idMax < m_id)
{
FileInfo::m_idMax = m_id;
}
}
void DupInfo::SetId(int id)
{
m_id = id;
if (NzbInfo::m_idMax < m_id)
{
NzbInfo::m_idMax = m_id;
}
}
HistoryInfo::~HistoryInfo()
{
if ((m_kind == hkNzb || m_kind == hkUrl) && m_info)
{
delete (NzbInfo*)m_info;
}
else if (m_kind == hkDup && m_info)
{
delete (DupInfo*)m_info;
}
}
int HistoryInfo::GetId()
{
if ((m_kind == hkNzb || m_kind == hkUrl))
{
return ((NzbInfo*)m_info)->GetId();
}
else // if (m_eKind == hkDup)
{
return ((DupInfo*)m_info)->GetId();
}
}
const char* HistoryInfo::GetName()
{
if (m_kind == hkNzb || m_kind == hkUrl)
{
return GetNzbInfo()->GetName();
}
else if (m_kind == hkDup)
{
return GetDupInfo()->GetName();
}
else
{
return "<unknown>";
}
}
HistoryList::~HistoryList()
{
for (HistoryInfo* historyInfo : this)
{
delete historyInfo;
}
}
HistoryInfo* HistoryList::Find(int id)
{
for (HistoryInfo* historyInfo : this)
{
if (historyInfo->GetId() == id)
{
return historyInfo;
}
}
return nullptr;
}
DownloadQueue* DownloadQueue::Lock()
{
g_DownloadQueue->m_lockMutex.Lock();
return g_DownloadQueue;
}
void DownloadQueue::Unlock()
{
g_DownloadQueue->m_lockMutex.Unlock();
}
void DownloadQueue::CalcRemainingSize(int64* remaining, int64* remainingForced)
{
int64 remainingSize = 0;
int64 remainingForcedSize = 0;
for (NzbInfo* nzbInfo : m_queue)
{
for (FileInfo* fileInfo : nzbInfo->GetFileList())
{
if (!fileInfo->GetPaused() && !fileInfo->GetDeleted())
{
remainingSize += fileInfo->GetRemainingSize();
if (nzbInfo->GetForcePriority())
{
remainingForcedSize += fileInfo->GetRemainingSize();
}
}
}
}
*remaining = remainingSize;
if (remainingForced)
{
*remainingForced = remainingForcedSize;
}
}