← Back to team overview

linuxdcpp-team team mailing list archive

[Branch ~dcplusplus-team/dcplusplus/trunk] Rev 3017: Add QP support along with fixing L#305811 and some compiler warnings

 

------------------------------------------------------------
revno: 3017
committer: iceman50 <bdcdevel@xxxxxxxxx>
branch nick: dcplusplus
timestamp: Wed 2012-08-01 19:25:23 -0500
message:
  Add QP support along with fixing L#305811 and some compiler warnings
modified:
  dcpp/ConnectionManager.cpp
  dcpp/StringMatch.cpp
  dcpp/UploadManager.cpp
  dcpp/UploadManager.h
  dcpp/UserConnection.cpp
  dcpp/UserConnection.h
  dcpp/UserConnectionListener.h
  dcpp/UserMatch.cpp
  dwt/src/widgets/TabView.cpp


--
lp:dcplusplus
https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk

Your team Dcplusplus-team is subscribed to branch lp:dcplusplus.
To unsubscribe from this branch go to https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk/+edit-subscription
=== modified file 'dcpp/ConnectionManager.cpp'
--- dcpp/ConnectionManager.cpp	2012-06-21 18:52:47 +0000
+++ dcpp/ConnectionManager.cpp	2012-08-02 00:25:23 +0000
@@ -682,6 +682,7 @@
 		/** @todo check tokens for upload connections */
 	}
 
+	aSource->setToken(token);
 	if(down) {
 		aSource->setFlag(UserConnection::FLAG_DOWNLOAD);
 		addDownloadConnection(aSource);

=== modified file 'dcpp/StringMatch.cpp'
--- dcpp/StringMatch.cpp	2012-03-03 19:33:45 +0000
+++ dcpp/StringMatch.cpp	2012-08-02 00:25:23 +0000
@@ -34,6 +34,7 @@
 	case PARTIAL: search = StringSearch::List(); break;
 	case EXACT: search = string(); break;
 	case REGEX: search = boost::regex(); break;
+	case METHOD_LAST: break;
 	}
 }
 

=== modified file 'dcpp/UploadManager.cpp'
--- dcpp/UploadManager.cpp	2012-06-21 18:52:47 +0000
+++ dcpp/UploadManager.cpp	2012-08-02 00:25:23 +0000
@@ -105,22 +105,22 @@
 	if(!aSource.isSet(UserConnection::FLAG_HASSLOT)) {
 		bool hasReserved = hasReservedSlot(aSource.getUser());
 		bool isFavorite = FavoriteManager::getInstance()->hasSlot(aSource.getUser());
+		bool hasFreeSlot = (getFreeSlots() > 0) && ((waitingFiles.empty() && connectingUsers.empty()) || isConnecting(aSource.getUser()));
 
-		if(!(hasReserved || isFavorite || getFreeSlots() > 0 || getAutoSlot())) {
+		if(!(hasReserved || isFavorite || getAutoSlot() || hasFreeSlot)) {
 			bool supportsMini = aSource.isSet(UserConnection::FLAG_SUPPORTS_MINISLOTS);
 			bool allowedMini = aSource.isSet(UserConnection::FLAG_HASEXTRASLOT) || aSource.isSet(UserConnection::FLAG_OP) || getFreeExtraSlots() > 0;
 			if(miniSlot && supportsMini && allowedMini) {
 				extraSlot = true;
 			} else {
-				aSource.maxedOut();
 
 				// Check for tth root identifier
 				string tFile = aFile;
 				if (tFile.compare(0, 4, "TTH/") == 0)
 					tFile = ShareManager::getInstance()->toVirtual(TTHValue(aFile.substr(4)));
 
-				addFailedUpload(aSource, tFile +
-					" (" +  Util::formatBytes(aStartPos) + " - " + Util::formatBytes(aStartPos + aBytes) + ")");
+				aSource.maxedOut(addFailedUpload(aSource, tFile +
+					" (" +  Util::formatBytes(aStartPos) + " - " + Util::formatBytes(aStartPos + aBytes) + ")"));
 				aSource.disconnect();
 				return false;
 			}
@@ -199,6 +199,7 @@
 				is = mis;
 				break;
 			}
+		case Transfer::TYPE_LAST: break;
 		}
 
 	} catch(const ShareException& e) {
@@ -243,6 +244,12 @@
 
 		if(gotFullSlot) {
 			clearUserFiles(aSource.getUser());	// this user is using a full slot, nix them.
+
+			// remove user from connecting list
+			auto cu = connectingUsers.find(aSource.getUser());
+			if(cu != connectingUsers.end()) {
+				connectingUsers.erase(cu);
+			}
 		}
 	}
 
@@ -281,8 +288,12 @@
 		Lock l(cs);
 		reservedSlots.insert(aUser);
 	}
-	if(aUser.user->isOnline())
-		ClientManager::getInstance()->connect(aUser, Util::toString(Util::rand()));
+	if(aUser.user->isOnline()) {
+		 auto it = find_if(waitingUsers.cbegin(), waitingUsers.cend(), [&](const UserPtr& u) { return u == aUser.user; });
+		 if(it != waitingUsers.cend()) {
+			ClientManager::getInstance()->connect(aUser, it->token);
+		}
+	}
 }
 
 bool UploadManager::hasReservedSlot(const UserPtr& user) const {
@@ -392,30 +403,29 @@
 	removeUpload(u);
 }
 
-void UploadManager::addFailedUpload(const UserConnection& source, string filename) {
+size_t UploadManager::addFailedUpload(const UserConnection& source, string filename) {
+	size_t queue_position = 0;
 	{
 		Lock l(cs);
-		auto it = find_if(waitingUsers.begin(), waitingUsers.end(), CompareFirst<UserPtr, uint32_t>(source.getUser()));
+		auto it = find_if(waitingUsers.begin(), waitingUsers.end(), [&](const UserPtr& u) -> bool { ++queue_position; return u == source.getUser(); });
 		if (it==waitingUsers.end()) {
-			waitingUsers.emplace_back(source.getHintedUser(), GET_TICK());
-		} else {
-			it->second = GET_TICK();
+			waitingUsers.emplace_back(source.getHintedUser(), source.getToken());
 		}
 		waitingFiles[source.getUser()].insert(filename);		//files for which user's asked
 	}
-
 	fire(UploadManagerListener::WaitingAddFile(), source.getHintedUser(), filename);
+	return queue_position;
 }
 
 void UploadManager::clearUserFiles(const UserPtr& source) {
 	Lock l(cs);
 	//run this when a user's got a slot or goes offline.
-	auto sit = find_if(waitingUsers.begin(), waitingUsers.end(), CompareFirst<UserPtr, uint32_t>(source));
+	auto sit = find_if(waitingUsers.begin(), waitingUsers.end(), [&source](const UserPtr& other) { return other == source; });
 	if (sit == waitingUsers.end()) return;
 
-	auto fit = waitingFiles.find(sit->first);
+	auto fit = waitingFiles.find(sit->user);
 	if (fit != waitingFiles.end()) waitingFiles.erase(fit);
-	fire(UploadManagerListener::WaitingRemoveUser(), sit->first);
+	fire(UploadManagerListener::WaitingRemoveUser(), sit->user);
 
 	waitingUsers.erase(sit);
 }
@@ -424,7 +434,7 @@
 	Lock l(cs);
 	HintedUserList u;
 	for(auto i = waitingUsers.begin(), iend = waitingUsers.end(); i != iend; ++i) {
-		u.push_back(i->first);
+		u.push_back(i->user);
 	}
 	return u;
 }
@@ -462,20 +472,42 @@
 	}
 }
 
-void UploadManager::on(TimerManagerListener::Minute, uint64_t /* aTick */) noexcept {
+void UploadManager::notifyQueuedUsers() {
+	if(waitingUsers.empty()) return;	//no users to notify
+
+	int freeSlots = getFreeSlots();
+	if(freeSlots > 0) {
+		freeSlots -= connectingUsers.size();
+		while(!waitingUsers.empty() && freeSlots > 0) {
+			// let's keep him in the connectingList until he asks for a file
+			WaitingUser queuedUser = waitingUsers.front();
+			auto isOnline = queuedUser.user.user->isOnline();
+			if(isOnline) {
+				clearUserFiles(queuedUser.user);
+				connectingUsers[queuedUser.user] = GET_TICK();
+				ClientManager::getInstance()->connect(queuedUser.user, queuedUser.token);
+				freeSlots--;
+			} else {
+				clearUserFiles(queuedUser.user);
+			}
+		}
+	}
+}
+
+void UploadManager::on(TimerManagerListener::Minute, uint64_t  aTick ) noexcept {
 	UserList disconnects;
 	{
 		Lock l(cs);
 
-		auto i = stable_partition(waitingUsers.begin(), waitingUsers.end(), WaitingUserFresh());
-		for (auto j = i; j != waitingUsers.end(); ++j) {
-			auto fit = waitingFiles.find(j->first);
-			if (fit != waitingFiles.end()) waitingFiles.erase(fit);
-			fire(UploadManagerListener::WaitingRemoveUser(), j->first);
+		for(auto i = connectingUsers.begin(); i != connectingUsers.end();) {
+			if((i->second + (90 * 1000)) < aTick) {
+				clearUserFiles(i->first);
+				connectingUsers.erase(i++);
+			} else {
+				++i;
+			}
 		}
 
-		waitingUsers.erase(i, waitingUsers.end());
-
 		if( SETTING(AUTO_KICK) ) {
 			for(auto u: uploads) {
 				if(u->getUser()->isOnline()) {
@@ -554,6 +586,8 @@
 
 	if(!uploads.empty())
 		fire(UploadManagerListener::Tick(), UploadList(uploads));
+		
+	notifyQueuedUsers();
 }
 
 void UploadManager::on(ClientManagerListener::UserDisconnected, const UserPtr& aUser) noexcept {

=== modified file 'dcpp/UploadManager.h'
--- dcpp/UploadManager.h	2012-05-27 12:53:12 +0000
+++ dcpp/UploadManager.h	2012-08-02 00:25:23 +0000
@@ -34,6 +34,7 @@
 #include "Speaker.h"
 #include "SettingsManager.h"
 #include "HintedUser.h"
+#include "UserConnection.h"
 #include "GetSet.h"
 
 namespace dcpp {
@@ -43,6 +44,15 @@
 using std::set;
 using std::unordered_map;
 
+struct WaitingUser {
+	HintedUser user;
+	string token;
+	
+	WaitingUser(const HintedUser& _user, const std::string& _token) : user(_user), token(_token) { }
+	
+	operator const UserPtr&() const { return user.user; }
+};
+
 class UploadManager : private ClientManagerListener, private UserConnectionListener, public Speaker<UploadManagerListener>, private TimerManagerListener, public Singleton<UploadManager>
 {
 public:
@@ -65,6 +75,7 @@
 
 	/** @param aUser Reserve an upload slot for this user and connect. */
 	void reserveSlot(const HintedUser& aUser);
+	bool isConnecting(const UserPtr& aUser) const { return connectingUsers.find(aUser) != connectingUsers.end(); }
 
 	typedef set<string> FileSet;
 	typedef unordered_map<UserPtr, FileSet, User::Hash> FilesMap;
@@ -87,20 +98,20 @@
 	typedef unordered_set<UserPtr, User::Hash> SlotSet;
 	typedef SlotSet::iterator SlotIter;
 	SlotSet reservedSlots;
+	
+	typedef unordered_map<UserPtr, uint64_t, User::Hash> SlotMap;
+	typedef SlotMap::iterator SlotMapIter;
+	SlotMap connectingUsers;
 
 	int lastFreeSlots; /// amount of free slots at the previous minute
 
-	typedef pair<HintedUser, uint64_t> WaitingUser;
 	typedef list<WaitingUser> WaitingUserList;
 
-	struct WaitingUserFresh {
-		bool operator()(const WaitingUser& wu) { return wu.second > GET_TICK() - 5*60*1000; }
-	};
-
 	//functions for manipulating waitingFiles and waitingUsers
 	WaitingUserList waitingUsers;		//this one merely lists the users waiting for slots
 	FilesMap waitingFiles;		//set of files which this user has asked for
-	void addFailedUpload(const UserConnection& source, string filename);
+	size_t addFailedUpload(const UserConnection& source, string filename);
+	void notifyQueuedUsers();
 
 	friend class Singleton<UploadManager>;
 	UploadManager() noexcept;

=== modified file 'dcpp/UserConnection.cpp'
--- dcpp/UserConnection.cpp	2012-07-20 13:55:11 +0000
+++ dcpp/UserConnection.cpp	2012-08-02 00:25:23 +0000
@@ -127,7 +127,7 @@
 	} else if(cmd == "$Send") {
 		fire(UserConnectionListener::Send(), this);
 	} else if(cmd == "$MaxedOut") {
-		fire(UserConnectionListener::MaxedOut(), this);
+		fire(UserConnectionListener::MaxedOut(), this, param);
 	} else if(cmd == "$Supports") {
 		if(!param.empty()) {
 			fire(UserConnectionListener::Supports(), this, StringTokenizer<string>(param, ' ').getTokens());

=== modified file 'dcpp/UserConnection.h'
--- dcpp/UserConnection.h	2012-07-01 18:41:13 +0000
+++ dcpp/UserConnection.h	2012-08-02 00:25:23 +0000
@@ -110,7 +110,21 @@
 	void fileLength(const string& aLength) { send("$FileLength " + aLength + '|'); }
 	void error(const string& aError) { send("$Error " + aError + '|'); }
 	void listLen(const string& aLength) { send("$ListLen " + aLength + '|'); }
-	void maxedOut() { isSet(FLAG_NMDC) ? send("$MaxedOut|") : send(AdcCommand(AdcCommand::SEV_RECOVERABLE, AdcCommand::ERROR_SLOTS_FULL, "Slots full")); }
+	
+	void maxedOut(size_t queue_position = 0) {
+		bool sendPos = queue_position > 0;
+
+		if(isSet(FLAG_NMDC)) {
+			send("$MaxedOut" + (sendPos ? (" " + Util::toString(queue_position)) : Util::emptyString) + "|");
+		} else {
+			AdcCommand cmd(AdcCommand::SEV_RECOVERABLE, AdcCommand::ERROR_SLOTS_FULL, "Slots full");
+			if(sendPos) {
+				cmd.addParam("QP", Util::toString(queue_position));
+			}
+			send(cmd);
+		}
+	}
+	
 	void fileNotAvail(const std::string& msg = FILE_NOT_AVAILABLE) { isSet(FLAG_NMDC) ? send("$Error " + msg + "|") : send(AdcCommand(AdcCommand::SEV_RECOVERABLE, AdcCommand::ERROR_FILE_NOT_AVAILABLE, msg)); }
 	void supports(const StringList& feat);
 

=== modified file 'dcpp/UserConnectionListener.h'
--- dcpp/UserConnectionListener.h	2012-01-13 20:55:20 +0000
+++ dcpp/UserConnectionListener.h	2012-08-02 00:25:23 +0000
@@ -22,6 +22,7 @@
 #include "forward.h"
 #include "AdcCommand.h"
 #include "noexcept.h"
+#include "Util.h"
 
 namespace dcpp {
 
@@ -60,7 +61,7 @@
 	virtual void on(Get, UserConnection*, const string&, int64_t) noexcept { }
 	virtual void on(Send, UserConnection*) noexcept { }
 	virtual void on(GetListLength, UserConnection*) noexcept { }
-	virtual void on(MaxedOut, UserConnection*) noexcept { }
+	virtual void on(MaxedOut, UserConnection*, string param = Util::emptyString) noexcept { }
 	virtual void on(ModeChange, UserConnection*) noexcept { }
 	virtual void on(MyNick, UserConnection*, const string&) noexcept { }
 	virtual void on(TransmitDone, UserConnection*) noexcept { }

=== modified file 'dcpp/UserMatch.cpp'
--- dcpp/UserMatch.cpp	2012-06-18 15:56:01 +0000
+++ dcpp/UserMatch.cpp	2012-08-02 00:25:23 +0000
@@ -61,6 +61,7 @@
 		case UserMatch::Rule::CID: str = identity.getUser()->getCID().toBase32(); break;
 		case UserMatch::Rule::IP: str = identity.getIp(); break;
 		case UserMatch::Rule::HUB_ADDRESS: str = user.getClient().getHubUrl(); break;
+		case UserMatch::Rule::FIELD_LAST: break;
 		}
 		if(!i.match(str)) {
 			return false;

=== modified file 'dwt/src/widgets/TabView.cpp'
--- dwt/src/widgets/TabView.cpp	2012-03-03 19:33:45 +0000
+++ dwt/src/widgets/TabView.cpp	2012-08-02 00:25:23 +0000
@@ -633,6 +633,11 @@
 	switch(mouseEvent.ButtonPressed) {
 	case MouseEvent::X1: next(true); break;
 	case MouseEvent::X2: next(); break;
+	
+	case MouseEvent::OTHER: break;
+	case MouseEvent::LEFT: break;
+	case MouseEvent::RIGHT: break;
+	case MouseEvent::MIDDLE: break;
 	}
 	return true;
 }