Azure IoT / serializer

Dependents:   sht15_remote_monitoring f767zi_mqtt remote_monitoring simplesample_amqp ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers datapublisher.c Source File

datapublisher.c

00001 // Copyright (c) Microsoft. All rights reserved.
00002 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
00003 
00004 #include <stdlib.h>
00005 #include "azure_c_shared_utility/gballoc.h"
00006 
00007 #include <stdbool.h>
00008 #include "datapublisher.h"
00009 #include "jsonencoder.h"
00010 #include "datamarshaller.h"
00011 #include "agenttypesystem.h"
00012 #include "schema.h"
00013 #include "azure_c_shared_utility/crt_abstractions.h"
00014 #include "azure_c_shared_utility/xlogging.h"
00015 #include "azure_c_shared_utility/vector.h"
00016 
00017 DEFINE_ENUM_STRINGS(DATA_PUBLISHER_RESULT, DATA_PUBLISHER_RESULT_VALUES)
00018 
00019 #define LOG_DATA_PUBLISHER_ERROR \
00020     LogError("(result = %s)", ENUM_TO_STRING(DATA_PUBLISHER_RESULT, result))
00021 
00022 #define DEFAULT_MAX_BUFFER_SIZE 10240
00023 /* Codes_SRS_DATA_PUBLISHER_99_066:[ A single value shall be used by all instances of DataPublisher.] */
00024 /* Codes_SRS_DATA_PUBLISHER_99_067:[ Before any call to DataPublisher_SetMaxBufferSize, the default max buffer size shall be equal to 10KB.] */
00025 static size_t maxBufferSize_ = DEFAULT_MAX_BUFFER_SIZE;
00026 
00027 typedef struct DATA_PUBLISHER_HANDLE_DATA_TAG
00028 {
00029     DATA_MARSHALLER_HANDLE DataMarshallerHandle;
00030     SCHEMA_MODEL_TYPE_HANDLE ModelHandle;
00031 } DATA_PUBLISHER_HANDLE_DATA;
00032 
00033 typedef struct TRANSACTION_HANDLE_DATA_TAG
00034 {
00035     DATA_PUBLISHER_HANDLE_DATA* DataPublisherInstance;
00036     size_t ValueCount;
00037     DATA_MARSHALLER_VALUE* Values;
00038 } TRANSACTION_HANDLE_DATA;
00039 
00040 typedef struct REPORTED_PROPERTIES_TRANSACTION_HANDLE_DATA_TAG
00041 {
00042     DATA_PUBLISHER_HANDLE_DATA* DataPublisherInstance;
00043     VECTOR_HANDLE value; /*holds (DATA_MARSHALLER_VALUE*) */
00044 }REPORTED_PROPERTIES_TRANSACTION_HANDLE_DATA;
00045 
00046 DATA_PUBLISHER_HANDLE DataPublisher_Create(SCHEMA_MODEL_TYPE_HANDLE modelHandle, bool includePropertyPath)
00047 {
00048     DATA_PUBLISHER_HANDLE_DATA* result;
00049 
00050     /* Codes_SRS_DATA_PUBLISHER_99_042:[ If a NULL argument is passed to it, DataPublisher_Create shall return NULL.] */
00051     if (modelHandle == NULL)
00052     {
00053         result = NULL;
00054         LogError("(result = %s)", ENUM_TO_STRING(DATA_PUBLISHER_RESULT, DATA_PUBLISHER_INVALID_ARG));
00055     }
00056     else if ((result = (DATA_PUBLISHER_HANDLE_DATA*)malloc(sizeof(DATA_PUBLISHER_HANDLE_DATA))) == NULL)
00057     {
00058         /* Codes_SRS_DATA_PUBLISHER_99_047:[ For any other error not specified here, DataPublisher_Create shall return NULL.] */
00059         result = NULL;
00060         LogError("(result = %s)", ENUM_TO_STRING(DATA_PUBLISHER_RESULT, DATA_PUBLISHER_ERROR));
00061     }
00062     else
00063     {
00064         /* Codes_SRS_DATA_PUBLISHER_99_043:[ DataPublisher_Create shall initialize and hold a handle to a DataMarshaller instance.] */
00065         /* Codes_SRS_DATA_PUBLISHER_01_001: [DataPublisher_Create shall pass the includePropertyPath argument to DataMarshaller_Create.] */
00066         if ((result->DataMarshallerHandle = DataMarshaller_Create(modelHandle, includePropertyPath)) == NULL)
00067         {
00068             free(result);
00069 
00070             /* Codes_SRS_DATA_PUBLISHER_99_044:[ If the creation of the DataMarshaller instance fails, DataPublisher_Create shall return NULL.] */
00071             result = NULL;
00072             LogError("(result = %s)", ENUM_TO_STRING(DATA_PUBLISHER_RESULT, DATA_PUBLISHER_MARSHALLER_ERROR));
00073         }
00074         else
00075         {
00076             /* Codes_SRS_DATA_PUBLISHER_99_041:[ DataPublisher_Create shall create a new DataPublisher instance and return a non-NULL handle in case of success.] */
00077             result->ModelHandle = modelHandle;
00078         }
00079     }
00080 
00081     return result;
00082 }
00083 
00084 void DataPublisher_Destroy(DATA_PUBLISHER_HANDLE dataPublisherHandle)
00085 {
00086     if (dataPublisherHandle != NULL)
00087     {
00088         DATA_PUBLISHER_HANDLE_DATA* dataPublisherInstance = (DATA_PUBLISHER_HANDLE_DATA*)dataPublisherHandle;
00089         DataMarshaller_Destroy(dataPublisherInstance->DataMarshallerHandle);
00090 
00091         free(dataPublisherHandle);
00092     }
00093 }
00094 
00095 TRANSACTION_HANDLE DataPublisher_StartTransaction(DATA_PUBLISHER_HANDLE dataPublisherHandle)
00096 {
00097     TRANSACTION_HANDLE_DATA* transaction;
00098 
00099     /* Codes_SRS_DATA_PUBLISHER_99_038:[ If DataPublisher_StartTransaction is called with a NULL argument it shall return NULL.] */
00100     if (dataPublisherHandle == NULL)
00101     {
00102         transaction = NULL;
00103         LogError("(Error code: %s)", ENUM_TO_STRING(DATA_PUBLISHER_RESULT, DATA_PUBLISHER_INVALID_ARG));
00104     }
00105     else
00106     {
00107         /* Codes_SRS_DATA_PUBLISHER_99_007:[ A call to DataPublisher_StartTransaction shall start a new transaction.] */
00108         transaction = (TRANSACTION_HANDLE_DATA*)malloc(sizeof(TRANSACTION_HANDLE_DATA));
00109         if (transaction == NULL)
00110         {
00111             LogError("Allocating transaction failed (Error code: %s)", ENUM_TO_STRING(DATA_PUBLISHER_RESULT, DATA_PUBLISHER_ERROR));
00112         }
00113         else
00114         {
00115             transaction->ValueCount = 0;
00116             transaction->Values = NULL;
00117             transaction->DataPublisherInstance = (DATA_PUBLISHER_HANDLE_DATA*)dataPublisherHandle;
00118         }
00119     }
00120 
00121     /* Codes_SRS_DATA_PUBLISHER_99_008:[ DataPublisher_StartTransaction shall return a non-NULL handle upon success.] */
00122     /* Codes_SRS_DATA_PUBLISHER_99_009:[ DataPublisher_StartTransaction shall return NULL upon failure.] */
00123     return transaction;
00124 }
00125 
00126 DATA_PUBLISHER_RESULT DataPublisher_PublishTransacted(TRANSACTION_HANDLE transactionHandle, const char* propertyPath, const AGENT_DATA_TYPE* data)
00127 {
00128     DATA_PUBLISHER_RESULT result;
00129     char* propertyPathCopy;
00130 
00131     /* Codes_SRS_DATA_PUBLISHER_99_017:[ When one or more NULL parameter(s) are specified, DataPublisher_PublishTransacted is called with a NULL transactionHandle, it shall return DATA_PUBLISHER_INVALID_ARG.] */
00132     if ((transactionHandle == NULL) ||
00133         (propertyPath == NULL) ||
00134         (data == NULL))
00135     {
00136         result = DATA_PUBLISHER_INVALID_ARG;
00137         LOG_DATA_PUBLISHER_ERROR;
00138     }
00139     else if (mallocAndStrcpy_s(&propertyPathCopy, propertyPath) != 0)
00140     {
00141         /* Codes_SRS_DATA_PUBLISHER_99_020:[ For any errors not explicitly mentioned here the DataPublisher APIs shall return DATA_PUBLISHER_ERROR.] */
00142         result = DATA_PUBLISHER_ERROR;
00143         LOG_DATA_PUBLISHER_ERROR;
00144     }
00145     else
00146     {
00147         TRANSACTION_HANDLE_DATA* transaction = (TRANSACTION_HANDLE_DATA*)transactionHandle;
00148         AGENT_DATA_TYPE* propertyValue;
00149 
00150         if (!Schema_ModelPropertyByPathExists(transaction->DataPublisherInstance->ModelHandle, propertyPath))
00151         {
00152             free(propertyPathCopy);
00153 
00154             /* Codes_SRS_DATA_PUBLISHER_99_040:[ When propertyPath does not exist in the supplied model, DataPublisher_Publish shall return DATA_PUBLISHER_SCHEMA_FAILED without dispatching data.] */
00155             result = DATA_PUBLISHER_SCHEMA_FAILED;
00156             LOG_DATA_PUBLISHER_ERROR;
00157         }
00158         else if ((propertyValue = (AGENT_DATA_TYPE*)malloc(sizeof(AGENT_DATA_TYPE))) == NULL)
00159         {
00160             free(propertyPathCopy);
00161 
00162             /* Codes_SRS_DATA_PUBLISHER_99_020:[ For any errors not explicitly mentioned here the DataPublisher APIs shall return DATA_PUBLISHER_ERROR.] */
00163             result = DATA_PUBLISHER_ERROR;
00164             LOG_DATA_PUBLISHER_ERROR;
00165         }
00166         else if (Create_AGENT_DATA_TYPE_from_AGENT_DATA_TYPE(propertyValue, data) != AGENT_DATA_TYPES_OK)
00167         {
00168             free(propertyPathCopy);
00169             free(propertyValue);
00170 
00171             /* Codes_SRS_DATA_PUBLISHER_99_028:[ If creating the copy fails then DATA_PUBLISHER_AGENT_DATA_TYPES_ERROR shall be returned.] */
00172             result = DATA_PUBLISHER_AGENT_DATA_TYPES_ERROR;
00173             LOG_DATA_PUBLISHER_ERROR;
00174         }
00175         else
00176         {
00177             size_t i;
00178             DATA_MARSHALLER_VALUE* propertySlot = NULL;
00179 
00180             /* Codes_SRS_DATA_PUBLISHER_99_019:[ If the same property is associated twice with a transaction, then the last value shall be kept associated with the transaction.] */
00181             for (i = 0; i < transaction->ValueCount; i++)
00182             {
00183                 if (strcmp(transaction->Values[i].PropertyPath, propertyPath) == 0)
00184                 {
00185                     propertySlot = &transaction->Values[i];
00186                     break;
00187                 }
00188             }
00189 
00190             if (propertySlot == NULL)
00191             {
00192                 DATA_MARSHALLER_VALUE* newValues = (DATA_MARSHALLER_VALUE*)realloc(transaction->Values, sizeof(DATA_MARSHALLER_VALUE)* (transaction->ValueCount + 1));
00193                 if (newValues != NULL)
00194                 {
00195                     transaction->Values = newValues;
00196                     propertySlot = &transaction->Values[transaction->ValueCount];
00197                     propertySlot->Value = NULL;
00198                     propertySlot->PropertyPath = NULL;
00199                     transaction->ValueCount++;
00200                 }
00201             }
00202 
00203             if (propertySlot == NULL)
00204             {
00205                 Destroy_AGENT_DATA_TYPE((AGENT_DATA_TYPE*)propertyValue);
00206                 free(propertyValue);
00207                 free(propertyPathCopy);
00208 
00209                 /* Codes_SRS_DATA_PUBLISHER_99_020:[ For any errors not explicitly mentioned here the DataPublisher APIs shall return DATA_PUBLISHER_ERROR.] */
00210                 result = DATA_PUBLISHER_ERROR;
00211                 LOG_DATA_PUBLISHER_ERROR;
00212             }
00213             else
00214             {
00215                 if (propertySlot->Value != NULL)
00216                 {
00217                     Destroy_AGENT_DATA_TYPE((AGENT_DATA_TYPE*)propertySlot->Value);
00218                     free((AGENT_DATA_TYPE*)propertySlot->Value);
00219                 }
00220                 if (propertySlot->PropertyPath != NULL)
00221                 {
00222                     char* existingValue = (char*)propertySlot->PropertyPath;
00223                     free(existingValue);
00224                 }
00225 
00226                 /* Codes_SRS_DATA_PUBLISHER_99_016:[ When DataPublisher_PublishTransacted is invoked, DataPublisher shall associate the data with the transaction identified by the transactionHandle argument and return DATA_PUBLISHER_OK. No data shall be dispatched at the time of the call.] */
00227                 propertySlot->PropertyPath = propertyPathCopy;
00228                 propertySlot->Value = propertyValue;
00229 
00230                 result = DATA_PUBLISHER_OK;
00231             }
00232         }
00233     }
00234 
00235     return result;
00236 }
00237 
00238 DATA_PUBLISHER_RESULT DataPublisher_EndTransaction(TRANSACTION_HANDLE transactionHandle, unsigned char** destination, size_t* destinationSize)
00239 {
00240     DATA_PUBLISHER_RESULT result;
00241 
00242     /*Codes_SRS_DATA_PUBLISHER_02_006: [If the destination argument is NULL, DataPublisher_EndTransaction shall return DATA_PUBLISHER_INVALID_ARG.] */
00243     /*Codes_SRS_DATA_PUBLISHER_02_007: [If the destinationSize argument is NULL, DataPublisher_EndTransaction shall return DATA_PUBLISHER_INVALID_ARG.] */
00244     if (
00245         (transactionHandle == NULL) ||
00246         (destination == NULL) ||
00247         (destinationSize == NULL)
00248         )
00249     {
00250         /* Codes_SRS_DATA_PUBLISHER_99_011:[ If the transactionHandle argument is NULL, DataPublisher_EndTransaction shall return DATA_PUBLISHER_INVALID_ARG.] */
00251         result = DATA_PUBLISHER_INVALID_ARG;
00252         LOG_DATA_PUBLISHER_ERROR;
00253     }
00254     else
00255     {
00256         TRANSACTION_HANDLE_DATA* transaction = (TRANSACTION_HANDLE_DATA*)transactionHandle;
00257 
00258         if (transaction->ValueCount == 0)
00259         {
00260             /* Codes_SRS_DATA_PUBLISHER_99_024:[ If no values have been associated with the transaction, no data shall be dispatched
00261                                             to DataMarshaller, the transaction shall be discarded and DataPublisher_EndTransaction shall return DATA_PUBLISHER_EMPTY_TRANSACTION.] */
00262             result = DATA_PUBLISHER_EMPTY_TRANSACTION;
00263             LOG_DATA_PUBLISHER_ERROR;
00264         }
00265         /* Codes_SRS_DATA_PUBLISHER_99_010:[ A call to DataPublisher_EndTransaction shall mark the end of a transaction and, trigger a dispatch of all the data grouped by that transaction.] */
00266         else if (DataMarshaller_SendData(transaction->DataPublisherInstance->DataMarshallerHandle, transaction->ValueCount, transaction->Values, destination, destinationSize) != DATA_MARSHALLER_OK)
00267         {
00268             /* Codes_SRS_DATA_PUBLISHER_99_025:[ When the DataMarshaller_SendData call fails, DataPublisher_EndTransaction shall return DATA_PUBLISHER_MARSHALLER_ERROR.] */
00269             result = DATA_PUBLISHER_MARSHALLER_ERROR;
00270             LOG_DATA_PUBLISHER_ERROR;
00271         }
00272         else
00273         {
00274             /* Codes_SRS_DATA_PUBLISHER_99_026:[ On success, DataPublisher_EndTransaction shall return DATA_PUBLISHER_OK.] */
00275             result = DATA_PUBLISHER_OK;
00276         }
00277 
00278         /* Codes_SRS_DATA_PUBLISHER_99_012:[ DataPublisher_EndTransaction shall dispose of any resources associated with the transaction.] */
00279         (void)DataPublisher_CancelTransaction(transactionHandle);
00280     }
00281 
00282     return result;
00283 }
00284 
00285 DATA_PUBLISHER_RESULT DataPublisher_CancelTransaction(TRANSACTION_HANDLE transactionHandle)
00286 {
00287     DATA_PUBLISHER_RESULT result;
00288 
00289     if (transactionHandle == NULL)
00290     {
00291         /* Codes_SRS_DATA_PUBLISHER_99_014:[ If the transactionHandle argument is NULL DataPublisher_CancelTransaction shall return DATA_PUBLISHER_INVALID_ARG.] */
00292         result = DATA_PUBLISHER_INVALID_ARG;
00293         LOG_DATA_PUBLISHER_ERROR;
00294     }
00295     else
00296     {
00297         TRANSACTION_HANDLE_DATA* transaction = (TRANSACTION_HANDLE_DATA*)transactionHandle;
00298         size_t i;
00299 
00300         /* Codes_SRS_DATA_PUBLISHER_99_015:[ DataPublisher_CancelTransaction shall dispose of any resources associated with the transaction.] */
00301         for (i = 0; i < transaction->ValueCount; i++)
00302         {
00303             Destroy_AGENT_DATA_TYPE((AGENT_DATA_TYPE*)transaction->Values[i].Value);
00304             free((char*)transaction->Values[i].PropertyPath);
00305             free((AGENT_DATA_TYPE*)transaction->Values[i].Value);
00306         }
00307 
00308         /* Codes_SRS_DATA_PUBLISHER_99_015:[ DataPublisher_CancelTransaction shall dispose of any resources associated with the transaction.] */
00309         free(transaction->Values);
00310         free(transaction);
00311 
00312         /* Codes_SRS_DATA_PUBLISHER_99_013:[ A call to DataPublisher_CancelTransaction shall dispose of the transaction without dispatching
00313                                         the data to the DataMarshaller module and it shall return DATA_PUBLISHER_OK.] */
00314         result = DATA_PUBLISHER_OK;
00315     }
00316 
00317     return result;
00318 }
00319 
00320 /* Codes_SRS_DATA_PUBLISHER_99_065:[ DataPublisher_SetMaxBufferSize shall directly update the value used to limit how much data (in bytes) can be buffered in the BufferStorage instance.] */
00321 void DataPublisher_SetMaxBufferSize(size_t value)
00322 {
00323     maxBufferSize_ = value;
00324 }
00325 
00326 /* Codes_SRS_DATA_PUBLISHER_99_069:[ DataMarshaller_GetMaxBufferSize shall return the current max buffer size value used by any new instance of DataMarshaller.] */
00327 size_t DataPublisher_GetMaxBufferSize(void)
00328 {
00329     return maxBufferSize_;
00330 }
00331 
00332 REPORTED_PROPERTIES_TRANSACTION_HANDLE DataPublisher_CreateTransaction_ReportedProperties(DATA_PUBLISHER_HANDLE dataPublisherHandle)
00333 {
00334     REPORTED_PROPERTIES_TRANSACTION_HANDLE_DATA* result;
00335     /*Codes_SRS_DATA_PUBLISHER_02_027: [ If argument dataPublisherHandle is NULL then DataPublisher_CreateTransaction_ReportedProperties shall fail and return NULL. ]*/
00336     if (dataPublisherHandle == NULL)
00337     {
00338         LogError("invalid argument DATA_PUBLISHER_HANDLE dataPublisherHandle=%p", dataPublisherHandle);
00339         result = NULL;
00340     }
00341     else
00342     {
00343         /*Codes_SRS_DATA_PUBLISHER_02_028: [ DataPublisher_CreateTransaction_ReportedProperties shall create a VECTOR_HANDLE holding the individual elements of the transaction (DATA_MARSHALLER_VALUE). ]*/
00344         result = (REPORTED_PROPERTIES_TRANSACTION_HANDLE_DATA*)malloc(sizeof(REPORTED_PROPERTIES_TRANSACTION_HANDLE_DATA));
00345         if (result == NULL)
00346         {
00347             /*Codes_SRS_DATA_PUBLISHER_02_029: [ If any error occurs then DataPublisher_CreateTransaction_ReportedProperties shall fail and return NULL. ]*/
00348             LogError("unable to malloc");
00349             /*return as is */
00350         }
00351         else
00352         {
00353             result->value = VECTOR_create(sizeof(DATA_MARSHALLER_VALUE*));
00354             if (result->value == NULL)
00355             {
00356                 /*Codes_SRS_DATA_PUBLISHER_02_029: [ If any error occurs then DataPublisher_CreateTransaction_ReportedProperties shall fail and return NULL. ]*/
00357                 LogError("unable to VECTOR_create");
00358                 free(result);
00359                 result = NULL;
00360             }
00361             else
00362             {
00363                 /*Codes_SRS_DATA_PUBLISHER_02_030: [ Otherwise DataPublisher_CreateTransaction_ReportedProperties shall succeed and return a non-NULL handle. ]*/
00364                 result->DataPublisherInstance = dataPublisherHandle;
00365             }
00366         }
00367     }
00368 
00369     return result;
00370 }
00371 
00372 static bool reportedPropertyExistsByPath(const void* element, const void* value)
00373 {
00374     DATA_MARSHALLER_VALUE* dataMarshallerValue = *(DATA_MARSHALLER_VALUE**)element;
00375     return (strcmp(dataMarshallerValue->PropertyPath, (const char*)value) == 0);
00376 }
00377 
00378 DATA_PUBLISHER_RESULT DataPublisher_PublishTransacted_ReportedProperty(REPORTED_PROPERTIES_TRANSACTION_HANDLE transactionHandle, const char* reportedPropertyPath, const AGENT_DATA_TYPE* data)
00379 {
00380     DATA_PUBLISHER_RESULT result;
00381     /*Codes_SRS_DATA_PUBLISHER_02_009: [ If argument transactionHandle is NULL then DataPublisher_PublishTransacted_ReportedProperty shall fail and return DATA_PUBLISHER_INVALID_ARG. ]*/
00382     /*Codes_SRS_DATA_PUBLISHER_02_010: [ If argument reportedPropertyPath is NULL then DataPublisher_PublishTransacted_ReportedProperty shall fail and return DATA_PUBLISHER_INVALID_ARG. ]*/
00383     /*Codes_SRS_DATA_PUBLISHER_02_011: [ If argument data is NULL then DataPublisher_PublishTransacted_ReportedProperty shall fail and return DATA_PUBLISHER_INVALID_ARG. ]*/
00384     if (
00385         (transactionHandle == NULL) ||
00386         (reportedPropertyPath == NULL) ||
00387         (data == NULL)
00388         )
00389     {
00390         LogError("invalid argument REPORTED_PROPERTIES_TRANSACTION_HANDLE transactionHandle=%p, const char* reportedPropertyPath=%p, const AGENT_DATA_TYPE* data=%p", transactionHandle, reportedPropertyPath, data);
00391         result = DATA_PUBLISHER_INVALID_ARG;
00392     }
00393     else
00394     {
00395         REPORTED_PROPERTIES_TRANSACTION_HANDLE_DATA* handleData = (REPORTED_PROPERTIES_TRANSACTION_HANDLE_DATA*)transactionHandle;
00396         /*Codes_SRS_DATA_PUBLISHER_02_012: [ DataPublisher_PublishTransacted_ReportedProperty shall verify that a reported property having the path reportedPropertyPath exists in the model by calling Schema_ModelReportedPropertyByPathExists ]*/
00397         if (!Schema_ModelReportedPropertyByPathExists(handleData->DataPublisherInstance->ModelHandle, reportedPropertyPath))
00398         {
00399             /*Codes_SRS_DATA_PUBLISHER_02_013: [ If a reported property with path reportedPropertyPath does not exist in the model then DataPublisher_PublishTransacted_ReportedProperty shall fail and return DATA_PUBLISHER_INVALID_ARG. ]*/
00400             LogError("unable to find a reported property by path \"%s\"", reportedPropertyPath);
00401             result = DATA_PUBLISHER_INVALID_ARG;
00402         }
00403         else
00404         {
00405             DATA_MARSHALLER_VALUE** existingValue = VECTOR_find_if(handleData->value, reportedPropertyExistsByPath, reportedPropertyPath);
00406             if(existingValue != NULL)
00407             {
00408                 /*Codes_SRS_DATA_PUBLISHER_02_014: [ If the same (by reportedPropertypath) reported property has already been added to the transaction, then DataPublisher_PublishTransacted_ReportedProperty shall overwrite the previous reported property. ]*/
00409                 AGENT_DATA_TYPE *clone = (AGENT_DATA_TYPE *)malloc(sizeof(AGENT_DATA_TYPE));
00410                 if(clone == NULL)
00411                 {
00412                     /*Codes_SRS_DATA_PUBLISHER_02_016: [ If any error occurs then DataPublisher_PublishTransacted_ReportedProperty shall fail and return DATA_PUBLISHER_ERROR. ]*/
00413                     LogError("unable to malloc");
00414                     result = DATA_PUBLISHER_ERROR;
00415                 }
00416                 else
00417                 {
00418                     if (Create_AGENT_DATA_TYPE_from_AGENT_DATA_TYPE(clone, data) != AGENT_DATA_TYPES_OK)
00419                     {
00420                         /*Codes_SRS_DATA_PUBLISHER_02_016: [ If any error occurs then DataPublisher_PublishTransacted_ReportedProperty shall fail and return DATA_PUBLISHER_ERROR. ]*/
00421                         LogError("unable to Create_AGENT_DATA_TYPE_from_AGENT_DATA_TYPE");
00422                         free(clone);
00423                         result = DATA_PUBLISHER_ERROR;
00424                     }
00425                     else
00426                     {
00427                         /*Codes_SRS_DATA_PUBLISHER_02_017: [ Otherwise DataPublisher_PublishTransacted_ReportedProperty shall succeed and return DATA_PUBLISHER_OK. ]*/
00428                         Destroy_AGENT_DATA_TYPE((AGENT_DATA_TYPE*)((*existingValue)->Value));
00429                         free((void*)((*existingValue)->Value));
00430                         (*existingValue)->Value = clone;
00431                         result = DATA_PUBLISHER_OK;
00432                     }
00433                 }
00434             }
00435             else
00436             {
00437                 /*totally new reported property*/
00438                 DATA_MARSHALLER_VALUE* newValue = (DATA_MARSHALLER_VALUE*)malloc(sizeof(DATA_MARSHALLER_VALUE));
00439                 if (newValue == NULL)
00440                 {
00441                     /*Codes_SRS_DATA_PUBLISHER_02_016: [ If any error occurs then DataPublisher_PublishTransacted_ReportedProperty shall fail and return DATA_PUBLISHER_ERROR. ]*/
00442                     LogError("unable to malloc");
00443                     result = DATA_PUBLISHER_ERROR;
00444                 }
00445                 else
00446                 {
00447                     if (mallocAndStrcpy_s((char**)&(newValue->PropertyPath), reportedPropertyPath) != 0)
00448                     {
00449                         /*Codes_SRS_DATA_PUBLISHER_02_016: [ If any error occurs then DataPublisher_PublishTransacted_ReportedProperty shall fail and return DATA_PUBLISHER_ERROR. ]*/
00450                         LogError("unable to mallocAndStrcpy_s");
00451                         free(newValue);
00452                         result = DATA_PUBLISHER_ERROR;
00453                     }
00454                     else
00455                     {
00456                         if ((newValue->Value = (AGENT_DATA_TYPE*)malloc(sizeof(AGENT_DATA_TYPE))) == NULL)
00457                         {
00458                             LogError("unable to malloc");
00459                             free((void*)newValue->PropertyPath);
00460                             free(newValue);
00461                             result = DATA_PUBLISHER_ERROR;
00462                         }
00463                         else
00464                         {
00465                             if (Create_AGENT_DATA_TYPE_from_AGENT_DATA_TYPE((AGENT_DATA_TYPE*)newValue->Value, data) != AGENT_DATA_TYPES_OK)
00466                             {
00467                                 /*Codes_SRS_DATA_PUBLISHER_02_016: [ If any error occurs then DataPublisher_PublishTransacted_ReportedProperty shall fail and return DATA_PUBLISHER_ERROR. ]*/
00468                                 LogError("unable to Create_AGENT_DATA_TYPE_from_AGENT_DATA_TYPE");
00469                                 free((void*)newValue->Value);
00470                                 free((void*)newValue->PropertyPath);
00471                                 free(newValue);
00472                                 result = DATA_PUBLISHER_ERROR;
00473                             }
00474                             else
00475                             {
00476                                 /*Codes_SRS_DATA_PUBLISHER_02_015: [ DataPublisher_PublishTransacted_ReportedProperty shall add a new DATA_MARSHALLER_VALUE to the VECTOR_HANDLE. ]*/
00477                                 if (VECTOR_push_back(handleData->value, &newValue, 1) != 0)
00478                                 {
00479                                     /*Codes_SRS_DATA_PUBLISHER_02_016: [ If any error occurs then DataPublisher_PublishTransacted_ReportedProperty shall fail and return DATA_PUBLISHER_ERROR. */
00480                                     LogError("unable to VECTOR_push_back");
00481                                     Destroy_AGENT_DATA_TYPE((AGENT_DATA_TYPE*)newValue->Value);
00482                                     free((void*)newValue->Value);
00483                                     free((void*)newValue->PropertyPath);
00484                                     free(newValue);
00485                                     result = DATA_PUBLISHER_ERROR;
00486                                 }
00487                                 else
00488                                 {
00489                                     /*Codes_SRS_DATA_PUBLISHER_02_017: [ Otherwise DataPublisher_PublishTransacted_ReportedProperty shall succeed and return DATA_PUBLISHER_OK. ]*/
00490                                     result = DATA_PUBLISHER_OK;
00491                                 }
00492                             }
00493                         }
00494                     }
00495                 }
00496             }
00497         }
00498     }
00499     return result;
00500 }
00501 
00502 DATA_PUBLISHER_RESULT DataPublisher_CommitTransaction_ReportedProperties(REPORTED_PROPERTIES_TRANSACTION_HANDLE transactionHandle, unsigned char** destination, size_t* destinationSize)
00503 {
00504     DATA_PUBLISHER_RESULT result;
00505     /*Codes_SRS_DATA_PUBLISHER_02_019: [ If argument transactionHandle is NULL then DataPublisher_CommitTransaction_ReportedProperties shall fail and return DATA_PUBLISHER_INVALID_ARG. ]*/
00506     /*Codes_SRS_DATA_PUBLISHER_02_020: [ If argument destination is NULL then DataPublisher_CommitTransaction_ReportedProperties shall fail and return DATA_PUBLISHER_INVALID_ARG. ]*/
00507     /*Codes_SRS_DATA_PUBLISHER_02_021: [ If argument destinationSize NULL then DataPublisher_CommitTransaction_ReportedProperties shall fail and return DATA_PUBLISHER_INVALID_ARG. ]*/
00508     if (
00509         (transactionHandle == NULL) ||
00510         (destination == NULL) ||
00511         (destinationSize == NULL)
00512         )
00513     {
00514         LogError("invalid argument REPORTED_PROPERTIES_TRANSACTION_HANDLE transactionHandle=%p, unsigned char** destination=%p, size_t* destinationSize=%p", transactionHandle, destination, destinationSize);
00515         result = DATA_PUBLISHER_INVALID_ARG;
00516     }
00517     else
00518     {
00519         /*Codes_SRS_DATA_PUBLISHER_02_031: [ If the transaction contains zero elements then DataPublisher_CommitTransaction_ReportedProperties shall fail and return DATA_PUBLISHER_INVALID_ARG. ]*/
00520         REPORTED_PROPERTIES_TRANSACTION_HANDLE_DATA* handle = (REPORTED_PROPERTIES_TRANSACTION_HANDLE_DATA*)transactionHandle;
00521         if (VECTOR_size(handle->value) == 0)
00522         {
00523             LogError("cannot commit empty transaction");
00524             result = DATA_PUBLISHER_INVALID_ARG;
00525         }
00526         else
00527         {
00528             /*Codes_SRS_DATA_PUBLISHER_02_022: [ DataPublisher_CommitTransaction_ReportedProperties shall call DataMarshaller_SendData_ReportedProperties providing the VECTOR_HANDLE holding the transacted reported properties, destination and destinationSize. ]*/
00529             if (DataMarshaller_SendData_ReportedProperties(handle->DataPublisherInstance->DataMarshallerHandle, handle->value, destination, destinationSize) != DATA_MARSHALLER_OK)
00530             {
00531                 /*Codes_SRS_DATA_PUBLISHER_02_023: [ If any error occurs then DataPublisher_CommitTransaction_ReportedProperties shall fail and return DATA_PUBLISHER_ERROR. ]*/
00532                 LogError("unable to DataMarshaller_SendData_ReportedProperties");
00533                 result = DATA_PUBLISHER_ERROR;
00534             }
00535             else
00536             {
00537                 /*Codes_SRS_DATA_PUBLISHER_02_024: [ Otherwise DataPublisher_CommitTransaction_ReportedProperties shall succeed and return DATA_PUBLISHER_OK. ]*/
00538                 result = DATA_PUBLISHER_OK;
00539             }
00540         }
00541     }
00542 
00543     return result;
00544 }
00545 
00546 void DataPublisher_DestroyTransaction_ReportedProperties(REPORTED_PROPERTIES_TRANSACTION_HANDLE transactionHandle)
00547 {
00548     /*Codes_SRS_DATA_PUBLISHER_02_025: [ If argument transactionHandle is NULL then DataPublisher_DestroyTransaction_ReportedProperties shall return. ]*/
00549     if (transactionHandle == NULL)
00550     {
00551         LogError("invalig argument REPORTED_PROPERTIES_TRANSACTION_HANDLE transactionHandle=%p", transactionHandle);
00552     }
00553     else
00554     {
00555         /*Codes_SRS_DATA_PUBLISHER_02_026: [ Otherwise DataPublisher_DestroyTransaction_ReportedProperties shall free all resources associated with the reported properties transactionHandle. ]*/
00556         REPORTED_PROPERTIES_TRANSACTION_HANDLE_DATA* handleData = (REPORTED_PROPERTIES_TRANSACTION_HANDLE_DATA*)transactionHandle;
00557         size_t i, nReportedProperties;
00558         nReportedProperties = VECTOR_size(handleData->value);
00559         for (i = 0;i < nReportedProperties;i++)
00560         {
00561             DATA_MARSHALLER_VALUE *value = *(DATA_MARSHALLER_VALUE**)VECTOR_element(handleData->value, i);
00562             Destroy_AGENT_DATA_TYPE((AGENT_DATA_TYPE*)value->Value);
00563             free((void*)value->Value);
00564             free((void*)value->PropertyPath);
00565             free((void*)value);
00566         }
00567         VECTOR_destroy(handleData->value);
00568         free(handleData);
00569     }
00570     return;
00571 }