bool 
CachePurgerRelTTL::isResponsibleForDataObject(
    DataObjectRef &dObj) 
{
    if (!dObj) {
        return false;
    }

    const Attribute *attr;
    attr = dObj->getAttribute (tagField, tagFieldValue, 1);
    
    if (!attr) {
        return false;
    }

    attr = dObj->getAttribute (metricField, "*", 1);

    if (!attr) {
        return false;
    }

    return true; 
}
/**
* This routine was taken from the benchmark manager, to create Dataobjects in code.
* It is used for the self test.    Depending on compile options, benchmark manager
* may not be included, so the relevant code is copied here to be always available.
*
* @see BenchmarkManager::createDataObject
*
*/
DataObjectRef CacheStrategyUtility::createDataObject(unsigned int numAttr)
{
	char name[128];
	char value[128];
	unsigned int r;

	unsigned char macaddr[6];
	macaddr[0] = (unsigned char) RANDOM_INT(255);
	macaddr[1] = (unsigned char) RANDOM_INT(255);
	macaddr[2] = (unsigned char) RANDOM_INT(255);
	macaddr[3] = (unsigned char) RANDOM_INT(255);
	macaddr[4] = (unsigned char) RANDOM_INT(255);
	macaddr[5] = (unsigned char) RANDOM_INT(255);
	
	unsigned char macaddr2[6];
	macaddr2[0] = (unsigned char) RANDOM_INT(255);
	macaddr2[1] = (unsigned char) RANDOM_INT(255);
	macaddr2[2] = (unsigned char) RANDOM_INT(255);
	macaddr2[3] = (unsigned char) RANDOM_INT(255);
	macaddr2[4] = (unsigned char) RANDOM_INT(255);
	macaddr2[5] = (unsigned char) RANDOM_INT(255);
	
	EthernetAddress addr(macaddr);
	EthernetAddress addr2(macaddr2);
	InterfaceRef localIface = Interface::create<EthernetInterface>(macaddr, "eth", addr, 0);		
	InterfaceRef remoteIface = Interface::create<EthernetInterface>(macaddr2, "eth2", addr2, 0);		
	DataObjectRef dObj = DataObject::create(NULL, 0, localIface, remoteIface);

	for (unsigned int i = 0; i < numAttr; i++) {
		int tries = 0;
		do {
			r = RANDOM_INT(32000);
			sprintf(name, "name");
			sprintf(value, "value %d", r);
			if (tries++ > 10) {
				HAGGLE_ERR("WARNING: Cannot generate unique attributes in data object... check attribute pool size!\n");
				break;
			}
		} while (dObj->getAttribute(name, value));

		dObj->addAttribute(name, value, 1); //r);
	}

	return dObj;
}
    void initializationCallback(Event *e) 
    {
        DataObjectRefList dObjs = e->getDataObjectList();
        
        for (DataObjectRefList::iterator it = dObjs.begin(); it != dObjs.end(); it++) {
            DataObjectRef dObj = *it;
            if (!purger->isResponsibleForDataObject(dObj)) {
                continue;
            }
            double now = (Timeval::now()).getTimeAsSecondsDouble();
            double then = (dObj->getReceiveOrCreateTime()).getTimeAsSecondsDouble();
		    const Attribute *attr = dObj->getAttribute(purger->getMetricField(), "*", 1);
            double ttl = atof(attr->getValue().c_str()); 

            if (now < (then + ttl + purger->getMinDBTimeS())) {
                purger->schedulePurge(dObj);
            } 
            else {
                kernel->getDataStore()->deleteDataObject(dObj, purger->getKeepInBloomfilter());
            }
        }
    }
string 
ProtocolClassifierAttribute::getClassNameForDataObject(
    const DataObjectRef& dObj)
{
    if (!initialized) {
        HAGGLE_ERR("Classifier has not been fully initialized.\n");
        return PROTOCOL_CLASSIFIER_INVALID_CLASS;
    }

    if (!dObj) {
        HAGGLE_ERR("Received null data object.\n");
        return PROTOCOL_CLASSIFIER_INVALID_CLASS;
    }
    
    const Attribute *attr = dObj->getAttribute(attrName, attrValue);
    
    // only mark node descriptions as light-weight content
    if (!attr) {
        return PROTOCOL_CLASSIFIER_INVALID_CLASS;
    }

    return className;
}
void
CachePurgerRelTTL::schedulePurge(
    DataObjectRef &dObj) 
{
    if (!isResponsibleForDataObject(dObj)) {
        HAGGLE_ERR("Cannot schedule purge for DO not responsible for\n");
        return;
    }

    const Attribute *attr = dObj->getAttribute(metricField, "*", 1);
    if (!attr) {
        HAGGLE_ERR("Attribute not specified\n");
        return;
    }

    double now = (Timeval::now()).getTimeAsSecondsDouble();
    double ttl = atof(attr->getValue().c_str());
    double then = (dObj->getReceiveOrCreateTime()).getTimeAsSecondsDouble();
    
    double expTime = ttl - (now - then); 
    expTime = expTime > minDBtimeS ? expTime : minDBtimeS;

    getKernel()->addEvent(new Event(deleteCallback, dObj, expTime));
}