diff options
author | Michele Papalini <micpapal+fdio@cisco.com> | 2017-02-24 08:00:13 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@fd.io> | 2017-02-24 08:00:13 +0000 |
commit | 6d4b6878ceff22f9ec8d8e9423214f9666007472 (patch) | |
tree | fa27e0c747676519cb87ff8448bfed62fce5009d /libccnx-common/ccnx/common/ccnx_ManifestHashGroup.c | |
parent | f28308bd99381ef5f1e178e2e1f870f245e35873 (diff) | |
parent | d18ae43123fcd7604d1c36a1ec8450dbe6071824 (diff) |
Merge "Initial commit: ccnxlibs." into ccnxlibs/master
Diffstat (limited to 'libccnx-common/ccnx/common/ccnx_ManifestHashGroup.c')
-rw-r--r-- | libccnx-common/ccnx/common/ccnx_ManifestHashGroup.c | 592 |
1 files changed, 592 insertions, 0 deletions
diff --git a/libccnx-common/ccnx/common/ccnx_ManifestHashGroup.c b/libccnx-common/ccnx/common/ccnx_ManifestHashGroup.c new file mode 100644 index 00000000..cfe37742 --- /dev/null +++ b/libccnx-common/ccnx/common/ccnx_ManifestHashGroup.c @@ -0,0 +1,592 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + */ +#include <config.h> +#include <stdio.h> +#include <string.h> + +#include <LongBow/runtime.h> + +#include <parc/algol/parc_Object.h> +#include <parc/algol/parc_LinkedList.h> + +#include <ccnx/common/ccnx_Interest.h> +#include <ccnx/common/ccnx_ManifestHashGroup.h> +#include <ccnx/common/internal/ccnx_WireFormatMessageInterface.h> + +#define MAX_NUMBER_OF_POINTERS 1500 // loose upper bound imposed by packet format + +struct ccnx_manifest_hash_group { + PARCLinkedList *pointers; + + // Metadata + const PARCBuffer *overallDataDigest; // overall *application data* digest + size_t dataSize; // size for all pointers (last pointer might not be entrySize unless perfectly balanced) + size_t entrySize; // size per pointer + size_t blockSize; // size of nodes used in the tree (e.g., 4K for each Manifest or Data node) + size_t treeHeight; // height of sub-tree referred to by each pointer + const CCNxName *locator; // locator for the hash group +}; + +struct ccnx_manifest_hash_group_pointer { + CCNxManifestHashGroupPointerType pointerType; + PARCBuffer *digest; +}; + +static bool +CCNxManifestHashGroupPointer_FinalRelease(CCNxManifestHashGroupPointer **ptrP) +{ + if ((*ptrP)->digest != NULL) { + parcBuffer_Release(&(*ptrP)->digest); + } + return true; +} + +static bool +_CCNxManifestHashGroupPointer_Equals(const CCNxManifestHashGroupPointer *objectA, const CCNxManifestHashGroupPointer *objectB) +{ + if (objectA == objectB) { + return true; + } + if (objectA == NULL || objectB == NULL) { + return false; + } + if (objectA->pointerType == objectB->pointerType) { + if (parcBuffer_Equals(objectA->digest, objectB->digest)) { + return true; + } + } + return false; +} + +parcObject_Override(CCNxManifestHashGroupPointer, PARCObject, + .destructor = (PARCObjectDestructor *) CCNxManifestHashGroupPointer_FinalRelease, + .equals = (PARCObjectEquals *) _CCNxManifestHashGroupPointer_Equals); + +parcObject_ImplementAcquire(ccnxManifestHashGroupPointer, CCNxManifestHashGroupPointer); +parcObject_ImplementRelease(ccnxManifestHashGroupPointer, CCNxManifestHashGroupPointer); + +CCNxManifestHashGroupPointer * +ccnxManifestHashGroupPointer_Create(CCNxManifestHashGroupPointerType type, const PARCBuffer *digest) +{ + CCNxManifestHashGroupPointer *ptr = parcObject_CreateAndClearInstance(CCNxManifestHashGroupPointer); + if (ptr != NULL) { + ptr->pointerType = type; + ptr->digest = parcBuffer_Acquire(digest); + } + return ptr; +} + +CCNxManifestHashGroupPointerType +ccnxManifestHashGroupPointer_GetType(const CCNxManifestHashGroupPointer *ptr) +{ + return ptr->pointerType; +} + +const PARCBuffer * +ccnxManifestHashGroupPointer_GetDigest(const CCNxManifestHashGroupPointer *ptr) +{ + return ptr->digest; +} + +static bool +_ccnxManifestHashGroup_Destructor(CCNxManifestHashGroup **groupP) +{ + if ((*groupP)->pointers != NULL) { + parcLinkedList_Release(&(*groupP)->pointers); + } + if ((*groupP)->overallDataDigest != NULL) { + parcBuffer_Release((PARCBuffer **) &(*groupP)->overallDataDigest); + } + if ((*groupP)->locator != NULL) { + ccnxName_Release((CCNxName **) &(*groupP)->locator); + } + return true; +} + +parcObject_Override(CCNxManifestHashGroup, PARCObject, + .destructor = (PARCObjectDestructor *) _ccnxManifestHashGroup_Destructor, + .toString = (PARCObjectToString *) ccnxManifestHashGroup_ToString, + .equals = (PARCObjectEquals *) ccnxManifestHashGroup_Equals); + +parcObject_ImplementAcquire(ccnxManifestHashGroup, CCNxManifestHashGroup); +parcObject_ImplementRelease(ccnxManifestHashGroup, CCNxManifestHashGroup); + +CCNxManifestHashGroup * +ccnxManifestHashGroup_Create(void) +{ + CCNxManifestHashGroup *section = parcObject_CreateAndClearInstance(CCNxManifestHashGroup); + + if (section != NULL) { + section->pointers = parcLinkedList_Create(); + + section->overallDataDigest = NULL; + section->dataSize = 0; + section->entrySize = 0; + section->blockSize = 0; + section->treeHeight = 0; + section->locator = NULL; + } + + return section; +} + +bool +ccnxManifestHashGroup_AppendPointer(CCNxManifestHashGroup *group, CCNxManifestHashGroupPointerType type, const PARCBuffer *buffer) +{ + if (!ccnxManifestHashGroup_IsFull(group)) { + CCNxManifestHashGroupPointer *ptr = ccnxManifestHashGroupPointer_Create(type, buffer); + parcLinkedList_Append(group->pointers, ptr); + ccnxManifestHashGroupPointer_Release(&ptr); + return true; + } + return false; +} + +bool +ccnxManifestHashGroup_PrependPointer(CCNxManifestHashGroup *group, CCNxManifestHashGroupPointerType type, const PARCBuffer *buffer) +{ + if (!ccnxManifestHashGroup_IsFull(group)) { + CCNxManifestHashGroupPointer *ptr = ccnxManifestHashGroupPointer_Create(type, buffer); + parcLinkedList_Prepend(group->pointers, ptr); + ccnxManifestHashGroupPointer_Release(&ptr); + return true; + } + return false; +} + +void +ccnxManifestHashGroup_SetOverallDataDigest(CCNxManifestHashGroup *group, const PARCBuffer *digest) +{ + group->overallDataDigest = parcBuffer_Acquire(digest); +} + +const PARCBuffer * +ccnxManifestHashGroup_GetOverallDataDigest(const CCNxManifestHashGroup *group) +{ + return group->overallDataDigest; +} + +size_t +ccnxManifestHashGroup_GetTotalSize(const CCNxManifestHashGroup *group) +{ + return group->dataSize; +} + +size_t +ccnxManifestHashGroup_GetChildBlockSize(const CCNxManifestHashGroup *group) +{ + return group->entrySize; +} + +void +ccnxManifestHashGroup_SetLocator(CCNxManifestHashGroup *group, const CCNxName *locator) +{ + group->locator = ccnxName_Acquire(locator); +} + +const CCNxName * +ccnxManifestHashGroup_GetLocator(const CCNxManifestHashGroup *group) +{ + return group->locator; +} + +size_t +ccnxManifestHashGroup_GetNumberOfPointers(const CCNxManifestHashGroup *group) +{ + return parcLinkedList_Size(group->pointers); +} + +CCNxManifestHashGroupPointer * +ccnxManifestHashGroup_GetPointerAtIndex(const CCNxManifestHashGroup *group, size_t index) +{ + CCNxManifestHashGroupPointer *entry = parcLinkedList_GetAtIndex(group->pointers, index); + return entry; +} + +CCNxManifestHashGroupPointerType +ccnxManifestHashGroup_GetPointerTypeAtIndex(const CCNxManifestHashGroup *group, size_t index) +{ + CCNxManifestHashGroupPointer *entry = parcLinkedList_GetAtIndex(group->pointers, index); + return entry->pointerType; +} + +PARCBuffer * +ccnxManifestHashGroup_GetPointerDigestAtIndex(const CCNxManifestHashGroup *group, size_t index) +{ + CCNxManifestHashGroupPointer *entry = parcLinkedList_GetAtIndex(group->pointers, index); + return entry->digest; +} + +bool +ccnxManifestHashGroup_IsFull(const CCNxManifestHashGroup *group) +{ + size_t size = parcLinkedList_Size(group->pointers); + return size >= MAX_NUMBER_OF_POINTERS; +} + +bool +ccnxManifestHashGroup_Equals(const CCNxManifestHashGroup *objectA, const CCNxManifestHashGroup *objectB) +{ + if (objectA == objectB) { + return true; + } + if (objectA == NULL || objectB == NULL) { + return false; + } + + if (objectA->dataSize == objectB->dataSize) { + if (objectA->entrySize == objectB->entrySize) { + if (objectA->blockSize == objectB->blockSize) { + if (objectA->treeHeight == objectB->treeHeight) { + if (ccnxName_Equals(objectA->locator, objectB->locator)) { + if (parcBuffer_Equals(objectA->overallDataDigest, objectB->overallDataDigest)) { + if (parcLinkedList_Size(objectA->pointers) == parcLinkedList_Size(objectB->pointers)) { + for (size_t i = 0; i < parcLinkedList_Size(objectA->pointers); i++) { + CCNxManifestHashGroupPointer *ptrA = parcLinkedList_GetAtIndex(objectA->pointers, i); + CCNxManifestHashGroupPointer *ptrB = parcLinkedList_GetAtIndex(objectB->pointers, i); + if (!_CCNxManifestHashGroupPointer_Equals(ptrA, ptrB)) { + return false; + } + } + return true; + } + } + } + } + } + } + } + + return false; +} + +char * +ccnxManifestHashGroup_ToString(const CCNxManifestHashGroup *section) +{ + PARCJSON *json = ccnxManifestHashGroup_ToJson(section); + char *stringRep = parcJSON_ToString(json); + parcJSON_Release(&json); + return stringRep; +} + +PARCJSON * +ccnxManifestHashGroup_ToJson(const CCNxManifestHashGroup *group) +{ + PARCJSON *root = parcJSON_Create(); + + PARCJSONArray *ptrList = parcJSONArray_Create(); + for (size_t i = 0; i < parcLinkedList_Size(group->pointers); i++) { + CCNxManifestHashGroupPointer *ptr = (CCNxManifestHashGroupPointer *) parcLinkedList_GetAtIndex(group->pointers, i); + PARCJSON *ptrJson = parcJSON_Create(); + + // Type. + parcJSON_AddInteger(ptrJson, "type", ccnxManifestHashGroupPointer_GetType(ptr)); + + // Digest. + char *digestString = parcBuffer_ToHexString(ptr->digest); + parcJSON_AddString(ptrJson, "digest", digestString); + parcMemory_Deallocate(&digestString); + + // Add the tuple to the list. + PARCJSONValue *val = parcJSONValue_CreateFromJSON(ptrJson); + parcJSONArray_AddValue(ptrList, val); + + // Cleanup + parcJSONValue_Release(&val); + parcJSON_Release(&ptrJson); + } + root = parcJSON_AddArray(root, "HashGroup", ptrList); + parcJSONArray_Release(&ptrList); + + if (group->overallDataDigest != NULL) { + char *digestString = parcBuffer_ToHexString(group->overallDataDigest); + root = parcJSON_AddString(root, "overallDataDigest", digestString); + parcMemory_Deallocate((void **) &digestString); + } + + if (group->locator != NULL) { + char *locatorString = ccnxName_ToString(group->locator); + root = parcJSON_AddString(root, "locator", locatorString); + parcMemory_Deallocate((void **) &locatorString); + } + + if (group->entrySize > 0) { + root = parcJSON_AddInteger(root, "entrySize", group->entrySize); + } + + if (group->dataSize > 0) { + root = parcJSON_AddInteger(root, "dataSize", group->dataSize); + } + + if (group->blockSize > 0) { + root = parcJSON_AddInteger(root, "blockSize", group->blockSize); + } + + if (group->treeHeight > 0) { + root = parcJSON_AddInteger(root, "treeHeight", group->treeHeight); + } + + return root; +} + +CCNxManifestHashGroup * +ccnxManifestHashGroup_CreateFromJson(const PARCJSON *json) +{ + CCNxManifestHashGroup *group = ccnxManifestHashGroup_Create(); + + PARCJSONValue *ptrListValue = parcJSON_GetValueByName(json, "HashGroup"); + PARCJSONArray *ptrList = parcJSONValue_GetArray(ptrListValue); + size_t numberOfPointers = parcJSONArray_GetLength(ptrList); + for (size_t i = 0; i < numberOfPointers; i++) { + PARCJSONValue *pointerValue = parcJSONArray_GetValue(ptrList, i); + + PARCJSON *typeJson = parcJSONValue_GetJSON(pointerValue); + PARCJSONValue *typeValue = parcJSON_GetValueByName(typeJson, "type"); + CCNxManifestHashGroupPointerType type; + + if (parcJSONValue_GetInteger(typeValue) == 0) { + type = CCNxManifestHashGroupPointerType_Data; + } else { + type = CCNxManifestHashGroupPointerType_Manifest; + } + + PARCJSON *digestJson = parcJSONValue_GetJSON(pointerValue); + PARCJSONValue *digestValue = parcJSON_GetValueByName(digestJson, "digest"); + PARCBuffer *digestHex = parcJSONValue_GetString(digestValue); + + char *hexString = parcBuffer_ToString(digestHex); + PARCBuffer *digest = parcBuffer_Flip(parcBuffer_ParseHexString(hexString)); + parcMemory_Deallocate(&hexString); + + ccnxManifestHashGroup_AppendPointer(group, type, digest); + parcBuffer_Release(&digest); + } + + if (parcJSON_GetPairByName(json, "overallDataDigest") != NULL) { + PARCJSONValue *overallDataDigestValue = parcJSON_GetValueByName(json, "overallDataDigest"); + PARCBuffer *digestHex = parcJSONValue_GetString(overallDataDigestValue); + + char *hexString = parcBuffer_ToString(digestHex); + group->overallDataDigest = parcBuffer_Flip(parcBuffer_ParseHexString(hexString)); + parcMemory_Deallocate(&hexString); + } + + if (parcJSON_GetPairByName(json, "locator") != NULL) { + PARCJSONValue *locatorValue = parcJSON_GetValueByName(json, "locator"); + PARCBuffer *buffer = parcJSONValue_GetString(locatorValue); + char *locator = parcBuffer_ToString(buffer); + group->locator = ccnxName_CreateFromCString(locator); + parcMemory_Deallocate(&locator); + } + + if (parcJSON_GetPairByName(json, "entrySize") != NULL) { + PARCJSONValue *childBlockNodeSizeValue = parcJSON_GetValueByName(json, "entrySize"); + group->entrySize = parcJSONValue_GetInteger(childBlockNodeSizeValue); + } + + if (parcJSON_GetPairByName(json, "dataSize") != NULL) { + PARCJSONValue *totalSizeValue = parcJSON_GetValueByName(json, "dataSize"); + group->dataSize = parcJSONValue_GetInteger(totalSizeValue); + } + + if (parcJSON_GetPairByName(json, "blockSize") != NULL) { + PARCJSONValue *blockSizeValue = parcJSON_GetValueByName(json, "blockSize"); + group->blockSize = parcJSONValue_GetInteger(blockSizeValue); + } + + if (parcJSON_GetPairByName(json, "treeHeight") != NULL) { + PARCJSONValue *treeHeightValue = parcJSON_GetValueByName(json, "treeHeight"); + group->treeHeight = parcJSONValue_GetInteger(treeHeightValue); + } + + return group; +} + +struct _hashgroup_ccnxManifestHashGroupIterator_state { + size_t pointerNumber; + bool atEnd; +}; +typedef struct _hashgroup_ccnxManifestHashGroupIterator_state _HashgroupIteratorState; + +static void * +_ccnxManifestHashGroupIterator_Init(CCNxManifestHashGroup *group) +{ + _HashgroupIteratorState *state = parcMemory_Allocate(sizeof(_HashgroupIteratorState)); + state->pointerNumber = 0; + state->atEnd = false; + return state; +} + +static bool +_ccnxManifestHashGroupIterator_HasNext(CCNxManifestHashGroup *group, void *voidstate) +{ + _HashgroupIteratorState *state = (_HashgroupIteratorState *) voidstate; + return !state->atEnd; +} + +static void * +_ccnxManifestHashGroupIterator_Next(CCNxManifestHashGroup *group, void *state) +{ + _HashgroupIteratorState *thestate = (_HashgroupIteratorState *) state; + thestate->pointerNumber++; + + if (thestate->pointerNumber == parcLinkedList_Size(group->pointers)) { + thestate->atEnd = true; + } + + return thestate; +} + +static void +_ccnxManifestHashGroupIterator_RemoveAt(CCNxManifestHashGroup *group, void **state) +{ + // pass +} + +static void * +_ccnxManifestHashGroupIterator_GetElement(CCNxManifestHashGroup *group, void *state) +{ + _HashgroupIteratorState *thestate = (_HashgroupIteratorState *) state; + CCNxManifestHashGroupPointer *ptr = + (CCNxManifestHashGroupPointer *) parcLinkedList_GetAtIndex(group->pointers, thestate->pointerNumber - 1); + return ptr; +} + +static void +_ccnxManifestHashGroupIterator_Finish(CCNxManifestHashGroup *group, void *state) +{ + _HashgroupIteratorState *thestate = (_HashgroupIteratorState *) state; + parcMemory_Deallocate(&thestate); +} + +static void +_ccnxManifestHashGroupIterator_AssertValid(const void *state) +{ + // pass +} + +PARCIterator * +ccnxManifestHashGroup_Iterator(const CCNxManifestHashGroup *group) +{ + PARCIterator *iterator = parcIterator_Create((void *) group, + (void *(*)(PARCObject *))_ccnxManifestHashGroupIterator_Init, + (bool (*)(PARCObject *, void *))_ccnxManifestHashGroupIterator_HasNext, + (void *(*)(PARCObject *, void *))_ccnxManifestHashGroupIterator_Next, + (void (*)(PARCObject *, void **))_ccnxManifestHashGroupIterator_RemoveAt, + (void *(*)(PARCObject *, void *))_ccnxManifestHashGroupIterator_GetElement, + (void (*)(PARCObject *, void *))_ccnxManifestHashGroupIterator_Finish, + (void (*)(const void *))_ccnxManifestHashGroupIterator_AssertValid); + + return iterator; +} + +size_t +ccnxManifestHashGroup_GetBlockSize(const CCNxManifestHashGroup *group) +{ + return group->blockSize; +} + +void +ccnxManifestHashGroup_SetBlockSize(CCNxManifestHashGroup *group, size_t blockSize) +{ + group->blockSize = blockSize; +} + +size_t +ccnxManifestHashGroup_GetDataSize(const CCNxManifestHashGroup *group) +{ + return group->dataSize; +} + +void +ccnxManifestHashGroup_SetDataSize(CCNxManifestHashGroup *group, size_t dataSize) +{ + group->dataSize = dataSize; +} + +size_t +ccnxManifestHashGroup_GetEntrySize(const CCNxManifestHashGroup *group) +{ + return group->entrySize; +} + +void +ccnxManifestHashGroup_SetEntrySize(CCNxManifestHashGroup *group, size_t entrySize) +{ + group->entrySize = entrySize; +} + +size_t +ccnxManifestHashGroup_GetTreeHeight(const CCNxManifestHashGroup *group) +{ + return group->treeHeight; +} + +void +ccnxManifestHashGroup_SetTreeHeight(CCNxManifestHashGroup *group, size_t treeHeight) +{ + group->treeHeight = treeHeight; +} + +bool +ccnxManifestHashGroup_HasMetadata(const CCNxManifestHashGroup *group) +{ + // Check the existence of each metadata value. + if (group->blockSize > 0) { + return true; + } + if (group->dataSize > 0) { + return true; + } + if (group->entrySize > 0) { + return true; + } + if (group->locator != NULL) { + return true; + } + if (group->overallDataDigest != NULL) { + return true; + } + + return false; +} + +PARCLinkedList * +ccnxManifestHashGroup_CreateInterestList(const CCNxManifestHashGroup *group, const CCNxName *locator) +{ + PARCLinkedList *interestList = parcLinkedList_Create(); + + PARCIterator *itr = ccnxManifestHashGroup_Iterator(group); + while (parcIterator_HasNext(itr)) { + // Extract the name and digest + CCNxManifestHashGroupPointer *ptr = parcIterator_Next(itr); + const PARCBuffer *digest = ccnxManifestHashGroupPointer_GetDigest(ptr); + const CCNxName *name = group->locator == NULL ? locator : group->locator; + + // Build the interest and append it to the running list + if (name != NULL) { + CCNxInterest *interest = ccnxInterest_CreateSimple(name); + ccnxInterest_SetContentObjectHashRestriction(interest, digest); + parcLinkedList_Append(interestList, interest); + ccnxInterest_Release(&interest); + } + } + parcIterator_Release(&itr); + + return interestList; +} |