/*
 * Publish a data object with utility based caching statistics.
 */
void
CacheStrategyUtility::_publishStatsDataObject()
{
    DataObjectRef dObj = DataObject::create();
    dObj->addAttribute("CacheStrategyUtility", "stats");
    dObj->addAttribute("Timestamp", Timeval::now().getAsString().c_str());
    dObj->addAttribute("PublisherID", getManager()->getKernel()->getThisNode()->getIdStr());
    dObj->addAttribute("Statistics", _generateStatsString().c_str());

#ifdef DEBUG
    dObj->print(NULL); // MOS - NULL means print to debug trace
#endif

    getManager()->getKernel()->addEvent(new Event(EVENT_TYPE_DATAOBJECT_RECEIVED, dObj));
}
Exemple #2
0
DataObjectRef Forwarder::createRoutingInformationDataObject()
{
	// No need to have a reference in this function because it won't be 
	// visible outside until this function is done with it.
	DataObjectRef dObj = DataObject::create();
	
	if (!dObj)
		return NULL;

	HAGGLE_DBG2("Creating routing info data object\n");

	dObj->setPersistent(false);
	dObj->addAttribute("Forwarding", getName());
	
	// Add the metric data to the forwarding section:
	Metadata *md = dObj->getMetadata()->addMetadata(getManager()->getName());
	
	md = md->addMetadata(getName());
	md->setParameter("node_id", getKernel()->getThisNode()->getIdStr());
	
	if (!addRoutingInformation(dObj, md)) {
        // SW: ERR->DBG, this is not fatal, we return false when we don't want
        // to add routing data.
	        // HAGGLE_DBG("Could not add routing information\n");
		return NULL;
	}

	return dObj;
}
void DebugManager::onFindRepositoryKey(Event *e)
{
	if (!e || !e->hasData())
		return;
	
	DataStoreQueryResult *qr = static_cast < DataStoreQueryResult * >(e->getData());
	
	RepositoryEntryRef re = qr->detachFirstRepositoryEntry();
	
	if (!re) {
		// No repository entry: no data object.
		DataObjectRef dObj;

		// Name the log so that the files are more easily readable on the 
		// machine that receives them:
		char filename[128];
		sprintf(filename, "log-%s.txt", kernel->getThisNode()->getIdStr());

		// Create data object:
		
		// Empty at first:
		dObj = DataObject::create(LogTrace::ltrace.getFile(), filename);
		
		if (!dObj) {
			HAGGLE_ERR("Could not create data object\n");
			return;
		}
		// Add log file attribute:
		Attribute a("Log file","Trace");
		dObj->addAttribute(a);
		
		// Add node id of local node, to make sure that two logs from different 
		// nodes don't clash:
		Attribute b("Node id", kernel->getThisNode()->getIdStr());
		dObj->addAttribute(b);
		
		// Insert data object:
		kernel->getDataStore()->insertDataObject(dObj);
		
		// Insert a repository entry to show the data object exists:
		kernel->getDataStore()->insertRepository(new RepositoryEntry("DebugManager", "has saved log file data object", "yes"));
	}
	
	delete qr;
}
/**
* 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;
}
bool FragmentationEncoderService::addAttributes(DataObjectRef originalDataObject, DataObjectRef fragmentDataObject,
        string sequenceNumberListCsv) {

    //copy attributes. though eventually will use rich metadata?
    const Attributes* originalAttributes = originalDataObject->getAttributes();
    for (Attributes::const_iterator it = originalAttributes->begin(); it != originalAttributes->end(); it++) {
        const Attribute attr = (*it).second;
        bool addAttribute = fragmentDataObject->addAttribute(attr);
        if (!addAttribute) {
            HAGGLE_ERR("unable to add attribute\n");
            return false;
        }
    }

    //add sequence number attribute
//	char sequenceBuffer[33];
//	memset(sequenceBuffer, 0, sizeof(sequenceBuffer));
//	sprintf(sequenceBuffer, "%d", sequenceNumber);
//	HAGGLE_DBG("stringSequenceNumber=%s\n", sequenceBuffer);
//	bool addedSequenceNUmber = fragmentDataObject->addAttribute(
//			HAGGLE_ATTR_FRAGMENTATION_SEQUENCE_NUMBER, sequenceBuffer, 0);
//	if (!addedSequenceNUmber) {
//		HAGGLE_ERR("unable to add addedSequenceNUmber attribute\n");
//		return false;
//	}

    HAGGLE_DBG2("stringSequenceNumber=%s\n", sequenceNumberListCsv.c_str());
    bool addedSequenceNumber = fragmentDataObject->addAttribute(HAGGLE_ATTR_FRAGMENTATION_SEQUENCE_NUMBER,
            sequenceNumberListCsv, 0);
    if (!addedSequenceNumber) {
        HAGGLE_ERR("Unable to add sequence number attribute\n");
        return false;
    }

    //add attribute to indicate data object is fragmentation block
    bool addedIsFragmentationCodedAttribute = fragmentDataObject->addAttribute(HAGGLE_ATTR_FRAGMENTATION_NAME, "TRUE",
            0);
    if (!addedIsFragmentationCodedAttribute) {
        HAGGLE_ERR("Unable to add fragmentation attribute\n");
        return false;
    }

    //add original data len attribute
    char lenBuffer[33];
    memset(lenBuffer, 0, sizeof(lenBuffer));
    int len = fragmentationDataObjectUtility->getFileLength(originalDataObject);
    if(len == 0) {
        HAGGLE_ERR("Orignal data len is zero - file already deleted\n");
        return false;
    }
    sprintf(lenBuffer, "%d", len);
    bool addedDataLenAttribute = fragmentDataObject->addAttribute(HAGGLE_ATTR_FRAGMENTATION_PARENT_ORIG_LEN, lenBuffer,
            0);
    if (!addedDataLenAttribute) {
        HAGGLE_ERR("Unable to add original data len attribute\n");
        return false;
    }

    //add dataobject id
    const char* originalId = originalDataObject->getIdStr();
    string originalStringId = originalId;
    bool addedIdAttribute = fragmentDataObject->addAttribute(HAGGLE_ATTR_FRAGMENTATION_PARENT_DATAOBJECT_ID,
            originalStringId, 0);
    if (!addedIdAttribute) {
        HAGGLE_ERR("Unable to add original data object id attribute\n");
        return false;
    }

    //add dataobject name
    string originalName = fragmentationDataObjectUtility->getFileName(originalDataObject);
    HAGGLE_DBG2("Add original name %s as attribute\n", originalName.c_str());
    bool addedNameAttribute = fragmentDataObject->addAttribute(HAGGLE_ATTR_FRAGMENTATION_PARENT_ORIG_NAME, originalName,
            0);
    if (!addedNameAttribute) {
        HAGGLE_ERR("Unable to add original name attribute\n");
        return false;
    }

    //add create time
    string originalCreateTime = originalDataObject->getCreateTime().getAsString();
    HAGGLE_DBG2("Add original create time %s as attribute\n", originalCreateTime.c_str());
    bool addedCreatedTimeAttribute = fragmentDataObject->addAttribute(HAGGLE_ATTR_FRAGMENTATION_PARENT_CREATION_TIME,
            originalCreateTime, 0);
    if (!addedCreatedTimeAttribute) {
        HAGGLE_ERR("Unable to add original create time attribute\n");
        return false;
    }

    //set create time of fragment to same create time as parent so fragment data object ids can match up
    Timeval createTime(originalCreateTime);
    fragmentDataObject->setCreateTime(createTime);

    if(originalDataObject->getSignature()) { // MOS
      //add signee
      string parentSignee = originalDataObject->getSignee();
      HAGGLE_DBG2("Add original signee %s as attribute\n",parentSignee.c_str());
      bool addedSigneeAttribute = fragmentDataObject->
	addAttribute(HAGGLE_ATTR_FRAGMENTATION_PARENT_ORIG_SIGNEE,parentSignee,0);
      if(!addedSigneeAttribute) {
        HAGGLE_ERR("Unable to add original signee attribute\n");
        return false;
      }
      
      //add signature
      char *base64_signature = NULL;
      if (base64_encode_alloc((char *)originalDataObject->getSignature(), originalDataObject->getSignatureLength(), &base64_signature) <= 0) {
        HAGGLE_ERR("Unable to generate base64 encoded signature\n");
        return false;
      }
      string parentSignature = base64_signature;
      HAGGLE_DBG2("Add original signature %s as attribute\n",parentSignature.c_str());
      bool addedSignatureAttribute = fragmentDataObject->
	addAttribute(HAGGLE_ATTR_FRAGMENTATION_PARENT_ORIG_SIGNATURE,parentSignature,0);
      if(!addedSignatureAttribute) {
        HAGGLE_ERR("Unable to add original signature attribute\n");
        return false;
      }
      if(base64_signature) {
        free(base64_signature);
        base64_signature = NULL;
      }
    }

    return true;
}
/**
* selfTest() depends upon periodic purging.   Every call, it will first fill up the database, taking memory snapshots,
* then purge, taking more memory snapshots.   It creates a number of random data objects, inserts them into the system,
* and records current memory usage into a file called 'mem.results', for every interation.   It does in the following steps:
*
* 1.  Add, approximately, 20 DO's per second, done every poll period (e.g. 10 seconds, means add 200 for that interval).
*
* 2.  When the number of DO's in the system match the threshold setting, we drop the threshold by the same number
* we increased it in step 1.   In this case, we decrease it by 20, allowing the memory threshold purger to do its job.
*
* 3.  Repeat step 1.
*
* 4.  Repeat step 2.
*
* 5.  Reset system functions to original defaults.
*
* This allows the system to approach maximum usage, drop to zero, back to maximum usage, then back to zero.
* The file can be parse into a plot showing how much memory is freed.   This test works regardless of using
* in memory database, the improved all memory database, or disk based database.
* 
* WARNING: We use mallinfo() to determine the amount of memory used and released, as the system does NOT
* see any memory freed at all, due to the fact dlmallopt(-1) is set in main.cpp.  This tells free to not
* return freed memory to the system.    Thus, using mallinfo is the only means available to show how much
* memory is actually freed to the application (but not to the system).
* 
*  
*/
void
CacheStrategyUtility::selfTest()
{
    static int init=0;
    static float amount_do=0;
    static int count=0;
    char countStr[50];
    static float threshold_backup;
    static char *direction;
    if (!init) {
       init=1;
       threshold_backup=db_size_threshold;
       amount_do=20.0*pollPeriodMs/1000; //20 per second seems reasonable
       if (amount_do > db_size_threshold/10) {
         amount_do = db_size_threshold/10;
       }
       direction="Start";

    }   // JM: Start DB purging
        // JM: Testing code only, to prove it works.   Lets do linear testing.
        struct mallinfo mi=mallinfo();
	//Due to file permission difficulties in android, we'll write it as a log
        HAGGLE_DBG("\nThreshold(%s): %lld/%d -- Used bytes: %d, Free bytes: %d, SQL: %lld\n\n", direction, db_size_threshold,current_num_do, mi.uordblks, mi.fordblks, sqlite3_memory_used());
        //send db_size_threshold DO's
	//init = 1 means send DO's
	//init = 2 means we are in purging mode
        if ((init == 1) || (init == 3)) {
          float upperlimit=current_num_do+amount_do;
          if (upperlimit > db_size_threshold) {
            upperlimit = db_size_threshold+1;
	    init++;
          }
          if (init ==1) {
             direction="Up1";
          } else if (init == 3) {
             direction="Up2";
          } else { 
             direction="StateChangeFromUp";
          }

          for(int i=current_num_do; i<upperlimit; i++) {
	    DataObjectRef dObj = createDataObject(2);
	    dObj->addAttribute("ContentOriginator", "self");
	    dObj->addAttribute("ContentType", "DelByRelTTL");
	    dObj->addAttribute("ContentType2", "DelByAbsTTL");
	    dObj->addAttribute("purge_by_timestamp", "2000000000");
	    dObj->addAttribute("purge_after_seconds", "2000000000");
            char buffer[1025];
            snprintf(buffer, 1024, "%llu", (unsigned long long)time(NULL));
            sprintf(countStr, "%d", count++);
	    dObj->addAttribute("ContentCreationTime", buffer);
	    dObj->addAttribute("count", countStr);
            dObj->calcId();
	    _handleNewDataObject(dObj);
          }
         } else if ((init == 2) || (init == 4)) {   //init==2, reduction
            db_size_threshold -= amount_do;
            if (db_size_threshold < 0.0) {
              init++;
              db_size_threshold=threshold_backup;
            }
            if (init == 2) {
               direction="Down1";
            } else if (init == 4) {
               direction="Down2";
            } else {
               direction="StateChangeFromDown";
            }
         } else { //if (init == 5) 
           //clear seltTest?
           self_test = false;
           db_size_threshold=threshold_backup;
           HAGGLE_DBG("Self Test completed!\n");
           //remove any last DO's
           //write any STAT information
           getKernel()->shutdown();
           //return;
         }
        // JM: End testing
}