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);
}
LONGBOW_TEST_CASE(Local, _athenaLRUContentStore_GetMatchByNameAndObjectHash)
{
    AthenaLRUContentStore *impl = _createLRUContentStore();

    PARCBuffer *payload = parcBuffer_Allocate(1200);

    CCNxName *name = ccnxName_CreateFromURI("lci:/boose/roo/pie");
    CCNxContentObject *contentObject = ccnxContentObject_CreateWithDataPayload(name, NULL);

    parcBuffer_Release(&payload);
    _AthenaLRUContentStoreEntry *entry1 = _athenaLRUContentStoreEntry_Create(contentObject);

    entry1->hasKeyId = false;
    entry1->hasContentObjectHash = false;

    bool status = _athenaLRUContentStore_PutLRUContentStoreEntry(impl, entry1);
    assertTrue(status, "Expected to add the entry");

    // Now add another content object with the same name, but an object hash too.

    CCNxContentObject *contentObject2 = ccnxContentObject_CreateWithDataPayload(name, NULL);

    _AthenaLRUContentStoreEntry *entry2 = _athenaLRUContentStoreEntry_Create(contentObject2);

    entry2->contentObjectHash = parcBuffer_WrapCString("corned beef");
    entry2->hasContentObjectHash = true;

    status = _athenaLRUContentStore_PutLRUContentStoreEntry(impl, entry2);
    assertTrue(status, "Expected to add the entry");
    assertTrue(impl->numEntries == 2, "Expected 2 store items");

    // Now match on Name + ObjectHash.

    CCNxInterest *interest = ccnxInterest_CreateSimple(name);
    PARCBuffer *hashRestriction = parcBuffer_Copy(entry2->contentObjectHash);
    ccnxInterest_SetContentObjectHashRestriction(interest, hashRestriction);
    parcBuffer_Release(&hashRestriction);

    CCNxContentObject *match = _athenaLRUContentStore_GetMatch(impl, interest);
    assertNotNull(match, "Expected to match something");
    assertTrue(match == contentObject2, "Expected the content object with the keyId");

    _athenaLRUContentStoreEntry_Release(&entry1);
    _athenaLRUContentStoreEntry_Release(&entry2);
    ccnxContentObject_Release(&contentObject2);
    ccnxContentObject_Release(&contentObject);
    ccnxName_Release(&name);
    ccnxInterest_Release(&interest);

    _athenaLRUContentStore_Release((AthenaContentStoreImplementation *) &impl);
}
Beispiel #3
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;
}
LONGBOW_TEST_CASE(Local, getMatch_Expired)
{
    AthenaLRUContentStore *impl = _createLRUContentStore();

    CCNxName *name = ccnxName_CreateFromURI("lci:/boose/roo/pie");
    CCNxContentObject *contentObject = ccnxContentObject_CreateWithDataPayload(name, NULL);

    _AthenaLRUContentStoreEntry *entry = _athenaLRUContentStoreEntry_Create(contentObject);
    ccnxContentObject_Release(&contentObject);

    entry->expiryTime = 10000;
    entry->hasExpiryTime = true;

    bool status = _athenaLRUContentStore_PutLRUContentStoreEntry(impl, entry);

    assertTrue(status, "Expected to put content into the store");

    assertTrue(status, "Expected to put content into the store a second time");
    assertTrue(impl->numEntries == 1, "Expected 1 entry in the store");
    assertTrue(impl->stats.numAdds == 1, "Expected stats to show 1 adds");

    CCNxInterest *interest = ccnxInterest_CreateSimple(name);
    ccnxName_Release(&name);

    CCNxContentObject *match = _athenaLRUContentStore_GetMatch(impl, interest);
    assertNull(match, "Expected to NOT match an interest, due to expired content");

    assertTrue(impl->numEntries == 0, "Expected 0 entries in the store, after removing expired content");

    _athenaLRUContentStoreEntry_Release(&entry);
    ccnxInterest_Release(&interest);

    _athenaLRUContentStore_Release((AthenaContentStoreImplementation *) &impl);
}
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);
}
LONGBOW_TEST_CASE(Local, _compareByRecommendedCacheTime)
{
    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);


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

    // There is no interface (yet) for assigning the recommended cache time. So update the store entries directly.

    entry1->hasRecommendedCacheTime = true;
    entry1->recommendedCacheTime = 1000;

    entry2->hasRecommendedCacheTime = true;
    entry2->recommendedCacheTime = 5000;

    entry3->hasRecommendedCacheTime = false;   // treat contentObject3 as if it has no RCT
    entry3->recommendedCacheTime = 10;

    assertTrue(_compareByRecommendedCacheTime(entry1, entry2) == -1, "Expected result -1");
    assertTrue(_compareByRecommendedCacheTime(entry2, entry1) == 1, "Expected result 1");
    assertTrue(_compareByRecommendedCacheTime(entry2, entry2) == 0, "Expected result 0");

    assertTrue(_compareByRecommendedCacheTime(entry1, entry3) == -1, "Expected result -1");
    assertTrue(_compareByRecommendedCacheTime(entry3, entry2) == 1, "Expected result 1");
    assertTrue(_compareByRecommendedCacheTime(entry3, entry3) == 0, "Expected result 0");

    _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);
}
LONGBOW_TEST_CASE(Local, _athenaLRUContentStoreEntry_CreateRelease)
{
    CCNxContentObject *contentObject = _createContentObject("lci:/boose/roo/pie", 0, NULL);
    _AthenaLRUContentStoreEntry *entry = _athenaLRUContentStoreEntry_Create(contentObject);

    _athenaLRUContentStoreEntry_Release(&entry);

    ccnxContentObject_Release(&contentObject);
}
Beispiel #8
0
/**
 * Release all of the AthenaLRUContentStoreEntry items in the store's LRU.
 */
static void
_athenaLRUContentStoreEntry_ReleaseAllInLRU(AthenaLRUContentStore *impl)
{
    _AthenaLRUContentStoreEntry *entry = impl->lruHead;
    while (entry != NULL) {
        _AthenaLRUContentStoreEntry *next = entry->next;
        _athenaLRUContentStoreEntry_Release(&entry);
        entry = next;
    }
}
LONGBOW_TEST_CASE(Local, _compareByExpiryTime)
{
    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);

    ccnxContentObject_SetExpiryTime(contentObject1, 100);
    ccnxContentObject_SetExpiryTime(contentObject2, 200);
    // contentObject3 has no expiry time.

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

    assertTrue(_compareByExpiryTime(entry1, entry2) == -1, "Expected result -1");
    assertTrue(_compareByExpiryTime(entry2, entry1) == 1, "Expected result 1");
    assertTrue(_compareByExpiryTime(entry2, entry2) == 0, "Expected result 0");

    assertTrue(_compareByExpiryTime(entry1, entry3) == -1, "Expected result -1");
    assertTrue(_compareByExpiryTime(entry3, entry2) == 1, "Expected result 1");
    assertTrue(_compareByExpiryTime(entry3, entry3) == 0, "Expected result 0");

    _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);
}
LONGBOW_TEST_CASE(Local, _athenaLRUContentStoreEntry_Display)
{
    CCNxName *name1 = ccnxName_CreateFromURI("lci:/first/entry");
    CCNxContentObject *contentObject1 = ccnxContentObject_CreateWithDataPayload(name1, NULL);

    ccnxContentObject_SetExpiryTime(contentObject1, 87654321);
    _AthenaLRUContentStoreEntry *entry1 = _athenaLRUContentStoreEntry_Create(contentObject1);

    _athenaLRUContentStoreEntry_Display(entry1, 4);

    _athenaLRUContentStoreEntry_Release(&entry1);
    ccnxContentObject_Release(&contentObject1);
    ccnxName_Release(&name1);
}
Beispiel #11
0
static void
_athenaLRUContentStore_RemoveContentStoreEntryFromLRU(AthenaLRUContentStore *impl,
                                                      _AthenaLRUContentStoreEntry *storeEntry)
{
    if (storeEntry->next != NULL) {
        storeEntry->next->prev = storeEntry->prev;
    }

    if (storeEntry->prev != NULL) {
        storeEntry->prev->next = storeEntry->next;
    }

    if (impl->lruHead == storeEntry) {
        impl->lruHead = storeEntry->next;   // Could be NULL
    }

    if (impl->lruTail == storeEntry) {
        impl->lruTail = storeEntry->prev;   // Could be NULL;
    }

    _athenaLRUContentStoreEntry_Release(&storeEntry);
}
LONGBOW_TEST_CASE(Local, _athenaLRUContentStore_PutLRUContentStoreEntry)
{
    AthenaLRUContentStore *impl = _createLRUContentStore();

    PARCBuffer *payload = parcBuffer_Allocate(1200);

    CCNxContentObject *contentObject = _createContentObject("lci:/boose/roo/pie", 10, NULL);

    parcBuffer_Release(&payload);
    _AthenaLRUContentStoreEntry *entry = _athenaLRUContentStoreEntry_Create(contentObject);
    ccnxContentObject_Release(&contentObject);

    entry->expiryTime = 10000;
    entry->contentObjectHash = parcBuffer_WrapCString("object hash buffer");
    entry->keyId = parcBuffer_WrapCString("key id buffer");
    entry->hasContentObjectHash = true;
    entry->hasKeyId = true;

    bool status = _athenaLRUContentStore_PutLRUContentStoreEntry(impl, entry);

    assertTrue(status, "Expected to put content into the store");

    assertTrue(status, "Expected to put content into the store a second time");
    assertTrue(impl->numEntries == 1, "Expected 1 entry in the store");
    assertTrue(impl->stats.numAdds == 1, "Expected stats to show 1 adds");

    _athenaLRUContentStore_PurgeContentStoreEntry(impl, entry);

    assertTrue(impl->numEntries == 0, "Expected 0 entries in the store");

    parcBuffer_Release(&entry->keyId);
    parcBuffer_Release(&entry->contentObjectHash);
    _athenaLRUContentStoreEntry_Release(&entry);

    _athenaLRUContentStore_Release((AthenaContentStoreImplementation *) &impl);
}
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);
}