Example #1
0
static int rw_log(struct log_c *lc, int do_write)
{
	int r;

	r = (int)lseek(lc->disk_fd, 0, SEEK_SET);
	if (r < 0) {
		LOG_ERROR("[%s] rw_log:  lseek failure: %s",
			  SHORT_UUID(lc->uuid), strerror(errno));
		return -errno;
	}

	if (do_write) {
		/* FIXME Cope with full set of non-error conditions */
		r = write(lc->disk_fd, lc->disk_buffer, lc->disk_size);
		if (r < 0) {
			LOG_ERROR("[%s] rw_log:  write failure: %s",
				  SHORT_UUID(lc->uuid), strerror(errno));
			return -EIO; /* Failed disk write */
		}
		return 0;
	}

	/* Read */
	/* FIXME Cope with full set of non-error conditions */
	r = read(lc->disk_fd, lc->disk_buffer, lc->disk_size);
	if (r < 0)
		LOG_ERROR("[%s] rw_log:  read failure: %s",
			  SHORT_UUID(lc->uuid), strerror(errno));
	if (r != lc->disk_size)
		return -EIO; /* Failed disk read */
	return 0;
}
Example #2
0
void NodeQuery::notifyResultSet() {
	ScopeLock lock(_mutex);
	set<NodeStub>::const_iterator nodeIter;

	for (nodeIter = _pendingRemovals.begin(); nodeIter != _pendingRemovals.end(); nodeIter++) {
		assert(*nodeIter);
		UM_LOG_DEBUG("Removed node %s", SHORT_UUID(nodeIter->getUUID()).c_str());
		_listener->removed(*nodeIter);
		_nodes.erase(nodeIter->getUUID());
	}

	for (nodeIter = _pendingFinds.begin(); nodeIter != _pendingFinds.end(); nodeIter++) {
		assert(*nodeIter);
		if (_nodes.find(nodeIter->getUUID()) != _nodes.end()) {
//      UM_LOG_DEBUG("Changed node %s", SHORT_UUID((*nodeIter)->getUUID()).c_str());
			_listener->changed(NodeStub(*nodeIter));
		} else {
			UM_LOG_DEBUG("Added node %s", SHORT_UUID(nodeIter->getUUID()).c_str());
			_listener->added(*nodeIter);
			_nodes[nodeIter->getUUID()] = *nodeIter;
		}
	}

	_pendingRemovals.clear();
	_pendingFinds.clear();
}
Example #3
0
void RTPSubscriber::init(const Options* config) {
	RScopeLock lock(_mutex);
	int status;
	uint16_t min=16384;		//minimum rtp port
	uint16_t max=65534;		//maximum rtp port
	uint16_t portbase=strTo<uint16_t>(config->getKVPs()["sub.rtp.portbase"]);
	_multicastIP=config->getKVPs()["sub.rtp.multicast"];
	if(config->getKVPs().count("pub.rtp.multicast") && !config->getKVPs().count("pub.rtp.portbase")) {
		UM_LOG_ERR("%s: error RTPSubscriber.init(): you need to specify a valid multicast portbase (0 < portbase < 65535) when using multicast", SHORT_UUID(_uuid).c_str());
		return;
	}
	if(config->getKVPs().count("sub.rtp.portbase") && (portbase==0 || portbase==65535)) {
		UM_LOG_ERR("%s: error RTPSubscriber.init(): you need to specify a valid portbase (0 < portbase < 65535)", SHORT_UUID(_uuid).c_str());
		return;
	}

	_helper=new RTPHelpers();		//this starts the re_main() mainloop
	if(config->getKVPs().count("sub.rtp.portbase")) {
		min=portbase;
		max=portbase+1;
	}
	struct libre::sa ip;
	libre::sa_init(&ip, AF_INET);
	libre::sa_set_in(&ip, INADDR_ANY, 0);
	if((status=RTPHelpers::call(boost::bind(libre::rtp_listen, &_rtp_socket, static_cast<int>(IPPROTO_UDP), &ip, min, max, false, rtp_recv, (void (*)(const libre::sa*, libre::rtcp_msg*, void*)) NULL, this)))) {
		UM_LOG_ERR("%s: error %d in libre::rtp_listen()", SHORT_UUID(_uuid).c_str(), status);
		delete _helper;
		return;
	}
	_port=libre::sa_port(libre::rtp_local(_rtp_socket));
	libre::udp_sockbuf_set((libre::udp_sock*)libre::rtp_sock(_rtp_socket), 8192*1024);		//try to set something large

	if(config->getKVPs().count("sub.rtp.multicast")) {
		struct libre::sa maddr;
		libre::sa_init(&maddr, AF_INET);
		if((status=libre::sa_set_str(&maddr, _multicastIP.c_str(), _port)))
			UM_LOG_WARN("%s: error %d in libre::sa_set_str(%s:%u): %s", SHORT_UUID(_uuid).c_str(), status, _multicastIP.c_str(), _port, strerror(status));
		else {
			//test for multicast support
			status=libre::udp_multicast_join((libre::udp_sock*)libre::rtp_sock(_rtp_socket), &maddr);
			status|=libre::udp_multicast_leave((libre::udp_sock*)libre::rtp_sock(_rtp_socket), &maddr);
			if(status)
				UM_LOG_ERR("%s: system not supporting multicast, using unicast", SHORT_UUID(_uuid).c_str());
			else
				_multicast=true;
		}
	}

	_initDone=true;
}
Example #4
0
void RTPPublisher::init(const Options* config) {
	RScopeLock lock(_mutex);
	int status;
	uint16_t min = 16384;		//minimum rtp port
	uint16_t max = 65534;		//maximum rtp port

	std::map<std::string, std::string> options = config->getKVPs();

	uint16_t portbase   = (options.find("pub.rtp.portbase") !=  options.end() ? strTo<uint16_t>(options["pub.rtp.portbase"]) : 0);
	_timestampIncrement = (options.find("pub.rtp.timestampIncrement") !=  options.end() ? strTo<uint32_t>(options["pub.rtp.timestampIncrement"]) : 0);
	_payloadType        = (options.find("pub.rtp.payloadType") !=  options.end() ? strTo<uint8_t>(options["pub.rtp.payloadType"]) : 96); //dynamic [RFC3551]

	if (options.find("pub.rtp.portbase") != options.end()) { // user did specify portbase
		if((portbase > 0 && portbase < 65534)) {
			min=portbase;
			max=portbase+1;
		} else {
			UM_LOG_ERR("%s: error RTPPublisher.init(): you need to specify a valid portbase (0 < portbase < 65535)", SHORT_UUID(_uuid).c_str());
		}
	}

	if (_timestampIncrement == 0) {
		UM_LOG_ERR("%s: error RTPPublisher.init(): you need to specify a valid timestampIncrement (timestampIncrement > 0)", SHORT_UUID(_uuid).c_str());
		return;
	}

	_rtpThread = RTPThread::getInstance();			// this starts the re_main() mainloop...


	struct libre::sa ip;
	libre::sa_init(&ip, AF_INET);
	libre::sa_set_in(&ip, INADDR_ANY, 0);
	//we always have to specify a rtp_recv() handler (so specify an empty function)
	status = _rtpThread->call(boost::bind(libre::rtp_listen,
	                                      &_rtp_socket,
	                                      static_cast<int>(IPPROTO_UDP),
	                                      &ip,
	                                      min,
	                                      max,
	                                      false,
	                                      rtp_recv,
	                                      (void (*)(const libre::sa*, libre::rtcp_msg*, void*))
	                                      NULL,
	                                      this));
	if (status) {
		UM_LOG_ERR("%s: error %d in libre::rtp_listen(): %s", SHORT_UUID(_uuid).c_str(), status, strerror(status));
		return;
	}

	_port           = libre::sa_port(libre::rtp_local(_rtp_socket));
	_timestamp      = libre::rand_u32();
	_sequenceNumber = _rtp_socket->enc.seq;

	libre::udp_sockbuf_set((libre::udp_sock*)libre::rtp_sock(_rtp_socket), 8192*1024);		//try to set something large

	_initDone = true;
}
Example #5
0
void NodeQuery::removed(const NodeStub& node) {
	ScopeLock lock(_mutex);
	assert(node);
	if (_notifyImmediately) {
		UM_LOG_DEBUG("Removed node %s", SHORT_UUID(node.getUUID()).c_str());
		_listener->removed(node);
		_nodes.erase(node.getUUID());
	} else {
		_pendingRemovals.insert(node);
	}
}
Example #6
0
void RTPPublisher::removed(const SubscriberStub& sub, const NodeStub& node) {
	RScopeLock lock(_mutex);
	int status;
	std::string ip = sub.getIP();
	uint16_t port = sub.getPort();
	if (!ip.length())		//only use separate subscriber ip (for multicast support etc.), if specified
		ip = node.getIP();

	// do we now about this sub via this node?
	bool subscriptionFound = false;
	std::pair<_domainSubs_t::iterator, _domainSubs_t::iterator> subIter = _domainSubs.equal_range(sub.getUUID());
	while(subIter.first !=  subIter.second) {
		if (subIter.first->second.first.getUUID() ==  node.getUUID()) {
			subscriptionFound = true;
			break;
		}
		subIter.first++;
	}
	if (!subscriptionFound)
		return;

	UM_LOG_INFO("%s: lost a %s subscriber (%s:%u) for channel %s", SHORT_UUID(_uuid).c_str(), sub.isMulticast() ? "multicast" : "unicast", ip.c_str(), port, _channelName.c_str());

	struct libre::sa addr;
	libre::sa_init(&addr, AF_INET);
	if ((status = libre::sa_set_str(&addr, ip.c_str(), port)))
		UM_LOG_WARN("%s: error %d in libre::sa_set_str(%s:%u): %s", SHORT_UUID(_uuid).c_str(), status, ip.c_str(), port, strerror(status));
	else
		_destinations.erase(ip+":"+toStr(port));

	if (_domainSubs.count(sub.getUUID()) ==  1) { // about to vanish
		if (_greeter !=  NULL) {
			Publisher pub(Publisher(StaticPtrCast<PublisherImpl>(shared_from_this())));
			_greeter->farewell(pub, sub);
		}
		_subs.erase(sub.getUUID());
	}

	_domainSubs.erase(subIter.first);
	UMUNDO_SIGNAL(_pubLock);
}
Example #7
0
void RTPPublisher::added(const SubscriberStub& sub, const NodeStub& node) {
	RScopeLock lock(_mutex);
	int status;

	std::string ip = sub.getIP();
	uint16_t port = sub.getPort();
	if (!ip.length())		//only use separate subscriber ip (for multicast support etc.), if specified
		ip = node.getIP();

	// do we already now about this sub via this node?
	std::pair<_domainSubs_t::iterator, _domainSubs_t::iterator> subIter = _domainSubs.equal_range(sub.getUUID());
	while(subIter.first !=  subIter.second) {
		if (subIter.first->second.first.getUUID() ==  node.getUUID())
			return; // we already know about this sub from this node
		subIter.first++;
	}

	UM_LOG_INFO("%s: received a new %s subscriber (%s:%u) for channel %s", SHORT_UUID(_uuid).c_str(), sub.isMulticast() ? "multicast" : "unicast", ip.c_str(), port, _channelName.c_str());

	struct libre::sa addr;
	libre::sa_init(&addr, AF_INET);
	status = libre::sa_set_str(&addr, ip.c_str(), port);

	if (status) {
		UM_LOG_WARN("%s: error %d in libre::sa_set_str(%s:%u): %s", SHORT_UUID(_uuid).c_str(), status, ip.c_str(), port, strerror(status));
	} else {
		_destinations[ip + ":" + toStr(port)] = addr;
	}

	_subs[sub.getUUID()] = sub;
	_domainSubs.insert(std::make_pair(sub.getUUID(), std::make_pair(node, sub)));

	if (_greeter !=  NULL && _domainSubs.count(sub.getUUID()) ==  1) {
		// only perform greeting for first occurence of subscriber
		Publisher pub(StaticPtrCast<PublisherImpl>(shared_from_this()));
		_greeter->welcome(pub, sub);
	}

	UMUNDO_SIGNAL(_pubLock);
}
Example #8
0
void RTPSubscriber::added(const PublisherStub& pub, const NodeStub& node) {
	RScopeLock lock(_mutex);
	int status;
	uint16_t port=pub.getPort();
	std::string ip=node.getIP();

	if(_domainPubs.count(pub.getDomain()) == 0) {
		UM_LOG_INFO("%s: subscribing to %s (%s:%d)", SHORT_UUID(_uuid).c_str(), pub.getChannelName().c_str(), ip.c_str(), port);

		if(_multicast && _pubs.size()==0) {
			UM_LOG_INFO("%s: first publisher found and we are using multicast, joining multicast group %s:%d now", SHORT_UUID(_uuid).c_str(), _multicastIP.c_str(), _port);

			struct libre::sa maddr;
			libre::sa_init(&maddr, AF_INET);
			if((status=libre::sa_set_str(&maddr, _multicastIP.c_str(), _port)))
				UM_LOG_ERR("%s: error %d in libre::sa_set_str(%s:%u): %s, ignoring publisher", SHORT_UUID(_uuid).c_str(), status, _multicastIP.c_str(), _port, strerror(status));
			else if(libre::udp_multicast_join((libre::udp_sock*)libre::rtp_sock(_rtp_socket), &maddr))
				UM_LOG_ERR("%s: system not supporting multicast, ignoring publisher (%s:%d)", SHORT_UUID(_uuid).c_str(), _multicastIP.c_str(), _port);
		}
	}
	_pubs[pub.getUUID()] = pub;
	_domainPubs.insert(std::make_pair(pub.getDomain(), pub.getUUID()));
}
Example #9
0
void RTPPublisher::send(Message* msg) {
	RScopeLock lock(_mutex);
	int status = 0;
	uint32_t timestamp = 0;
	uint8_t payloadType = _payloadType;
	uint16_t sequenceNumber = strTo<uint16_t>(msg->getMeta("um.sequenceNumber"));		//only for internal use by umundo-bridge
	bool marker = strTo<bool>(msg->getMeta("um.marker"));
	if (!msg->getMeta("um.sequenceNumber").size())
		sequenceNumber = _sequenceNumber++;

	if (!msg->getMeta("um.marker").size())
		marker = false;

	std::string timestampIncrement = msg->getMeta("um.timestampIncrement");

	if (!timestampIncrement.size())
		timestampIncrement = _mandatoryMeta["um.timestampIncrement"];

	if (msg->getMeta("um.timestamp").size())	{					//mainly for internal use by umundo-bridge
		timestamp = strTo<uint32_t>(msg->getMeta("um.timestamp"));
	} else {
		if (timestampIncrement.size()) {
			timestamp = (_timestamp += strTo<uint32_t>(timestampIncrement));
		}	else {
			timestamp = (_timestamp += _timestampIncrement);
		}
	}
	if (msg->getMeta("um.payloadType").size())							//mainly for internal use by umundo-bridge
		payloadType = strTo<uint8_t>(msg->getMeta("um.payloadType"));

	//allocate buffer
	libre::mbuf *mb = libre::mbuf_alloc(libre::RTP_HEADER_SIZE + msg->size());
	//make room for rtp header
	libre::mbuf_set_end(mb, libre::RTP_HEADER_SIZE);
	libre::mbuf_skip_to_end(mb);
	//write data
	libre::mbuf_write_mem(mb, (const uint8_t*)msg->data(), msg->size());
	//send data
	typedef std::map<std::string, struct libre::sa>::iterator it_type;
	for(it_type iterator = _destinations.begin(); iterator !=  _destinations.end(); iterator++) {
		//reset buffer pos to start of data
		libre::mbuf_set_pos(mb, libre::RTP_HEADER_SIZE);
		if (sequenceNumber)
			_rtp_socket->enc.seq = sequenceNumber;
		if ((status = libre::rtp_send(_rtp_socket, &iterator->second, marker, payloadType, timestamp, mb)))
			UM_LOG_INFO("%s: error in libre::rtp_send() for destination '%s': %s", SHORT_UUID(_uuid).c_str(), iterator->first.c_str(), strerror(status));
	}
	//cleanup
	libre::mem_deref(mb);
}
Example #10
0
void NodeQuery::found(const NodeStub& node) {
	ScopeLock lock(_mutex);
	assert(node);
	if (_notifyImmediately) {
		if (_nodes.find(node.getUUID()) != _nodes.end()) {
//      UM_LOG_DEBUG("Changed node %s", SHORT_UUID(node->getUUID()).c_str());
			_listener->changed(node);
		} else {
			UM_LOG_DEBUG("Added node %s", SHORT_UUID(node.getUUID()).c_str());
			_listener->added(node);
			_nodes[node.getUUID()] = node;
		}
	} else {
		_pendingFinds.insert(node);
	}
}
Example #11
0
void RTPSubscriber::removed(const PublisherStub& pub, const NodeStub& node) {
	RScopeLock lock(_mutex);
	int status;
	uint16_t port=pub.getPort();
	std::string ip=node.getIP();

	// TODO: This fails for publishers added via different nodes
	if (_pubs.find(pub.getUUID()) != _pubs.end())
		_pubs.erase(pub.getUUID());

	if (_domainPubs.count(pub.getDomain()) == 0)
		return;

	std::multimap<std::string, std::string>::iterator domIter = _domainPubs.find(pub.getDomain());

	while(domIter != _domainPubs.end()) {
		if (domIter->second == pub.getUUID()) {
			_domainPubs.erase(domIter++);
		} else {
			domIter++;
		}
	}

	if (_domainPubs.count(pub.getDomain()) == 0) {
		UM_LOG_INFO("%s unsubscribing from %s (%s:%d)", SHORT_UUID(_uuid).c_str(), pub.getChannelName().c_str(), ip.c_str(), port);

		if(_multicast && _pubs.size()==0) {
			UM_LOG_INFO("%s: last publisher vanished and we are using multicast, leaving multicast group %s:%d now", SHORT_UUID(_uuid).c_str(), _multicastIP.c_str(), _port);

			struct libre::sa maddr;
			libre::sa_init(&maddr, AF_INET);
			if((status=libre::sa_set_str(&maddr, _multicastIP.c_str(), _port)))
				UM_LOG_ERR("%s: error %d in libre::sa_set_str(%s:%u): %s, not leaving multicast group", SHORT_UUID(_uuid).c_str(), status, _multicastIP.c_str(), _port, strerror(status));
			else if(libre::udp_multicast_join((libre::udp_sock*)libre::rtp_sock(_rtp_socket), &maddr))
				UM_LOG_ERR("%s: system not supporting multicast, not leaving multicast group (%s:%d)", SHORT_UUID(_uuid).c_str(), _multicastIP.c_str(), _port);
		}

	}
}
Example #12
0
/*
 * do_local_work
 *
 * Any processing errors are placed in the 'rq'
 * structure to be reported back to the kernel.
 * It may be pointless for this function to
 * return an int.
 *
 * Returns: 0 on success, -EXXX on failure
 */
static int do_local_work(void *data)
{
	int r;
	struct clog_request *rq;
	struct dm_ulog_request *u_rq = NULL;

	r = kernel_recv(&rq);
	if (r)
		return r;

	if (!rq)
		return 0;

	u_rq = &rq->u_rq;
	LOG_DBG("[%s]  Request from kernel received: [%s/%u]",
		SHORT_UUID(u_rq->uuid), RQ_TYPE(u_rq->request_type),
		u_rq->seq);
	switch (u_rq->request_type) {
	case DM_ULOG_CTR:
	case DM_ULOG_DTR:
	case DM_ULOG_GET_REGION_SIZE:
	case DM_ULOG_IN_SYNC:
	case DM_ULOG_GET_SYNC_COUNT:
	case DM_ULOG_STATUS_INFO:
	case DM_ULOG_STATUS_TABLE:
	case DM_ULOG_PRESUSPEND:
		/* We do not specify ourselves as server here */
		r = do_request(rq, 0);
		if (r)
			LOG_DBG("Returning failed request to kernel [%s]",
				RQ_TYPE(u_rq->request_type));
		r = kernel_send(u_rq);
		if (r)
			LOG_ERROR("Failed to respond to kernel [%s]",
				  RQ_TYPE(u_rq->request_type));
			
		break;
	case DM_ULOG_RESUME:
		/*
		 * Resume is a special case that requires a local
		 * component to join the CPG, and a cluster component
		 * to handle the request.
		 */
		r = local_resume(u_rq);
		if (r) {
			LOG_DBG("Returning failed request to kernel [%s]",
				RQ_TYPE(u_rq->request_type));
			r = kernel_send(u_rq);
			if (r)
				LOG_ERROR("Failed to respond to kernel [%s]",
					  RQ_TYPE(u_rq->request_type));
			break;
		}
		/* ELSE, fall through */
	case DM_ULOG_IS_CLEAN:
	case DM_ULOG_FLUSH:
	case DM_ULOG_MARK_REGION:
	case DM_ULOG_GET_RESYNC_WORK:
	case DM_ULOG_SET_REGION_SYNC:
	case DM_ULOG_IS_REMOTE_RECOVERING:
	case DM_ULOG_POSTSUSPEND:
		r = cluster_send(rq);
		if (r) {
			u_rq->data_size = 0;
			u_rq->error = r;
			kernel_send(u_rq);
		}

		break;
	case DM_ULOG_CLEAR_REGION:
		r = kernel_ack(u_rq->seq, 0);

		r = cluster_send(rq);
		if (r) {
			/*
			 * FIXME: store error for delivery on flush
			 *        This would allow us to optimize MARK_REGION
			 *        too.
			 */
		}

		break;
	default:
		LOG_ERROR("Invalid log request received (%u), ignoring.",
			  u_rq->request_type);

		return 0;
	}

	if (r && !u_rq->error)
		u_rq->error = r;

	return r;
}