Exemple #1
0
void DCMessenger::startReceiveMsg( classy_counted_ptr<DCMsg> msg, Sock *sock )
{
		// Currently, only one pending message per messenger.
	ASSERT( !m_callback_msg.get() );
	ASSERT( !m_callback_sock );
	ASSERT( m_pending_operation == NOTHING_PENDING );

	msg->setMessenger( this );

	std::string name;
	formatstr(name, "DCMessenger::receiveMsgCallback %s", msg->name());

	incRefCount();

	int reg_rc = daemonCore->
		Register_Socket( sock, peerDescription(),
						 (SocketHandlercpp)&DCMessenger::receiveMsgCallback,
						 name.c_str(), this, ALLOW );
	if(reg_rc < 0) {
		msg->addError(
			CEDAR_ERR_REGISTER_SOCK_FAILED,
			"failed to register socket (Register_Socket returned %d)",
			reg_rc );
		msg->callMessageReceiveFailed( this );
		doneWithSock(sock);
		decRefCount();
		return;
	}

	m_callback_msg = msg; // prevent msg from going out of reference
	m_callback_sock = sock;
	m_pending_operation = RECEIVE_MSG_PENDING;
}
ProtocolEvent ProtocolUDPGeneric::receiveDataObjectNoControl()
{
    ProtocolEvent pEvent;
    size_t len;
    pEvent = receiveData(buffer, bufferSize, MSG_DONTWAIT, &len);
    if (pEvent != PROT_EVENT_SUCCESS) {
        return pEvent;
    }

    buffer[bufferSize-1] = '\0';

    if (len == 0) {
        HAGGLE_DBG("%s Received zero-length message\n", getName());
        return PROT_EVENT_ERROR;
    }

    if(lastReceivedSessionNo == lastValidReceivedSessionNo && lastReceivedSeqNo == lastValidReceivedSeqNo) {
      HAGGLE_DBG("%s Ignoring duplicate message - session no %s sequence no %d\n", getName(), DataObject::idString(lastValidReceivedSessionNo).c_str(), lastReceivedSeqNo);
      return PROT_EVENT_SUCCESS;
    }

    memcpy(lastValidReceivedSessionNo, lastReceivedSessionNo, sizeof(DataObjectId_t)); 
    lastValidReceivedSeqNo = lastReceivedSeqNo; 

    // MOS - fastpath based on session id = data object id
    
    if (getKernel()->getThisNode()->getBloomfilter()->has(lastValidReceivedSessionNo)) {
      HAGGLE_DBG("%s Data object (session no %s) already in bloom filter - no event generated\n", getName(), DataObject::idString(lastValidReceivedSessionNo).c_str()); 
	dataObjectsNotReceived += 1; // MOS
        return PROT_EVENT_SUCCESS;
    }

    
    // MOS - quickly add to Bloom filter to reduce redundant processing in other procotols
    getKernel()->getThisNode()->getBloomfilter()->add(lastValidReceivedSessionNo);

    DataObjectRef dObj = DataObject::create_for_putting(localIface,
                                                        peerIface,  
                                                        getKernel()->getStoragePath());
    if (!dObj) {
        HAGGLE_DBG("%s Could not create data object\n", getName());
        return PROT_EVENT_ERROR;
    }

    size_t bytesRemaining = DATAOBJECT_METADATA_PENDING;
    ssize_t bytesPut = dObj->putData(buffer, len, &bytesRemaining, true);

    if (bytesPut < 0) {
        HAGGLE_ERR("%s Could not put data\n", getName());
        return PROT_EVENT_ERROR;
    }

    if(bytesRemaining != len - bytesPut) {
        HAGGLE_ERR("%s Received data object not complete - discarding\n", getName());
        return PROT_EVENT_ERROR;
    }

    HAGGLE_DBG("%s Metadata header received [%s].\n", getName(), dObj->getIdStr());
    
    dObj->setReceiveTime(Timeval::now());

    // MOS - the following was happening after posting INCOMING but that distorts the statistics
    HAGGLE_DBG("%s %ld bytes data received (including header), %ld bytes put\n", getName(), len, bytesPut);
    dataObjectsIncoming += 1; // MOS
    if(!dObj->isControlMessage()) dataObjectsIncomingNonControl += 1; // MOS
    dataObjectBytesIncoming += len; // MOS

    HAGGLE_DBG("%s Received data object [%s] from node %s\n", getName(), 
	       DataObject::idString(dObj).c_str(), peerDescription().c_str()); 
    // MOS - removed interface due to locking issue

    if (getKernel()->getThisNode()->getBloomfilter()->hasParentDataObject(dObj)) {
        HAGGLE_DBG("%s Data object [%s] already in bloom filter - no event generated\n", getName(), DataObject::idString(dObj).c_str()); 
	dataObjectsNotReceived += 1; // MOS
        return PROT_EVENT_SUCCESS;
    }

    NodeRef node = Node::create(dObj);
    if (node && (node == getKernel()->getThisNode())) {
        HAGGLE_DBG("%s Received own node description, discarding early.\n", getName());
	dataObjectsNotReceived += 1; // MOS
        return PROT_EVENT_SUCCESS;
    }

    // MOS - this now happens even before xml parsing
    // getKernel()->getThisNode()->getBloomfilter()->add(dObj);

    if(bytesRemaining > 0) {
      ssize_t bytesPut2 = dObj->putData(buffer + bytesPut, len - bytesPut, &bytesRemaining, false);
      HAGGLE_DBG("%s processing payload - %ld bytes put\n", getName(), bytesPut2);

      if (bytesPut2 < 0) {
        HAGGLE_ERR("%s Could not put data\n", getName());
        return PROT_EVENT_ERROR;
      }
      
      if(bytesRemaining != 0) {
        HAGGLE_ERR("%s Received data object not complete - discarding\n", getName());
        return PROT_EVENT_ERROR;
      }
    }

    NodeRef currentPeer;
    { Mutex::AutoLocker l(mutex); currentPeer = peerNode; } // MOS

    // Generate first an incoming event to conform with the base Protocol class
    getKernel()->addEvent(new Event(EVENT_TYPE_DATAOBJECT_INCOMING, dObj, currentPeer));

    receiveDataObjectSuccessHook(dObj);

    // Since there is no data following, we generate the received event immediately 
    // following the incoming one
    getKernel()->addEvent(new Event(EVENT_TYPE_DATAOBJECT_RECEIVED, dObj, currentPeer));

    dataObjectsReceived += 1; // MOS
    dataObjectBytesReceived += len; // MOS
    if(dObj->isNodeDescription()) { nodeDescReceived += 1; nodeDescBytesReceived += len; } // MOS

    return PROT_EVENT_SUCCESS;
}
Exemple #3
0
void DCMessenger::startCommand( classy_counted_ptr<DCMsg> msg )
{
	MyString error;
	msg->setMessenger( this );

	if( msg->deliveryStatus() == DCMsg::DELIVERY_CANCELED ) {
		msg->callMessageSendFailed( this );
		return;
	}

	time_t deadline = msg->getDeadline();
	if( deadline && deadline < time(NULL) ) {
		msg->addError(CEDAR_ERR_DEADLINE_EXPIRED,
					  "deadline for delivery of this message expired");
		msg->callMessageSendFailed( this );
		return;
	}

		// For a UDP message, we may need to register two sockets, one for
		// the SafeSock and another for a ReliSock to establish the
		// security session.
	Stream::stream_type st = msg->getStreamType();
	if( daemonCore->TooManyRegisteredSockets(-1,&error,st==Stream::safe_sock?2:1) ) {
			// Try again in a sec
			// Eventually, it would be better to queue this centrally
			// (i.e. in DaemonCore) rather than having an independent
			// timer for each case.  Then it would be possible to control
			// priority of different messages etc.
		dprintf(D_FULLDEBUG, "Delaying delivery of %s to %s, because %s\n",
				msg->name(),peerDescription(),error.Value());
		startCommandAfterDelay( 1, msg );
		return;
	}

		// Currently, there may be only one pending operation per messenger.
	ASSERT(!m_callback_msg.get());
	ASSERT(!m_callback_sock);
	ASSERT(m_pending_operation == NOTHING_PENDING);

	m_pending_operation = START_COMMAND_PENDING;
	m_callback_msg = msg;
	m_callback_sock = m_sock.get();
	if( !m_callback_sock ) {

		if (IsDebugLevel(D_COMMAND)) {
			const char * addr = m_daemon->addr();
			const int cmd = msg->m_cmd;
			dprintf (D_COMMAND, "DCMessenger::startCommand(%s,...) making non-blocking connection to %s\n", getCommandStringSafe(cmd), addr ? addr : "NULL");
		}

		const bool nonblocking = true;
		m_callback_sock = m_daemon->makeConnectedSocket(st,msg->getTimeout(),msg->getDeadline(),&msg->m_errstack,nonblocking);
		if( !m_callback_sock ) {
			msg->callMessageSendFailed( this );
			return;
		}
	}

	incRefCount();
	m_daemon->startCommand_nonblocking (
		msg->m_cmd,
		m_callback_sock,
		msg->getTimeout(),
		&msg->m_errstack,
		&DCMessenger::connectCallback,
		this,
		msg->name(),
		msg->getRawProtocol(),
		msg->getSecSessionId());
}
ProtocolEvent ProtocolUDPGeneric::sendDataObjectNowNoControl(
    const DataObjectRef& dObj)
{
    NodeRef currentPeer;
    { Mutex::AutoLocker l(mutex); currentPeer = peerNode; } // MOS

    NodeRef actualPeer = getManager()->getKernel()->getNodeStore()->retrieve(currentPeer, true);
    if (!actualPeer) {
        HAGGLE_ERR("%s Peer not in node store\n", getName());
        return PROT_EVENT_ERROR;
    }

    // check if already in peers bloomfilter
    if (actualPeer->hasThisOrParentDataObject(dObj)) { // MOS
        HAGGLE_DBG("%s Peer already had data object.\n", getName());
        return PROT_EVENT_SUCCESS;
    }
    // done

    // SW: we move the hook here to minimize race condition where we send
    // too many redundant node descriptions
    // TODO: we may want to synchronize on the dObj or have some serial
    // queue so this is not probabilistic
    sendDataObjectNowSuccessHook(dObj);

    HAGGLE_DBG("%s Sending data object [%s] to peer \'%s\'\n", 
        getName(), dObj->getIdStr(), peerDescription().c_str());

    DataObjectDataRetrieverRef retriever = dObj->getDataObjectDataRetriever();
    if (!retriever || !retriever->isValid()) {
        HAGGLE_ERR("%s unable to start reading data\n", getName());
        return PROT_EVENT_ERROR;
    }

    ProtocolEvent pEvent = PROT_EVENT_SUCCESS;

    ssize_t len = retriever->retrieve(buffer, bufferSize, false);

    if (0 == len) {
        HAGGLE_ERR("%s DataObject is empty\n", getName());
        return PROT_EVENT_ERROR;
    }

    if (len < 0) {
        HAGGLE_ERR("%s Could not retrieve data from data object\n", getName());
        return PROT_EVENT_ERROR;
    }

    if ((size_t) len == bufferSize) {
        HAGGLE_ERR("%s Buffer is too small for message\n", getName());
        return PROT_EVENT_ERROR;
    }

    Timeval t_start;
    t_start.setNow();

    setSessionNo(dObj->getId()); // MOS
    setSeqNo(0); // MOS

    size_t bytesSent = 0;

    // MOS - simple way to increase udp redundancy
    for(int i = 0; i <= getConfiguration()->getRedundancy(); i++) {

    pEvent = sendData(buffer, (size_t) len, 0, &bytesSent);
    if (bytesSent != (size_t) len) {
        pEvent = PROT_EVENT_ERROR;
    }

    if (pEvent != PROT_EVENT_SUCCESS) {
        HAGGLE_ERR("%s Broadcast - Error\n", getName());
        return pEvent;
    }
    }

#ifdef DEBUG
    Timeval tx_time = Timeval::now() - t_start;

    HAGGLE_DBG("%s Sent %lu bytes data in %.3lf seconds, average speed = %.2lf kB/s\n", 
        getName(), len, tx_time.getTimeAsSecondsDouble(), 
        (double)len / (1000*tx_time.getTimeAsSecondsDouble()));
#endif

    dataObjectsOutgoing += 1; // MOS
    dataObjectsSent += 1; // MOS
    if(!dObj->isControlMessage()) dataObjectsOutgoingNonControl += 1; // MOS
    dataObjectBytesOutgoing += bytesSent; // MOS
    dataObjectBytesSent += len; // MOS
    if(dObj->isNodeDescription()) { nodeDescSent += 1; nodeDescBytesSent += len; } // MOS

    return PROT_EVENT_SUCCESS;
}