bool ProtocolUDP::sendDataObject(const DataObjectRef& dObj, const NodeRef& peer, const InterfaceRef& _peerIface) { int ret = PROT_EVENT_ERROR; if (peerIface) { HAGGLE_ERR("%s Peer interface %s is set when it shouldn't be\n", getName(), peerIface->getIdentifierStr()); } else { // Reassign the peer interface to our target destination peerIface = _peerIface; // Reassign peer node to our target node for accurate logging peerNode = peer; // MOS // SW: START: late bloomfilter add NodeRef actualPeer = getManager()->getKernel()->getNodeStore()->retrieve(peerNode); if (!actualPeer) { // SW: NOTE: this is OK behavior during start-up w/ config.xml HAGGLE_DBG("%s Peer not in node store\n", getName()); actualPeer = peerNode; } if(actualPeer->getBloomfilter()->has(dObj)) { dataObjectsNotSent += 1; // MOS ret = PROT_EVENT_SUCCESS; } else { actualPeer->getBloomfilter()->add(dObj); ret = sendDataObjectNow(dObj); } // SW: END: late bloomfilter add /* Call send function */ // ret = sendDataObjectNow(dObj); // Send success event with this DO. // Note: failures are handled by the caller (ProtocolManager) if (ret == PROT_EVENT_SUCCESS) { getKernel()->addEvent(new Event(EVENT_TYPE_DATAOBJECT_SEND_SUCCESSFUL, dObj, peer)); } } // Release the peer interface again, such that we can assign it another // destination next time peerIface = NULL; return ret == PROT_EVENT_SUCCESS; }
void DataManager::onSendResult(Event *e) { DataObjectRef& dObj = e->getDataObject(); NodeRef node = e->getNode(); if (!dObj) { HAGGLE_ERR("No data object in send result\n"); return; } if(dObj->isControlMessage()) { // MOS - keep control messages out of Bloom filter return; } if (!node) { HAGGLE_ERR("No node in send result\n"); return; } if (!node->isStored()) { HAGGLE_DBG2("Send result node %s is not in node store, trying to retrieve\n", node->getName().c_str()); NodeRef peer = kernel->getNodeStore()->retrieve(node); if (peer) { HAGGLE_DBG2("Found node %s in node store, using the one in store\n", node->getName().c_str()); node = peer; } else { HAGGLE_ERR("Did not find node %s in node store\n", node->getName().c_str()); } } if (e->getType() == EVENT_TYPE_DATAOBJECT_SEND_SUCCESSFUL) { // Add data object to node's bloomfilter. HAGGLE_DBG("Adding data object [%s] to node %s's bloomfilter\n", DataObject::idString(dObj).c_str(), node->getName().c_str()); node->getBloomfilter()->add(dObj); if (dataObjectsSent.size() >= MAX_DATAOBJECTS_LISTED) { dataObjectsSent.pop_front(); } dataObjectsSent.push_back(dObj->getIdStr()); // SW: JLM: START CACHE STRATEGY: if ((e->getType() == EVENT_TYPE_DATAOBJECT_SEND_SUCCESSFUL) && cacheStrategy && !cacheStrategy->isDone()) { cacheStrategy->handleSendSuccess(dObj, node); } // SW: JLM: END CACHE STRATEGY. } }
/** * Find the next best data object to replicate towards neighbor with id * `node_id`, given that we have an estimated `bytes_left` bytes left to * send. If `bytes_left == 0` then we assume the bag size is infinite * and therefore send data objects with highest utility first. * If the computed bytes_left < 0 then the bag is full and no data objects * will be replicated. */ bool ReplicationOptimizer::getNextDataObject(string node_id, List<string> &dobj_blacklist, int bytes_left, DataObjectRef& o_dobj, NodeRef& o_node) { neighbor_node_id_map_t::iterator it = utils.find(node_id); if (it == utils.end()) { // no data objects for node if (dobjs.size() != 0) { errorCount++; HAGGLE_ERR("Neighbors map missing data objects.\n"); } return false; } { node_map_t::iterator it = node_map.find(node_id); if (it == node_map.end()) { HAGGLE_ERR("Node missing from data structure.\n"); return false; } o_node = (*it).second; if (!o_node) { HAGGLE_ERR("NULL node.\n"); return false; } } // remove in-flight data objects from the bag size for (List<string>::iterator itt = dobj_blacklist.begin(); itt != dobj_blacklist.end(); itt++) { string dobj_id = (*itt); if (bytes_left != 0) { //0 means unilmited bytes_left = bytes_left - getCost(dobj_id, node_id); if (bytes_left == 0) { bytes_left = -1; } } } if (bytes_left < 0) { // buffer already full return false; } // used when bytes_left == 0 double best_utility = 0; int best_cost = 0; string best_dobj_id = ""; List<ReplicationDataObjectUtilityMetadataRef> process_dos; List<ReplicationDataObjectUtilityMetadataRef> include_dos; List<ReplicationDataObjectUtilityMetadataRef> exclude_dos; for (;it != utils.end() && (*it).first == node_id; it++) { ReplicationDataObjectUtilityMetadataRef do_info = (*it).second; Timeval now = Timeval::now(); if (!do_info) { errorCount++; HAGGLE_ERR("NULL DO in cache\n"); continue; } string do_id = do_info->getId(); DataObjectId_t id; DataObject::idStrToId(do_id, id); bool inBloomfilter = o_node->getBloomfilter()->has(id); if (inBloomfilter) { HAGGLE_DBG("Skipping, %s already in bloomfilter.\n", Node::nameString(o_node).c_str()); continue; } // skip over data objects in the black list bool inBlacklist = false; for (List<string>::iterator itt = dobj_blacklist.begin(); itt != dobj_blacklist.end(); itt++) { if ((*itt) == do_id) { inBlacklist = true; break; } } if (inBlacklist) { continue; } // recompute the utility if need be double delta = now.getTimeAsMilliSecondsDouble() - do_info->getComputedTime().getTimeAsMilliSecondsDouble(); if (delta > computePeriodMs && utilFunction) { double new_utility = utilFunction->compute(do_info->getId(), do_info->getNodeId()); do_info->setUtility(new_utility, now); } // skip utilites beneeath threshold int cost = do_info->getCost(); double util = do_info->getUtility(); if (util >= globalOptimizer->getMinimumThreshold()) { process_dos.push_front(do_info); if (util > best_utility || (util == best_utility && cost < best_cost)) { best_utility = util; best_cost = cost; best_dobj_id = do_info->getId(); } } } if (process_dos.size() == 0) { // nothing to replicate return false; } if (bytes_left == 0) { DO_map_t::iterator it = do_map.find(best_dobj_id); if (it == do_map.end()) { errorCount++; HAGGLE_ERR("Missing data object %s.\n", best_dobj_id.c_str()); return false; } o_dobj = (*it).second; return true; } // call solver ReplicationKnapsackOptimizerResults results = knapsack->solve(&process_dos, &include_dos, &exclude_dos, bytes_left); if (results.getHadError()) { errorCount++; HAGGLE_ERR("error during knapsack.\n"); return false; } if (include_dos.size() == 0) { HAGGLE_DBG("Nothing to replicate.\n"); return false; } ReplicationDataObjectUtilityMetadataRef best = include_dos.front(); best_dobj_id = best->getId(); DO_map_t::iterator ittt = do_map.find(best_dobj_id); if (ittt == do_map.end()) { errorCount++; HAGGLE_ERR("Missing data object %s.\n", best_dobj_id.c_str()); return false; } o_dobj = (*ittt).second; return true; //JM was false }
void DataManager::onIncomingDataObject(Event *e) { if (!e || !e->hasData()) return; DataObjectRef& dObj = e->getDataObject(); if (!dObj) { HAGGLE_DBG("Incoming data object event without data object!\n"); return; } if(dObj->isControlMessage()) { // MOS - keep control messages out of Bloom filter return; } // Add the data object to the bloomfilter of the one who sent it: NodeRef peer = e->getNode(); // JM End: Associate origin social group to DO if (!peer || peer->getType() == Node::TYPE_UNDEFINED) { // No valid node in event, try to figure out from interface // Find the interface it came from: const InterfaceRef& iface = dObj->getRemoteInterface(); if (iface) { HAGGLE_DBG2("Incoming data object [%s] has no valid peer node but valid peer interface %s\n", DataObject::idString(dObj).c_str(), iface->getIdentifierStr()); peer = kernel->getNodeStore()->retrieve(iface); if(peer && peer->getType() != Node::TYPE_UNDEFINED) HAGGLE_DBG2("Setting incoming data object peer node to %s\n", peer->getName().c_str()); } else { HAGGLE_DBG("No valid peer interface in data object, cannot figure out peer node\n"); } } if (peer) { if (peer->getType() != Node::TYPE_APPLICATION && peer->getType() != Node::TYPE_UNDEFINED) { // Add the data object to the peer's bloomfilter so that // we do not send the data object back. HAGGLE_DBG("Adding data object [%s] to peer node %s's (%s num=%lu) bloomfilter\n", DataObject::idString(dObj).c_str(), peer->getName().c_str(), peer->isStored() ? "stored" : "not stored", peer->getNum()); /* LOG_ADD("%s: BLOOMFILTER:ADD %s\t%s:%s\n", Timeval::now().getAsString().c_str(), dObj->getIdStr(), peer->getTypeStr(), peer->getIdStr()); */ peer->getBloomfilter()->add(dObj); } } else { HAGGLE_DBG("No valid peer node for incoming data object [%s]\n", dObj->getIdStr()); } // Check if this is a control message from an application. We do not want // to bloat our bloomfilter with such messages, because they are sent // everytime an application connects. if (!dObj->isControlMessage()) { // Add the incoming data object also to our own bloomfilter // We do this early in order to avoid receiving duplicates in case // the same object is received at nearly the same time from multiple neighbors if (localBF->has(dObj)) { HAGGLE_DBG("Data object [%s] already in our bloomfilter, marking as duplicate...\n", dObj->getIdStr()); dObj->setDuplicate(); } else { if(!dObj->isNodeDescription()) { // MOS - local BF only contains data objects in new design localBF->add(dObj); HAGGLE_DBG("Adding data object [%s] to our bloomfilter, #objs=%d\n", DataObject::idString(dObj).c_str(), localBF->numObjects()); kernel->getThisNode()->getBloomfilter()->add(dObj); // MOS if(isNodeDescUpdateOnReceptionEnabled) { // MOS - immediately disseminate updated bloomfilter kernel->getThisNode()->setNodeDescriptionCreateTime(); kernel->addEvent(new Event(EVENT_TYPE_NODE_DESCRIPTION_SEND)); } } if(!periodicBloomfilterUpdateEvent->isScheduled()) // MOS - update now happening periodically kernel->getThisNode()->setBloomfilter(*localBF, setCreateTimeOnBloomfilterUpdate); } } }