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; }
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(); }
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; }
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; }
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); } }
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); }
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); }
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())); }
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); }
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); } }
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); } } }
/* * 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; }