Microsoft Azure IoTHub client libraries
Dependents: sht15_remote_monitoring RobotArmDemo iothub_client_sample_amqp f767zi_mqtt ... more
This library implements the Microsoft Azure IoTHub client library. The code is replicated from https://github.com/Azure/azure-iot-sdks
Diff: iothub_client.c
- Revision:
- 82:f94e6bed4495
- Parent:
- 80:db5f5237bc95
- Child:
- 83:18ccaa6567d0
diff -r 8de701563187 -r f94e6bed4495 iothub_client.c --- a/iothub_client.c Wed Jan 17 08:56:33 2018 -0800 +++ b/iothub_client.c Tue Jan 30 08:21:20 2018 -0800 @@ -54,23 +54,27 @@ { unsigned char* source; size_t size; - char* destinationFileName; IOTHUB_CLIENT_FILE_UPLOAD_CALLBACK iotHubClientFileUploadCallback; - void* context; - THREAD_HANDLE uploadingThreadHandle; - IOTHUB_CLIENT_HANDLE iotHubClientHandle; - LOCK_HANDLE lockGarbage; - int canBeGarbageCollected; /*flag indicating that the UPLOADTOBLOB_SAVED_DATA structure can be freed because the thread deadling with it finished*/ }UPLOADTOBLOB_SAVED_DATA; typedef struct UPLOADTOBLOB_MULTIBLOCK_SAVED_DATA_TAG { + IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK getDataCallback; + IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX getDataCallbackEx; +}UPLOADTOBLOB_MULTIBLOCK_SAVED_DATA; + +typedef struct UPLOADTOBLOB_THREAD_INFO_TAG +{ char* destinationFileName; - IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK getDataCallback; + THREAD_HANDLE uploadingThreadHandle; + LOCK_HANDLE lockGarbage; + int canBeGarbageCollected; /*flag indicating that the UPLOADTOBLOB_SAVED_DATA structure can be freed because the thread deadling with it finished*/ + IOTHUB_CLIENT_HANDLE iotHubClientHandle; void* context; - THREAD_HANDLE uploadingThreadHandle; - IOTHUB_CLIENT_HANDLE iotHubClientHandle; -}UPLOADTOBLOB_MULTIBLOCK_SAVED_DATA; + UPLOADTOBLOB_SAVED_DATA uploadBlobSavedData; + UPLOADTOBLOB_MULTIBLOCK_SAVED_DATA uploadBlobMultiblockSavedData; +}UPLOADTOBLOB_THREAD_INFO; + #endif #define USER_CALLBACK_TYPE_VALUES \ @@ -140,6 +144,14 @@ const size_t IoTHubClient_ThreadTerminationOffset = offsetof(IOTHUB_CLIENT_INSTANCE, StopThread); #ifndef DONT_USE_UPLOADTOBLOB +static void freeUploadToBlobThreadInfo(UPLOADTOBLOB_THREAD_INFO* threadInfo) +{ + Lock_Deinit(threadInfo->lockGarbage); + free(threadInfo->uploadBlobSavedData.source); + free(threadInfo->destinationFileName); + free(threadInfo); +} + /*this function is called from _Destroy and from ScheduleWork_Thread to join finished blobUpload threads and free that memory*/ static void garbageCollectorImpl(IOTHUB_CLIENT_INSTANCE* iotHubClientInstance) { @@ -148,37 +160,34 @@ LIST_ITEM_HANDLE item = singlylinkedlist_get_head_item(iotHubClientInstance->savedDataToBeCleaned); while (item != NULL) { - const UPLOADTOBLOB_SAVED_DATA* savedData = (const UPLOADTOBLOB_SAVED_DATA*)singlylinkedlist_item_get_value(item); + UPLOADTOBLOB_THREAD_INFO* threadInfo = (UPLOADTOBLOB_THREAD_INFO*)singlylinkedlist_item_get_value(item); LIST_ITEM_HANDLE old_item = item; item = singlylinkedlist_get_next_item(item); - if (Lock(savedData->lockGarbage) != LOCK_OK) + if (Lock(threadInfo->lockGarbage) != LOCK_OK) { LogError("unable to Lock"); } else { - if (savedData->canBeGarbageCollected == 1) + if (threadInfo->canBeGarbageCollected == 1) { int notUsed; - if (ThreadAPI_Join(savedData->uploadingThreadHandle, ¬Used) != THREADAPI_OK) + if (ThreadAPI_Join(threadInfo->uploadingThreadHandle, ¬Used) != THREADAPI_OK) { LogError("unable to ThreadAPI_Join"); } (void)singlylinkedlist_remove(iotHubClientInstance->savedDataToBeCleaned, old_item); - free((void*)savedData->source); - free((void*)savedData->destinationFileName); - if (Unlock(savedData->lockGarbage) != LOCK_OK) + if (Unlock(threadInfo->lockGarbage) != LOCK_OK) { LogError("unable to unlock after locking"); } - (void)Lock_Deinit(savedData->lockGarbage); - free((void*)savedData); + freeUploadToBlobThreadInfo(threadInfo); } else { - if (Unlock(savedData->lockGarbage) != LOCK_OK) + if (Unlock(threadInfo->lockGarbage) != LOCK_OK) { LogError("unable to unlock after locking"); } @@ -1856,17 +1865,135 @@ } #ifndef DONT_USE_UPLOADTOBLOB +static IOTHUB_CLIENT_RESULT startUploadToBlobWorkerThread(UPLOADTOBLOB_THREAD_INFO* threadInfo, THREAD_START_FUNC uploadThreadFunc) +{ + IOTHUB_CLIENT_RESULT result; + + LIST_ITEM_HANDLE item; + + if (Lock(threadInfo->iotHubClientHandle->LockHandle) != LOCK_OK) + { + LogError("Lock failed"); + result = IOTHUB_CLIENT_ERROR; + } + else + { + if ((item = singlylinkedlist_add(threadInfo->iotHubClientHandle->savedDataToBeCleaned, threadInfo)) == NULL) + { + LogError("Adding item to list failed"); + result = IOTHUB_CLIENT_ERROR; + } + else if (ThreadAPI_Create(&threadInfo->uploadingThreadHandle, uploadThreadFunc, threadInfo) != THREADAPI_OK) + { + /*Codes_SRS_IOTHUBCLIENT_02_053: [ If copying to the structure or spawning the thread fails, then IoTHubClient_UploadToBlobAsync shall fail and return IOTHUB_CLIENT_ERROR. ]*/ + LogError("unable to ThreadAPI_Create"); + // Remove the item from linked list here, while we're still under lock. Final garbage collector also does it under lock. + (void)singlylinkedlist_remove(threadInfo->iotHubClientHandle->savedDataToBeCleaned, item); + result = IOTHUB_CLIENT_ERROR; + } + else + { + result = IOTHUB_CLIENT_OK; + } + (void)Unlock(threadInfo->iotHubClientHandle->LockHandle); + } + + return result; +} + +static UPLOADTOBLOB_THREAD_INFO* allocateUploadToBlob(const char* destinationFileName, IOTHUB_CLIENT_HANDLE iotHubClientHandle, void* context) +{ + UPLOADTOBLOB_THREAD_INFO* threadInfo = (UPLOADTOBLOB_THREAD_INFO*)malloc(sizeof(UPLOADTOBLOB_THREAD_INFO)); + if (threadInfo == NULL) + { + LogError("unable to allocate thread object"); + } + else + { + memset(threadInfo, 0, sizeof(UPLOADTOBLOB_THREAD_INFO)); + threadInfo->iotHubClientHandle = iotHubClientHandle; + threadInfo->context = context; + + if (mallocAndStrcpy_s(&threadInfo->destinationFileName, destinationFileName) != 0) + { + /*Codes_SRS_IOTHUBCLIENT_02_053: [ If copying to the structure or spawning the thread fails, then IoTHubClient_UploadToBlobAsync shall fail and return IOTHUB_CLIENT_ERROR. ]*/ + LogError("unable to mallocAndStrcpy_s"); + freeUploadToBlobThreadInfo(threadInfo); + threadInfo = NULL; + } + else if ((threadInfo->lockGarbage = Lock_Init()) == NULL) + { + LogError("unable to allocate a lock"); + freeUploadToBlobThreadInfo(threadInfo); + threadInfo = NULL; + } + } + + return threadInfo; +} + +static int markThreadReadyToBeGarbageCollected(UPLOADTOBLOB_THREAD_INFO* threadInfo) +{ + /*Codes_SRS_IOTHUBCLIENT_02_071: [ The thread shall mark itself as disposable. ]*/ + if (Lock(threadInfo->lockGarbage) != LOCK_OK) + { + LogError("unable to Lock - trying anyway"); + threadInfo->canBeGarbageCollected = 1; + } + else + { + threadInfo->canBeGarbageCollected = 1; + + if (Unlock(threadInfo->lockGarbage) != LOCK_OK) + { + LogError("unable to Unlock after locking"); + } + } + + ThreadAPI_Exit(0); + return 0; +} + +static IOTHUB_CLIENT_RESULT initializeUploadToBlobData(UPLOADTOBLOB_THREAD_INFO* threadInfo, const unsigned char* source, size_t size, IOTHUB_CLIENT_FILE_UPLOAD_CALLBACK iotHubClientFileUploadCallback) +{ + IOTHUB_CLIENT_RESULT result; + + threadInfo->uploadBlobSavedData.size = size; + threadInfo->uploadBlobSavedData.iotHubClientFileUploadCallback = iotHubClientFileUploadCallback; + + if (size != 0) + { + if ((threadInfo->uploadBlobSavedData.source = (unsigned char*)malloc(size)) == NULL) + { + LogError("Cannot allocate source field"); + result = IOTHUB_CLIENT_ERROR; + } + else + { + memcpy(threadInfo->uploadBlobSavedData.source, source, size); + result = IOTHUB_CLIENT_OK; + } + } + else + { + result = IOTHUB_CLIENT_OK; + } + + return result; +} + + static int uploadingThread(void *data) { - UPLOADTOBLOB_SAVED_DATA* savedData = (UPLOADTOBLOB_SAVED_DATA*)data; + UPLOADTOBLOB_THREAD_INFO* threadInfo = (UPLOADTOBLOB_THREAD_INFO*)data; - if (Lock(savedData->iotHubClientHandle->LockHandle) == LOCK_OK) + if (Lock(threadInfo->iotHubClientHandle->LockHandle) == LOCK_OK) { IOTHUB_CLIENT_FILE_UPLOAD_RESULT upload_result; /*it so happens that IoTHubClient_LL_UploadToBlob is thread-safe because there's no saved state in the handle and there are no globals, so no need to protect it*/ /*not having it protected means multiple simultaneous uploads can happen*/ /*Codes_SRS_IOTHUBCLIENT_02_054: [ The thread shall call IoTHubClient_LL_UploadToBlob passing the information packed in the structure. ]*/ - if (IoTHubClient_LL_UploadToBlob(savedData->iotHubClientHandle->IoTHubClientLLHandle, savedData->destinationFileName, savedData->source, savedData->size) == IOTHUB_CLIENT_OK) + if (IoTHubClient_LL_UploadToBlob(threadInfo->iotHubClientHandle->IoTHubClientLLHandle, threadInfo->destinationFileName, threadInfo->uploadBlobSavedData.source, threadInfo->uploadBlobSavedData.size) == IOTHUB_CLIENT_OK) { upload_result = FILE_UPLOAD_OK; } @@ -1875,12 +2002,12 @@ LogError("unable to IoTHubClient_LL_UploadToBlob"); upload_result = FILE_UPLOAD_ERROR; } - (void)Unlock(savedData->iotHubClientHandle->LockHandle); + (void)Unlock(threadInfo->iotHubClientHandle->LockHandle); - if (savedData->iotHubClientFileUploadCallback != NULL) + if (threadInfo->uploadBlobSavedData.iotHubClientFileUploadCallback != NULL) { /*Codes_SRS_IOTHUBCLIENT_02_055: [ If IoTHubClient_LL_UploadToBlob fails then the thread shall call iotHubClientFileUploadCallbackInternal passing as result FILE_UPLOAD_ERROR and as context the structure from SRS IOTHUBCLIENT 02 051. ]*/ - savedData->iotHubClientFileUploadCallback(upload_result, savedData->context); + threadInfo->uploadBlobSavedData.iotHubClientFileUploadCallback(upload_result, threadInfo->context); } } else @@ -1888,28 +2015,9 @@ LogError("Lock failed"); } - /*Codes_SRS_IOTHUBCLIENT_02_071: [ The thread shall mark itself as disposable. ]*/ - if (Lock(savedData->lockGarbage) != LOCK_OK) - { - LogError("unable to Lock - trying anyway"); - savedData->canBeGarbageCollected = 1; - } - else - { - savedData->canBeGarbageCollected = 1; + return markThreadReadyToBeGarbageCollected(threadInfo); +} - if (Unlock(savedData->lockGarbage) != LOCK_OK) - { - LogError("unable to Unlock after locking"); - } - } - - ThreadAPI_Exit(0); - return 0; -} -#endif - -#ifndef DONT_USE_UPLOADTOBLOB IOTHUB_CLIENT_RESULT IoTHubClient_UploadToBlobAsync(IOTHUB_CLIENT_HANDLE iotHubClientHandle, const char* destinationFileName, const unsigned char* source, size_t size, IOTHUB_CLIENT_FILE_UPLOAD_CALLBACK iotHubClientFileUploadCallback, void* context) { IOTHUB_CLIENT_RESULT result; @@ -1935,213 +2043,128 @@ else { /*Codes_SRS_IOTHUBCLIENT_02_051: [IoTHubClient_UploadToBlobAsync shall copy the souce, size, iotHubClientFileUploadCallback, context into a structure.]*/ - UPLOADTOBLOB_SAVED_DATA *savedData = (UPLOADTOBLOB_SAVED_DATA *)malloc(sizeof(UPLOADTOBLOB_SAVED_DATA)); - if (savedData == NULL) + UPLOADTOBLOB_THREAD_INFO *threadInfo = allocateUploadToBlob(destinationFileName, iotHubClientHandle, context); + if (threadInfo == NULL) + { + /*Codes_SRS_IOTHUBCLIENT_02_053: [ If copying to the structure or spawning the thread fails, then IoTHubClient_UploadToBlobAsync shall fail and return IOTHUB_CLIENT_ERROR. ]*/ + LogError("unable to create upload thread info"); + result = IOTHUB_CLIENT_ERROR; + } + else if ((result = initializeUploadToBlobData(threadInfo, source, size, iotHubClientFileUploadCallback)) != IOTHUB_CLIENT_OK) + { + /*Codes_SRS_IOTHUBCLIENT_02_053: [ If copying to the structure or spawning the thread fails, then IoTHubClient_UploadToBlobAsync shall fail and return IOTHUB_CLIENT_ERROR. ]*/ + LogError("unable to initialize upload blob info"); + result = IOTHUB_CLIENT_ERROR; + } + else if ((result = StartWorkerThreadIfNeeded(iotHubClientHandle)) != IOTHUB_CLIENT_OK) + { + /*Codes_SRS_IOTHUBCLIENT_02_053: [ If copying to the structure or spawning the thread fails, then IoTHubClient_UploadToBlobAsync shall fail and return IOTHUB_CLIENT_ERROR. ]*/ + LogError("Could not start worker thread"); + freeUploadToBlobThreadInfo(threadInfo); + } + /*Codes_SRS_IOTHUBCLIENT_02_052: [ IoTHubClient_UploadToBlobAsync shall spawn a thread passing the structure build in SRS IOTHUBCLIENT 02 051 as thread data.]*/ + else if ((result = startUploadToBlobWorkerThread(threadInfo, uploadingThread)) != IOTHUB_CLIENT_OK) { /*Codes_SRS_IOTHUBCLIENT_02_053: [ If copying to the structure or spawning the thread fails, then IoTHubClient_UploadToBlobAsync shall fail and return IOTHUB_CLIENT_ERROR. ]*/ - LogError("unable to malloc - oom"); + LogError("unable to start upload thread"); + freeUploadToBlobThreadInfo(threadInfo); + } + else + { + result = IOTHUB_CLIENT_OK; + } + } + + return result; +} + +static int uploadMultipleBlock_thread(void* data) +{ + UPLOADTOBLOB_THREAD_INFO* threadInfo = (UPLOADTOBLOB_THREAD_INFO*)data; + IOTHUB_CLIENT_LL_HANDLE llHandle = threadInfo->iotHubClientHandle->IoTHubClientLLHandle; + + /*Codes_SRS_IOTHUBCLIENT_99_078: [ The thread shall call `IoTHubClient_LL_UploadMultipleBlocksToBlob` or `IoTHubClient_LL_UploadMultipleBlocksToBlobEx` passing the information packed in the structure. ]*/ + IOTHUB_CLIENT_RESULT result; + + if (threadInfo->uploadBlobMultiblockSavedData.getDataCallback != NULL) + { + result = IoTHubClient_LL_UploadMultipleBlocksToBlob(llHandle, threadInfo->destinationFileName, threadInfo->uploadBlobMultiblockSavedData.getDataCallback, threadInfo->context); + } + else + { + result = IoTHubClient_LL_UploadMultipleBlocksToBlobEx(llHandle, threadInfo->destinationFileName, threadInfo->uploadBlobMultiblockSavedData.getDataCallbackEx, threadInfo->context); + } + + return markThreadReadyToBeGarbageCollected(threadInfo); +} + +IOTHUB_CLIENT_RESULT IoTHubClient_UploadMultipleBlocksToBlobAsync_Impl(IOTHUB_CLIENT_HANDLE iotHubClientHandle, const char* destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK getDataCallback, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX getDataCallbackEx, void* context) +{ + IOTHUB_CLIENT_RESULT result; + + /*Codes_SRS_IOTHUBCLIENT_99_072: [ If `iotHubClientHandle` is `NULL` then `IoTHubClient_UploadMultipleBlocksToBlobAsync(Ex)` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/ + /*Codes_SRS_IOTHUBCLIENT_99_073: [ If `destinationFileName` is `NULL` then `IoTHubClient_UploadMultipleBlocksToBlobAsync(Ex)` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/ + /*Codes_SRS_IOTHUBCLIENT_99_074: [ If `getDataCallback` is `NULL` then `IoTHubClient_UploadMultipleBlocksToBlobAsync(Ex)` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/ + if ( + (iotHubClientHandle == NULL) || + (destinationFileName == NULL) || + ((getDataCallback == NULL) && (getDataCallbackEx == NULL)) + ) + { + LogError("invalid parameters iotHubClientHandle = %p , destinationFileName = %p, getDataCallback = %p, getDataCallbackEx = %p", + iotHubClientHandle, + destinationFileName, + getDataCallback, + getDataCallbackEx + ); + result = IOTHUB_CLIENT_INVALID_ARG; + } + else + { + /*Codes_SRS_IOTHUBCLIENT_99_075: [ `IoTHubClient_UploadMultipleBlocksToBlobAsync(Ex)` shall copy the `destinationFileName`, `getDataCallback`, `context` and `iotHubClientHandle` into a structure. ]*/ + UPLOADTOBLOB_THREAD_INFO *threadInfo = allocateUploadToBlob(destinationFileName, iotHubClientHandle, context); + if (threadInfo == NULL) + { + /*Codes_SRS_IOTHUBCLIENT_02_053: [ If copying to the structure or spawning the thread fails, then IoTHubClient_UploadToBlobAsync shall fail and return IOTHUB_CLIENT_ERROR. ]*/ + LogError("unable to create upload thread info"); result = IOTHUB_CLIENT_ERROR; } else { - if (mallocAndStrcpy_s((char**)&savedData->destinationFileName, destinationFileName) != 0) + /*Codes_SRS_IOTHUBCLIENT_99_075: [ `IoTHubClient_UploadMultipleBlocksToBlobAsync(Ex)` shall copy the `destinationFileName`, `getDataCallback`, `context` and `iotHubClientHandle` into a structure. ]*/ + threadInfo->uploadBlobMultiblockSavedData.getDataCallback = getDataCallback; + threadInfo->uploadBlobMultiblockSavedData.getDataCallbackEx = getDataCallbackEx; + + if ((result = StartWorkerThreadIfNeeded(iotHubClientHandle)) != IOTHUB_CLIENT_OK) { /*Codes_SRS_IOTHUBCLIENT_02_053: [ If copying to the structure or spawning the thread fails, then IoTHubClient_UploadToBlobAsync shall fail and return IOTHUB_CLIENT_ERROR. ]*/ - LogError("unable to mallocAndStrcpy_s"); - free(savedData); - result = IOTHUB_CLIENT_ERROR; + LogError("Could not start worker thread"); + freeUploadToBlobThreadInfo(threadInfo); + } + else if ((result = startUploadToBlobWorkerThread(threadInfo, uploadMultipleBlock_thread)) != IOTHUB_CLIENT_OK) + { + /*Codes_SRS_IOTHUBCLIENT_02_053: [ If copying to the structure or spawning the thread fails, then IoTHubClient_UploadToBlobAsync shall fail and return IOTHUB_CLIENT_ERROR. ]*/ + LogError("unable to start upload thread"); + freeUploadToBlobThreadInfo(threadInfo); } else { - savedData->size = size; - int sourceCloned; - if (size == 0) - { - savedData->source = NULL; - sourceCloned = 1; - } - else - { - savedData->source = (unsigned char*)malloc(size); - if (savedData->source == NULL) - { - /*Codes_SRS_IOTHUBCLIENT_02_053: [ If copying to the structure or spawning the thread fails, then IoTHubClient_UploadToBlobAsync shall fail and return IOTHUB_CLIENT_ERROR. ]*/ - LogError("unable to malloc - oom"); - free(savedData->destinationFileName); - free(savedData); - sourceCloned = 0; - } - else - { - sourceCloned = 1; - } - } - - if (sourceCloned == 0) - { - result = IOTHUB_CLIENT_ERROR; - } - else - { - IOTHUB_CLIENT_INSTANCE* iotHubClientHandleData = (IOTHUB_CLIENT_INSTANCE*)iotHubClientHandle; - - savedData->iotHubClientFileUploadCallback = iotHubClientFileUploadCallback; - savedData->context = context; - (void)memcpy(savedData->source, source, size); - - if ((result = StartWorkerThreadIfNeeded(iotHubClientHandleData)) != IOTHUB_CLIENT_OK) - { - free(savedData->source); - free(savedData->destinationFileName); - free(savedData); - result = IOTHUB_CLIENT_ERROR; - LogError("Could not start worker thread"); - } - else - { - if (Lock(iotHubClientHandleData->LockHandle) != LOCK_OK) /*locking because the next statement is changing blobThreadsToBeJoined*/ - { - LogError("unable to lock"); - free(savedData->source); - free(savedData->destinationFileName); - free(savedData); - result = IOTHUB_CLIENT_ERROR; - } - else - { - /*Codes_SRS_IOTHUBCLIENT_02_058: [ IoTHubClient_UploadToBlobAsync shall add the structure to the list of structures that need to be cleaned once file upload finishes. ]*/ - LIST_ITEM_HANDLE item = singlylinkedlist_add(iotHubClientHandleData->savedDataToBeCleaned, savedData); - if (item == NULL) - { - LogError("unable to singlylinkedlist_add"); - free(savedData->source); - free(savedData->destinationFileName); - free(savedData); - result = IOTHUB_CLIENT_ERROR; - } - else - { - savedData->iotHubClientHandle = iotHubClientHandle; - savedData->canBeGarbageCollected = 0; - if ((savedData->lockGarbage = Lock_Init()) == NULL) - { - (void)singlylinkedlist_remove(iotHubClientHandleData->savedDataToBeCleaned, item); - free(savedData->source); - free(savedData->destinationFileName); - free(savedData); - result = IOTHUB_CLIENT_ERROR; - LogError("unable to Lock_Init"); - } - else - { - /*Codes_SRS_IOTHUBCLIENT_02_052: [ IoTHubClient_UploadToBlobAsync shall spawn a thread passing the structure build in SRS IOTHUBCLIENT 02 051 as thread data.]*/ - if (ThreadAPI_Create(&savedData->uploadingThreadHandle, uploadingThread, savedData) != THREADAPI_OK) - { - /*Codes_SRS_IOTHUBCLIENT_02_053: [ If copying to the structure or spawning the thread fails, then IoTHubClient_UploadToBlobAsync shall fail and return IOTHUB_CLIENT_ERROR. ]*/ - LogError("unablet to ThreadAPI_Create"); - (void)Lock_Deinit(savedData->lockGarbage); - (void)singlylinkedlist_remove(iotHubClientHandleData->savedDataToBeCleaned, item); - free(savedData->source); - free(savedData->destinationFileName); - free(savedData); - result = IOTHUB_CLIENT_ERROR; - } - else - { - result = IOTHUB_CLIENT_OK; - } - } - } - - (void)Unlock(iotHubClientHandleData->LockHandle); - } - } - } + /*Codes_SRS_IOTHUBCLIENT_99_077: [ If copying to the structure and spawning the thread succeeds, then `IoTHubClient_UploadMultipleBlocksToBlobAsync(Ex)` shall return `IOTHUB_CLIENT_OK`. ]*/ + result = IOTHUB_CLIENT_OK; } } } return result; } -static int uploadMultipleBlock_thread(void* data) -{ - UPLOADTOBLOB_MULTIBLOCK_SAVED_DATA *blocksData = (UPLOADTOBLOB_MULTIBLOCK_SAVED_DATA *)data; - IOTHUB_CLIENT_LL_HANDLE llHandle = blocksData->iotHubClientHandle->IoTHubClientLLHandle; - - /*Codes_SRS_IOTHUBCLIENT_99_078: [ The thread shall call `IoTHubClient_LL_UploadMultipleBlocksToBlob` passing the information packed in the structure. ]*/ - IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadMultipleBlocksToBlob(llHandle, blocksData->destinationFileName, blocksData->getDataCallback, blocksData->context); - - // Clean resources - free(blocksData->destinationFileName); - free(blocksData); - ThreadAPI_Exit(result); - return 0; -} - IOTHUB_CLIENT_RESULT IoTHubClient_UploadMultipleBlocksToBlobAsync(IOTHUB_CLIENT_HANDLE iotHubClientHandle, const char* destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK getDataCallback, void* context) { - IOTHUB_CLIENT_RESULT result; + return IoTHubClient_UploadMultipleBlocksToBlobAsync_Impl(iotHubClientHandle, destinationFileName, getDataCallback, NULL, context); +} - /*Codes_SRS_IOTHUBCLIENT_99_072: [ If `iotHubClientHandle` is `NULL` then `IoTHubClient_UploadMultipleBlocksToBlobAsync` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/ - /*Codes_SRS_IOTHUBCLIENT_99_073: [ If `destinationFileName` is `NULL` then `IoTHubClient_UploadMultipleBlocksToBlobAsync` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/ - /*Codes_SRS_IOTHUBCLIENT_99_074: [ If `getDataCallback` is `NULL` then `IoTHubClient_UploadMultipleBlocksToBlobAsync` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/ - if ( - (iotHubClientHandle == NULL) || - (destinationFileName == NULL) || - (getDataCallback == NULL) - ) - { - LogError("invalid parameters iotHubClientHandle = %p , destinationFileName = %p, getDataCallback = %p", - iotHubClientHandle, - destinationFileName, - getDataCallback - ); - result = IOTHUB_CLIENT_INVALID_ARG; - } - else - { - /*Codes_SRS_IOTHUBCLIENT_99_075: [ `IoTHubClient_UploadMultipleBlocksToBlobAsync` shall copy the `destinationFileName`, `getDataCallback`, `context` and `iotHubClientHandle` into a structure. ]*/ - UPLOADTOBLOB_MULTIBLOCK_SAVED_DATA *blocksData = (UPLOADTOBLOB_MULTIBLOCK_SAVED_DATA *)malloc(sizeof(UPLOADTOBLOB_MULTIBLOCK_SAVED_DATA)); - if (blocksData == NULL) - { - /*Codes_SRS_IOTHUBCLIENT_99_077: [ If copying to the structure or spawning the thread fails, then `IoTHubClient_UploadMultipleBlocksToBlobAsync` shall fail and return `IOTHUB_CLIENT_ERROR`. ]*/ - LogError("unable to malloc"); - result = IOTHUB_CLIENT_ERROR; - } - else - { - /*Codes_SRS_IOTHUBCLIENT_99_075: [ `IoTHubClient_UploadMultipleBlocksToBlobAsync` shall copy the `destinationFileName`, `getDataCallback`, `context` and `iotHubClientHandle` into a structure. ]*/ - if (mallocAndStrcpy_s((char**)&blocksData->destinationFileName, destinationFileName) != 0) - { - /*Codes_SRS_IOTHUBCLIENT_99_077: [ If copying to the structure or spawning the thread fails, then `IoTHubClient_UploadMultipleBlocksToBlobAsync` shall fail and return `IOTHUB_CLIENT_ERROR`. ]*/ - LogError("unable to mallocAndStrcpy_s"); - free(blocksData); - result = IOTHUB_CLIENT_ERROR; - } - else - { - /*Codes_SRS_IOTHUBCLIENT_99_075: [ `IoTHubClient_UploadMultipleBlocksToBlobAsync` shall copy the `destinationFileName`, `getDataCallback`, `context` and `iotHubClientHandle` into a structure. ]*/ - blocksData->getDataCallback = getDataCallback; - blocksData->context = context; - blocksData->iotHubClientHandle = iotHubClientHandle; - if (ThreadAPI_Create(&blocksData->uploadingThreadHandle, uploadMultipleBlock_thread, blocksData) != THREADAPI_OK) - { - /*Codes_SRS_IOTHUBCLIENT_99_077: [ If copying to the structure or spawning the thread fails, then `IoTHubClient_UploadMultipleBlocksToBlobAsync` shall fail and return `IOTHUB_CLIENT_ERROR`. ]*/ - LogError("unable to ThreadAPI_Create"); - free(blocksData->destinationFileName); - free(blocksData); - result = IOTHUB_CLIENT_ERROR; - } - else - { - /*Codes_SRS_IOTHUBCLIENT_99_077: [ If copying to the structure and spawning the thread succeeds, then `IoTHubClient_UploadMultipleBlocksToBlobAsync` shall return `IOTHUB_CLIENT_OK`. ]*/ - result = IOTHUB_CLIENT_OK; - } - } - } - } - - return result; +IOTHUB_CLIENT_RESULT IoTHubClient_UploadMultipleBlocksToBlobAsyncEx(IOTHUB_CLIENT_HANDLE iotHubClientHandle, const char* destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX getDataCallbackEx, void* context) +{ + return IoTHubClient_UploadMultipleBlocksToBlobAsync_Impl(iotHubClientHandle, destinationFileName, NULL, getDataCallbackEx, context); } #endif /*DONT_USE_UPLOADTOBLOB*/