Example #1
0
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;
}
Example #2
0
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
}
Example #4
0
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);
		}
	}
}