Beispiel #1
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;
}
Beispiel #2
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;
}
Beispiel #3
0
static bool
_athenaLRUContentStore_RemoveMatch(AthenaContentStoreImplementation *store, const CCNxName *name,
                                   const PARCBuffer *keyIdRestriction, const PARCBuffer *contentObjectHash)
{
    AthenaLRUContentStore *impl = (AthenaLRUContentStore *) store;
    bool wasRemoved = false;

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

        if (entry != NULL) {
            _athenaLRUContentStore_PurgeContentStoreEntry(store, entry);
            wasRemoved = true;
        }
    }

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

        if (entry != NULL) {
            _athenaLRUContentStore_PurgeContentStoreEntry(store, entry);
            wasRemoved = true;
        }
    }

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

        if (entry != NULL) {
            _athenaLRUContentStore_PurgeContentStoreEntry(store, entry);
            wasRemoved = true;
        }
    }

    return wasRemoved;
}
LONGBOW_TEST_CASE(Local, _getLeastUsedFromLRU)
{
    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);

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

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

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

    athenaLRUContentStore_Display(impl, 2);

    _AthenaLRUContentStoreEntry *entry1 = _getLeastUsedFromLRU(impl);
    assertTrue(ccnxContentObject_Equals(entry1->contentObject, contentObject1), "Expected to retrieve contentObject1");
    _athenaLRUContentStore_PurgeContentStoreEntry(impl, entry1);

    _AthenaLRUContentStoreEntry *entry2 = _getLeastUsedFromLRU(impl);
    assertTrue(ccnxContentObject_Equals(entry2->contentObject, contentObject2), "Expected to retrieve contentObject1");
    _athenaLRUContentStore_PurgeContentStoreEntry(impl, entry2);

    _AthenaLRUContentStoreEntry *entry3 = _getLeastUsedFromLRU(impl);
    assertTrue(ccnxContentObject_Equals(entry3->contentObject, contentObject3), "Expected to retrieve contentObject1");
    _athenaLRUContentStore_PurgeContentStoreEntry(impl, 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_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);
}
Beispiel #6
0
static bool
_athenaLRUContentStore_PutLRUContentStoreEntry(AthenaContentStoreImplementation *store,
                                               const _AthenaLRUContentStoreEntry *entry)
{
    bool result = false;

    AthenaLRUContentStore *impl = (AthenaLRUContentStore *) store;

    // Enforce capacity limit. If adding the next store item would put us over the limit, we have to remove
    // entrie(s) until there is room.

    bool isEnoughRoomInStore = true;
    if ((entry->sizeInBytes + impl->currentSizeInBytes) > impl->maxSizeInBytes) {
        isEnoughRoomInStore = _makeRoomInStore(impl, entry->sizeInBytes);
    }

    if (isEnoughRoomInStore) {
        _AthenaLRUContentStoreEntry *newEntry = _athenaLRUContentStoreEntry_Acquire(entry);

        // New entries go to the HEAD of the LRU.
        _addContentStoreEntryToLRUHead(impl, newEntry);

        // DO NOT RELEASE the newEntry after adding it to the containers. We will let the LRU be responsible for the
        // final release. At this point, the reference count of the new LRUContentStoreEntry is 1 and the LRU
        // points to it. The other containers (hashmap indices, sorted lists, etc) can acquire and release on their
        // own, but the LRU holds the final reference.

        _AthenaLRUContentStoreEntry *existingEntry = NULL;
        CCNxName *name = ccnxContentObject_GetName(newEntry->contentObject);
        if (name != NULL) {
            PARCObject *nameKey = _createHashableKey(name, NULL, NULL);
            existingEntry = _addEntryToIndexTableIfNotAlreadyInIt(impl->tableByName, nameKey, newEntry);
            parcObject_Release((PARCObject **) &nameKey);
        }

        if (newEntry->hasKeyId) {
            PARCObject *nameAndKeyIdKey = _createHashableKey(name, newEntry->keyId, NULL);
            existingEntry = _addEntryToIndexTableIfNotAlreadyInIt(impl->tableByNameAndKeyId, nameAndKeyIdKey, newEntry);
            parcObject_Release((PARCObject **) &nameAndKeyIdKey);
        }

        if (newEntry->hasContentObjectHash) {
            PARCObject *nameAndObjectHashKey = _createHashableKey(name, NULL, newEntry->contentObjectHash);
            existingEntry = _addEntryToIndexTableIfNotAlreadyInIt(impl->tableByNameAndObjectHash, nameAndObjectHashKey,
                                                                  newEntry);
            parcObject_Release((PARCObject **) &nameAndObjectHashKey);
        }

        if (existingEntry != NULL && existingEntry->indexCount < 1) {
            // The existing entry is in no indexes, which means it cannot be matched and serves no further purpose.
            // Remove it completely from all containers.
            //printf("Releasing previously held store entry\n");
            _athenaLRUContentStore_PurgeContentStoreEntry(impl, existingEntry);
        }

        // Add the new entry to the time-ordered lists, if it has an RCT or ExpiryTime.
        if (newEntry->hasExpiryTime) {
            parcSortedList_Add(impl->listByExpiryTime, newEntry);
        }

        if (newEntry->hasRecommendedCacheTime) {
            parcSortedList_Add(impl->listByRecommendedCacheTime, newEntry);
        }

        impl->stats.numAdds++;
        impl->numEntries++;
        impl->currentSizeInBytes += newEntry->sizeInBytes;
        result = true;
    }

    return result;
}