/* * Returns true iff */ bool CacheStrategyUtility::isResponsibleForDataObject( DataObjectRef &dObj) { string id = string(dObj->getIdStr()); /* // THIS IS NOT THREAD SAFE!! added getOrigSize // to grab unaltered file size. if (utilMetadata.find(id) != utilMetadata.end()) { return true; } */ if (dObj->isDuplicate()) { return false; } // SW: TODO: NOTE: this might not be the best way to check if it's from // a local application, but it works for now... bool isLocal = dObj->getRemoteInterface() && dObj->getRemoteInterface()->isApplication(); bool notResponsible = dObj->isControlMessage() || dObj->isNodeDescription(); bool isResponsible = !notResponsible; if (!handle_zero_size) { isResponsible = isResponsible && (dObj->getOrigDataLen() > 0); } if (!manage_locally_sent_files) { isResponsible = isResponsible && dObj->isPersistent(); } if (stats_replacement_strat && stats_replacement_strat->isResponsibleForDataObject(dObj)) { isResponsible = true; } else if (manage_only_remote_files) { isResponsible = isResponsible && !isLocal; } return isResponsible; }
ProtocolEvent ProtocolUDP::receiveDataObject() { size_t len = 0; string haggleTag = "</Haggle>"; DataObjectRef dObj; char buf[SOCKADDR_SIZE]; struct sockaddr *peer_addr = (struct sockaddr *)buf; ProtocolEvent pEvent; unsigned short port; Address *addr = NULL; struct sockaddr_in *sa = NULL; #ifdef OS_WINDOWS pEvent = receiveData(buffer, bufferSize, peer_addr, 0, &len); #else pEvent = receiveData(buffer, bufferSize, peer_addr, MSG_DONTWAIT, &len); #endif if (pEvent != PROT_EVENT_SUCCESS) return pEvent; if (peer_addr->sa_family == AF_INET) { sa = (struct sockaddr_in *)peer_addr; port = ntohs(sa->sin_port); addr = new IPv4Address(sa->sin_addr, TransportUDP(port)); } #if defined(ENABLE_IPv6) else if (peer_addr->sa_family == AF_INET6) { struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)peer_addr; port = ntohs(sa6->sin6_port); addr = new IPv6Address(sa6->sin6_addr, TransportUDP(port)); } #endif if (addr == NULL) return PROT_EVENT_ERROR; if (peerIface) { HAGGLE_ERR("%s UDP peer interface was not null\n", getName()); delete addr; return PROT_EVENT_ERROR; } peerIface = new ApplicationPortInterface(port, "Application", addr, IFFLAG_UP); peerNode = getKernel()->getNodeStore()->retrieve(peerIface); delete addr; if (!peerNode) { peerNode = Node::create(Node::TYPE_APPLICATION, "Unknown application"); if (!peerNode) { HAGGLE_ERR("%s Could not create application node\n", getName()); return PROT_EVENT_ERROR; } } dObj = DataObject::create(buffer, len, localIface, peerIface); if (!dObj) { HAGGLE_DBG("%s Could not create data object\n", getName()); return PROT_EVENT_ERROR; } // Haggle doesn't own files that applications have put in: // MOS - not true - maybe some code missing here Timeval ct = dObj->getCreateTime(); Timeval now = Timeval::now(); if(!ct.isValid()) dObj->setCreateTime(now); // MOS - in case it was not set by application dObj->setReceiveTime(now); dataObjectsIncoming += 1; // MOS dataObjectBytesIncoming += len; // MOS if(!dObj->isControlMessage()) dataObjectsIncomingNonControl += 1; // MOS // We must release the peer interface reference after // the data object is created as the next incoming // data might be from another peer peerIface = NULL; // MOS - no need to ignore objects from local application (avoid risk of blocking control messages) // if (getKernel()->getThisNode()->getBloomfilter()->has(dObj)) { // HAGGLE_DBG("Data object [%s] from interface %s:%u has already been received, ignoring.\n", // dObj->getIdStr(), sa ? ip_to_str(sa->sin_addr) : "undefined", port); // return PROT_EVENT_SUCCESS; // } // Generate first an incoming event to conform with the base Protocol class getKernel()->addEvent(new Event(EVENT_TYPE_DATAOBJECT_INCOMING, dObj, peerNode)); dataObjectsReceived += 1; // MOS dataObjectBytesReceived += len; // MOS HAGGLE_DBG("%s Received data object [%s] from interface %s:%u\n", getName(), dObj->getIdStr(), sa ? ip_to_str(sa->sin_addr) : "undefined", port); // 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, peerNode)); peerNode = NULL; // MOS - similar to peerIface return PROT_EVENT_SUCCESS; }
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; }
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; }