Fix a limitation of the maximum number of child resources of a collection
authorJihun Ha <jihun.ha@samsung.com>
Mon, 22 Feb 2016 02:01:45 +0000 (11:01 +0900)
committerJon A. Cruz <jonc@osg.samsung.com>
Wed, 24 Feb 2016 00:11:45 +0000 (00:11 +0000)
We found that there is the maximum number of child resource able to be
registered to a collection resource which is 5. This commit is to eliminate
the limitation by using link-list rather than static array allocation
(refer to ocresource.h in csdk folder).

Change-Id: I23e9d200ae39b33497d8fd9863adb9dbadfb3c70
Signed-off-by: Jihun Ha <jihun.ha@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/5037
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: John Light <john.j.light@intel.com>
Reviewed-by: Junghyun Oh <junghyun.oh@samsung.com>
Reviewed-by: Jon A. Cruz <jonc@osg.samsung.com>
resource/csdk/stack/include/internal/ocresource.h [changed mode: 0644->0755]
resource/csdk/stack/src/occollection.c [changed mode: 0644->0755]
resource/csdk/stack/src/ocresource.c [changed mode: 0644->0755]
resource/csdk/stack/src/ocstack.c [changed mode: 0644->0755]
resource/csdk/stack/test/stacktests.cpp [changed mode: 0644->0755]

old mode 100644 (file)
new mode 100755 (executable)
index 0a30750..2113320
@@ -183,6 +183,13 @@ typedef struct resourceinterface_t {
     /** Future placeholder for access control and policy.*/
 } OCResourceInterface;
 
+/**
+ * Data structure for holding child resources associated with a collection
+ */
+typedef struct OCChildResource {
+    struct OCResource *rsrcResource;
+    struct OCChildResource *next;
+} OCChildResource;
 
 /**
  * Data structure for holding data type and definition for OIC resource.
@@ -207,7 +214,8 @@ typedef struct OCResource {
     /** Array of pointers to resources; can be used to represent a container of resources.
      * (i.e. hierarchies of resources) or for reference resources (i.e. for a resource collection).*/
 
-    struct OCResource *rsrcResources[MAX_CONTAINED_RESOURCES];
+    /** Child resource(s); linked list.*/
+    OCChildResource *rsrcChildResourcesHead;
 
     /** Pointer to function that handles the entity bound to the resource.
      *  This handler has to be explicitly defined by the programmer.*/
old mode 100644 (file)
new mode 100755 (executable)
index 4f38fec..551cdd4
@@ -237,23 +237,29 @@ HandleLinkedListInterface(OCEntityHandlerRequest *ehRequest,
     }
 
     OCResource *collResource = (OCResource *)ehRequest->resource;
-
+    OCChildResource *tempChildResource = NULL;
     OCRepPayload* payload = NULL;
+
+    if(!collResource)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
     OCStackResult ret = BuildResponseRepresentation(collResource, &payload);
     if (ret == OC_STACK_OK)
     {
-        for (size_t i = 0; i < MAX_CONTAINED_RESOURCES && ret == OC_STACK_OK; i++)
+        tempChildResource = collResource->rsrcChildResourcesHead;
+        while (tempChildResource && ret == OC_STACK_OK)
         {
-            if (collResource)
+            OCResource* temp = tempChildResource->rsrcResource;
+            if (temp)
             {
-                OCResource* temp = collResource->rsrcResources[i];
-                if (temp)
-                {
-                    //TODO : Add resource type filtering once collections
-                    // start supporting queries.
-                    ret = BuildResponseRepresentation(temp, &payload);
-                }
+                //TODO : Add resource type filtering once collections
+                // start supporting queries.
+                ret = BuildResponseRepresentation(temp, &payload);
             }
+
+            tempChildResource = tempChildResource->next;
         }
     }
 
@@ -267,6 +273,7 @@ HandleLinkedListInterface(OCEntityHandlerRequest *ehRequest,
         response.resourceHandle = (OCResourceHandle) collResource;
         ret = OCDoResponse(&response);
     }
+
     OCRepPayloadDestroy(payload);
     return ret;
 }
@@ -280,6 +287,7 @@ HandleBatchInterface(OCEntityHandlerRequest *ehRequest)
     }
 
     OCResource * collResource = (OCResource *) ehRequest->resource;
+    OCChildResource *tempChildResource = NULL;
 
     OCRepPayload* payload = OCRepPayloadCreate();
     if (!payload)
@@ -302,18 +310,21 @@ HandleBatchInterface(OCEntityHandlerRequest *ehRequest)
 
     if (stackRet == OC_STACK_OK)
     {
-        for (uint8_t i = 0; i < MAX_CONTAINED_RESOURCES; i++)
+        tempChildResource = collResource->rsrcChildResourcesHead;
+
+        while(tempChildResource)
         {
-            OCResource* temp = collResource->rsrcResources[i];
-            if (temp)
+            OCResource* tempRsrcResource = tempChildResource->rsrcResource;
+
+            if (tempRsrcResource)
             {
                 // Note that all entity handlers called through a collection
                 // will get the same pointer to ehRequest, the only difference
                 // is ehRequest->resource
-                ehRequest->resource = (OCResourceHandle) temp;
+                ehRequest->resource = (OCResourceHandle) tempRsrcResource;
 
-                OCEntityHandlerResult ehResult = temp->entityHandler(OC_REQUEST_FLAG, ehRequest,
-                                                                     temp->entityHandlerCallbackParam);
+                OCEntityHandlerResult ehResult = tempRsrcResource->entityHandler(OC_REQUEST_FLAG, ehRequest,
+                                                        tempRsrcResource->entityHandlerCallbackParam);
 
                 // The default collection handler is returning as OK
                 if (stackRet != OC_STACK_SLOW_RESOURCE)
@@ -333,7 +344,11 @@ HandleBatchInterface(OCEntityHandlerRequest *ehRequest)
             {
                 break;
             }
+
+            tempChildResource = tempChildResource->next;
+
         }
+
         ehRequest->resource = (OCResourceHandle) collResource;
     }
     return stackRet;
@@ -344,13 +359,16 @@ uint8_t GetNumOfResourcesInCollection (OCResource *resource)
     if (resource)
     {
         uint8_t num = 0;
-        for (uint8_t i = 0; i < MAX_CONTAINED_RESOURCES; i++)
+        OCChildResource *tempChildResource = NULL;
+
+        tempChildResource = resource->rsrcChildResourcesHead;
+
+        while(tempChildResource)
         {
-            if (resource->rsrcResources[i])
-            {
-                num++;
-            }
+            num++;
+            tempChildResource = tempChildResource->next;
         }
+
         return num;
     }
     else
old mode 100644 (file)
new mode 100755 (executable)
index 523278c..adef7db
@@ -310,13 +310,11 @@ uint8_t IsCollectionResource (OCResource *resource)
         return 0;
     }
 
-    for (int i = 0; i < MAX_CONTAINED_RESOURCES; i++)
+    if(resource->rsrcChildResourcesHead != NULL)
     {
-        if (resource->rsrcResources[i])
-        {
-            return 1;
-        }
+        return 1;
     }
+
     return 0;
 }
 
old mode 100644 (file)
new mode 100755 (executable)
index 0f161c4..0dda57c
@@ -3141,6 +3141,9 @@ OCStackResult OCCreateResource(OCResourceHandle *handle,
         pointer->entityHandlerCallbackParam = NULL;
     }
 
+    // Initialize a pointer indicating child resources in case of collection
+    pointer->rsrcChildResourcesHead = NULL;
+
     *handle = pointer;
     result = OC_STACK_OK;
 
@@ -3160,12 +3163,12 @@ exit:
     return result;
 }
 
-
 OCStackResult OCBindResource(
         OCResourceHandle collectionHandle, OCResourceHandle resourceHandle)
 {
     OCResource *resource = NULL;
-    uint8_t i = 0;
+    OCChildResource *tempChildResource = NULL;
+    OCChildResource *newChildResource = NULL;
 
     OIC_LOG(INFO, TAG, "Entering OCBindResource");
 
@@ -3189,35 +3192,54 @@ OCStackResult OCBindResource(
 
     // Look for an open slot to add add the child resource.
     // If found, add it and return success
-    for (i = 0; i < MAX_CONTAINED_RESOURCES; i++)
+
+    tempChildResource = resource->rsrcChildResourcesHead;
+
+    while(resource->rsrcChildResourcesHead && tempChildResource->next)
     {
-        if (!resource->rsrcResources[i])
-        {
-            resource->rsrcResources[i] = (OCResource *) resourceHandle;
-            OIC_LOG(INFO, TAG, "resource bound");
+        // TODO: what if one of child resource was deregistered without unbinding?
+        tempChildResource = tempChildResource->next;
+    }
 
-#ifdef WITH_PRESENCE
-            if (presenceResource.handle)
-            {
-                ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
-                SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType,
-                        OC_PRESENCE_TRIGGER_CHANGE);
-            }
-#endif
-            return OC_STACK_OK;
+    // Do memory allocation for child resource
+    newChildResource = (OCChildResource *) OICCalloc(1, sizeof(OCChildResource));
+    if(!newChildResource)
+    {
+        OIC_LOG(ERROR, TAG, "Adding new child resource is failed due to memory allocation failure");
+        return OC_STACK_ERROR;
+    }
 
-        }
+    newChildResource->rsrcResource = (OCResource *) resourceHandle;
+    newChildResource->next = NULL;
+
+    if(!resource->rsrcChildResourcesHead)
+    {
+        resource->rsrcChildResourcesHead = newChildResource;
+    }
+    else {
+        tempChildResource->next = newChildResource;
     }
 
-    // Unable to add resourceHandle, so return error
-    return OC_STACK_ERROR;
+    OIC_LOG(INFO, TAG, "resource bound");
+
+#ifdef WITH_PRESENCE
+    if (presenceResource.handle)
+    {
+        ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
+        SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType,
+                OC_PRESENCE_TRIGGER_CHANGE);
+    }
+#endif
+
+    return OC_STACK_OK;
 }
 
 OCStackResult OCUnBindResource(
         OCResourceHandle collectionHandle, OCResourceHandle resourceHandle)
 {
     OCResource *resource = NULL;
-    uint8_t i = 0;
+    OCChildResource *tempChildResource = NULL;
+    OCChildResource *tempLastChildResource = NULL;
 
     OIC_LOG(INFO, TAG, "Entering OCUnBindResource");
 
@@ -3241,11 +3263,37 @@ OCStackResult OCUnBindResource(
 
     // Look for an open slot to add add the child resource.
     // If found, add it and return success
-    for (i = 0; i < MAX_CONTAINED_RESOURCES; i++)
+    if(!resource->rsrcChildResourcesHead)
     {
-        if (resourceHandle == resource->rsrcResources[i])
+        OIC_LOG(INFO, TAG, "resource not found in collection");
+
+        // Unable to add resourceHandle, so return error
+        return OC_STACK_ERROR;
+
+    }
+
+    tempChildResource = resource->rsrcChildResourcesHead;
+
+    while (tempChildResource)
+    {
+        if(tempChildResource->rsrcResource == resourceHandle)
         {
-            resource->rsrcResources[i] = (OCResource *) NULL;
+            // if resource going to be unbinded is the head one.
+            if( tempChildResource == resource->rsrcChildResourcesHead )
+            {
+                OCChildResource *temp = resource->rsrcChildResourcesHead->next;
+                OICFree(resource->rsrcChildResourcesHead);
+                resource->rsrcChildResourcesHead = temp;
+                temp = NULL;
+            }
+            else
+            {
+                OCChildResource *temp = tempChildResource->next;
+                OICFree(tempChildResource);
+                tempLastChildResource->next = temp;
+                temp = NULL;
+            }
+
             OIC_LOG(INFO, TAG, "resource unbound");
 
             // Send notification when resource is unbounded successfully.
@@ -3257,12 +3305,22 @@ OCStackResult OCUnBindResource(
                         OC_PRESENCE_TRIGGER_CHANGE);
             }
 #endif
+            tempChildResource = NULL;
+            tempLastChildResource = NULL;
+
             return OC_STACK_OK;
+
         }
+
+        tempLastChildResource = tempChildResource;
+        tempChildResource = tempChildResource->next;
     }
 
     OIC_LOG(INFO, TAG, "resource not found in collection");
 
+    tempChildResource = NULL;
+    tempLastChildResource = NULL;
+
     // Unable to add resourceHandle, so return error
     return OC_STACK_ERROR;
 }
@@ -3582,19 +3640,30 @@ OCResourceHandle OCGetResourceHandleFromCollection(OCResourceHandle collectionHa
         uint8_t index)
 {
     OCResource *resource = NULL;
+    OCChildResource *tempChildResource = NULL;
+    uint8_t num = 0;
 
-    if (index >= MAX_CONTAINED_RESOURCES)
+    resource = findResource((OCResource *) collectionHandle);
+    if (!resource)
     {
         return NULL;
     }
 
-    resource = findResource((OCResource *) collectionHandle);
-    if (!resource)
+    tempChildResource = resource->rsrcChildResourcesHead;
+
+    while(tempChildResource)
     {
-        return NULL;
+        if( num == index )
+        {
+            return tempChildResource->rsrcResource;
+        }
+        num++;
+        tempChildResource = tempChildResource->next;
     }
 
-    return resource->rsrcResources[index];
+    // In this case, the number of resource handles in the collection exceeds the index
+    tempChildResource = NULL;
+    return NULL;
 }
 
 OCStackResult OCBindResourceHandler(OCResourceHandle handle,
old mode 100644 (file)
new mode 100755 (executable)
index 20060bd..0f966ee
@@ -1280,15 +1280,14 @@ TEST(StackBind, BindContainedResourceGood)
     EXPECT_EQ(OC_STACK_OK, OCBindResource(containerHandle, handle2));
     EXPECT_EQ(OC_STACK_OK, OCBindResource(containerHandle, handle3));
     EXPECT_EQ(OC_STACK_OK, OCBindResource(containerHandle, handle4));
-    EXPECT_EQ(OC_STACK_ERROR, OCBindResource(containerHandle, handle5));
+    EXPECT_EQ(OC_STACK_OK, OCBindResource(containerHandle, handle5));
 
     EXPECT_EQ(handle0, OCGetResourceHandleFromCollection(containerHandle, 0));
     EXPECT_EQ(handle1, OCGetResourceHandleFromCollection(containerHandle, 1));
     EXPECT_EQ(handle2, OCGetResourceHandleFromCollection(containerHandle, 2));
     EXPECT_EQ(handle3, OCGetResourceHandleFromCollection(containerHandle, 3));
     EXPECT_EQ(handle4, OCGetResourceHandleFromCollection(containerHandle, 4));
-
-    EXPECT_EQ(NULL, OCGetResourceHandleFromCollection(containerHandle, 5));
+    EXPECT_EQ(handle5, OCGetResourceHandleFromCollection(containerHandle, 5));
 
     EXPECT_EQ(OC_STACK_OK, OCStop());
 }