<commit_before>#include "FileTransfer.h"
#include "Torrent.h"
#include "Files.h"
#include "PeerCommunication.h"
#include "Peers.h"
#include "Configuration.h"
#include "utils/ScheduledTimer.h"
#include "utils/FastIpToCountry.h"
#include <fstream>

FastIpToCountry ipToCountry;
bool ipToCountryLoaded = false;

#define TRANSFER_LOG(x) WRITE_LOG("Transfer", x)

mtt::FileTransfer::FileTransfer(TorrentPtr t) : downloader(t), torrent(t)
{
	uploader = std::make_shared<Uploader>(t);
	log.init("download");

	if (!ipToCountryLoaded)
	{
		ipToCountryLoaded = true;
		ipToCountry.fromFile(mtt::config::getInternal().programFolderPath);
	}
}

void mtt::FileTransfer::start()
{
	piecesAvailability.resize(torrent->infoFile.info.pieces.size());
	updatePiecesPriority();
	downloader.reset();

	torrent->peers->start([this](Status s, mtt::PeerSource)
		{
			if (s == Status::Success)
			{
				evaluateCurrentPeers();
			}
		}
	, this);

	refreshTimer = ScheduledTimer::create(torrent->service.io, [this]
		{
			evalCurrentPeers();
			updateMeasures();
			uploader->refreshRequest();

			refreshTimer->schedule(1);
		}
	);

	refreshTimer->schedule(1);
}

void mtt::FileTransfer::stop()
{
	saveLogEvents();

	{
		std::lock_guard<std::mutex> guard(peersMutex);
		activePeers.clear();
	}

	torrent->peers->stop();
	downloader.reset();
	torrent->files.storage.flush();

	if(refreshTimer)
		refreshTimer->disable();
}

void mtt::FileTransfer::reevaluate()
{
	TRANSFER_LOG("reevaluate");

	std::lock_guard<std::mutex> guard(peersMutex);
	for(auto& p : activePeers)
		downloader.evaluateNextRequests(&p);
}

void mtt::FileTransfer::handshakeFinished(PeerCommunication* p)
{
	TRANSFER_LOG("handshake " << p->getAddressName());
	if (!torrent->files.progress.empty())
		p->sendBitfield(torrent->files.progress.toBitfield());

	addPeer(p);
}

void mtt::FileTransfer::connectionClosed(PeerCommunication* p, int code)
{
	TRANSFER_LOG("closed " << p->getAddressName());
	removePeer(p);
}

void mtt::FileTransfer::messageReceived(PeerCommunication* p, PeerMessage& msg)
{
	TRANSFER_LOG("msg " << msg.id << " " << p->getAddressName());

	if (msg.id == Piece)
	{
		auto status = downloader.pieceBlockReceived(msg.piece);

		std::lock_guard<std::mutex> guard(peersMutex);
		downloader.removeBlockRequests(activePeers, msg.piece, status, p);

		if (auto peer = getActivePeer(p))
		{
			peer->lastActivityTime = (uint32_t)time(0);
		}
	}
	else if (msg.id == Unchoke)
	{
		std::lock_guard<std::mutex> guard(peersMutex);
		if (auto peer = getActivePeer(p))
		{
			downloader.unchokePeer(peer);
			peer->lastActivityTime = (uint32_t)time(0);
		}
	}
	else if (msg.id == Interested)
	{
		uploader->isInterested(p);
	}
	else if (msg.id == Request)
	{
		uploader->pieceRequest(p, msg.request);
	}
}

void mtt::FileTransfer::extHandshakeFinished(PeerCommunication*)
{
}

void mtt::FileTransfer::metadataPieceReceived(PeerCommunication*, ext::UtMetadata::Message&)
{
}

void mtt::FileTransfer::pexReceived(PeerCommunication*, ext::PeerExchange::Message&)
{
}

void mtt::FileTransfer::progressUpdated(PeerCommunication* p, uint32_t idx)
{
	if (idx != -1)
		piecesAvailability[idx]++;
	else
	{
		auto& peerPieces = p->info.pieces.pieces;

		for(size_t i = 0; i < piecesAvailability.size(); i++)
		{
			piecesAvailability[i] += peerPieces[i] ? 1 : 0;
		}
	}

	if(!torrent->selectionFinished())
		evaluateNextRequests(p);
}

uint64_t mtt::FileTransfer::getUploadSum()
{
	return uploader->uploaded;
}

uint32_t mtt::FileTransfer::getDownloadSpeed()
{
	uint32_t sum = 0;

	std::lock_guard<std::mutex> guard(peersMutex);
	for (auto& peer : activePeers)
		sum += peer.downloadSpeed;

	return sum;
}

uint32_t mtt::FileTransfer::getUploadSpeed()
{
	uint32_t sum = 0;

	std::lock_guard<std::mutex> guard(peersMutex);
	for (auto& peer : activePeers)
		sum += peer.uploadSpeed;

	return sum;
}

size_t mtt::FileTransfer::getUnfinishedPiecesDownloadSize()
{
	return downloader.getUnfinishedPiecesDownloadSize();
}

std::vector<mtt::ActivePeerInfo> mtt::FileTransfer::getPeersInfo()
{
	auto allPeers = torrent->peers->getActivePeers();

	std::vector<mtt::ActivePeerInfo> out;
	out.resize(allPeers.size());

	std::lock_guard<std::mutex> guard(peersMutex);

	uint32_t i = 0;
	for (auto& comm : allPeers)
	{
		auto addr = comm->getAddress();
		out[i].address = addr.toString();
		out[i].country = addr.ipv6 ? "" : ipToCountry.GetCountry(_byteswap_ulong(*reinterpret_cast<uint32_t*>(addr.addrBytes)));
		out[i].percentage = comm->info.pieces.getPercentage();
		out[i].client = comm->ext.state.client;

		for (auto& active : activePeers)
		{
			if (active.comm == comm.get())
			{
				out[i].downloadSpeed = active.downloadSpeed;
				out[i].uploadSpeed = active.uploadSpeed;
				break;
			}
		}

		i++;
	}

	return out;
}

std::vector<uint32_t> mtt::FileTransfer::getCurrentRequests()
{
	return downloader.getCurrentRequests();
}

uint32_t mtt::FileTransfer::getCurrentRequestsCount()
{
	return downloader.getCurrentRequestsCount();
}

void mtt::FileTransfer::updatePiecesPriority()
{
	piecesPriority.resize(torrent->infoFile.info.pieces.size(), Priority(0));

	for (auto& f : torrent->files.selection.files)
	{
		for (size_t i = f.info.startPieceIndex; i < f.info.endPieceIndex; i++)
		{
			piecesPriority[i] = std::max(piecesPriority[i], f.priority);
		}
	}
}

mtt::ActivePeer* mtt::FileTransfer::getActivePeer(PeerCommunication* p)
{
	for (auto& peer : activePeers)
		if (peer.comm == p)
			return &peer;

	return nullptr;
}

void mtt::FileTransfer::addPeer(PeerCommunication* p)
{
	std::lock_guard<std::mutex> guard(peersMutex);
	bool found = false;
	for (auto& peer : activePeers)
	{
		if (peer.comm == p)
		{
			found = true;
			break;
		}
	}

	if (!found)
	{
		activePeers.push_back({ p,{} });
		activePeers.back().connectionTime = activePeers.back().lastActivityTime = (uint32_t)time(0);
		downloader.evaluateNextRequests(&activePeers.back());
	}
}

void mtt::FileTransfer::evaluateNextRequests(PeerCommunication* p)
{
	std::lock_guard<std::mutex> guard(peersMutex);
	if (auto peer = getActivePeer(p))
		downloader.evaluateNextRequests(peer);
}

void mtt::FileTransfer::removePeer(PeerCommunication * p)
{
	{
		std::lock_guard<std::mutex> guard(peersMutex);

		for (auto it = activePeers.begin(); it != activePeers.end(); it++)
		{
			if (it->comm == p)
			{
				activePeers.erase(it);
				break;
			}
		}
	}

	evaluateCurrentPeers();
}

void mtt::FileTransfer::removePeers(std::vector<uint32_t> sortedIdx)
{
	for (auto it = sortedIdx.rbegin(); it != sortedIdx.rend(); it++)
	{
		TRANSFER_LOG("remove " << (activePeers.begin() + *it)->comm->getAddressName());
		activePeers.erase(activePeers.begin() + *it);
	}
}

void mtt::FileTransfer::evaluateCurrentPeers()
{
	TRANSFER_LOG("evalCurrentPeers?");
	if (activePeers.size() < mtt::config::getExternal().connection.maxTorrentConnections && !torrent->selectionFinished())
		torrent->peers->connectNext(10);
}

void mtt::FileTransfer::evalCurrentPeers()
{
	TRANSFER_LOG("evalCurrentPeers");
	const uint32_t peersEvalInterval = 5;

	if (peersEvalCounter-- > 0)
		return;

	peersEvalCounter = peersEvalInterval;

	std::vector<uint32_t> removedPeers;
	{
		std::lock_guard<std::mutex> guard(peersMutex);

		uint32_t currentTime = (uint32_t)::time(0);

#ifdef PEER_DIAGNOSTICS
		std::lock_guard<std::mutex> guardLog(logmtx);
		logEvals.push_back({ clock(), (uint32_t)activePeers.size() });

		size_t logStartIdx = logEvalPeers.size();

		if (activePeers.size())
		{
			logEvalPeers.resize(logEvalPeers.size() + activePeers.size());

			size_t idx = logStartIdx;
			for (auto peer : activePeers)
			{
				logEvalPeers[idx].addr = peer.comm->getAddress();
				logEvalPeers[idx].dl = peer.downloadSpeed;
				logEvalPeers[idx].up = peer.uploadSpeed;
				logEvalPeers[idx].activityTime = currentTime - peer.lastActivityTime;
				idx++;
			}
		}
#endif

		if ((uint32_t)activePeers.size() < mtt::config::getExternal().connection.maxTorrentConnections)
		{
			return;
		}

		const uint32_t minPeersTimeChance = 10;

		auto minTimeToEval = currentTime - minPeersTimeChance;

		const uint32_t minPeersPiecesTimeChance = 20;
		auto minTimeToReceive = currentTime - minPeersPiecesTimeChance;

		uint32_t slowestSpeed = -1;
		uint32_t slowestPeer = -1;

		uint32_t maxUploads = 5;
		std::vector<uint32_t> currentUploads;

		uint32_t idx = 0;
		for (auto peer : activePeers)
		{
			if (peer.connectionTime > minTimeToEval)
			{
#ifdef PEER_DIAGNOSTICS
				logEvalPeers[logStartIdx + idx].action = LogEvalPeer::TooSoon;
#endif
				continue;
			}

			if (peer.comm->state.peerInterested)
			{
				currentUploads.push_back(idx);
			}

			if (peer.lastActivityTime < minTimeToReceive)
			{
#ifdef PEER_DIAGNOSTICS
				logEvalPeers[logStartIdx + idx].action = LogEvalPeer::NotResponding;
#endif
				removedPeers.push_back(idx);
				continue;
			}

			if (peer.downloadSpeed < slowestSpeed)
			{
				slowestSpeed = peer.downloadSpeed;
				slowestPeer = idx;
			}

			idx++;
		}

		if (removedPeers.empty() && slowestPeer != -1)
		{
#ifdef PEER_DIAGNOSTICS
			logEvalPeers[logStartIdx + idx].action = LogEvalPeer::TooSlow;
#endif
			removedPeers.push_back(slowestPeer);
		}

		if (!currentUploads.empty())
		{
			std::sort(currentUploads.begin(), currentUploads.end(), [&](const auto & l, const auto & r) { return activePeers[l].uploadSpeed > activePeers[r].uploadSpeed; });
			currentUploads.resize(std::min((uint32_t)currentUploads.size(), maxUploads));

			for (auto idx : currentUploads)
			{
				auto it = std::find(removedPeers.begin(), removedPeers.end(), idx);
				if (it != removedPeers.end())
					removedPeers.erase(it);

#ifdef PEER_DIAGNOSTICS
				logEvalPeers[logStartIdx + idx].action = LogEvalPeer::Upload;
#endif
			}
		}

		removePeers(removedPeers);
	}

	evaluateCurrentPeers();
}

void mtt::FileTransfer::updateMeasures()
{
	auto& freshPieces = torrent->files.freshPieces;
	std::vector<std::pair<PeerCommunication*, std::pair<uint64_t, uint64_t>>> currentMeasure;

	{
		std::lock_guard<std::mutex> guard(peersMutex);

		auto finishedUploadRequests = uploader->popHandledRequests();
		for(auto& r : finishedUploadRequests)
		{
			if (auto peer = getActivePeer(r.first))
				peer->uploaded += r.second;
		}

		for (auto& peer : activePeers)
		{
			peer.downloaded = peer.comm->getReceivedDataCount();
			currentMeasure.push_back({ peer.comm, {peer.downloaded, peer.uploaded} });
			peer.downloadSpeed = 0;
			peer.uploadSpeed = 0;

			for (auto last : lastSpeedMeasure)
			{
				if (last.first == peer.comm)
				{
					if (peer.downloaded > last.second.first)
						peer.downloadSpeed = (uint32_t)(peer.downloaded - last.second.first);
					if (peer.uploaded > last.second.second)
						peer.uploadSpeed = (uint32_t)(peer.uploaded - last.second.second);

					break;
				}
			}

			for (auto& piece : freshPieces)
				if (peer.comm->isEstablished())
					peer.comm->sendHave(piece);
		}
	}
	freshPieces.clear();
	lastSpeedMeasure = currentMeasure;

	if (!torrent->selectionFinished())
	{
		downloader.sortPriorityByAvailability(piecesAvailability);
		downloader.sortPriority(piecesPriority);
	}
}

#ifdef PEER_DIAGNOSTICS
extern std::string FormatLogTime(long);

void mtt::FileTransfer::saveLogEvents()
{
	std::lock_guard<std::mutex> guard(logmtx);

	if (logEvals.empty())
		return;

	std::ofstream file("logs\\" + torrent->name() + "\\downloader.log");

	if (!file)
		return;

	size_t logIndex = 0;

	for (auto& eval : logEvals)
	{
		file << FormatLogTime(eval.time) << ": Count:" << eval.count << "\n";

		for (size_t i = logIndex; i < logIndex + eval.count; i++)
		{
			auto& peerLog = logEvalPeers[i];

			file << peerLog.addr.toString() << " Action:" << (int)peerLog.action << " dl:" << peerLog.dl/1024.f << " up:" << peerLog.up/ 1024.f << " dead:" << peerLog.activityTime << "\n";
		}

		logIndex += eval.count;
	}

	file << "\n\n";
}
#endif<commit_msg>force known peers connect on start<commit_after>#include "FileTransfer.h"
#include "Torrent.h"
#include "Files.h"
#include "PeerCommunication.h"
#include "Peers.h"
#include "Configuration.h"
#include "utils/ScheduledTimer.h"
#include "utils/FastIpToCountry.h"
#include <fstream>

FastIpToCountry ipToCountry;
bool ipToCountryLoaded = false;

#define TRANSFER_LOG(x) WRITE_LOG("Transfer", x)

mtt::FileTransfer::FileTransfer(TorrentPtr t) : downloader(t), torrent(t)
{
	uploader = std::make_shared<Uploader>(t);
	log.init("download");

	if (!ipToCountryLoaded)
	{
		ipToCountryLoaded = true;
		ipToCountry.fromFile(mtt::config::getInternal().programFolderPath);
	}
}

void mtt::FileTransfer::start()
{
	piecesAvailability.resize(torrent->infoFile.info.pieces.size());
	updatePiecesPriority();
	downloader.reset();

	torrent->peers->start([this](Status s, mtt::PeerSource)
		{
			if (s == Status::Success)
			{
				evaluateCurrentPeers();
			}
		}
	, this);

	refreshTimer = ScheduledTimer::create(torrent->service.io, [this]
		{
			evalCurrentPeers();
			updateMeasures();
			uploader->refreshRequest();

			refreshTimer->schedule(1);
		}
	);

	refreshTimer->schedule(1);
	evaluateCurrentPeers();
}

void mtt::FileTransfer::stop()
{
	saveLogEvents();

	{
		std::lock_guard<std::mutex> guard(peersMutex);
		activePeers.clear();
	}

	torrent->peers->stop();
	downloader.reset();
	torrent->files.storage.flush();

	if(refreshTimer)
		refreshTimer->disable();
}

void mtt::FileTransfer::reevaluate()
{
	TRANSFER_LOG("reevaluate");

	std::lock_guard<std::mutex> guard(peersMutex);
	for(auto& p : activePeers)
		downloader.evaluateNextRequests(&p);
}

void mtt::FileTransfer::handshakeFinished(PeerCommunication* p)
{
	TRANSFER_LOG("handshake " << p->getAddressName());
	if (!torrent->files.progress.empty())
		p->sendBitfield(torrent->files.progress.toBitfield());

	addPeer(p);
}

void mtt::FileTransfer::connectionClosed(PeerCommunication* p, int code)
{
	TRANSFER_LOG("closed " << p->getAddressName());
	removePeer(p);
}

void mtt::FileTransfer::messageReceived(PeerCommunication* p, PeerMessage& msg)
{
	TRANSFER_LOG("msg " << msg.id << " " << p->getAddressName());

	if (msg.id == Piece)
	{
		auto status = downloader.pieceBlockReceived(msg.piece);

		std::lock_guard<std::mutex> guard(peersMutex);
		downloader.removeBlockRequests(activePeers, msg.piece, status, p);

		if (auto peer = getActivePeer(p))
		{
			peer->lastActivityTime = (uint32_t)time(0);
		}
	}
	else if (msg.id == Unchoke)
	{
		std::lock_guard<std::mutex> guard(peersMutex);
		if (auto peer = getActivePeer(p))
		{
			downloader.unchokePeer(peer);
			peer->lastActivityTime = (uint32_t)time(0);
		}
	}
	else if (msg.id == Interested)
	{
		uploader->isInterested(p);
	}
	else if (msg.id == Request)
	{
		uploader->pieceRequest(p, msg.request);
	}
}

void mtt::FileTransfer::extHandshakeFinished(PeerCommunication*)
{
}

void mtt::FileTransfer::metadataPieceReceived(PeerCommunication*, ext::UtMetadata::Message&)
{
}

void mtt::FileTransfer::pexReceived(PeerCommunication*, ext::PeerExchange::Message&)
{
}

void mtt::FileTransfer::progressUpdated(PeerCommunication* p, uint32_t idx)
{
	if (idx != -1)
		piecesAvailability[idx]++;
	else
	{
		auto& peerPieces = p->info.pieces.pieces;

		for(size_t i = 0; i < piecesAvailability.size(); i++)
		{
			piecesAvailability[i] += peerPieces[i] ? 1 : 0;
		}
	}

	if(!torrent->selectionFinished())
		evaluateNextRequests(p);
}

uint64_t mtt::FileTransfer::getUploadSum()
{
	return uploader->uploaded;
}

uint32_t mtt::FileTransfer::getDownloadSpeed()
{
	uint32_t sum = 0;

	std::lock_guard<std::mutex> guard(peersMutex);
	for (auto& peer : activePeers)
		sum += peer.downloadSpeed;

	return sum;
}

uint32_t mtt::FileTransfer::getUploadSpeed()
{
	uint32_t sum = 0;

	std::lock_guard<std::mutex> guard(peersMutex);
	for (auto& peer : activePeers)
		sum += peer.uploadSpeed;

	return sum;
}

size_t mtt::FileTransfer::getUnfinishedPiecesDownloadSize()
{
	return downloader.getUnfinishedPiecesDownloadSize();
}

std::vector<mtt::ActivePeerInfo> mtt::FileTransfer::getPeersInfo()
{
	auto allPeers = torrent->peers->getActivePeers();

	std::vector<mtt::ActivePeerInfo> out;
	out.resize(allPeers.size());

	std::lock_guard<std::mutex> guard(peersMutex);

	uint32_t i = 0;
	for (auto& comm : allPeers)
	{
		auto addr = comm->getAddress();
		out[i].address = addr.toString();
		out[i].country = addr.ipv6 ? "" : ipToCountry.GetCountry(_byteswap_ulong(*reinterpret_cast<uint32_t*>(addr.addrBytes)));
		out[i].percentage = comm->info.pieces.getPercentage();
		out[i].client = comm->ext.state.client;

		for (auto& active : activePeers)
		{
			if (active.comm == comm.get())
			{
				out[i].downloadSpeed = active.downloadSpeed;
				out[i].uploadSpeed = active.uploadSpeed;
				break;
			}
		}

		i++;
	}

	return out;
}

std::vector<uint32_t> mtt::FileTransfer::getCurrentRequests()
{
	return downloader.getCurrentRequests();
}

uint32_t mtt::FileTransfer::getCurrentRequestsCount()
{
	return downloader.getCurrentRequestsCount();
}

void mtt::FileTransfer::updatePiecesPriority()
{
	piecesPriority.resize(torrent->infoFile.info.pieces.size(), Priority(0));

	for (auto& f : torrent->files.selection.files)
	{
		for (size_t i = f.info.startPieceIndex; i < f.info.endPieceIndex; i++)
		{
			piecesPriority[i] = std::max(piecesPriority[i], f.priority);
		}
	}
}

mtt::ActivePeer* mtt::FileTransfer::getActivePeer(PeerCommunication* p)
{
	for (auto& peer : activePeers)
		if (peer.comm == p)
			return &peer;

	return nullptr;
}

void mtt::FileTransfer::addPeer(PeerCommunication* p)
{
	std::lock_guard<std::mutex> guard(peersMutex);
	bool found = false;
	for (auto& peer : activePeers)
	{
		if (peer.comm == p)
		{
			found = true;
			break;
		}
	}

	if (!found)
	{
		activePeers.push_back({ p,{} });
		activePeers.back().connectionTime = activePeers.back().lastActivityTime = (uint32_t)time(0);
		downloader.evaluateNextRequests(&activePeers.back());
	}
}

void mtt::FileTransfer::evaluateNextRequests(PeerCommunication* p)
{
	std::lock_guard<std::mutex> guard(peersMutex);
	if (auto peer = getActivePeer(p))
		downloader.evaluateNextRequests(peer);
}

void mtt::FileTransfer::removePeer(PeerCommunication * p)
{
	{
		std::lock_guard<std::mutex> guard(peersMutex);

		for (auto it = activePeers.begin(); it != activePeers.end(); it++)
		{
			if (it->comm == p)
			{
				activePeers.erase(it);
				break;
			}
		}
	}

	evaluateCurrentPeers();
}

void mtt::FileTransfer::removePeers(std::vector<uint32_t> sortedIdx)
{
	for (auto it = sortedIdx.rbegin(); it != sortedIdx.rend(); it++)
	{
		TRANSFER_LOG("remove " << (activePeers.begin() + *it)->comm->getAddressName());
		activePeers.erase(activePeers.begin() + *it);
	}
}

void mtt::FileTransfer::evaluateCurrentPeers()
{
	TRANSFER_LOG("evalCurrentPeers?");
	if (activePeers.size() < mtt::config::getExternal().connection.maxTorrentConnections && !torrent->selectionFinished())
		torrent->peers->connectNext(10);
}

void mtt::FileTransfer::evalCurrentPeers()
{
	TRANSFER_LOG("evalCurrentPeers");
	const uint32_t peersEvalInterval = 5;

	if (peersEvalCounter-- > 0)
		return;

	peersEvalCounter = peersEvalInterval;

	std::vector<uint32_t> removedPeers;
	{
		std::lock_guard<std::mutex> guard(peersMutex);

		uint32_t currentTime = (uint32_t)::time(0);

#ifdef PEER_DIAGNOSTICS
		std::lock_guard<std::mutex> guardLog(logmtx);
		logEvals.push_back({ clock(), (uint32_t)activePeers.size() });

		size_t logStartIdx = logEvalPeers.size();

		if (activePeers.size())
		{
			logEvalPeers.resize(logEvalPeers.size() + activePeers.size());

			size_t idx = logStartIdx;
			for (auto peer : activePeers)
			{
				logEvalPeers[idx].addr = peer.comm->getAddress();
				logEvalPeers[idx].dl = peer.downloadSpeed;
				logEvalPeers[idx].up = peer.uploadSpeed;
				logEvalPeers[idx].activityTime = currentTime - peer.lastActivityTime;
				idx++;
			}
		}
#endif

		if ((uint32_t)activePeers.size() < mtt::config::getExternal().connection.maxTorrentConnections)
		{
			return;
		}

		const uint32_t minPeersTimeChance = 10;

		auto minTimeToEval = currentTime - minPeersTimeChance;

		const uint32_t minPeersPiecesTimeChance = 20;
		auto minTimeToReceive = currentTime - minPeersPiecesTimeChance;

		uint32_t slowestSpeed = -1;
		uint32_t slowestPeer = -1;

		uint32_t maxUploads = 5;
		std::vector<uint32_t> currentUploads;

		uint32_t idx = 0;
		for (auto peer : activePeers)
		{
			if (peer.connectionTime > minTimeToEval)
			{
#ifdef PEER_DIAGNOSTICS
				logEvalPeers[logStartIdx + idx].action = LogEvalPeer::TooSoon;
#endif
				continue;
			}

			if (peer.comm->state.peerInterested)
			{
				currentUploads.push_back(idx);
			}

			if (peer.lastActivityTime < minTimeToReceive)
			{
#ifdef PEER_DIAGNOSTICS
				logEvalPeers[logStartIdx + idx].action = LogEvalPeer::NotResponding;
#endif
				removedPeers.push_back(idx);
				continue;
			}

			if (peer.downloadSpeed < slowestSpeed)
			{
				slowestSpeed = peer.downloadSpeed;
				slowestPeer = idx;
			}

			idx++;
		}

		if (removedPeers.empty() && slowestPeer != -1)
		{
#ifdef PEER_DIAGNOSTICS
			logEvalPeers[logStartIdx + idx].action = LogEvalPeer::TooSlow;
#endif
			removedPeers.push_back(slowestPeer);
		}

		if (!currentUploads.empty())
		{
			std::sort(currentUploads.begin(), currentUploads.end(), [&](const auto & l, const auto & r) { return activePeers[l].uploadSpeed > activePeers[r].uploadSpeed; });
			currentUploads.resize(std::min((uint32_t)currentUploads.size(), maxUploads));

			for (auto idx : currentUploads)
			{
				auto it = std::find(removedPeers.begin(), removedPeers.end(), idx);
				if (it != removedPeers.end())
					removedPeers.erase(it);

#ifdef PEER_DIAGNOSTICS
				logEvalPeers[logStartIdx + idx].action = LogEvalPeer::Upload;
#endif
			}
		}

		removePeers(removedPeers);
	}

	evaluateCurrentPeers();
}

void mtt::FileTransfer::updateMeasures()
{
	auto& freshPieces = torrent->files.freshPieces;
	std::vector<std::pair<PeerCommunication*, std::pair<uint64_t, uint64_t>>> currentMeasure;

	{
		std::lock_guard<std::mutex> guard(peersMutex);

		auto finishedUploadRequests = uploader->popHandledRequests();
		for(auto& r : finishedUploadRequests)
		{
			if (auto peer = getActivePeer(r.first))
				peer->uploaded += r.second;
		}

		for (auto& peer : activePeers)
		{
			peer.downloaded = peer.comm->getReceivedDataCount();
			currentMeasure.push_back({ peer.comm, {peer.downloaded, peer.uploaded} });
			peer.downloadSpeed = 0;
			peer.uploadSpeed = 0;

			for (auto last : lastSpeedMeasure)
			{
				if (last.first == peer.comm)
				{
					if (peer.downloaded > last.second.first)
						peer.downloadSpeed = (uint32_t)(peer.downloaded - last.second.first);
					if (peer.uploaded > last.second.second)
						peer.uploadSpeed = (uint32_t)(peer.uploaded - last.second.second);

					break;
				}
			}

			for (auto& piece : freshPieces)
				if (peer.comm->isEstablished())
					peer.comm->sendHave(piece);
		}
	}
	freshPieces.clear();
	lastSpeedMeasure = currentMeasure;

	if (!torrent->selectionFinished())
	{
		downloader.sortPriorityByAvailability(piecesAvailability);
		downloader.sortPriority(piecesPriority);
	}
}

#ifdef PEER_DIAGNOSTICS
extern std::string FormatLogTime(long);

void mtt::FileTransfer::saveLogEvents()
{
	std::lock_guard<std::mutex> guard(logmtx);

	if (logEvals.empty())
		return;

	std::ofstream file("logs\\" + torrent->name() + "\\downloader.log");

	if (!file)
		return;

	size_t logIndex = 0;

	for (auto& eval : logEvals)
	{
		file << FormatLogTime(eval.time) << ": Count:" << eval.count << "\n";

		for (size_t i = logIndex; i < logIndex + eval.count; i++)
		{
			auto& peerLog = logEvalPeers[i];

			file << peerLog.addr.toString() << " Action:" << (int)peerLog.action << " dl:" << peerLog.dl/1024.f << " up:" << peerLog.up/ 1024.f << " dead:" << peerLog.activityTime << "\n";
		}

		logIndex += eval.count;
	}

	file << "\n\n";
}
#endif<|endoftext|>


<commit_before>/*!
 *  Copyright (c) 2018 by Contributors
 * \file correct_layout.cc
 * \brief Infer and correct layout.
 */
#include <nnvm/graph.h>
#include <nnvm/op_attr_types.h>
#include <nnvm/graph_attr_types.h>
#include <nnvm/pass.h>
#include <nnvm/layout.h>

namespace nnvm {
namespace pass {

nnvm::NodePtr CreateLayoutTransformNode(const Layout& src,
                                        const Layout& dst) {
  static const nnvm::Op* trans_op = nnvm::Op::Get("__layout_transform__");
  static int count = 0;
  nnvm::NodePtr n = nnvm::Node::Create();
  n->attrs.op = trans_op;
  n->attrs.name = src.name() + "_to_" + dst.name() + std::to_string(count++);
  n->attrs.dict["src_layout"] = src.name();
  n->attrs.dict["dst_layout"] = dst.name();
  n->op()->attr_parser(&(n->attrs));
  return n;
}

using LayoutAttrDict = std::unordered_map<const Node*, std::vector<Layout> >;

/*!
 * \brief A simple layout infer pass that will
 *        insert layout transform nodes automatically.
 */
nnvm::Graph CorrectLayout(nnvm::Graph src) {
  static auto& op_infer_layout =
    nnvm::Op::GetAttr<FCorrectLayout>("FCorrectLayout");

  const IndexedGraph& idx = src.indexed_graph();
  std::vector<nnvm::NodePtr> mirror_vec(idx.num_nodes(), nullptr);

  // (new) NodePtr -> output_layouts
  LayoutAttrDict new_layouts;

  for (uint32_t nid = 0; nid < idx.num_nodes(); ++nid) {
    const auto& inode = idx[nid];
    nnvm::NodePtr new_node = nnvm::Node::Create();
    *new_node = *(inode.source);
    if (new_node->is_variable()) {
      // Variable node. No operator. Only one output entry.
      auto input_iter = std::find(
        idx.input_nodes().cbegin(), idx.input_nodes().cend(), nid);
      CHECK(input_iter != idx.input_nodes().cend());
      int64_t input_id = std::distance(idx.input_nodes().cbegin(), input_iter);
      if (src.HasAttr("layout_inputs")) {
        new_layouts[new_node.get()] =
          {src.GetAttr<std::vector<Layout> >("layout_inputs")[input_id]};
      } else {
        new_layouts[new_node.get()] = {Layout::Undef()};
      }
      mirror_vec[nid] = new_node;
      continue;
    }

    const uint32_t num_inputs = inode.inputs.size();
    const uint32_t num_outputs = inode.source->num_outputs();
    // set up output and input layouts
    std::vector<Layout> request_ilayouts(num_inputs, Layout::Undef());
    for (size_t i = 0; i < num_inputs; ++i) {
      const IndexedGraph::NodeEntry& input_entry = inode.inputs[i];
      const NodePtr& new_input_node = mirror_vec[input_entry.node_id];
      CHECK(new_input_node != nullptr);

      // fill inputs by previous node (DFS order) inferred layouts.
      const auto& layouts_iter = new_layouts.find(new_input_node.get());
      CHECK(layouts_iter != new_layouts.end());
      request_ilayouts[i] = layouts_iter->second[input_entry.index];
    }
    // layouts produced by previous node.
    std::vector<Layout> produce_ilayouts(request_ilayouts);
    // input layouts from last pass of LayoutTransform (if apply)
    std::vector<Layout> last_request_ilayouts(num_inputs, Layout::Undef());
    // fill outputs by last pass of LayoutTransform (if apply)
    std::vector<Layout> produce_olayouts(num_outputs, Layout::Undef());
    if (src.HasAttr("layout")) {
      const auto& layouts = src.GetAttr<std::vector<Layout> >("layout");
      for (uint32_t i = 0; i < num_outputs; ++i) {
        produce_olayouts[i] = layouts[idx.entry_id(nid, i)];
      }
      for (uint32_t i = 0; i < num_inputs; ++i) {
        last_request_ilayouts[i] = layouts[idx.entry_id(inode.inputs[i])];
      }
    }

    const auto& flayout = op_infer_layout[new_node->op()];
    CHECK(flayout != nullptr) << "Attribute FCorrectLayout"
                              << " is not registered by op " << inode.source->op()->name
                              << " we are not able to complete layout transform.";
    CHECK(flayout(new_node->attrs, &request_ilayouts, &last_request_ilayouts, &produce_olayouts))
        << "Layout infer fail";
    CHECK_EQ(request_ilayouts.size(), num_inputs);
    CHECK_EQ(produce_olayouts.size(), num_outputs);

    // update new layouts
    new_layouts[new_node.get()] = std::move(produce_olayouts);

    for (uint32_t i = 0; i < inode.inputs.size(); ++i) {
      const auto& e = inode.inputs[i];
      const nnvm::NodePtr& in = mirror_vec[e.node_id];
      new_node->inputs[i] = nnvm::NodeEntry{in, e.index, e.version};

      // insert layout_transform if necessary
      const Layout& produce = produce_ilayouts[i];
      const Layout& request = request_ilayouts[i];
      if (produce != request && produce.defined()) {
        nnvm::NodePtr tnode = CreateLayoutTransformNode(produce, request);
        tnode->attrs.name = idx[e.node_id].source->attrs.name + "_" + request.name();
        tnode->inputs.emplace_back(new_node->inputs[i]);
        nnvm::NodeEntry tnode_output{tnode, 0, 0};
        new_node->inputs[i] = tnode_output;
        // layout produced by LayoutTransformNode
        new_layouts[tnode.get()] = {request};
      } else if (!produce.defined()) {
        // do reverse infer
        new_layouts[in.get()][e.index] = request;
      }
    }
    mirror_vec[nid] = new_node;
  }

  std::vector<nnvm::NodeEntry> outputs;
  for (const auto& e : idx.outputs()) {
    outputs.emplace_back(nnvm::NodeEntry{mirror_vec[e.node_id], e.index, e.version});
  }

  nnvm::Graph ret;
  ret.outputs = outputs;
  // restore the layouts to return graph
  const auto& ret_idx = ret.indexed_graph();
  std::vector<Layout> ret_layouts(ret_idx.num_node_entries(), Layout::Undef());
  for (uint32_t nid = 0; nid < ret_idx.num_nodes(); ++nid) {
    const auto& inode = ret_idx[nid];
    const auto& layout_iter = new_layouts.find(inode.source);
    if (layout_iter != new_layouts.end()) {
      for (uint32_t i = 0; i < inode.source->num_outputs(); ++i) {
        ret_layouts[ret_idx.entry_id(nid, i)] = std::move(layout_iter->second[i]);
      }
    }
  }

  // cannot call indexed_graph() before return the origin Graph,
  // thus create a new one
  nnvm::Graph new_ret;
  new_ret.outputs = std::move(outputs);
  new_ret.attrs["layout"] = std::make_shared<any>(std::move(ret_layouts));

  return new_ret;
}

// register pass
NNVM_REGISTER_PASS(CorrectLayout)
.describe("Return a layout-transformed graph of src.")
.set_body(CorrectLayout)
.provide_graph_attr("layout")
.set_change_graph(true);

DMLC_JSON_ENABLE_ANY(LayoutVector, list_layout);

}  // namespace pass
}  // namespace nnvm
<commit_msg>allow missing FCorrectLayout (#457)<commit_after>/*!
 *  Copyright (c) 2018 by Contributors
 * \file correct_layout.cc
 * \brief Infer and correct layout.
 */
#include <nnvm/graph.h>
#include <nnvm/op_attr_types.h>
#include <nnvm/graph_attr_types.h>
#include <nnvm/pass.h>
#include <nnvm/layout.h>

namespace nnvm {
namespace pass {

nnvm::NodePtr CreateLayoutTransformNode(const Layout& src,
                                        const Layout& dst) {
  static const nnvm::Op* trans_op = nnvm::Op::Get("__layout_transform__");
  static int count = 0;
  nnvm::NodePtr n = nnvm::Node::Create();
  n->attrs.op = trans_op;
  n->attrs.name = src.name() + "_to_" + dst.name() + std::to_string(count++);
  n->attrs.dict["src_layout"] = src.name();
  n->attrs.dict["dst_layout"] = dst.name();
  n->op()->attr_parser(&(n->attrs));
  return n;
}

using LayoutAttrDict = std::unordered_map<const Node*, std::vector<Layout> >;

/*!
 * \brief A simple layout infer & correct pass that will
 *        insert layout transform nodes automatically.
 */
nnvm::Graph CorrectLayout(nnvm::Graph src) {
  static auto& op_correct_layout =
    nnvm::Op::GetAttr<FCorrectLayout>("FCorrectLayout");

  const IndexedGraph& idx = src.indexed_graph();
  std::vector<nnvm::NodePtr> mirror_vec(idx.num_nodes(), nullptr);

  // (new) NodePtr -> output_layouts
  LayoutAttrDict new_layouts;

  for (uint32_t nid = 0; nid < idx.num_nodes(); ++nid) {
    const auto& inode = idx[nid];
    nnvm::NodePtr new_node = nnvm::Node::Create();
    *new_node = *(inode.source);
    if (new_node->is_variable()) {
      // Variable node. No operator. Only one output entry.
      auto input_iter = std::find(
        idx.input_nodes().cbegin(), idx.input_nodes().cend(), nid);
      CHECK(input_iter != idx.input_nodes().cend());
      int64_t input_id = std::distance(idx.input_nodes().cbegin(), input_iter);
      if (src.HasAttr("layout_inputs")) {
        new_layouts[new_node.get()] =
          {src.GetAttr<std::vector<Layout> >("layout_inputs")[input_id]};
      } else {
        new_layouts[new_node.get()] = {Layout::Undef()};
      }
      mirror_vec[nid] = new_node;
      continue;
    }

    const uint32_t num_inputs = inode.inputs.size();
    const uint32_t num_outputs = inode.source->num_outputs();
    // set up output and input layouts
    std::vector<Layout> request_ilayouts(num_inputs, Layout::Undef());
    for (size_t i = 0; i < num_inputs; ++i) {
      const IndexedGraph::NodeEntry& input_entry = inode.inputs[i];
      const NodePtr& new_input_node = mirror_vec[input_entry.node_id];
      CHECK(new_input_node != nullptr);

      // fill inputs by previous node (DFS order) inferred layouts.
      const auto& layouts_iter = new_layouts.find(new_input_node.get());
      CHECK(layouts_iter != new_layouts.end());
      request_ilayouts[i] = layouts_iter->second[input_entry.index];
    }
    // layouts produced by previous node.
    std::vector<Layout> produce_ilayouts(request_ilayouts);
    // input layouts from last pass of LayoutTransform (if apply)
    std::vector<Layout> last_request_ilayouts(num_inputs, Layout::Undef());
    // fill outputs by last pass of LayoutTransform (if apply)
    std::vector<Layout> produce_olayouts(num_outputs, Layout::Undef());
    if (src.HasAttr("layout")) {
      const auto& layouts = src.GetAttr<std::vector<Layout> >("layout");
      for (uint32_t i = 0; i < num_outputs; ++i) {
        produce_olayouts[i] = layouts[idx.entry_id(nid, i)];
      }
      for (uint32_t i = 0; i < num_inputs; ++i) {
        last_request_ilayouts[i] = layouts[idx.entry_id(inode.inputs[i])];
      }
    }

    if (op_correct_layout.count(new_node->op())) {
      const auto &flayout = op_correct_layout[new_node->op()];
      CHECK(flayout(new_node->attrs, &request_ilayouts, &last_request_ilayouts, &produce_olayouts))
        << "Layout infer fail";
      CHECK_EQ(request_ilayouts.size(), num_inputs);
      CHECK_EQ(produce_olayouts.size(), num_outputs);
    }

    // update new layouts
    new_layouts[new_node.get()] = std::move(produce_olayouts);

    for (uint32_t i = 0; i < inode.inputs.size(); ++i) {
      const auto& e = inode.inputs[i];
      const nnvm::NodePtr& in = mirror_vec[e.node_id];
      new_node->inputs[i] = nnvm::NodeEntry{in, e.index, e.version};

      // insert layout_transform if necessary
      const Layout& produce = produce_ilayouts[i];
      const Layout& request = request_ilayouts[i];
      if (produce != request && produce.defined()) {
        nnvm::NodePtr tnode = CreateLayoutTransformNode(produce, request);
        tnode->attrs.name = idx[e.node_id].source->attrs.name + "_" + request.name();
        tnode->inputs.emplace_back(new_node->inputs[i]);
        nnvm::NodeEntry tnode_output{tnode, 0, 0};
        new_node->inputs[i] = tnode_output;
        // layout produced by LayoutTransformNode
        new_layouts[tnode.get()] = {request};
      } else if (!produce.defined()) {
        // do reverse infer
        new_layouts[in.get()][e.index] = request;
      }
    }
    mirror_vec[nid] = new_node;
  }

  std::vector<nnvm::NodeEntry> outputs;
  for (const auto& e : idx.outputs()) {
    outputs.emplace_back(nnvm::NodeEntry{mirror_vec[e.node_id], e.index, e.version});
  }

  nnvm::Graph ret;
  ret.outputs = outputs;
  // restore the layouts to return graph
  const auto& ret_idx = ret.indexed_graph();
  std::vector<Layout> ret_layouts(ret_idx.num_node_entries(), Layout::Undef());
  for (uint32_t nid = 0; nid < ret_idx.num_nodes(); ++nid) {
    const auto& inode = ret_idx[nid];
    const auto& layout_iter = new_layouts.find(inode.source);
    if (layout_iter != new_layouts.end()) {
      for (uint32_t i = 0; i < inode.source->num_outputs(); ++i) {
        ret_layouts[ret_idx.entry_id(nid, i)] = std::move(layout_iter->second[i]);
      }
    }
  }

  // cannot call indexed_graph() before return the origin Graph,
  // thus create a new one
  nnvm::Graph new_ret;
  new_ret.outputs = std::move(outputs);
  new_ret.attrs["layout"] = std::make_shared<any>(std::move(ret_layouts));

  return new_ret;
}

// register pass
NNVM_REGISTER_PASS(CorrectLayout)
.describe("Return a layout-transformed graph of src.")
.set_body(CorrectLayout)
.provide_graph_attr("layout")
.set_change_graph(true);

DMLC_JSON_ENABLE_ANY(LayoutVector, list_layout);

}  // namespace pass
}  // namespace nnvm
<|endoftext|>


<commit_before>#include "AliHMPIDPreprocessor.h" //header

#include <AliCDBMetaData.h>
#include <AliDCSValue.h>
#include <TF1.h>              //Process()
#include <TF2.h>              //Process()
#include <TGraph.h>           //Process()
#include <AliLog.h>           //Process()

ClassImp(AliHMPIDPreprocessor)

char *AliHMPIDPreprocessor::fP ="HMP_DET/HMP_MP%i/HMP_MP%i_GAS/HMP_MP%i_GAS_PMWC.actual.value";
char *AliHMPIDPreprocessor::fT1="HMP_DET/HMP_MP%i/HMP_MP%i_LIQ_LOOP.actual.sensors.Rad%iIn_Temp";
char *AliHMPIDPreprocessor::fT2="HMP_DET/HMP_MP%i/HMP_MP%i_LIQ_LOOP.actual.sensors.Rad%iOut_Temp";
char *AliHMPIDPreprocessor::fHV="HMP_DET/HMP_MP%i/HMP_MP%i_PW/HMP_MP%i_SEC0/HMP_MP%i_SEC0_HV.actual.vMon";

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void AliHMPIDPreprocessor::Initialize(Int_t run, UInt_t startTime,UInt_t endTime)
{
  AliPreprocessor::Initialize(run, startTime, endTime);
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
UInt_t AliHMPIDPreprocessor::Process(TMap* pMap)
{
// Process: 1. inlet and outlet C6F14 temperature, stores TObjArray of 21 TF1, where TF1 is Nmean=f(t), one per radiator
//          2. CH4 pressure and HV                 stores TObjArray of 7 TF1 where TF1 is thr=f(t), one per chamber
// Arguments: pDcsMap - map of structure "alias name" - TObjArray of AliDCSValue
// Assume that: HV is the same during the run for a given chamber, different chambers might have different HV
//              P=f(t), different for different chambers

//  TList* list = GetFileSources(kDAQ, "MAP"); //first analyse a set of pedestal files
//  if (list){
//    Log("The following sources produced files with the id MAP");
//    list->Print();
//    delete list;
//  }

  if(!pMap)  return 0;                    //no DCS map provided
  Double_t sor=0,eor=1500;

  TF2 idx("RidxC4F14","sqrt(1+0.554*(1239.84/x)^2/((1239.84/x)^2-5796)-0.0005*(y-20))",5.5 ,8.5 ,0  ,50);  //N=f(Ephot,T) [eV,grad C] DiMauro mail
  TF2 thr("RthrCH4"  ,"x+170745848*exp(-y*0.0162012)"                                                      ,2000,3000,900,1200); //thr=f(HV,P)  [V,mBar]
//  Double_t eMean=6.67786;                                                                                //mean energy of photon defined  by transperancy window

//  TObjArray arTmean(21); arTmean.SetOwner(kTRUE);     //21 Tmean=f(time) one per radiator
//  TObjArray arPress(7);  arPress.SetOwner(kTRUE);     //7  Press=f(time) one pre chamber
  TObjArray arNmean(21); arNmean.SetOwner(kTRUE);     //21 Nmean=f(time) one per radiator
  TObjArray arQthre(7);  arQthre.SetOwner(kTRUE);     //7  Qthre=f(time) one pre chamber

//  AliDCSValue *pVal; Int_t cnt=0;

  for(Int_t iCh=0;iCh<7;iCh++){
 //   TObjArray *pHV=(TObjArray*)pMap->GetValue(Form("HMP_DET/HMP_MP%i/HMP_MP%i_PW/HMP_MP%i_SEC0/HMP_MP%i_SEC0_HV.actual.vMon",iCh,iCh,iCh,iCh)); //HV
//    pVal=(AliDCSValue*)pHV->At(0); Float_t hv=pVal->GetFloat();//HV

//    TObjArray *pP =(TObjArray*)pMap->GetValue(Form(fP,iCh,iCh,iCh)); //P
//    TGraph *pGrP; cnt=0;TIter nextp(pP); while((pVal=(AliDCSValue*)nextp())) pGrP->SetPoint(cnt++,pVal->GetTimeStamp(),pVal->GetFloat()); //P

//    TF1 *pFuP=new TF1(Form("P%i",iCh),"1005",sor,eor);
//    pGrP->Fit(pFuP,"Q"); delete pGrP;
    TF1 *pFuQ=new TF1(Form("HMP_Qthre%i",iCh),"100",sor,eor);
    arQthre.AddAt(pFuQ,iCh);
    for(Int_t iRad=0;iRad<3;iRad++){
//      TObjArray *pT1=(TObjArray*)pMap->GetValue(Form(fT1,iCh,iCh,iRad)); //Tin
//      TGraph *pGrT1=new TGraph; cnt=0; TIter next1(pT1); while((pVal=(AliDCSValue*)next1())) pGrT1->SetPoint(cnt++,pVal->GetTimeStamp(),pVal->GetFloat()); //inlet temperature
//      pGrT1->Fit(new TF1(Form("Tin%i%i",iCh,iRad),"[0]+[1]*x+[2]*sin([3]*x)",sor,eor),"Q");       //now fit the temp graph

//      TObjArray *pT2=(TObjArray*)pMap->GetValue(Form(fT2,iCh,iCh,iRad));//Tout
//      TGraph *pGrT2=new TGraph; cnt=0; TIter next2(pT2); while((pVal=(AliDCSValue*)next2())) pGrT2->SetPoint(cnt++,pVal->GetTimeStamp(),pVal->GetFloat()); //outlet temperature
//      TF1*pFuT1=new TF1(Form("Tout%i%i",iCh,iRad),"13",sor,eor)
//      pGrT2->Fit(,"Q");       //now fit the temp graph

//      arTmean.Add(pRadTempF);
      TF1 *pFuN=new TF1(Form("HMP_Nmean%i-%i",iCh,iRad),"1.292",sor,eor); pFuN->SetLineColor(iRad+2); pFuN->SetLineWidth(1);
      arNmean.AddAt(pFuN,3*iCh+iRad);
//      delete pGrT1;  delete pGrT2;
    }//radiators loop
  }//chambers loop

  AliCDBMetaData metaData; metaData.SetBeamPeriod(0); metaData.SetResponsible("AliHMPIDPreprocessor"); metaData.SetComment("SIMULATED");

  arQthre.Print();
//  Store("Calib", "Press" , &arPress , &metaData);
//  Store("Calib", "Tmean" , &arTmean , &metaData);

  if( Store("Calib", "Qthre" , &arQthre , &metaData) == kTRUE && Store("Calib", "Nmean" , &arNmean , &metaData) == kTRUE ) return 0;   //clm: compatibility with new Store and preprocessor requirement
  else return 0;

  //  AliInfo("End.");

}//Process()
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

<commit_msg>Bug in return code (L. Molnar)<commit_after>#include "AliHMPIDPreprocessor.h" //header

#include <AliCDBMetaData.h>
#include <AliDCSValue.h>
#include <TF1.h>              //Process()
#include <TF2.h>              //Process()
#include <TGraph.h>           //Process()
#include <AliLog.h>           //Process()

ClassImp(AliHMPIDPreprocessor)

char *AliHMPIDPreprocessor::fP ="HMP_DET/HMP_MP%i/HMP_MP%i_GAS/HMP_MP%i_GAS_PMWC.actual.value";
char *AliHMPIDPreprocessor::fT1="HMP_DET/HMP_MP%i/HMP_MP%i_LIQ_LOOP.actual.sensors.Rad%iIn_Temp";
char *AliHMPIDPreprocessor::fT2="HMP_DET/HMP_MP%i/HMP_MP%i_LIQ_LOOP.actual.sensors.Rad%iOut_Temp";
char *AliHMPIDPreprocessor::fHV="HMP_DET/HMP_MP%i/HMP_MP%i_PW/HMP_MP%i_SEC0/HMP_MP%i_SEC0_HV.actual.vMon";

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void AliHMPIDPreprocessor::Initialize(Int_t run, UInt_t startTime,UInt_t endTime)
{
  AliPreprocessor::Initialize(run, startTime, endTime);
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
UInt_t AliHMPIDPreprocessor::Process(TMap* pMap)
{
// Process: 1. inlet and outlet C6F14 temperature, stores TObjArray of 21 TF1, where TF1 is Nmean=f(t), one per radiator
//          2. CH4 pressure and HV                 stores TObjArray of 7 TF1 where TF1 is thr=f(t), one per chamber
// Arguments: pDcsMap - map of structure "alias name" - TObjArray of AliDCSValue
// Assume that: HV is the same during the run for a given chamber, different chambers might have different HV
//              P=f(t), different for different chambers

//  TList* list = GetFileSources(kDAQ, "MAP"); //first analyse a set of pedestal files
//  if (list){
//    Log("The following sources produced files with the id MAP");
//    list->Print();
//    delete list;
//  }

  if(!pMap)  return 0;                    //no DCS map provided
  Double_t sor=0,eor=1500;

  TF2 idx("RidxC4F14","sqrt(1+0.554*(1239.84/x)^2/((1239.84/x)^2-5796)-0.0005*(y-20))",5.5 ,8.5 ,0  ,50);  //N=f(Ephot,T) [eV,grad C] DiMauro mail
  TF2 thr("RthrCH4"  ,"x+170745848*exp(-y*0.0162012)"                                                      ,2000,3000,900,1200); //thr=f(HV,P)  [V,mBar]
//  Double_t eMean=6.67786;                                                                                //mean energy of photon defined  by transperancy window

//  TObjArray arTmean(21); arTmean.SetOwner(kTRUE);     //21 Tmean=f(time) one per radiator
//  TObjArray arPress(7);  arPress.SetOwner(kTRUE);     //7  Press=f(time) one pre chamber
  TObjArray arNmean(21); arNmean.SetOwner(kTRUE);     //21 Nmean=f(time) one per radiator
  TObjArray arQthre(7);  arQthre.SetOwner(kTRUE);     //7  Qthre=f(time) one pre chamber

//  AliDCSValue *pVal; Int_t cnt=0;

  for(Int_t iCh=0;iCh<7;iCh++){
 //   TObjArray *pHV=(TObjArray*)pMap->GetValue(Form("HMP_DET/HMP_MP%i/HMP_MP%i_PW/HMP_MP%i_SEC0/HMP_MP%i_SEC0_HV.actual.vMon",iCh,iCh,iCh,iCh)); //HV
//    pVal=(AliDCSValue*)pHV->At(0); Float_t hv=pVal->GetFloat();//HV

//    TObjArray *pP =(TObjArray*)pMap->GetValue(Form(fP,iCh,iCh,iCh)); //P
//    TGraph *pGrP; cnt=0;TIter nextp(pP); while((pVal=(AliDCSValue*)nextp())) pGrP->SetPoint(cnt++,pVal->GetTimeStamp(),pVal->GetFloat()); //P

//    TF1 *pFuP=new TF1(Form("P%i",iCh),"1005",sor,eor);
//    pGrP->Fit(pFuP,"Q"); delete pGrP;
    TF1 *pFuQ=new TF1(Form("HMP_Qthre%i",iCh),"100",sor,eor);
    arQthre.AddAt(pFuQ,iCh);
    for(Int_t iRad=0;iRad<3;iRad++){
//      TObjArray *pT1=(TObjArray*)pMap->GetValue(Form(fT1,iCh,iCh,iRad)); //Tin
//      TGraph *pGrT1=new TGraph; cnt=0; TIter next1(pT1); while((pVal=(AliDCSValue*)next1())) pGrT1->SetPoint(cnt++,pVal->GetTimeStamp(),pVal->GetFloat()); //inlet temperature
//      pGrT1->Fit(new TF1(Form("Tin%i%i",iCh,iRad),"[0]+[1]*x+[2]*sin([3]*x)",sor,eor),"Q");       //now fit the temp graph

//      TObjArray *pT2=(TObjArray*)pMap->GetValue(Form(fT2,iCh,iCh,iRad));//Tout
//      TGraph *pGrT2=new TGraph; cnt=0; TIter next2(pT2); while((pVal=(AliDCSValue*)next2())) pGrT2->SetPoint(cnt++,pVal->GetTimeStamp(),pVal->GetFloat()); //outlet temperature
//      TF1*pFuT1=new TF1(Form("Tout%i%i",iCh,iRad),"13",sor,eor)
//      pGrT2->Fit(,"Q");       //now fit the temp graph

//      arTmean.Add(pRadTempF);
      TF1 *pFuN=new TF1(Form("HMP_Nmean%i-%i",iCh,iRad),"1.292",sor,eor); pFuN->SetLineColor(iRad+2); pFuN->SetLineWidth(1);
      arNmean.AddAt(pFuN,3*iCh+iRad);
//      delete pGrT1;  delete pGrT2;
    }//radiators loop
  }//chambers loop

  AliCDBMetaData metaData; metaData.SetBeamPeriod(0); metaData.SetResponsible("AliHMPIDPreprocessor"); metaData.SetComment("SIMULATED");

  arQthre.Print();
//  Store("Calib", "Press" , &arPress , &metaData);
//  Store("Calib", "Tmean" , &arTmean , &metaData);

  if( Store("Calib", "Qthre" , &arQthre , &metaData) == kTRUE && Store("Calib", "Nmean" , &arNmean , &metaData) == kTRUE ) return 0;   //clm: compatibility with new Store and preprocessor requirement
  else return 1;

  //  AliInfo("End.");

}//Process()
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

<|endoftext|>


<commit_before>//
// Created by a1 on 16-11-2.
//
#include "encode.h"
#include "util/bytes.h"

static string encode_key_internal(char type, const Bytes& key, const Bytes& field, uint16_t version);
static string encode_meta_val_internal(const char type, uint64_t length, uint16_t version, char del);

string encode_meta_key(const Bytes& key){
    string buf(1, DataType::META);

//    uint16_t slot = (uint16_t)keyHashSlot(key.data(), key.size());
//    slot = htobe16(slot);
//    buf.append((char *)&slot, sizeof(uint16_t));

    buf.append(key.data(), key.size());

    return buf;
}

static string encode_key_internal(char type, const Bytes& key, const Bytes& field, uint16_t version){
    string buf(1, type);

    uint16_t len = htobe16((uint16_t)key.size());
    buf.append((char *)&len, sizeof(uint16_t));
    buf.append(key.data(), key.size());

    version = htobe16(version);
    buf.append((char *)&version, sizeof(uint16_t));

    buf.append(field.data(), field.size());

    return buf;
}

string encode_hash_key(const Bytes& key, const Bytes& field, uint16_t version){
    return encode_key_internal(DataType::ITEM, key, field, version);
}

string encode_set_key(const Bytes& key, const Bytes& member, uint16_t version){
    return encode_key_internal(DataType::ITEM, key, member, version);
}

string encode_zset_key(const Bytes& key, const Bytes& member, uint16_t version){
    return encode_key_internal(DataType::ITEM, key, member, version);
}

string encode_zscore_prefix(const Bytes &key, uint16_t version){
    return encode_key_internal(DataType::ZSCORE, key, Bytes(""), version);
}

string encode_eset_key(const Bytes& member){
    string buf(1, DataType::EKEY);

    buf.append(member.data(), member.size());
    return buf;
}

uint64_t encodeScore(const double score) {
    int64_t iscore;
    if (score < 0) {
        iscore = (int64_t)(score * 100000LL - 0.5) + ZSET_SCORE_SHIFT;
    } else {
        iscore = (int64_t)(score * 100000LL + 0.5) + ZSET_SCORE_SHIFT;
    }
    return (uint64_t)(iscore);
}

string encode_zscore_key(const Bytes& key, const Bytes& field, double score, uint16_t version){
    string buf(1, DataType::ZSCORE);

    uint16_t len = htobe16((uint16_t)key.size());
    buf.append((char *)&len, sizeof(uint16_t));
    buf.append(key.data(), key.size());

    version = htobe16(version);
    buf.append((char *)&version, sizeof(uint16_t));

    uint64_t new_score = encodeScore(score);
    new_score = htobe64(new_score);
    buf.append((char *)&new_score, sizeof(uint64_t));

    buf.append(field.data(), field.size());

    return buf;
}

string encode_escore_key(const Bytes& member, uint64_t score){
    string buf(1, DataType::ESCORE);

    score = htobe64(score);
    buf.append((char *)&score, sizeof(uint64_t));
    buf.append(member.data(), member.size());

    return buf;
}

void update_list_key(std::string& old, uint64_t seq){
    auto u64size = sizeof(uint64_t);
    seq = htobe64(seq);
    old.replace(old.size()- u64size, u64size, (char *)&seq, u64size);
}

string encode_list_key(const Bytes& key, uint64_t seq, uint16_t version){
    string buf(1, DataType::ITEM);

    uint16_t len = htobe16((uint16_t)key.size());
    buf.append((char *)&len, sizeof(uint16_t));
    buf.append(key.data(), key.size());

    version = htobe16(version);
    buf.append((char *)&version, sizeof(uint16_t));

    seq = htobe64(seq);
    buf.append((char *)&seq, sizeof(uint64_t));

    return buf;
}

string encode_kv_val(const Bytes& val, uint16_t version, char del){
    string buf(1, DataType::KV);

    version = htobe16(version);
    buf.append((char *)&version, sizeof(uint16_t));

    buf.append(1, del);

    buf.append(val.data(), val.size());
    return buf;
}

static string encode_meta_val_internal(const char type, uint64_t length, uint16_t version, char del){
    string buf(1, type);

    version = htobe16(version);
    buf.append((char *)&version, sizeof(uint16_t));

    buf.append(1, del);

    length = htobe64(length);
    buf.append((char *)&length, sizeof(uint64_t));

    return buf;
}

string encode_hash_meta_val(uint64_t length, uint16_t version, char del){
    return encode_meta_val_internal(DataType::HSIZE, length, version, del);
}

string encode_set_meta_val(uint64_t length, uint16_t version, char del){
    return encode_meta_val_internal(DataType::SSIZE, length, version, del);
}

string encode_zset_meta_val(uint64_t length, uint16_t version, char del){
    return encode_meta_val_internal(DataType::ZSIZE, length, version, del);
}

string encode_list_meta_val(uint64_t length, uint64_t left, uint64_t right, uint16_t version, char del){
    string buf(1, DataType::LSIZE);

    version = htobe16(version);
    buf.append((char *)&version, sizeof(uint16_t));

    buf.append(1, del);

    length = htobe64(length);
    buf.append((char *)&length, sizeof(uint64_t));

    left = htobe64(left);
    buf.append((char *)&left, sizeof(uint64_t));

    right = htobe64(right);
    buf.append((char *)&right, sizeof(uint64_t));

    return buf;
}

/*
 * delete key
 */
string encode_delete_key(const Bytes& key, uint16_t version){
    string buf(1, KEY_DELETE_MASK);

//    uint16_t slot = (uint16_t)keyHashSlot(key.data(), key.size());
//    slot = htobe16(slot);
//    buf.append((char *)&slot, sizeof(uint16_t));

    uint16_t len = htobe16((uint16_t)key.size());
    buf.append((char *)&len, sizeof(uint16_t));
    buf.append(key.data(), key.size());

    version = htobe16(version);
    buf.append((char *)&version, sizeof(uint16_t));

    return buf;
}

string encode_repo_key() {
    string buf(1, DataType::REPOKEY);

    return buf;
}

string encode_repo_item(uint64_t timestamp, uint64_t index) {
    string buf(1, DataType::REPOITEM);

    timestamp = htobe64(timestamp);
    buf.append((char *)&timestamp, sizeof(uint64_t));

    index = htobe64(index);
    buf.append((char *)&index, sizeof(uint64_t));

    return buf;
}
<commit_msg>[Performance] list迭代中不使用encode_list_key,改用 update_list_key以增量更新key中字符<commit_after>//
// Created by a1 on 16-11-2.
//
#include "encode.h"
#include "util/bytes.h"

static string encode_key_internal(char type, const Bytes& key, const Bytes& field, uint16_t version);
static string encode_meta_val_internal(const char type, uint64_t length, uint16_t version, char del);

string encode_meta_key(const Bytes& key){
    string buf(1, DataType::META);

//    uint16_t slot = (uint16_t)keyHashSlot(key.data(), key.size());
//    slot = htobe16(slot);
//    buf.append((char *)&slot, sizeof(uint16_t));

    buf.append(key.data(), key.size());

    return buf;
}

static string encode_key_internal(char type, const Bytes& key, const Bytes& field, uint16_t version){
    string buf(1, type);

    uint16_t len = htobe16((uint16_t)key.size());
    buf.append((char *)&len, sizeof(uint16_t));
    buf.append(key.data(), key.size());

    version = htobe16(version);
    buf.append((char *)&version, sizeof(uint16_t));

    buf.append(field.data(), field.size());

    return buf;
}

string encode_hash_key(const Bytes& key, const Bytes& field, uint16_t version){
    return encode_key_internal(DataType::ITEM, key, field, version);
}

string encode_set_key(const Bytes& key, const Bytes& member, uint16_t version){
    return encode_key_internal(DataType::ITEM, key, member, version);
}

string encode_zset_key(const Bytes& key, const Bytes& member, uint16_t version){
    return encode_key_internal(DataType::ITEM, key, member, version);
}

string encode_zscore_prefix(const Bytes &key, uint16_t version){
    return encode_key_internal(DataType::ZSCORE, key, Bytes(""), version);
}

string encode_eset_key(const Bytes& member){
    string buf(1, DataType::EKEY);

    buf.append(member.data(), member.size());
    return buf;
}

uint64_t encodeScore(const double score) {
    int64_t iscore;
    if (score < 0) {
        iscore = (int64_t)(score * 100000LL - 0.5) + ZSET_SCORE_SHIFT;
    } else {
        iscore = (int64_t)(score * 100000LL + 0.5) + ZSET_SCORE_SHIFT;
    }
    return (uint64_t)(iscore);
}

string encode_zscore_key(const Bytes& key, const Bytes& field, double score, uint16_t version){
    string buf(1, DataType::ZSCORE);

    uint16_t len = htobe16((uint16_t)key.size());
    buf.append((char *)&len, sizeof(uint16_t));
    buf.append(key.data(), key.size());

    version = htobe16(version);
    buf.append((char *)&version, sizeof(uint16_t));

    uint64_t new_score = encodeScore(score);
    new_score = htobe64(new_score);
    buf.append((char *)&new_score, sizeof(uint64_t));

    buf.append(field.data(), field.size());

    return buf;
}

string encode_escore_key(const Bytes& member, uint64_t score){
    string buf(1, DataType::ESCORE);

    score = htobe64(score);
    buf.append((char *)&score, sizeof(uint64_t));
    buf.append(member.data(), member.size());

    return buf;
}

void update_list_key(std::string& old, uint64_t seq){
    static const auto u64size = sizeof(uint64_t);
    seq = htobe64(seq);
    old.replace(old.size()- u64size, u64size, (char *)&seq, u64size);
}

string encode_list_key(const Bytes& key, uint64_t seq, uint16_t version){
    string buf(1, DataType::ITEM);

    uint16_t len = htobe16((uint16_t)key.size());
    buf.append((char *)&len, sizeof(uint16_t));
    buf.append(key.data(), key.size());

    version = htobe16(version);
    buf.append((char *)&version, sizeof(uint16_t));

    seq = htobe64(seq);
    buf.append((char *)&seq, sizeof(uint64_t));

    return buf;
}

string encode_kv_val(const Bytes& val, uint16_t version, char del){
    string buf(1, DataType::KV);

    version = htobe16(version);
    buf.append((char *)&version, sizeof(uint16_t));

    buf.append(1, del);

    buf.append(val.data(), val.size());
    return buf;
}

static string encode_meta_val_internal(const char type, uint64_t length, uint16_t version, char del){
    string buf(1, type);

    version = htobe16(version);
    buf.append((char *)&version, sizeof(uint16_t));

    buf.append(1, del);

    length = htobe64(length);
    buf.append((char *)&length, sizeof(uint64_t));

    return buf;
}

string encode_hash_meta_val(uint64_t length, uint16_t version, char del){
    return encode_meta_val_internal(DataType::HSIZE, length, version, del);
}

string encode_set_meta_val(uint64_t length, uint16_t version, char del){
    return encode_meta_val_internal(DataType::SSIZE, length, version, del);
}

string encode_zset_meta_val(uint64_t length, uint16_t version, char del){
    return encode_meta_val_internal(DataType::ZSIZE, length, version, del);
}

string encode_list_meta_val(uint64_t length, uint64_t left, uint64_t right, uint16_t version, char del){
    string buf(1, DataType::LSIZE);

    version = htobe16(version);
    buf.append((char *)&version, sizeof(uint16_t));

    buf.append(1, del);

    length = htobe64(length);
    buf.append((char *)&length, sizeof(uint64_t));

    left = htobe64(left);
    buf.append((char *)&left, sizeof(uint64_t));

    right = htobe64(right);
    buf.append((char *)&right, sizeof(uint64_t));

    return buf;
}

/*
 * delete key
 */
string encode_delete_key(const Bytes& key, uint16_t version){
    string buf(1, KEY_DELETE_MASK);

//    uint16_t slot = (uint16_t)keyHashSlot(key.data(), key.size());
//    slot = htobe16(slot);
//    buf.append((char *)&slot, sizeof(uint16_t));

    uint16_t len = htobe16((uint16_t)key.size());
    buf.append((char *)&len, sizeof(uint16_t));
    buf.append(key.data(), key.size());

    version = htobe16(version);
    buf.append((char *)&version, sizeof(uint16_t));

    return buf;
}

string encode_repo_key() {
    string buf(1, DataType::REPOKEY);

    return buf;
}

string encode_repo_item(uint64_t timestamp, uint64_t index) {
    string buf(1, DataType::REPOITEM);

    timestamp = htobe64(timestamp);
    buf.append((char *)&timestamp, sizeof(uint64_t));

    index = htobe64(index);
    buf.append((char *)&index, sizeof(uint64_t));

    return buf;
}
<|endoftext|>


<commit_before>#include "viewer.h"

#include <cstdlib>
#include <ctime>

#include <GL/gl.h>
#include <SDL.h>

#include "base/Log.h"
#include "base/Guard.h"

namespace viewer {

namespace {
const float MINNOTE = 100;
const float MAXNOTE = 300;
}

int Viewer::run() {
  typedef base::PtrGuard<SDL_Surface, SDL_FreeSurface> SurfaceGuard;
  typedef base::RunGuard<SDL_Quit> SDLQuitGuard;

  if (SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO) != 0) {
    VIEWER_LOG_ERROR << SDL_GetError() << VIEWER_LOG_END;
    return 1;
  }
  SDLQuitGuard sdlQuitGuard;

  SDL_WM_SetCaption("viewer", "viewer");

  SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
  SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
  SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
  SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
  SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

  SurfaceGuard screen(SDL_SetVideoMode(1024, 600, 24, SDL_OPENGL));
  if (!screen) {
    VIEWER_LOG_ERROR << SDL_GetError() << VIEWER_LOG_END;
    return 1;
  }

#if 0
  SDL_WM_ToggleFullScreen(screen.get());
#endif

  try {
    m_driver = new video::Driver(screen->w, screen->h);
  } catch (const video::TextException& e) {
    VIEWER_LOG_ERROR << e.what() << VIEWER_LOG_END;
    return 1;
  }

  m_width = screen->w;
  m_height = screen->h;

  // Seed random number generator
  srand(time(NULL));

  Uint32 last_time;
  Uint32 fps = 120;

  // Initialize time difference counter
  last_time = SDL_GetTicks();

  // Main loop
  for (;;) {
    Uint32 this_time = SDL_GetTicks();

    SDL_Event event;
    while (SDL_PollEvent(&event)) {
      switch (event.type) {
      case SDL_QUIT:
	goto end;
	break;
      case SDL_MOUSEBUTTONDOWN: {
	double ypos = m_height - event.button.y;
        double note = ypos / (m_height / (MAXNOTE - MINNOTE)) + MINNOTE;
        std::cerr << "note = " << note << std::endl;
      } break;
      default:
	break;
      }
    }

    try {
      // TODO Fix wraparound for time difference
      tick(this_time - last_time);
    } catch (const std::exception& e) {
      VIEWER_LOG_ERROR << e.what() << VIEWER_LOG_END;
      return 1;
    }

    m_driver->beginScene();
    draw();
    m_driver->endScene();

    last_time = this_time;

    Sint32 sleep_time = (1000 / fps) - (SDL_GetTicks() - last_time);
    if (sleep_time > 0) {
      SDL_Delay(sleep_time);
    }
  }

 end:
  return 0;
}

void Viewer::draw()
{
  std::lock_guard<std::mutex> lockGuard(mutex());

  auto noteToPos = [this](double note) {
    return (note - MINNOTE) * (m_height / (MAXNOTE - MINNOTE));
  };

  const double noteWidth = 2;
  // const double noteHeight = 20;

  double position = 0;
  for (auto note : cb()) {
    if (note.f0 != 0) {  // TODO float compare

      double ypos = noteToPos(note.f0);

      m_driver->draw2DRectangle(position, ypos - 1, position + noteWidth,
                                ypos + 1, video::Color(255, 255, 255, 255));
    }

    {
      double ypos = note.rms * (m_height / 3 / 24000.0) + (2.0 * m_height / 3);

      m_driver->draw2DRectangle(position, ypos - 1, position + noteWidth,
                                ypos + 1, video::Color(0, 100, 100, 255));
    }

    position += noteWidth;
  }

  // G3
  {
    double ypos = noteToPos(196);
    m_driver->draw2DLine(0, ypos, m_width, ypos, video::Color(255, 0, 0, 255));
  }

  // A3 - reach
  {
    double ypos = noteToPos(220);
    m_driver->draw2DLine(0, ypos, m_width, ypos, video::Color(100, 0, 0, 255));
  }

  // C4 - wow!
  {
    double ypos = noteToPos(262);
    m_driver->draw2DLine(0, ypos, m_width, ypos, video::Color(100, 0, 0, 255));
  }

  // C3 - don't go here
  {
    double ypos = noteToPos(131);
    m_driver->draw2DLine(0, ypos, m_width, ypos, video::Color(100, 0, 0, 255));
  }

}
}
<commit_msg>new target: a3<commit_after>#include "viewer.h"

#include <cstdlib>
#include <ctime>

#include <GL/gl.h>
#include <SDL.h>

#include "base/Log.h"
#include "base/Guard.h"

namespace viewer {

namespace {
const float MINNOTE = 100;
const float MAXNOTE = 300;
}

int Viewer::run() {
  typedef base::PtrGuard<SDL_Surface, SDL_FreeSurface> SurfaceGuard;
  typedef base::RunGuard<SDL_Quit> SDLQuitGuard;

  if (SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO) != 0) {
    VIEWER_LOG_ERROR << SDL_GetError() << VIEWER_LOG_END;
    return 1;
  }
  SDLQuitGuard sdlQuitGuard;

  SDL_WM_SetCaption("viewer", "viewer");

  SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
  SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
  SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
  SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
  SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

  SurfaceGuard screen(SDL_SetVideoMode(1024, 600, 24, SDL_OPENGL));
  if (!screen) {
    VIEWER_LOG_ERROR << SDL_GetError() << VIEWER_LOG_END;
    return 1;
  }

#if 0
  SDL_WM_ToggleFullScreen(screen.get());
#endif

  try {
    m_driver = new video::Driver(screen->w, screen->h);
  } catch (const video::TextException& e) {
    VIEWER_LOG_ERROR << e.what() << VIEWER_LOG_END;
    return 1;
  }

  m_width = screen->w;
  m_height = screen->h;

  // Seed random number generator
  srand(time(NULL));

  Uint32 last_time;
  Uint32 fps = 120;

  // Initialize time difference counter
  last_time = SDL_GetTicks();

  // Main loop
  for (;;) {
    Uint32 this_time = SDL_GetTicks();

    SDL_Event event;
    while (SDL_PollEvent(&event)) {
      switch (event.type) {
      case SDL_QUIT:
	goto end;
	break;
      case SDL_MOUSEBUTTONDOWN: {
	double ypos = m_height - event.button.y;
        double note = ypos / (m_height / (MAXNOTE - MINNOTE)) + MINNOTE;
        std::cerr << "note = " << note << std::endl;
      } break;
      default:
	break;
      }
    }

    try {
      // TODO Fix wraparound for time difference
      tick(this_time - last_time);
    } catch (const std::exception& e) {
      VIEWER_LOG_ERROR << e.what() << VIEWER_LOG_END;
      return 1;
    }

    m_driver->beginScene();
    draw();
    m_driver->endScene();

    last_time = this_time;

    Sint32 sleep_time = (1000 / fps) - (SDL_GetTicks() - last_time);
    if (sleep_time > 0) {
      SDL_Delay(sleep_time);
    }
  }

 end:
  return 0;
}

void Viewer::draw()
{
  std::lock_guard<std::mutex> lockGuard(mutex());

  auto noteToPos = [this](double note) {
    return (note - MINNOTE) * (m_height / (MAXNOTE - MINNOTE));
  };

  const double noteWidth = 2;
  // const double noteHeight = 20;

  double position = 0;
  for (auto note : cb()) {
    if (note.f0 != 0) {  // TODO float compare

      double ypos = noteToPos(note.f0);

      m_driver->draw2DRectangle(position, ypos - 1, position + noteWidth,
                                ypos + 1, video::Color(255, 255, 255, 255));
    }

    {
      double ypos = note.rms * (m_height / 3 / 24000.0) + (2.0 * m_height / 3);

      m_driver->draw2DRectangle(position, ypos - 1, position + noteWidth,
                                ypos + 1, video::Color(0, 100, 100, 255));
    }

    position += noteWidth;
  }

  // A3
  {
    double ypos = noteToPos(220);
    m_driver->draw2DLine(0, ypos, m_width, ypos, video::Color(255, 0, 0, 255));
  }

  // B3
  {
    double ypos = noteToPos(247);
    m_driver->draw2DLine(0, ypos, m_width, ypos, video::Color(100, 0, 0, 255));
  }

  // C4 - wow!
  {
    double ypos = noteToPos(262);
    m_driver->draw2DLine(0, ypos, m_width, ypos, video::Color(100, 0, 0, 255));
  }

  // C3 - don't go here
  {
    double ypos = noteToPos(131);
    m_driver->draw2DLine(0, ypos, m_width, ypos, video::Color(100, 0, 0, 255));
  }

}
}
<|endoftext|>


<commit_before>#ifndef STAN_MATH_PRIM_FUN_GRAD_2F1_HPP
#define STAN_MATH_PRIM_FUN_GRAD_2F1_HPP

#include <stan/math/prim/meta.hpp>
#include <stan/math/prim/err.hpp>
#include <stan/math/prim/fun/constants.hpp>
#include <stan/math/prim/fun/exp.hpp>
#include <stan/math/prim/fun/fabs.hpp>
#include <stan/math/prim/fun/inv.hpp>
#include <stan/math/prim/fun/log.hpp>
#include <cmath>

namespace stan {
namespace math {

/**
 * Gradients of the hypergeometric function, 2F1.
 *
 * Calculate the gradients of the hypergeometric function (2F1)
 * as the power series stopping when the series converges
 * to within precision or throwing when the
 * function takes max_steps steps.
 *
 * This power-series representation converges for all gradients
 * under the same conditions as the 2F1 function itself.
 *
 * @tparam T type of arguments and result
 * @param[out] g_a1 g_a1 pointer to array of six values of type T, result.
 * @param[out] g_b1 g_b1 pointer to array of six values of type T, result.
 * @param[in] a1 a1 see generalized hypergeometric function definition.
 * @param[in] a2 a2 see generalized hypergeometric function definition.
 * @param[in] b1 b1 see generalized hypergeometric function definition.
 * @param[in] z z see generalized hypergeometric function definition.
 * @param[in] precision precision of the infinite sum.
 * @param[in] max_steps number of steps to take.
 */
template <typename T>
void grad_2F1(T& g_a1, T& g_b1, const T& a1, const T& a2, const T& b1,
              const T& z, double precision = 1e-10, int max_steps = 1e6) {
  check_2F1_converges("grad_2F1", a1, a2, b1, z);

  using stan::math::value_of;
  using std::exp;
  using std::fabs;
  using std::log;
  using std::max;

  g_a1 = 0.0;
  g_b1 = 0.0;

  T log_g_old[2];
  for (auto& i : log_g_old) {
    i = NEGATIVE_INFTY;
  }

  T log_t_old = 0.0;
  T log_t_new = 0.0;

  T log_z = log(z);

  double log_precision = log(precision);
  double log_t_new_sign = 1.0;
  double log_t_old_sign = 1.0;
  double log_g_old_sign[2];
  for (double& x : log_g_old_sign) {
    x = 1.0;
  }

  for (int k = 0; k <= max_steps; ++k) {
    T p = (a1 + k) * (a2 + k) / ((b1 + k) * (1 + k));
    if (p == 0) {
      return;
    }

    log_t_new += log(fabs(p)) + log_z;
    log_t_new_sign = p >= 0.0 ? log_t_new_sign : -log_t_new_sign;

    T term = log_g_old_sign[0] * log_t_old_sign * exp(log_g_old[0] - log_t_old)
             + inv(a1 + k);
    log_g_old[0] = log_t_new + log(fabs(term));
    log_g_old_sign[0] = term >= 0.0 ? log_t_new_sign : -log_t_new_sign;

    term = log_g_old_sign[1] * log_t_old_sign * exp(log_g_old[1] - log_t_old)
           - inv(b1 + k);
    log_g_old[1] = log_t_new + log(fabs(term));
    log_g_old_sign[1] = term >= 0.0 ? log_t_new_sign : -log_t_new_sign;

    g_a1 += log_g_old_sign[0] > 0 ? exp(log_g_old[0]) : -exp(log_g_old[0]);
    g_b1 += log_g_old_sign[1] > 0 ? exp(log_g_old[1]) : -exp(log_g_old[1]);

    if (log_t_new <= std::max(value_of(log_t_new) + log_precision, log_precision)) {
      return;
    }

    log_t_old = log_t_new;
    log_t_old_sign = log_t_new_sign;
  }
  throw_domain_error("grad_2F1", "k (internal counter)", max_steps, "exceeded ",
                     " iterations, hypergeometric function gradient "
                     "did not converge.");
  return;
}

}  // namespace math
}  // namespace stan
#endif
<commit_msg>[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final)<commit_after>#ifndef STAN_MATH_PRIM_FUN_GRAD_2F1_HPP
#define STAN_MATH_PRIM_FUN_GRAD_2F1_HPP

#include <stan/math/prim/meta.hpp>
#include <stan/math/prim/err.hpp>
#include <stan/math/prim/fun/constants.hpp>
#include <stan/math/prim/fun/exp.hpp>
#include <stan/math/prim/fun/fabs.hpp>
#include <stan/math/prim/fun/inv.hpp>
#include <stan/math/prim/fun/log.hpp>
#include <cmath>

namespace stan {
namespace math {

/**
 * Gradients of the hypergeometric function, 2F1.
 *
 * Calculate the gradients of the hypergeometric function (2F1)
 * as the power series stopping when the series converges
 * to within precision or throwing when the
 * function takes max_steps steps.
 *
 * This power-series representation converges for all gradients
 * under the same conditions as the 2F1 function itself.
 *
 * @tparam T type of arguments and result
 * @param[out] g_a1 g_a1 pointer to array of six values of type T, result.
 * @param[out] g_b1 g_b1 pointer to array of six values of type T, result.
 * @param[in] a1 a1 see generalized hypergeometric function definition.
 * @param[in] a2 a2 see generalized hypergeometric function definition.
 * @param[in] b1 b1 see generalized hypergeometric function definition.
 * @param[in] z z see generalized hypergeometric function definition.
 * @param[in] precision precision of the infinite sum.
 * @param[in] max_steps number of steps to take.
 */
template <typename T>
void grad_2F1(T& g_a1, T& g_b1, const T& a1, const T& a2, const T& b1,
              const T& z, double precision = 1e-10, int max_steps = 1e6) {
  check_2F1_converges("grad_2F1", a1, a2, b1, z);

  using stan::math::value_of;
  using std::exp;
  using std::fabs;
  using std::log;
  using std::max;

  g_a1 = 0.0;
  g_b1 = 0.0;

  T log_g_old[2];
  for (auto& i : log_g_old) {
    i = NEGATIVE_INFTY;
  }

  T log_t_old = 0.0;
  T log_t_new = 0.0;

  T log_z = log(z);

  double log_precision = log(precision);
  double log_t_new_sign = 1.0;
  double log_t_old_sign = 1.0;
  double log_g_old_sign[2];
  for (double& x : log_g_old_sign) {
    x = 1.0;
  }

  for (int k = 0; k <= max_steps; ++k) {
    T p = (a1 + k) * (a2 + k) / ((b1 + k) * (1 + k));
    if (p == 0) {
      return;
    }

    log_t_new += log(fabs(p)) + log_z;
    log_t_new_sign = p >= 0.0 ? log_t_new_sign : -log_t_new_sign;

    T term = log_g_old_sign[0] * log_t_old_sign * exp(log_g_old[0] - log_t_old)
             + inv(a1 + k);
    log_g_old[0] = log_t_new + log(fabs(term));
    log_g_old_sign[0] = term >= 0.0 ? log_t_new_sign : -log_t_new_sign;

    term = log_g_old_sign[1] * log_t_old_sign * exp(log_g_old[1] - log_t_old)
           - inv(b1 + k);
    log_g_old[1] = log_t_new + log(fabs(term));
    log_g_old_sign[1] = term >= 0.0 ? log_t_new_sign : -log_t_new_sign;

    g_a1 += log_g_old_sign[0] > 0 ? exp(log_g_old[0]) : -exp(log_g_old[0]);
    g_b1 += log_g_old_sign[1] > 0 ? exp(log_g_old[1]) : -exp(log_g_old[1]);

    if (log_t_new
        <= std::max(value_of(log_t_new) + log_precision, log_precision)) {
      return;
    }

    log_t_old = log_t_new;
    log_t_old_sign = log_t_new_sign;
  }
  throw_domain_error("grad_2F1", "k (internal counter)", max_steps, "exceeded ",
                     " iterations, hypergeometric function gradient "
                     "did not converge.");
  return;
}

}  // namespace math
}  // namespace stan
#endif
<|endoftext|>


<commit_before>/**
 * A class which describes the properties and actions of a client application.
 *
 * @date                    December 25, 2014
 * @author                  Joeri HERMANS
 * @version                 0.1
 *
 * Copyright 2014 Joeri HERMANS
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// BEGIN Includes. ///////////////////////////////////////////////////

// System dependencies.
#include <cassert>
#include <vector>
#include <unistd.h>
#include <netinet/in.h>

// Application dependencies.
#include <ias/application/client/model/client_application_model.h>
#include <ias/network/posix/posix_tcp_socket.h>
#include <ias/network/posix/ssl/posix_ssl_socket.h>
#include <ias/network/proxy/socks.h>
#include <ias/network/util.h>
#include <ias/user/command/command_stop.h>

// END Includes. /////////////////////////////////////////////////////

// BEGIN Constants. //////////////////////////////////////////////////

const char ClientApplicationModel::kCommandQuit[] = "quit";

// END Constants. ////////////////////////////////////////////////////

void ClientApplicationModel::initialize( void ) {
    mSocket = nullptr;
    mSslContext = nullptr;
    mSocksHost.clear();
    mSocksPort = 0;
    mLoggedIn = false;
    mCommunicationThreadSend = nullptr;
    mCommunicationThreadReceive = nullptr;
}

void ClientApplicationModel::setSocketTimeouts( void ) {
    struct timeval tv;

    // Checking the precondition.
    assert( mSocket != nullptr );

    tv.tv_sec = 1;
    tv.tv_usec = 0;
    mSocket->setReceiveTimeout(tv);
}

int ClientApplicationModel::connectToSocksProxy( const std::string & host,
                                                 const std::size_t port ) const {
    int fd;

    fd = connectToSocks(mSocksHost,mSocksPort,host,port);

    return ( fd );
}

void ClientApplicationModel::readResponses( void ) {
    std::uint8_t messageType;
    Reader * reader;

    // Checking the precondition.
    assert( mSocket->isConnected() );

    reader = mSocket->getReader();
    messageType = 0xff;
    if( reader->readBytes(reinterpret_cast<char *>(&messageType),1) == 1 ) {
        switch(messageType) {
        case 0x00:
            sendHeartbeat();
            break;
        case 0x01:
            readResponse();
            break;
        case 0xff:
            mSocket->closeConnection();
            break;
        }
    }
}

void ClientApplicationModel::sendHeartbeat( void ) {
    static const std::uint8_t beat = 0x00;
    Writer * writer;

    // Checking the precondition.
    assert( isConnected() );

    mSendMutex.lock();
    writer = mSocket->getWriter();
    writer->writeBytes(reinterpret_cast<const char *>(&beat),1);
    mSendMutex.unlock();
}

void ClientApplicationModel::readResponse( void ) {
    Reader * reader;
    std::uint16_t messageSize;

    if( mSocket->isConnected() ) {
        reader = mSocket->getReader();
        messageSize = 0;
        reader->readBytes(reinterpret_cast<char *>(&messageSize),
                          sizeof(messageSize));
        messageSize = ntohs(messageSize);
        char buffer[messageSize + 1];
        reader->readBytes(buffer,static_cast<std::size_t>(messageSize));
        buffer[messageSize] = 0;
        notifyObservers(buffer);
    }
}

void ClientApplicationModel::stopCommunicationThreads( void ) {
    if( mCommunicationThreadSend != nullptr ) {
        mSendLock.notify_one();
        mCommunicationThreadSend->join();
        delete mCommunicationThreadSend;
        mCommunicationThreadSend = nullptr;
    }
    if( mCommunicationThreadReceive != nullptr ) {
        mCommunicationThreadReceive->join();
        delete mCommunicationThreadReceive;
        mCommunicationThreadReceive = nullptr;
    }
}

void ClientApplicationModel::spawnCommunicationThreads( void ) {
    if( mCommunicationThreadReceive == nullptr ) {
        mCommunicationThreadReceive = new std::thread([this]{
                handleCommunicationReceive();
        });
    }
    if( mCommunicationThreadSend == nullptr ) {
        mCommunicationThreadSend = new std::thread([this]{
                handleCommunicationSend();
        });
    }
}

void ClientApplicationModel::handleCommunicationSend( void ) {
    std::unique_lock<std::mutex> lock(mMutexThreadSendLock);
    std::string command;

    while( isConnected() ) {
        mCommandMutex.lock();
        if( !mCommandQueue.empty() ) {
            command = mCommandQueue.front();
            mCommandMutex.unlock();
        } else {
            mCommandMutex.unlock();
            mSendLock.wait(lock);
            continue;
        }
        if( !command.empty() && isConnected() ) {
            sendCommand(command);
            mCommandMutex.lock();
            mCommandQueue.pop();
            mCommandMutex.unlock();
            if( command == kCommandQuit ||
                command == CommandStop::kIdentifier ) {
                break;
            }
        }
    }
}

void ClientApplicationModel::sendCommand( const std::string & command ) {
    static const std::uint8_t message_type = 0x01;
    Writer * writer;
    std::uint8_t bytesWritten;
    std::uint8_t commandLength;
    std::uint8_t dBytes;
    std::size_t n;

    mSendMutex.lock();
    writer = mSocket->getWriter();
    writer->writeBytes(reinterpret_cast<const char *>(&message_type),1);
    // Retrieve the command's length.
    commandLength = static_cast<std::uint8_t>(command.length());
    writer->writeBytes(reinterpret_cast<const char *>(&commandLength),1);
    bytesWritten = 0;
    while( mSocket->isConnected() && bytesWritten < commandLength ) {
        dBytes = commandLength - bytesWritten;
        n = writer->writeBytes(command.c_str() + bytesWritten,dBytes);
        if( n == 0 )
            break;
        bytesWritten += n;
    }
    mSendMutex.unlock();
}

void ClientApplicationModel::handleCommunicationReceive( void ) {
    while( isConnected() ) {
        readResponses();
    }
}

ClientApplicationModel::ClientApplicationModel( void ) {
    initialize();
}

ClientApplicationModel::~ClientApplicationModel( void ) {
    delete mSocket; mSocket = nullptr;
    SSL_CTX_free(mSslContext); mSslContext = nullptr;
}

void ClientApplicationModel::setProxy( const std::string & host,
                                       const std::size_t port ) {
    mSocksHost = host;
    mSocksPort = port;
}

bool ClientApplicationModel::proxySpecified( void ) const {
    return ( !mSocksHost.empty() && mSocksPort > 0 );
}

void ClientApplicationModel::closeConnection( void ) {
    if( mSocket != nullptr ) {
        mSendLock.notify_one();
        while( !mCommandQueue.empty() )
            usleep(10000);
        mSocket->closeConnection();
        stopCommunicationThreads();
        delete mSocket;
        mSocket = nullptr;
        mLoggedIn = false;
    }
    notifyObservers();
}

void ClientApplicationModel::requestSsl( const bool flag ) {
    // Checking the precondition.
    assert( mSocket == nullptr );

    if( flag ) {
        if( mSslContext == nullptr )
            mSslContext = SSL_CTX_new(SSLv23_client_method());
    } else {
        if( mSslContext != nullptr ) {
            SSL_CTX_free(mSslContext);
            mSslContext = nullptr;
        }
    }
}

bool ClientApplicationModel::sslRequested( void ) const {
    return ( mSslContext != nullptr );
}

bool ClientApplicationModel::isConnected( void ) const {
    return ( mSocket != nullptr && mSocket->isConnected() );
}

void ClientApplicationModel::createConnection( const std::string & host,
                                               const std::size_t port ) {
    int fd;

    // Checking the precondition.
    assert( !host.empty() && port > 0 && !isConnected() );

    fd = -1;
    // Initialize the connection with the remote IAS service.
    if( proxySpecified() )
        fd = connectToSocksProxy(host,port);
    else
        fd = connect(host,port);
    // Check if a connection could be established.
    if( fd >= 0 ) {
        if( sslRequested() ) {
            SSL * ssl;

            ssl = SSL_new(mSslContext);
            SSL_set_fd(ssl,fd);
            if( SSL_connect(ssl) <= 0 ) {
                SSL_free(ssl);
                close(fd);
            } else {
                mSocket = new PosixSslSocket(ssl);
            }
        } else {
            mSocket = new PosixTcpSocket(fd);
        }
        if( mSocket != nullptr )
            setSocketTimeouts();
    }
    notifyObservers();
}

bool ClientApplicationModel::isLoggedIn( void ) const {
    return ( mLoggedIn );
}

void ClientApplicationModel::authorize( const std::string & username,
                                        const std::string & password ) {
    static const std::uint8_t message_type = 0x00;
    std::uint8_t byte;
    Writer * writer;
    Reader * reader;

    // Checking the precondition.
    assert( !username.empty() && username.length() <= 0xff &&
            !password.empty() && !password.length() <= 0xff &&
            mSocket != nullptr );

    if( mSocket->isConnected() ) {
        writer = mSocket->getWriter();
        reader = mSocket->getReader();
        // Send the message type.
        writer->writeBytes(reinterpret_cast<const char *>(&message_type),1);
        // Send the username length and username.
        byte = static_cast<std::uint8_t>(username.length());
        writer->writeBytes(reinterpret_cast<const char *>(&byte),1);
        writer->writeBytes(username.c_str(),byte);
        // Send the password length and password.
        byte = static_cast<std::uint8_t>(password.length());
        writer->writeBytes(reinterpret_cast<const char *>(&byte),1);
        writer->writeBytes(password.c_str(),byte);
        // Check if authentication is successful.
        if( reader->readByte(reinterpret_cast<char *>(&byte)) == 1 &&
            byte == 0x00 &&
            reader->readByte(reinterpret_cast<char *>(&byte)) == 1 &&
            byte == 0x01 ) {
            mLoggedIn = true;
            stopCommunicationThreads();
            spawnCommunicationThreads();
        }
    }
    notifyObservers();
}

void ClientApplicationModel::execute( const std::string & command ) {
    // Checking the precondition.
    assert( isConnected() && !command.empty() && command.length() <= 0xff );

    mCommandMutex.lock();
    mCommandQueue.push(command);
    mSendLock.notify_one();
    mCommandMutex.unlock();
}
<commit_msg>Modify command execution.<commit_after>/**
 * A class which describes the properties and actions of a client application.
 *
 * @date                    December 25, 2014
 * @author                  Joeri HERMANS
 * @version                 0.1
 *
 * Copyright 2014 Joeri HERMANS
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// BEGIN Includes. ///////////////////////////////////////////////////

// System dependencies.
#include <cassert>
#include <vector>
#include <unistd.h>
#include <netinet/in.h>

// Application dependencies.
#include <ias/application/client/model/client_application_model.h>
#include <ias/network/posix/posix_tcp_socket.h>
#include <ias/network/posix/ssl/posix_ssl_socket.h>
#include <ias/network/proxy/socks.h>
#include <ias/network/util.h>
#include <ias/user/command/command_stop.h>

// END Includes. /////////////////////////////////////////////////////

// BEGIN Constants. //////////////////////////////////////////////////

const char ClientApplicationModel::kCommandQuit[] = "quit";

// END Constants. ////////////////////////////////////////////////////

void ClientApplicationModel::initialize( void ) {
    mSocket = nullptr;
    mSslContext = nullptr;
    mSocksHost.clear();
    mSocksPort = 0;
    mLoggedIn = false;
    mCommunicationThreadSend = nullptr;
    mCommunicationThreadReceive = nullptr;
}

void ClientApplicationModel::setSocketTimeouts( void ) {
    struct timeval tv;

    // Checking the precondition.
    assert( mSocket != nullptr );

    tv.tv_sec = 1;
    tv.tv_usec = 0;
    mSocket->setReceiveTimeout(tv);
}

int ClientApplicationModel::connectToSocksProxy( const std::string & host,
                                                 const std::size_t port ) const {
    int fd;

    fd = connectToSocks(mSocksHost,mSocksPort,host,port);

    return ( fd );
}

void ClientApplicationModel::readResponses( void ) {
    std::uint8_t messageType;
    Reader * reader;

    // Checking the precondition.
    assert( mSocket->isConnected() );

    reader = mSocket->getReader();
    messageType = 0xff;
    if( reader->readBytes(reinterpret_cast<char *>(&messageType),1) == 1 ) {
        switch(messageType) {
        case 0x00:
            sendHeartbeat();
            break;
        case 0x01:
            readResponse();
            break;
        case 0xff:
            mSocket->closeConnection();
            break;
        }
    }
}

void ClientApplicationModel::sendHeartbeat( void ) {
    static const std::uint8_t beat = 0x00;
    Writer * writer;

    // Checking the precondition.
    assert( isConnected() );

    mSendMutex.lock();
    writer = mSocket->getWriter();
    writer->writeBytes(reinterpret_cast<const char *>(&beat),1);
    mSendMutex.unlock();
}

void ClientApplicationModel::readResponse( void ) {
    Reader * reader;
    std::uint16_t messageSize;

    if( mSocket->isConnected() ) {
        reader = mSocket->getReader();
        messageSize = 0;
        reader->readBytes(reinterpret_cast<char *>(&messageSize),
                          sizeof(messageSize));
        messageSize = ntohs(messageSize);
        char buffer[messageSize + 1];
        reader->readBytes(buffer,static_cast<std::size_t>(messageSize));
        buffer[messageSize] = 0;
        notifyObservers(buffer);
    }
}

void ClientApplicationModel::stopCommunicationThreads( void ) {
    if( mCommunicationThreadSend != nullptr ) {
        mSendLock.notify_one();
        mCommunicationThreadSend->join();
        delete mCommunicationThreadSend;
        mCommunicationThreadSend = nullptr;
    }
    if( mCommunicationThreadReceive != nullptr ) {
        mCommunicationThreadReceive->join();
        delete mCommunicationThreadReceive;
        mCommunicationThreadReceive = nullptr;
    }
}

void ClientApplicationModel::spawnCommunicationThreads( void ) {
    if( mCommunicationThreadReceive == nullptr ) {
        mCommunicationThreadReceive = new std::thread([this]{
                handleCommunicationReceive();
        });
    }
    if( mCommunicationThreadSend == nullptr ) {
        mCommunicationThreadSend = new std::thread([this]{
                handleCommunicationSend();
        });
    }
}

void ClientApplicationModel::handleCommunicationSend( void ) {
    std::unique_lock<std::mutex> lock(mMutexThreadSendLock);
    std::string command;

    while( isConnected() ) {
        mCommandMutex.lock();
        if( !mCommandQueue.empty() ) {
            command = mCommandQueue.front();
            mCommandMutex.unlock();
        } else {
            mCommandMutex.unlock();
            mSendLock.wait(lock);
            continue;
        }
        if( !command.empty() && isConnected() ) {
            sendCommand(command);
            mCommandMutex.lock();
            mCommandQueue.pop();
            mCommandMutex.unlock();
            if( command == kCommandQuit ||
                command == CommandStop::kIdentifier ) {
                break;
            }
        }
    }
}

void ClientApplicationModel::sendCommand( const std::string & command ) {
    static const std::uint8_t message_type = 0x01;
    Writer * writer;
    std::uint8_t bytesWritten;
    std::uint8_t commandLength;
    std::uint8_t dBytes;
    std::size_t n;

    if( command != kCommandQuit ) {
        mSendMutex.lock();
        writer = mSocket->getWriter();
        writer->writeBytes(reinterpret_cast<const char *>(&message_type),1);
        // Retrieve the command's length.
        commandLength = static_cast<std::uint8_t>(command.length());
        writer->writeBytes(reinterpret_cast<const char *>(&commandLength),1);
        bytesWritten = 0;
        while( mSocket->isConnected() && bytesWritten < commandLength ) {
            dBytes = commandLength - bytesWritten;
            n = writer->writeBytes(command.c_str() + bytesWritten,dBytes);
            if( n == 0 )
                break;
            bytesWritten += n;
        }
        mSendMutex.unlock();
    }
}

void ClientApplicationModel::handleCommunicationReceive( void ) {
    while( isConnected() ) {
        readResponses();
    }
}

ClientApplicationModel::ClientApplicationModel( void ) {
    initialize();
}

ClientApplicationModel::~ClientApplicationModel( void ) {
    delete mSocket; mSocket = nullptr;
    SSL_CTX_free(mSslContext); mSslContext = nullptr;
}

void ClientApplicationModel::setProxy( const std::string & host,
                                       const std::size_t port ) {
    mSocksHost = host;
    mSocksPort = port;
}

bool ClientApplicationModel::proxySpecified( void ) const {
    return ( !mSocksHost.empty() && mSocksPort > 0 );
}

void ClientApplicationModel::closeConnection( void ) {
    if( mSocket != nullptr ) {
        mSendLock.notify_one();
        while( !mCommandQueue.empty() )
            usleep(10000);
        mSocket->closeConnection();
        stopCommunicationThreads();
        delete mSocket;
        mSocket = nullptr;
        mLoggedIn = false;
    }
    notifyObservers();
}

void ClientApplicationModel::requestSsl( const bool flag ) {
    // Checking the precondition.
    assert( mSocket == nullptr );

    if( flag ) {
        if( mSslContext == nullptr )
            mSslContext = SSL_CTX_new(SSLv23_client_method());
    } else {
        if( mSslContext != nullptr ) {
            SSL_CTX_free(mSslContext);
            mSslContext = nullptr;
        }
    }
}

bool ClientApplicationModel::sslRequested( void ) const {
    return ( mSslContext != nullptr );
}

bool ClientApplicationModel::isConnected( void ) const {
    return ( mSocket != nullptr && mSocket->isConnected() );
}

void ClientApplicationModel::createConnection( const std::string & host,
                                               const std::size_t port ) {
    int fd;

    // Checking the precondition.
    assert( !host.empty() && port > 0 && !isConnected() );

    fd = -1;
    // Initialize the connection with the remote IAS service.
    if( proxySpecified() )
        fd = connectToSocksProxy(host,port);
    else
        fd = connect(host,port);
    // Check if a connection could be established.
    if( fd >= 0 ) {
        if( sslRequested() ) {
            SSL * ssl;

            ssl = SSL_new(mSslContext);
            SSL_set_fd(ssl,fd);
            if( SSL_connect(ssl) <= 0 ) {
                SSL_free(ssl);
                close(fd);
            } else {
                mSocket = new PosixSslSocket(ssl);
            }
        } else {
            mSocket = new PosixTcpSocket(fd);
        }
        if( mSocket != nullptr )
            setSocketTimeouts();
    }
    notifyObservers();
}

bool ClientApplicationModel::isLoggedIn( void ) const {
    return ( mLoggedIn );
}

void ClientApplicationModel::authorize( const std::string & username,
                                        const std::string & password ) {
    static const std::uint8_t message_type = 0x00;
    std::uint8_t byte;
    Writer * writer;
    Reader * reader;

    // Checking the precondition.
    assert( !username.empty() && username.length() <= 0xff &&
            !password.empty() && !password.length() <= 0xff &&
            mSocket != nullptr );

    if( mSocket->isConnected() ) {
        writer = mSocket->getWriter();
        reader = mSocket->getReader();
        // Send the message type.
        writer->writeBytes(reinterpret_cast<const char *>(&message_type),1);
        // Send the username length and username.
        byte = static_cast<std::uint8_t>(username.length());
        writer->writeBytes(reinterpret_cast<const char *>(&byte),1);
        writer->writeBytes(username.c_str(),byte);
        // Send the password length and password.
        byte = static_cast<std::uint8_t>(password.length());
        writer->writeBytes(reinterpret_cast<const char *>(&byte),1);
        writer->writeBytes(password.c_str(),byte);
        // Check if authentication is successful.
        if( reader->readByte(reinterpret_cast<char *>(&byte)) == 1 &&
            byte == 0x00 &&
            reader->readByte(reinterpret_cast<char *>(&byte)) == 1 &&
            byte == 0x01 ) {
            mLoggedIn = true;
            stopCommunicationThreads();
            spawnCommunicationThreads();
        }
    }
    notifyObservers();
}

void ClientApplicationModel::execute( const std::string & command ) {
    // Checking the precondition.
    assert( isConnected() && !command.empty() && command.length() <= 0xff );

    mCommandMutex.lock();
    mCommandQueue.push(command);
    mSendLock.notify_one();
    mCommandMutex.unlock();
}
<|endoftext|>


<commit_before>#include "chainerx/python/cuda/cuda_module.h"

#include <cstddef>
#include <cstdint>
#include <memory>
#include <utility>

#include <pybind11/functional.h>
#include <pybind11/pybind11.h>

#include "chainerx/cuda/cuda_device.h"
#include "chainerx/cuda/memory_pool.h"
#include "chainerx/device.h"

#include "chainerx/python/backend.h"
#include "chainerx/python/common.h"
#include "chainerx/python/context.h"
#include "chainerx/python/device.h"

namespace chainerx {
namespace python {
namespace cuda {
namespace cuda_internal {

namespace py = pybind11;

using CudaDevice = chainerx::cuda::CudaDevice;

void* Malloc(void* backend, size_t bytesize, int device_id) {
    CudaDevice* device = dynamic_cast<CudaDevice*>(
            &reinterpret_cast<Backend*>(backend)->GetDevice(device_id));  // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
    return device->device_memory_pool()->Malloc(bytesize);
}

void Free(void* backend, void* ptr, int device_id) {
    CudaDevice* device = dynamic_cast<CudaDevice*>(
            &reinterpret_cast<Backend*>(backend)->GetDevice(device_id));  // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
    return device->device_memory_pool()->Free(ptr);
}

intptr_t GetBackendPtr() {
    return reinterpret_cast<intptr_t>(&GetBackend("cuda"));  // NOLINT(cppcoreguidelines-cppcoreguidelines);
}

std::pair<intptr_t, intptr_t> GetBackendMallocFreePtrs() {
    return std::make_pair(
            reinterpret_cast<intptr_t>(&Malloc), reinterpret_cast<intptr_t>(&Free));  // NOLINT(cppcoreguidelines-cppcoreguidelines);
}

void InitChainerxCudaModule(py::module& m) {
    // Exposes pointers to objects and functions so that external sources can allocate CUDA memory via ChainerX.
    m.def("get_backend_ptr", []() -> intptr_t { return GetBackendPtr(); });
    m.def("get_backend_malloc_free_ptrs", []() -> std::pair<intptr_t, intptr_t> { return GetBackendMallocFreePtrs(); });
}

}  // namespace cuda_internal
}  // namespace cuda
}  // namespace python
}  // namespace chainerx
<commit_msg>Fix includes<commit_after>#include "chainerx/python/cuda/cuda_module.h"

#include <cstddef>
#include <cstdint>
#include <utility>

#include <pybind11/pybind11.h>

#include "chainerx/backend.h"
#include "chainerx/context.h"
#include "chainerx/cuda/cuda_device.h"
#include "chainerx/cuda/memory_pool.h"

#include "chainerx/python/common.h"

namespace chainerx {
namespace python {
namespace cuda {
namespace cuda_internal {

namespace py = pybind11;

using CudaDevice = chainerx::cuda::CudaDevice;

void* Malloc(void* backend, size_t bytesize, int device_id) {
    CudaDevice* device = dynamic_cast<CudaDevice*>(
            &reinterpret_cast<Backend*>(backend)->GetDevice(device_id));  // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
    return device->device_memory_pool()->Malloc(bytesize);
}

void Free(void* backend, void* ptr, int device_id) {
    CudaDevice* device = dynamic_cast<CudaDevice*>(
            &reinterpret_cast<Backend*>(backend)->GetDevice(device_id));  // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
    return device->device_memory_pool()->Free(ptr);
}

intptr_t GetBackendPtr() {
    return reinterpret_cast<intptr_t>(&GetBackend("cuda"));  // NOLINT(cppcoreguidelines-cppcoreguidelines);
}

std::pair<intptr_t, intptr_t> GetBackendMallocFreePtrs() {
    return std::make_pair(
            reinterpret_cast<intptr_t>(&Malloc), reinterpret_cast<intptr_t>(&Free));  // NOLINT(cppcoreguidelines-cppcoreguidelines);
}

void InitChainerxCudaModule(py::module& m) {
    // Exposes pointers to objects and functions so that external sources can allocate CUDA memory via ChainerX.
    m.def("get_backend_ptr", []() -> intptr_t { return GetBackendPtr(); });
    m.def("get_backend_malloc_free_ptrs", []() -> std::pair<intptr_t, intptr_t> { return GetBackendMallocFreePtrs(); });
}

}  // namespace cuda_internal
}  // namespace cuda
}  // namespace python
}  // namespace chainerx
<|endoftext|>