📄 uploadmanager.cpp
字号:
/*
* Copyright (C) 2001-2006 Jacek Sieka, arnetheduck on gmail point com
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "stdinc.h"
#include "DCPlusPlus.h"
#include "UploadManager.h"
#include "ConnectionManager.h"
#include "LogManager.h"
#include "ShareManager.h"
#include "ClientManager.h"
#include "FilteredFile.h"
#include "ZUtils.h"
#include "ResourceManager.h"
#include "HashManager.h"
#include "AdcCommand.h"
#include "FavoriteManager.h"
#include <functional>
static const string UPLOAD_AREA = "Uploads";
UploadManager::UploadManager() throw() : running(0), extra(0), lastGrant(0) {
ClientManager::getInstance()->addListener(this);
TimerManager::getInstance()->addListener(this);
}
UploadManager::~UploadManager() throw() {
TimerManager::getInstance()->removeListener(this);
ClientManager::getInstance()->removeListener(this);
while(true) {
{
Lock l(cs);
if(uploads.empty())
break;
}
Thread::sleep(100);
}
}
bool UploadManager::prepareFile(UserConnection* aSource, const string& aType, const string& aFile, int64_t aStartPos, int64_t aBytes, bool listRecursive) {
if(aSource->getState() != UserConnection::STATE_GET) {
dcdebug("UM:prepFile Wrong state, ignoring\n");
return false;
}
dcassert(aFile.size() > 0);
InputStream* is = NULL;
int64_t size = 0;
bool userlist = false;
bool free = false;
bool leaves = false;
bool partList = false;
string file;
try {
if(aType == "file") {
file = ShareManager::getInstance()->translateFileName(aFile);
userlist = (aFile == "files.xml.bz2");
try {
File* f = new File(file, File::READ, File::OPEN);
size = f->getSize();
free = userlist || (size <= (int64_t)(SETTING(SET_MINISLOT_SIZE) * 1024) );
if(aBytes == -1) {
aBytes = size - aStartPos;
}
if((aBytes < 0) || ((aStartPos + aBytes) > size)) {
aSource->fileNotAvail();
delete f;
return false;
}
f->setPos(aStartPos);
is = f;
if((aStartPos + aBytes) < size) {
is = new LimitedInputStream<true>(is, aBytes);
}
} catch(const Exception&) {
aSource->fileNotAvail();
return false;
}
} else if(aType == "tthl") {
// TTH Leaves...
MemoryInputStream* mis = ShareManager::getInstance()->getTree(aFile);
file = ShareManager::getInstance()->translateFileName(aFile);
if(mis == NULL) {
aSource->fileNotAvail();
return false;
}
size = mis->getSize();
aStartPos = 0;
is = mis;
leaves = true;
free = true;
} else if(aType == "list") {
// Partial file list
MemoryInputStream* mis = ShareManager::getInstance()->generatePartialList(aFile, listRecursive);
if(mis == NULL) {
aSource->fileNotAvail();
return false;
}
// Some old dc++ clients err here...
aBytes = -1;
size = mis->getSize();
aStartPos = 0;
is = mis;
free = true;
partList = true;
} else {
aSource->fileNotAvail();
return false;
}
} catch(const ShareException& e) {
aSource->fileNotAvail(e.getError());
return false;
}
Lock l(cs);
bool extraSlot = false;
if(!aSource->isSet(UserConnection::FLAG_HASSLOT)) {
bool hasReserved = (reservedSlots.find(aSource->getUser()) != reservedSlots.end());
bool isFavorite = FavoriteManager::getInstance()->hasSlot(aSource->getUser());
if(!(hasReserved || isFavorite || getFreeSlots() > 0 || getAutoSlot())) {
bool supportsFree = aSource->isSet(UserConnection::FLAG_SUPPORTS_MINISLOTS) || !aSource->isSet(UserConnection::FLAG_NMDC);
bool allowedFree = aSource->isSet(UserConnection::FLAG_HASEXTRASLOT) || aSource->isSet(UserConnection::FLAG_OP) || getFreeExtraSlots() > 0;
if(free && supportsFree && allowedFree) {
extraSlot = true;
} else {
delete is;
aSource->maxedOut();
// Check for tth root identifier
string tFile = aFile;
if (tFile.compare(0, 4, "TTH/") == 0)
tFile = ShareManager::getInstance()->translateTTH(aFile.substr(4));
addFailedUpload(aSource, tFile +
" (" + Util::toString((aStartPos*1000/(File::getSize(file)+10))/10.0)+"% of " + Util::formatBytes(File::getSize(file)) + " done)");
aSource->disconnect();
return false;
}
} else {
clearUserFiles(aSource->getUser()); // this user is using a full slot, nix them.
}
setLastGrant(GET_TICK());
}
Upload* u = new Upload();
u->setUserConnection(aSource);
u->setFile(is);
if(aBytes == -1)
u->setSize(size);
else
u->setSize(aStartPos + aBytes);
u->setStartPos(aStartPos);
u->setFileName(file);
u->setLocalFileName(file);
if(userlist)
u->setFlag(Upload::FLAG_USER_LIST);
if(leaves)
u->setFlag(Upload::FLAG_TTH_LEAVES);
if(partList)
u->setFlag(Upload::FLAG_PARTIAL_LIST);
dcassert(aSource->getUpload() == NULL);
aSource->setUpload(u);
uploads.push_back(u);
if(!aSource->isSet(UserConnection::FLAG_HASSLOT)) {
if(extraSlot) {
if(!aSource->isSet(UserConnection::FLAG_HASEXTRASLOT)) {
aSource->setFlag(UserConnection::FLAG_HASEXTRASLOT);
extra++;
}
} else {
if(aSource->isSet(UserConnection::FLAG_HASEXTRASLOT)) {
aSource->unsetFlag(UserConnection::FLAG_HASEXTRASLOT);
extra--;
}
aSource->setFlag(UserConnection::FLAG_HASSLOT);
running++;
}
reservedSlots.erase(aSource->getUser());
}
return true;
}
void UploadManager::removeUpload(Upload* aUpload) {
Lock l(cs);
dcassert(find(uploads.begin(), uploads.end(), aUpload) != uploads.end());
uploads.erase(find(uploads.begin(), uploads.end(), aUpload));
aUpload->setUserConnection(NULL);
delete aUpload;
}
void UploadManager::reserveSlot(const User::Ptr& aUser) {
{
Lock l(cs);
reservedSlots.insert(aUser);
}
if(aUser->isOnline())
ClientManager::getInstance()->connect(aUser);
}
void UploadManager::on(UserConnectionListener::Get, UserConnection* aSource, const string& aFile, int64_t aResume) throw() {
if(prepareFile(aSource, "file", Util::toAdcFile(aFile), aResume, -1)) {
aSource->setState(UserConnection::STATE_SEND);
aSource->fileLength(Util::toString(aSource->getUpload()->getSize()));
}
}
void UploadManager::onGetBlock(UserConnection* aSource, const string& aFile, int64_t aStartPos, int64_t aBytes, bool z) {
if(!z || BOOLSETTING(COMPRESS_TRANSFERS)) {
if(prepareFile(aSource, "file", Util::toAdcFile(aFile), aStartPos, aBytes)) {
Upload* u = aSource->getUpload();
dcassert(u != NULL);
if(aBytes == -1)
aBytes = u->getSize() - aStartPos;
dcassert(aBytes >= 0);
u->setStart(GET_TICK());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -