Пример #1
0
void ChatGreeter::welcome(Publisher atPub, const std::string& nodeId, const std::string& subId) {
	Message* greeting = Message::toSubscriber(subId);
	greeting->putMeta("participant", _username);
	greeting->putMeta("subscriber", _subId);
	atPub.send(greeting);
	delete greeting;
}
Пример #2
0
	void receive(Message* msg) {

		RScopeLock lock(mutex);

		uint64_t currServerTimeStamp;
		Message::read(msg->data(), &currSeqNr);
		Message::read(msg->data() + 8, &currServerTimeStamp);
		Message::read(msg->data() + 16, &reportInterval);

		if (currSeqNr < lastSeqNr) {
			// new throughput run!
			lastSeqNr = 0;
			timeStampServerFirst = 0;
			currReportNr = 0;
			bytesRcvd = 0;
			pktsRecvd = 0;
			pktsDropped = 0;
		}

		bytesRcvd += msg->size();
		pktsRecvd++;

		if (timeStampServerFirst == 0)
			timeStampServerFirst = currServerTimeStamp;

		if (lastSeqNr > 0 && lastSeqNr != currSeqNr - 1) {
			pktsDropped += currSeqNr - lastSeqNr;
		}

		lastSeqNr = currSeqNr;

		// reply?
		if (currServerTimeStamp - reportInterval >= timeStampServerLast) {
			RScopeLock lock(mutex);
			timeStampServerLast = currServerTimeStamp;

			Message* msg = new Message();
			msg->putMeta("bytes.rcvd", toStr(bytesRcvd));
			msg->putMeta("pkts.dropped", toStr(pktsDropped));
			msg->putMeta("pkts.rcvd", toStr(pktsRecvd));
			msg->putMeta("last.seq", toStr(lastSeqNr));
			msg->putMeta("report.seq", toStr(currReportNr++));
			msg->putMeta("timestamp.server.last", toStr(timeStampServerLast));
			msg->putMeta("timestamp.server.first", toStr(timeStampServerFirst));
			msg->putMeta("hostname", umundo::Host::getHostname());
			reporter.send(msg);
			delete msg;

			pktsDropped = 0;
			pktsRecvd = 0;
			bytesRcvd = 0;
		}

	}
Пример #3
0
void testDomainReception() {
	Node* fooNode1 = new Node("foo");
	Node* fooNode2 = new Node("foo");
	Node* barNode = new Node("bar");
	assert(Node::instances == 3);

	Subscriber* sub = new Subscriber("test1", new TestReceiver("test1"));
	Publisher* pub = new Publisher("test1");

	fooNode1->addPublisher(pub);
	fooNode2->addPublisher(pub);
	barNode->addPublisher(pub);

	fooNode1->addSubscriber(sub);
	fooNode2->addSubscriber(sub);
	barNode->addSubscriber(sub);

	char buffer[BUFFER_SIZE];
	for (int i = 0; i < BUFFER_SIZE; i++) {
		buffer[i] = (char)i%255;
	}

	pub->waitForSubscribers(1);
	assert(pub->waitForSubscribers(1) >= 1);
	Thread::sleepMs(100);

	int iterations = 10; // this has to be less or equal to the high water mark / 3
	receives = 0;
	for (int i = 0; i < iterations; i++) {
		Message* msg = new Message();
		msg->setData(buffer, BUFFER_SIZE);
		msg->setMeta("type", "foo!");
		pub->send(msg);
		delete(msg);
	}

	Thread::sleepMs(200);
	std::cout << "Received " << receives << " messages, expected " << iterations << " messages" << std::endl;
//  assert(receives == iterations);

	delete(fooNode1);
	delete(fooNode2);
	delete(barNode);

	delete(sub);
	delete(pub);

}
Пример #4
0
void runAsServer() {
	ThroughputGreeter tpGreeter;
	
	Publisher pub;
	switch (type) {
		case PUB_RTP: {
			PublisherConfigRTP config("throughput.rtp");
			config.setTimestampIncrement(166);
			pub = Publisher(&config);
			pub.setGreeter(&tpGreeter);
			break;
		}
		case PUB_MCAST: {
			PublisherConfigMCast config("throughput.mcast");
			config.setTimestampIncrement(166);
			//			config.setPortbase(42142);
			pub = Publisher(&config);
			pub.setGreeter(&tpGreeter);
			break;
		}
		case PUB_TCP: {
			pub = Publisher("throughput.tcp");
			pub.setGreeter(&tpGreeter);
			break;
		}
	}
	
	node.addPublisher(pub);
	
	disc.add(node);
	timeStampStartedAt = Thread::getTimeStampMs();
	
	if (duration > 0)
		duration *= 1000; // convert to ms
	
	pub.waitForSubscribers(waitForSubs);
	
	// reserve 20 bytes for timestamp, sequence number and report interval
	size_t dataSize = (std::max)(mtu, (size_t)20);
	char* data = (char*)malloc(dataSize);
	Message* msg = NULL;
	if (useZeroCopy) {
		msg = new Message(data, dataSize, doneCallback, (void*)NULL);
	} else {
		msg = new Message();
	}
	
	uint64_t lastReportAt = Thread::getTimeStampMs();

	while(1) {
		uint64_t now = Thread::getTimeStampMs();
		
		if (duration > 0 && now - timeStampStartedAt > duration)
			break;
		
		// first 16 bytes are seqNr and timestamp
		Message::write(&data[0], ++currSeqNr);
		Message::write(&data[8], now);
		Message::write(&data[16], reportInterval);
		
		if (!useZeroCopy) {
			msg->setData(data, dataSize);
		}
		
		pub.send(msg);
		
		intervalFactor = 1000.0 / (double)reportInterval;
		bytesWritten += dataSize;
		bytesTotal += dataSize;
		packetsWritten++;
		
		// sleep just enough to reach the desired bps
		{
			RScopeLock lock(mutex);
			size_t packetsPerSecond = (std::max)(bytesPerSecond / dataSize, (size_t)1);
			delay = (std::max)((1000000) / (packetsPerSecond), (size_t)1);
		}
		
		// every report interval we are recalculating bandwith
		if (now - lastReportAt > reportInterval) {
			RScopeLock lock(mutex);
			
			std::string scaleInfo("--");
			// and recalculate bytes to send
			if (reports.size() > 0) {
				double decreasePressure = 0;
				
				// print report messages
				std::map<std::string, Report>::iterator repIter = reports.begin();
				
				// bandwidth is not fixed
				if (fixedBytesPerSecond == 0) {
					while(repIter != reports.end()) {
						const Report& report = repIter->second;
						double reportPressure = 0;
						
						// see if we need to decrease bandwidth
						if (report.pktsLate > packetsWritten / 2) {
							// client is lagging more than half a second, scale back somewhat
							reportPressure = (std::max)(1.1, reportPressure);
						}
						if (report.pcntLoss > pcntLossOk) {
							// we lost packages, scale back somewhat
							reportPressure = (std::max)((double)report.pktsDropped / report.pktsRcvd, reportPressure);
							reportPressure = (std::min)(reportPressure, 1.4);
						}
						if (report.pktsLate > 3 * packetsWritten) {
							// queues explode! scale back alot!
							reportPressure = (std::max)((double)report.pktsLate / packetsWritten, reportPressure);
							reportPressure = (std::min)(reportPressure, 2.0);
						}
						
						if (reportPressure > decreasePressure)
							decreasePressure = reportPressure;
						
						repIter++;
					}
					
					if (decreasePressure > 1) {
						bytesPerSecond *= (1.0 / decreasePressure);
						bytesPerSecond = (std::max)(bytesPerSecond, (size_t)(1024));
						scaleInfo = "down " + toStr(1.0 / decreasePressure);
					} else {
						bytesPerSecond *= 1.2;
						scaleInfo = "up 1.2";
					}
					std::cout << std::endl;
				} else {
					
					if (bytesWritten * intervalFactor < fixedBytesPerSecond) {
						bytesPerSecond *= 1.05;
					} else if (bytesWritten * intervalFactor > fixedBytesPerSecond)  {
						bytesPerSecond *= 0.95;
					}
				}
			}
			currReportNr++;

			writeReports(scaleInfo);

			bytesWritten = 0;
			packetsWritten = 0;
			
			lastReportAt = Thread::getTimeStampMs();
		}

		// now we sleep until we have to send another packet
		Thread::sleepUs(delay);
	}
	
	pub.setGreeter(NULL);
	delete(msg);
}
Пример #5
0
void runAsServer() {
	ThroughputGreeter tpGreeter;

	Publisher pub;
	PublisherConfig* config = NULL;

	switch (type) {
	case PUB_RTP: {
		config = new PublisherConfigRTP("throughput.rtp");
		((PublisherConfigRTP*)config)->setTimestampIncrement(166);
		break;
	}
	case PUB_MCAST: {
		config = new PublisherConfigMCast("throughput.mcast");
		((PublisherConfigMCast*)config)->setTimestampIncrement(166);
		//			config.setPortbase(42142);
		break;
	}
	case PUB_TCP: {
		config = new PublisherConfigTCP ("throughput.tcp");
		break;
	}
	}
	if (compressionType.size() != 0)
		config->enableCompression(compressionType, compressionWithState, compressionLevel, compressionRefreshInterval);

	pub = Publisher(config);
	pub.setGreeter(&tpGreeter);
	delete config;

	node.addPublisher(pub);

	disc.add(node);
    timeStampStartedDiscovery = Thread::getTimeStampMs();

	if (duration > 0)
		duration *= 1000; // convert to ms

    // open file with data
    std::ifstream fin(streamFile, std::ios::in | std::ios::binary);
    if (fin) {
        // streamFile exists on filesyste,, slurp content into streamData
        streamData = std::string((std::istreambuf_iterator<char>(fin) ),
                                 (std::istreambuf_iterator<char>()     ));
    } else {
        // stream file is no actual file, interpret as "size:compressability"
        char* compArg = streamFile;
        
        // http://stackoverflow.com/a/53878/990120
        std::list<std::string> compArgs;
        do {
            const char *begin = compArg;
            while(*compArg != ':' && *compArg)
                compArg++;
            compArgs.push_back(std::string(begin, compArg - begin));
        } while(0 != *compArg++);

        size_t streamDataSize = 0;
        double compressibility = 50;

        if (compArgs.size() < 1)
            printUsageAndExit();
        
        streamDataSize = displayToBytes(compArgs.front());
        compArgs.pop_front();
        
        if (!compArgs.empty()) {
            compressibility = strTo<double>(compArgs.front());
            if (toStr(compressibility) != compArgs.front())
                printUsageAndExit();
            compArgs.pop_front();
        }
        
        if (!compArgs.empty()) {
            printUsageAndExit();
        }
        
        streamData.resize(streamDataSize);
        RDG_genBuffer(&streamData[0], streamDataSize, 1 - (compressibility/(double)100), 0.0, 0);
    }
    
    {
        // determine compressionActualRatio
        Message msg(streamData.data(), streamData.size());
        size_t compressMaxPayload = msg.getCompressBounds("lz4", NULL, Message::Compression::PAYLOAD);
        char* compressPayloadData = (char*)malloc(compressMaxPayload);
        
        size_t compressActualPayload = msg.compress("lz4", NULL, compressPayloadData, compressMaxPayload, Message::Compression::PAYLOAD);
        compressionActualRatio = 100 * ((double)compressActualPayload / streamData.size());
    }
    
    pub.waitForSubscribers(waitForSubs);
    timeStampStartedPublishing = Thread::getTimeStampMs();

    uint64_t lastReportAt = Thread::getTimeStampMs();
    size_t streamDataOffset = 0;

	while(1) {
        
        // fill data from stream data
        Message* msg = new Message((char*)malloc(mtu), mtu);

        size_t msgDataOffset = 0;
        while(true) {
            size_t toRead = (mtu - msgDataOffset <= streamData.size() - streamDataOffset ? mtu - msgDataOffset : streamData.size() - streamDataOffset);
            memcpy(&msg->data()[msgDataOffset], &streamData[streamDataOffset], toRead);
            msgDataOffset += toRead;
            streamDataOffset += toRead;
//            UM_LOG_WARN("%d: %d / %d", streamData.size(), msgDataOffset, streamDataOffset);
            if (msgDataOffset == mtu)
                break;
            if (streamData.size() == streamDataOffset)
                streamDataOffset = 0;
        }
//        UM_LOG_WARN("%d: %s", msg->size(), md5(msg->data(), msg->size()).c_str());
        
		uint64_t now = Thread::getTimeStampMs();
		if (duration > 0 && now - timeStampStartedPublishing > duration)
			break;

		// first 16 bytes are seqNr and timestamp
		Message::write(&msg->data()[0], ++currSeqNr);
		Message::write(&msg->data()[8], now);
		Message::write(&msg->data()[16], reportInterval);

//        msg->putMeta("md5", md5(msg->data(), msg->size()));
		intervalFactor = 1000.0 / (double)reportInterval;
		bytesWritten += msg->size();
		bytesTotal += msg->size();
		packetsWritten++;

		// sleep just enough to reach the desired bps
		{
			RScopeLock lock(mutex);
			size_t packetsPerSecond = (std::max)(bytesPerSecond / msg->size(), (size_t)1);
			delay = (std::max)((1000000) / (packetsPerSecond), (size_t)1);
		}

		// sending with compression will alter msg->size(); not anymore ...
		pub.send(msg);

		// every report interval we are recalculating bandwith
		if (now - lastReportAt > reportInterval) {
			RScopeLock lock(mutex);

			std::string scaleInfo("--");
			// and recalculate bytes to send
			if (reports.size() > 0) {
				double decreasePressure = 0;

				// print report messages
				std::map<std::string, Report>::iterator repIter = reports.begin();

				// bandwidth is fixed
				if (fixedBytesPerSecond == 0) {
					while(repIter != reports.end()) {
						const Report& report = repIter->second;
						double reportPressure = 0;

						// see if we need to decrease bandwidth
						if (report.pktsLate > packetsWritten / 2) {
							// client is lagging more than half a second, scale back somewhat
							reportPressure = (std::max)(1.1, reportPressure);
						}
						if (report.pcntLoss > pcntLossOk) {
							// we lost packages, scale back somewhat
							reportPressure = (std::max)((double)report.pktsDropped / report.pktsRcvd, reportPressure);
							reportPressure = (std::min)(reportPressure, 1.4);
						}
						if (report.pktsLate > 3 * packetsWritten) {
							// queues explode! scale back alot!
							reportPressure = (std::max)((double)report.pktsLate / packetsWritten, reportPressure);
							reportPressure = (std::min)(reportPressure, 2.0);
						}

						if (reportPressure > decreasePressure)
							decreasePressure = reportPressure;

						repIter++;
					}

					if (decreasePressure > 1) {
						bytesPerSecond *= (1.0 / decreasePressure);
						bytesPerSecond = (std::max)(bytesPerSecond, (size_t)(1024));
						scaleInfo = "down " + toStr(1.0 / decreasePressure);
					} else {
						bytesPerSecond *= 1.3;
						scaleInfo = "up 1.3";
					}
					std::cout << std::endl;
				} else if (fixedBytesPerSecond == (size_t)-1) {
					// do nothing
				} else {

					if (bytesWritten * intervalFactor < fixedBytesPerSecond) {
						bytesPerSecond *= 1.05;
					} else if (bytesWritten * intervalFactor > fixedBytesPerSecond)  {
						bytesPerSecond *= 0.95;
					}
				}
			}
			currReportNr++;

			writeReports(scaleInfo);

			bytesWritten = 0;
			packetsWritten = 0;

			lastReportAt = Thread::getTimeStampMs();
		}

        delete(msg);

		// now we sleep until we have to send another packet
		if (delay > 50 && fixedBytesPerSecond != (size_t) - 1)
			Thread::sleepUs(delay);
	}

	pub.setGreeter(NULL);
}
Пример #6
0
	void receive(Message* msg) {

		RScopeLock lock(mutex);

        if (msg->getMeta("md5").size() > 0 && msg->getMeta("md5") != md5(msg->data(), msg->size())) {
            UM_LOG_WARN("Corrupted message received");
        }
            
        
		uint64_t currServerTimeStamp;
		Message::read(msg->data(), &currSeqNr);
		Message::read(msg->data() + 8, &currServerTimeStamp);
		Message::read(msg->data() + 16, &reportInterval);

		if (currSeqNr < lastSeqNr) {
			// new throughput run!
			lastSeqNr = 0;
			timeStampServerFirst = 0;
            timeStampServerLast = 0;
			currReportNr = 0;
			bytesRcvd = 0;
			pktsRecvd = 0;
			pktsDropped = 0;
		}
        
		bytesRcvd += msg->size();
		pktsRecvd++;

        if (timeStampServerFirst == 0)
            timeStampServerFirst = currServerTimeStamp;

		if (lastSeqNr > 0 && lastSeqNr != currSeqNr - 1) {
			pktsDropped += currSeqNr - lastSeqNr;
		}

		lastSeqNr = currSeqNr;

        compressRatioHead    += (msg->getMeta().find("um.compressRatio.head") != msg->getMeta().end() ? strTo<double>(msg->getMeta("um.compressRatio.head")) : 100);
        compressRatioPayload += (msg->getMeta().find("um.compressRatio.payload") != msg->getMeta().end() ? strTo<double>(msg->getMeta("um.compressRatio.payload")) : 100);
        
//        if (timeStampServerLast == 0)
//            timeStampServerLast = currServerTimeStamp;

        // may happen when initializing timeStampServerLast in client
        if (timeStampServerLast > currServerTimeStamp)
            timeStampServerLast = currServerTimeStamp;
        
		// reply?
		if (currServerTimeStamp - reportInterval >= timeStampServerLast) {
			RScopeLock lock(mutex);
			timeStampServerLast = currServerTimeStamp;
            
			Message* msg = new Message();
			msg->putMeta("bytes.rcvd", toStr(bytesRcvd));
			msg->putMeta("pkts.dropped", toStr(pktsDropped));
            msg->putMeta("compress.ratio.head", toStr(compressRatioHead / (double)pktsRecvd));
            msg->putMeta("compress.ratio.payload", toStr(compressRatioPayload / (double)pktsRecvd));
			msg->putMeta("pkts.rcvd", toStr(pktsRecvd));
			msg->putMeta("last.seq", toStr(lastSeqNr));
			msg->putMeta("report.seq", toStr(currReportNr++));
			msg->putMeta("timestamp.server.last", toStr(timeStampServerLast));
			msg->putMeta("timestamp.server.first", toStr(timeStampServerFirst));
			msg->putMeta("hostname", umundo::Host::getHostname());
			reporter.send(msg);
			delete msg;

			pktsDropped = 0;
			pktsRecvd = 0;
			bytesRcvd = 0;
            compressRatioHead = 0;
            compressRatioPayload = 0;
            
		}
        
	}