Example #1
0
static bool
_athenaLRUContentStore_PutContentObject(AthenaContentStoreImplementation *store, const CCNxContentObject *content)
{
    AthenaLRUContentStore *impl = (AthenaLRUContentStore *) store;

    // If there's no capacity at all, just return now.
    if (impl->maxSizeInBytes <= 0) {
        return false;
    }

    // Check to see if the ContentObject is expired. If so, don't bother to cache it.
    if (ccnxContentObject_HasExpiryTime(content)) {
        if (ccnxContentObject_GetExpiryTime(content) <= parcClock_GetTime(impl->wallClock)) {
            // the expiration time is now or earlier, so don't bother adding it.
            return false;
        }
    }

    _AthenaLRUContentStoreEntry *newEntry = _athenaLRUContentStoreEntry_Create(content);

    bool result = _athenaLRUContentStore_PutLRUContentStoreEntry(store, newEntry);

    if (result == false) {
        // We didn't have enough room in the store to add the new item.
    }

    _athenaLRUContentStoreEntry_Release(&newEntry);

    return result;
}
Example #2
0
LONGBOW_TEST_CASE(Global, getMatchByName)
{
    AthenaLRUContentStoreConfig config;
    config.capacityInMB = 10;
    AthenaContentStore *store = athenaContentStore_Create(&AthenaContentStore_LRUImplementation, &config);

    char *lci = "lci:/cakes/and/pies";

    PARCClock *clock = parcClock_Wallclock();

    CCNxName *truthName = ccnxName_CreateFromURI(lci);
    CCNxContentObject *truthObject = ccnxContentObject_CreateWithDataPayload(truthName, NULL);
    ccnxContentObject_SetExpiryTime(truthObject, parcClock_GetTime(clock) + 100);
    ccnxName_Release(&truthName);

    athenaContentStore_PutContentObject(store, truthObject);

    CCNxName *testName = ccnxName_CreateFromURI(lci);
    CCNxInterest *interest = ccnxInterest_CreateSimple(testName);
    ccnxName_Release(&testName);

    //athena_EncodeMessage(interest);

    CCNxContentObject *testObject = athenaContentStore_GetMatch(store, interest);
    ccnxInterest_Release(&interest);

    // TODO: match on other than name!
    assertTrue(ccnxContentObject_Equals(truthObject, testObject), "Expected to get the same ContentObject back");
    assertTrue(truthObject == testObject, "Expected the same pointer back");

    athenaContentStore_Release(&store);
    ccnxContentObject_Release(&truthObject);
    parcClock_Release(&clock);
}
Example #3
0
LONGBOW_TEST_CASE(Global, removeMatch)
{
    AthenaLRUContentStoreConfig config;
    config.capacityInMB = 10;
    AthenaContentStore *store = athenaContentStore_Create(&AthenaContentStore_LRUImplementation, &config);

    PARCClock *clock = parcClock_Wallclock();
    char *lci = "lci:/cakes/and/pies";

    CCNxName *origName = ccnxName_CreateFromURI(lci);
    CCNxContentObject *contentObject = ccnxContentObject_CreateWithDataPayload(origName, NULL);

    ccnxContentObject_SetExpiryTime(contentObject, parcClock_GetTime(clock) + 100);
    ccnxName_Release(&origName);

    athenaContentStore_PutContentObject(store, contentObject);
    ccnxContentObject_Release(&contentObject);

    CCNxName *testName = ccnxName_CreateFromURI(lci);
    bool status = athenaContentStore_RemoveMatch(store, testName, NULL, NULL);
    // TODO: match on other than name!
    assertTrue(status, "Expected to remove the contentobject we had");

    ccnxName_Release(&testName);
    parcClock_Release(&clock);
    athenaContentStore_Release(&store);
}
LONGBOW_TEST_CASE(Local, putWithExpiryTime)
{
    AthenaLRUContentStore *impl = _createLRUContentStore();

    CCNxName *name1 = ccnxName_CreateFromURI("lci:/first/entry");
    CCNxContentObject *contentObject1 = ccnxContentObject_CreateWithDataPayload(name1, NULL);

    CCNxName *name2 = ccnxName_CreateFromURI("lci:/second/entry");
    CCNxContentObject *contentObject2 = ccnxContentObject_CreateWithDataPayload(name2, NULL);

    CCNxName *name3 = ccnxName_CreateFromURI("lci:/third/entry");
    CCNxContentObject *contentObject3 = ccnxContentObject_CreateWithDataPayload(name3, NULL);

    uint64_t now = parcClock_GetTime(impl->wallClock);

    ccnxContentObject_SetExpiryTime(contentObject1, now + 200);  // Expires AFTER object 2
    ccnxContentObject_SetExpiryTime(contentObject2, now + 100);
    // contentObject3 has no expiry time, so it expires last.

    _AthenaLRUContentStoreEntry *entry1 = _athenaLRUContentStoreEntry_Create(contentObject1);
    _AthenaLRUContentStoreEntry *entry2 = _athenaLRUContentStoreEntry_Create(contentObject2);
    _AthenaLRUContentStoreEntry *entry3 = _athenaLRUContentStoreEntry_Create(contentObject3);

    bool status = _athenaLRUContentStore_PutContentObject(impl, contentObject1);
    assertTrue(status, "Exepected to insert content");

    status = _athenaLRUContentStore_PutContentObject(impl, contentObject2);
    assertTrue(status, "Exepected to insert content");

    _AthenaLRUContentStoreEntry *oldestEntry = _getEarliestExpiryTime(impl);

    assertTrue(oldestEntry->contentObject == entry2->contentObject, "Expected entry 2 to be the earliest expiring entry");

    status = _athenaLRUContentStore_PutContentObject(impl, contentObject3);
    assertTrue(status, "Exepected to insert content");

    // The entry with no expiration time should not affect list ordering.
    oldestEntry = _getEarliestExpiryTime(impl);
    assertTrue(oldestEntry->contentObject == entry2->contentObject, "Expected entry 2 to be the earliest expiring entry");

    // Now remove the oldest one we added. The next oldest one should be contentObject1
    _athenaLRUContentStore_RemoveMatch(impl, name2, NULL, NULL);

    // The entry with no expiration time should not affect list ordering.
    oldestEntry = _getEarliestExpiryTime(impl);
    assertTrue(oldestEntry->contentObject == entry1->contentObject, "Expected entry 1 to be the earliest expiring entry");

    _athenaLRUContentStoreEntry_Release(&entry1);
    _athenaLRUContentStoreEntry_Release(&entry2);
    _athenaLRUContentStoreEntry_Release(&entry3);

    ccnxContentObject_Release(&contentObject1);
    ccnxContentObject_Release(&contentObject2);
    ccnxContentObject_Release(&contentObject3);
    ccnxName_Release(&name1);
    ccnxName_Release(&name2);
    ccnxName_Release(&name3);

    _athenaLRUContentStore_Release((AthenaContentStoreImplementation *) &impl);
}
Example #5
0
static CCNxContentObject *
//_athenaLRUContentStore_GetMatch(AthenaContentStoreImplementation *store, const CCNxName *name, const PARCBuffer *keyIdRestriction,
//                                const PARCBuffer *contentObjectHash)
_athenaLRUContentStore_GetMatch(AthenaContentStoreImplementation *store, const CCNxInterest *interest)
{
    CCNxContentObject *result = NULL;
    AthenaLRUContentStore *impl = (AthenaLRUContentStore *) store;
    _AthenaLRUContentStoreEntry *entry = NULL;

    CCNxName *name = ccnxInterest_GetName(interest);
    PARCBuffer *contentObjectHashRestriction = ccnxInterest_GetContentObjectHashRestriction(interest);
    PARCBuffer *keyIdRestriction = ccnxInterest_GetKeyIdRestriction(interest);

    if (contentObjectHashRestriction != NULL) {
        PARCObject *nameAndHashKey = _createHashableKey(name, NULL, contentObjectHashRestriction);
        entry = (_AthenaLRUContentStoreEntry *) parcHashMap_Get(impl->tableByNameAndObjectHash, nameAndHashKey);
        parcObject_Release((PARCObject **) &nameAndHashKey);
    }

    if ((entry == NULL) && (keyIdRestriction != NULL)) {
        PARCObject *nameAndKeyIdKey = _createHashableKey(name, keyIdRestriction, NULL);
        entry = (_AthenaLRUContentStoreEntry *) parcHashMap_Get(impl->tableByNameAndKeyId, nameAndKeyIdKey);
        parcObject_Release((PARCObject **) &nameAndKeyIdKey);
    }

    if (entry == NULL) {
        PARCObject *nameKey = _createHashableKey(name, NULL, NULL);
        entry = (_AthenaLRUContentStoreEntry *) parcHashMap_Get(impl->tableByName, nameKey);
        parcObject_Release((PARCObject **) &nameKey);
    }

    // Matching is done. Now check for validity, if necessary.

    if (entry != NULL) {
        // We found matching content. Now make sure it's not expired before returning it. If it is expired,
        // remove it from the store and don't return anything.
        if (entry->hasExpiryTime && (entry->expiryTime < parcClock_GetTime(impl->wallClock))) {
            _athenaLRUContentStore_PurgeContentStoreEntry(impl, entry);
            entry = NULL;
        }

        // XXX: TODO: Check that the KeyId, if any, was verified.
    }

    // At this point, the cached content is considered valid for responding with. Return it.
    if (entry != NULL) {
        result = entry->contentObject;

        // Update LRU so that the matched entry is at the top of the list.
        _moveContentStoreEntryToLRUHead(impl, entry);

        impl->stats.numMatchHits++;
    } else {
        impl->stats.numMatchMisses++;
    }

    return result;
}
Example #6
0
static bool
_makeRoomInStore(AthenaLRUContentStore *impl, size_t sizeNeeded)
{
    bool result = false;

    if (sizeNeeded > impl->maxSizeInBytes) {
        return false; // not possible.
    }

    uint64_t nowInMillis = parcClock_GetTime(impl->wallClock);

    // Evict expired items until we have enough room, or don't have any expired items.
    while (sizeNeeded > (impl->maxSizeInBytes - impl->currentSizeInBytes)) {
        _AthenaLRUContentStoreEntry *entry = _getEarliestExpiryTime(impl);
        if (entry == NULL) {
            break;
        }
        if (nowInMillis > entry->expiryTime) {
            _athenaLRUContentStore_PurgeContentStoreEntry(impl, entry);
        } else {
            break;
        }
    }

    // Evict items past their recommended cache time until we have enough room, or don't have any items.
    while (sizeNeeded > (impl->maxSizeInBytes - impl->currentSizeInBytes)) {
        _AthenaLRUContentStoreEntry *entry = _getEarliestRecommendedCacheTime(impl);
        if (entry == NULL) {
            break;
        }
        if (nowInMillis > entry->recommendedCacheTime) {
            _athenaLRUContentStore_PurgeContentStoreEntry(impl, entry);
        } else {
            break;
        }
    }

    while (sizeNeeded > (impl->maxSizeInBytes - impl->currentSizeInBytes)) {
        _AthenaLRUContentStoreEntry *entry = _getLeastUsedFromLRU(impl);
        if (entry == NULL) {
            break;
        }
        _athenaLRUContentStore_PurgeContentStoreEntry(impl, entry);
    }

    if (impl->maxSizeInBytes - impl->currentSizeInBytes > sizeNeeded) {
        return true;
    }

    return result;
}
LONGBOW_TEST_CASE(Local, putWithExpiryTime_Expired)
{
    AthenaLRUContentStore *impl = _createLRUContentStore();

    CCNxName *name1 = ccnxName_CreateFromURI("lci:/first/entry");
    CCNxContentObject *contentObject1 = ccnxContentObject_CreateWithDataPayload(name1, NULL);

    CCNxName *name2 = ccnxName_CreateFromURI("lci:/second/entry");
    CCNxContentObject *contentObject2 = ccnxContentObject_CreateWithDataPayload(name2, NULL);

    CCNxName *name3 = ccnxName_CreateFromURI("lci:/third/entry");
    CCNxContentObject *contentObject3 = ccnxContentObject_CreateWithDataPayload(name3, NULL);

    uint64_t now = parcClock_GetTime(impl->wallClock);

    // NOTE: These two are considered expired and should NOT be added to the store.
    ccnxContentObject_SetExpiryTime(contentObject1, now);
    _AthenaLRUContentStoreEntry *entry1 = _athenaLRUContentStoreEntry_Create(contentObject1);

    ccnxContentObject_SetExpiryTime(contentObject2, now - 100);
    _AthenaLRUContentStoreEntry *entry2 = _athenaLRUContentStoreEntry_Create(contentObject2);

    // NOTE: This one does not have an expiry time, so should be added.
    _AthenaLRUContentStoreEntry *entry3 = _athenaLRUContentStoreEntry_Create(contentObject3);

    bool status = _athenaLRUContentStore_PutContentObject(impl, contentObject1);
    assertFalse(status, "Exepected to fail on inserting expired content");

    status = _athenaLRUContentStore_PutContentObject(impl, contentObject2);
    assertFalse(status, "Exepected to fail on inserting expired content");

    status = _athenaLRUContentStore_PutContentObject(impl, contentObject3);
    assertTrue(status, "Exepected to insert a ContentObject with no expiry time.");

    _athenaLRUContentStoreEntry_Release(&entry1);
    _athenaLRUContentStoreEntry_Release(&entry2);
    _athenaLRUContentStoreEntry_Release(&entry3);

    ccnxContentObject_Release(&contentObject1);
    ccnxContentObject_Release(&contentObject2);
    ccnxContentObject_Release(&contentObject3);
    ccnxName_Release(&name1);
    ccnxName_Release(&name2);
    ccnxName_Release(&name3);

    _athenaLRUContentStore_Release((AthenaContentStoreImplementation *) &impl);
}
Example #8
0
static CCNxMetaMessage *
_athenaLRUContentStore_ProcessMessage(AthenaContentStoreImplementation *store, const CCNxMetaMessage *message)
{
    CCNxMetaMessage *result = NULL;
    AthenaLRUContentStore *impl = (AthenaLRUContentStore *) store;

    if (ccnxMetaMessage_IsInterest(message)) {
        CCNxInterest *interest = ccnxMetaMessage_GetInterest(message);
        CCNxName *queryName = ccnxInterest_GetName(interest);

        uint64_t chunkNumber = 0;
        bool hasChunkNumber = false;
        _getChunkNumberFromName(queryName, &chunkNumber, &hasChunkNumber);
        assertFalse(hasChunkNumber, "LRUContentStore queries don't yet support more than 1 chunk.");

        PARCBuffer *responsePayload = NULL;

        // Find the arguments to our query.
        size_t argSegmentIndex = 0;
        if (_getSegmentIndexOfQueryArgs(queryName, AthenaModule_ContentStore, &argSegmentIndex)) {
            CCNxNameSegment *queryTypeSegment = ccnxName_GetSegment(queryName, argSegmentIndex);
            char *queryTypeString = ccnxNameSegment_ToString(queryTypeSegment);  // e.g. "stat"

            char *statString = "stat";
            if (strncasecmp(queryTypeString, statString, strlen(statString)) == 0) {
                responsePayload = _processStatQuery(impl, queryName, argSegmentIndex + 1, chunkNumber);
            }
            parcMemory_Deallocate(&queryTypeString);
        }

        if (responsePayload != NULL) {
            CCNxContentObject *contentObjectResponse = ccnxContentObject_CreateWithNameAndPayload(
                ccnxInterest_GetName(interest), responsePayload);

            result = ccnxMetaMessage_CreateFromContentObject(contentObjectResponse);
            ccnxContentObject_SetExpiryTime(contentObjectResponse,
                                            parcClock_GetTime(impl->wallClock) +
                                            100); // this response is good for 100 millis

            ccnxContentObject_Release(&contentObjectResponse);
            parcBuffer_Release(&responsePayload);
        }
    }

    return result;  // could be NULL
}
Example #9
0
/**
 * Create a PARCBuffer payload containing a JSON string with information about this ContentStore's
 * size.
 */
static PARCBuffer *
_createStatSizeResponsePayload(const AthenaLRUContentStore *impl, const CCNxName *name, uint64_t chunkNumber)
{
    PARCJSON *json = parcJSON_Create();

    parcJSON_AddString(json, "moduleName", AthenaContentStore_LRUImplementation.description);
    parcJSON_AddInteger(json, "time", parcClock_GetTime(impl->wallClock));
    parcJSON_AddInteger(json, "numEntries", impl->numEntries);
    parcJSON_AddInteger(json, "sizeInBytes", impl->currentSizeInBytes);

    char *jsonString = parcJSON_ToString(json);

    parcJSON_Release(&json);

    PARCBuffer *result = parcBuffer_CreateFromArray(jsonString, strlen(jsonString));

    parcMemory_Deallocate(&jsonString);

    return parcBuffer_Flip(result);
}
LONGBOW_TEST_CASE(Local, putContentAndExpireByExpiryTime)
{
    AthenaLRUContentStoreConfig config;
    config.capacityInMB = 1; // 2M

    AthenaLRUContentStore *impl = _athenaLRUContentStore_Create(&config);

    uint64_t now = parcClock_GetTime(impl->wallClock);

    PARCBuffer *payload = parcBuffer_Allocate(300 * 1000); // 300K payload. Should fit 3 into the store.

    CCNxName *name1 = ccnxName_CreateFromURI("lci:/object/1");
    CCNxName *name2 = ccnxName_CreateFromURI("lci:/object/2");
    CCNxName *name3 = ccnxName_CreateFromURI("lci:/object/3");
    CCNxName *name4 = ccnxName_CreateFromURI("lci:/object/4");

    CCNxContentObject *contentObject1 = ccnxContentObject_CreateWithDataPayload(name1, payload);
    _AthenaLRUContentStoreEntry *entry = _athenaLRUContentStoreEntry_Create(contentObject1);
    entry->hasExpiryTime = true;
    entry->expiryTime = now + 2000000;
    bool status = _athenaLRUContentStore_PutLRUContentStoreEntry(impl, entry);
    _athenaLRUContentStoreEntry_Release(&entry);
    assertTrue(status, "Expected to put the content in the store");

    CCNxContentObject *contentObject2 = ccnxContentObject_CreateWithDataPayload(name2, payload);
    entry = _athenaLRUContentStoreEntry_Create(contentObject2);
    entry->expiryTime = now - 10000; // This one expires first. (it's already expired)
    entry->hasExpiryTime = true;
    status = _athenaLRUContentStore_PutLRUContentStoreEntry(impl, entry);
    _athenaLRUContentStoreEntry_Release(&entry);
    assertTrue(status, "Expected to put the content in the store");

    CCNxContentObject *contentObject3 = ccnxContentObject_CreateWithDataPayload(name3, payload);
    entry = _athenaLRUContentStoreEntry_Create(contentObject3);
    entry->expiryTime = now + 3000000;
    entry->hasExpiryTime = true;
    status = _athenaLRUContentStore_PutLRUContentStoreEntry(impl, entry);
    _athenaLRUContentStoreEntry_Release(&entry);
    assertTrue(status, "Expected to put the content in the store");

    // At this point, there are three items in the store. Try to put in a 4th, which should force the one
    // with the earliest expiration time to be expired.

    CCNxContentObject *contentObject4 = ccnxContentObject_CreateWithDataPayload(name4, payload);
    entry = _athenaLRUContentStoreEntry_Create(contentObject4);
    entry->expiryTime = now + 3000000;
    entry->hasExpiryTime = true;
    status = _athenaLRUContentStore_PutLRUContentStoreEntry(impl, entry);
    _athenaLRUContentStoreEntry_Release(&entry);
    assertTrue(status, "Expected to put the content in the store");

    assertTrue(impl->currentSizeInBytes < impl->maxSizeInBytes, "Expected the current store size to be less than the capacity");

    athenaLRUContentStore_Display(impl, 0);

    // Now check that the oldest was removed.
    CCNxInterest *interest = ccnxInterest_CreateSimple(name2);
    CCNxContentObject *match = _athenaLRUContentStore_GetMatch(impl, interest);
    assertNull(match, "Expected the content for name2 to have been removed from the store");
    ccnxInterest_Release(&interest);

    // Now check that the others still exist.
    interest = ccnxInterest_CreateSimple(name1);
    match = _athenaLRUContentStore_GetMatch(impl, interest);
    assertNotNull(match, "Expected the content for name1 to be in the store");
    ccnxInterest_Release(&interest);

    interest = ccnxInterest_CreateSimple(name3);
    match = _athenaLRUContentStore_GetMatch(impl, interest);
    assertNotNull(match, "Expected the content for name3 to be in the store");
    ccnxInterest_Release(&interest);

    interest = ccnxInterest_CreateSimple(name4);
    match = _athenaLRUContentStore_GetMatch(impl, interest);
    assertNotNull(match, "Expected the content for name4 to be in the store");
    ccnxInterest_Release(&interest);

    ccnxContentObject_Release(&contentObject1);
    ccnxContentObject_Release(&contentObject2);
    ccnxContentObject_Release(&contentObject3);
    ccnxContentObject_Release(&contentObject4);
    ccnxName_Release(&name1);
    ccnxName_Release(&name2);
    ccnxName_Release(&name3);
    ccnxName_Release(&name4);
    parcBuffer_Release(&payload);

    _athenaLRUContentStore_Release((AthenaContentStoreImplementation *) &impl);
}