Xin Zhang / azure-iot-c-sdk-f767zi

Dependents:   samplemqtt

Committer:
XinZhangMS
Date:
Thu Aug 23 06:52:14 2018 +0000
Revision:
0:f7f1f0d76dd6
azure-c-sdk for mbed os supporting NUCLEO_F767ZI

Who changed what in which revision?

UserRevisionLine numberNew contents of line
XinZhangMS 0:f7f1f0d76dd6 1 // Copyright (c) Microsoft. All rights reserved.
XinZhangMS 0:f7f1f0d76dd6 2 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
XinZhangMS 0:f7f1f0d76dd6 3
XinZhangMS 0:f7f1f0d76dd6 4 #include <stdlib.h>
XinZhangMS 0:f7f1f0d76dd6 5 #include <stdarg.h>
XinZhangMS 0:f7f1f0d76dd6 6 #include "azure_c_shared_utility/gballoc.h"
XinZhangMS 0:f7f1f0d76dd6 7
XinZhangMS 0:f7f1f0d76dd6 8 #include "codefirst.h"
XinZhangMS 0:f7f1f0d76dd6 9 #include "azure_c_shared_utility/macro_utils.h"
XinZhangMS 0:f7f1f0d76dd6 10 #include "azure_c_shared_utility/crt_abstractions.h"
XinZhangMS 0:f7f1f0d76dd6 11 #include "azure_c_shared_utility/xlogging.h"
XinZhangMS 0:f7f1f0d76dd6 12 #include <stddef.h>
XinZhangMS 0:f7f1f0d76dd6 13 #include "azure_c_shared_utility/crt_abstractions.h"
XinZhangMS 0:f7f1f0d76dd6 14 #include "iotdevice.h"
XinZhangMS 0:f7f1f0d76dd6 15
XinZhangMS 0:f7f1f0d76dd6 16 DEFINE_ENUM_STRINGS(CODEFIRST_RESULT, CODEFIRST_RESULT_VALUES)
XinZhangMS 0:f7f1f0d76dd6 17 DEFINE_ENUM_STRINGS(EXECUTE_COMMAND_RESULT, EXECUTE_COMMAND_RESULT_VALUES)
XinZhangMS 0:f7f1f0d76dd6 18
XinZhangMS 0:f7f1f0d76dd6 19 #define LOG_CODEFIRST_ERROR \
XinZhangMS 0:f7f1f0d76dd6 20 LogError("(result = %s)", ENUM_TO_STRING(CODEFIRST_RESULT, result))
XinZhangMS 0:f7f1f0d76dd6 21
XinZhangMS 0:f7f1f0d76dd6 22 typedef struct DEVICE_HEADER_DATA_TAG
XinZhangMS 0:f7f1f0d76dd6 23 {
XinZhangMS 0:f7f1f0d76dd6 24 DEVICE_HANDLE DeviceHandle;
XinZhangMS 0:f7f1f0d76dd6 25 const REFLECTED_DATA_FROM_DATAPROVIDER* ReflectedData;
XinZhangMS 0:f7f1f0d76dd6 26 SCHEMA_MODEL_TYPE_HANDLE ModelHandle;
XinZhangMS 0:f7f1f0d76dd6 27 size_t DataSize;
XinZhangMS 0:f7f1f0d76dd6 28 unsigned char* data;
XinZhangMS 0:f7f1f0d76dd6 29 } DEVICE_HEADER_DATA;
XinZhangMS 0:f7f1f0d76dd6 30
XinZhangMS 0:f7f1f0d76dd6 31 #define COUNT_OF(A) (sizeof(A) / sizeof((A)[0]))
XinZhangMS 0:f7f1f0d76dd6 32
XinZhangMS 0:f7f1f0d76dd6 33 /*design considerations for lazy init of CodeFirst:
XinZhangMS 0:f7f1f0d76dd6 34 There are 2 main states: either CodeFirst is in an initialized state, or it is not initialized.
XinZhangMS 0:f7f1f0d76dd6 35 The initialized state means there's a g_OverrideSchemaNamespace set (even when it is set to NULL).
XinZhangMS 0:f7f1f0d76dd6 36 The uninitialized state means g_OverrideSchemaNamespace is not set.
XinZhangMS 0:f7f1f0d76dd6 37
XinZhangMS 0:f7f1f0d76dd6 38 To switch to Init state, either call CodeFirst_Init (that sets g_OverrideSchemaNamespace to something)
XinZhangMS 0:f7f1f0d76dd6 39 or call directly an API (that will set automatically g_OverrideSchemaNamespace to NULL).
XinZhangMS 0:f7f1f0d76dd6 40
XinZhangMS 0:f7f1f0d76dd6 41 To switch to NOT INIT state, depending on the method used to initialize:
XinZhangMS 0:f7f1f0d76dd6 42 - if CodeFirst_Init was called, then only by a call to CodeFirst_Deinit the switch will take place
XinZhangMS 0:f7f1f0d76dd6 43 (note how in this case g_OverrideSchemaNamespace survives destruction of all devices).
XinZhangMS 0:f7f1f0d76dd6 44 - if the init has been done "lazily" by an API call then the module returns to uninitialized state
XinZhangMS 0:f7f1f0d76dd6 45 when the number of devices reaches zero.
XinZhangMS 0:f7f1f0d76dd6 46
XinZhangMS 0:f7f1f0d76dd6 47 +-----------------------------+
XinZhangMS 0:f7f1f0d76dd6 48 Start +---------------->| |
XinZhangMS 0:f7f1f0d76dd6 49 | NOT INIT |
XinZhangMS 0:f7f1f0d76dd6 50 +---------------->| |
XinZhangMS 0:f7f1f0d76dd6 51 | +------------+----------------+
XinZhangMS 0:f7f1f0d76dd6 52 | |
XinZhangMS 0:f7f1f0d76dd6 53 | |
XinZhangMS 0:f7f1f0d76dd6 54 | | _Init | APIs
XinZhangMS 0:f7f1f0d76dd6 55 | |
XinZhangMS 0:f7f1f0d76dd6 56 | v
XinZhangMS 0:f7f1f0d76dd6 57 | +---------------------------------------------------+
XinZhangMS 0:f7f1f0d76dd6 58 | | Init State |
XinZhangMS 0:f7f1f0d76dd6 59 | | +-----------------+ +-----------------+ |
XinZhangMS 0:f7f1f0d76dd6 60 | | | | | | |
XinZhangMS 0:f7f1f0d76dd6 61 | | | init by _Init | | init by API | |
XinZhangMS 0:f7f1f0d76dd6 62 | | +------+----------+ +---------+-------+ |
XinZhangMS 0:f7f1f0d76dd6 63 | | | | |
XinZhangMS 0:f7f1f0d76dd6 64 | | |_DeInit | nDevices==0 |
XinZhangMS 0:f7f1f0d76dd6 65 | | | | |
XinZhangMS 0:f7f1f0d76dd6 66 | +--------v----------------+-----------v-------------+
XinZhangMS 0:f7f1f0d76dd6 67 | |
XinZhangMS 0:f7f1f0d76dd6 68 +-------------------------------+
XinZhangMS 0:f7f1f0d76dd6 69
XinZhangMS 0:f7f1f0d76dd6 70 */
XinZhangMS 0:f7f1f0d76dd6 71
XinZhangMS 0:f7f1f0d76dd6 72
XinZhangMS 0:f7f1f0d76dd6 73 #define CODEFIRST_STATE_VALUES \
XinZhangMS 0:f7f1f0d76dd6 74 CODEFIRST_STATE_NOT_INIT, \
XinZhangMS 0:f7f1f0d76dd6 75 CODEFIRST_STATE_INIT_BY_INIT, \
XinZhangMS 0:f7f1f0d76dd6 76 CODEFIRST_STATE_INIT_BY_API
XinZhangMS 0:f7f1f0d76dd6 77
XinZhangMS 0:f7f1f0d76dd6 78 DEFINE_ENUM(CODEFIRST_STATE, CODEFIRST_STATE_VALUES)
XinZhangMS 0:f7f1f0d76dd6 79
XinZhangMS 0:f7f1f0d76dd6 80 static CODEFIRST_STATE g_state = CODEFIRST_STATE_NOT_INIT;
XinZhangMS 0:f7f1f0d76dd6 81 static const char* g_OverrideSchemaNamespace;
XinZhangMS 0:f7f1f0d76dd6 82 static size_t g_DeviceCount = 0;
XinZhangMS 0:f7f1f0d76dd6 83 static DEVICE_HEADER_DATA** g_Devices = NULL;
XinZhangMS 0:f7f1f0d76dd6 84
XinZhangMS 0:f7f1f0d76dd6 85 static void deinitializeDesiredProperties(SCHEMA_MODEL_TYPE_HANDLE model, void* destination)
XinZhangMS 0:f7f1f0d76dd6 86 {
XinZhangMS 0:f7f1f0d76dd6 87 size_t nDesiredProperties;
XinZhangMS 0:f7f1f0d76dd6 88 if (Schema_GetModelDesiredPropertyCount(model, &nDesiredProperties) != SCHEMA_OK)
XinZhangMS 0:f7f1f0d76dd6 89 {
XinZhangMS 0:f7f1f0d76dd6 90 LogError("unexpected error in Schema_GetModelDesiredPropertyCount");
XinZhangMS 0:f7f1f0d76dd6 91 }
XinZhangMS 0:f7f1f0d76dd6 92 else
XinZhangMS 0:f7f1f0d76dd6 93 {
XinZhangMS 0:f7f1f0d76dd6 94 size_t nProcessedDesiredProperties = 0;
XinZhangMS 0:f7f1f0d76dd6 95 for (size_t i = 0;i < nDesiredProperties;i++)
XinZhangMS 0:f7f1f0d76dd6 96 {
XinZhangMS 0:f7f1f0d76dd6 97 SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle = Schema_GetModelDesiredPropertyByIndex(model, i);
XinZhangMS 0:f7f1f0d76dd6 98 if (desiredPropertyHandle == NULL)
XinZhangMS 0:f7f1f0d76dd6 99 {
XinZhangMS 0:f7f1f0d76dd6 100 LogError("unexpected error in Schema_GetModelDesiredPropertyByIndex");
XinZhangMS 0:f7f1f0d76dd6 101 i = nDesiredProperties;
XinZhangMS 0:f7f1f0d76dd6 102 }
XinZhangMS 0:f7f1f0d76dd6 103 else
XinZhangMS 0:f7f1f0d76dd6 104 {
XinZhangMS 0:f7f1f0d76dd6 105 pfDesiredPropertyDeinitialize desiredPropertyDeinitialize = Schema_GetModelDesiredProperty_pfDesiredPropertyDeinitialize(desiredPropertyHandle);
XinZhangMS 0:f7f1f0d76dd6 106 if (desiredPropertyDeinitialize == NULL)
XinZhangMS 0:f7f1f0d76dd6 107 {
XinZhangMS 0:f7f1f0d76dd6 108 LogError("unexpected error in Schema_GetModelDesiredProperty_pfDesiredPropertyDeinitialize");
XinZhangMS 0:f7f1f0d76dd6 109 i = nDesiredProperties;
XinZhangMS 0:f7f1f0d76dd6 110 }
XinZhangMS 0:f7f1f0d76dd6 111 else
XinZhangMS 0:f7f1f0d76dd6 112 {
XinZhangMS 0:f7f1f0d76dd6 113 size_t offset = Schema_GetModelDesiredProperty_offset(desiredPropertyHandle);
XinZhangMS 0:f7f1f0d76dd6 114 desiredPropertyDeinitialize((char*)destination + offset);
XinZhangMS 0:f7f1f0d76dd6 115 nProcessedDesiredProperties++;
XinZhangMS 0:f7f1f0d76dd6 116 }
XinZhangMS 0:f7f1f0d76dd6 117 }
XinZhangMS 0:f7f1f0d76dd6 118 }
XinZhangMS 0:f7f1f0d76dd6 119
XinZhangMS 0:f7f1f0d76dd6 120 if (nDesiredProperties == nProcessedDesiredProperties)
XinZhangMS 0:f7f1f0d76dd6 121 {
XinZhangMS 0:f7f1f0d76dd6 122 /*recursively go in the model and initialize the other fields*/
XinZhangMS 0:f7f1f0d76dd6 123 size_t nModelInModel;
XinZhangMS 0:f7f1f0d76dd6 124 if (Schema_GetModelModelCount(model, &nModelInModel) != SCHEMA_OK)
XinZhangMS 0:f7f1f0d76dd6 125 {
XinZhangMS 0:f7f1f0d76dd6 126 LogError("unexpected error in Schema_GetModelModelCount");
XinZhangMS 0:f7f1f0d76dd6 127 }
XinZhangMS 0:f7f1f0d76dd6 128 else
XinZhangMS 0:f7f1f0d76dd6 129 {
XinZhangMS 0:f7f1f0d76dd6 130 size_t nProcessedModelInModel = 0;
XinZhangMS 0:f7f1f0d76dd6 131 for (size_t i = 0; i < nModelInModel;i++)
XinZhangMS 0:f7f1f0d76dd6 132 {
XinZhangMS 0:f7f1f0d76dd6 133 SCHEMA_MODEL_TYPE_HANDLE modelInModel = Schema_GetModelModelyByIndex(model, i);
XinZhangMS 0:f7f1f0d76dd6 134 if (modelInModel == NULL)
XinZhangMS 0:f7f1f0d76dd6 135 {
XinZhangMS 0:f7f1f0d76dd6 136 LogError("unexpected failure in Schema_GetModelModelyByIndex");
XinZhangMS 0:f7f1f0d76dd6 137 i = nModelInModel;
XinZhangMS 0:f7f1f0d76dd6 138 }
XinZhangMS 0:f7f1f0d76dd6 139 else
XinZhangMS 0:f7f1f0d76dd6 140 {
XinZhangMS 0:f7f1f0d76dd6 141 size_t offset = Schema_GetModelModelByIndex_Offset(model, i);
XinZhangMS 0:f7f1f0d76dd6 142 deinitializeDesiredProperties(modelInModel, (char*)destination + offset);
XinZhangMS 0:f7f1f0d76dd6 143 nProcessedModelInModel++;
XinZhangMS 0:f7f1f0d76dd6 144 }
XinZhangMS 0:f7f1f0d76dd6 145 }
XinZhangMS 0:f7f1f0d76dd6 146
XinZhangMS 0:f7f1f0d76dd6 147 if (nProcessedModelInModel == nModelInModel)
XinZhangMS 0:f7f1f0d76dd6 148 {
XinZhangMS 0:f7f1f0d76dd6 149 /*all is fine... */
XinZhangMS 0:f7f1f0d76dd6 150 }
XinZhangMS 0:f7f1f0d76dd6 151 }
XinZhangMS 0:f7f1f0d76dd6 152 }
XinZhangMS 0:f7f1f0d76dd6 153 }
XinZhangMS 0:f7f1f0d76dd6 154 }
XinZhangMS 0:f7f1f0d76dd6 155
XinZhangMS 0:f7f1f0d76dd6 156 static void DestroyDevice(DEVICE_HEADER_DATA* deviceHeader)
XinZhangMS 0:f7f1f0d76dd6 157 {
XinZhangMS 0:f7f1f0d76dd6 158 /* Codes_SRS_CODEFIRST_99_085:[CodeFirst_DestroyDevice shall free all resources associated with a device.] */
XinZhangMS 0:f7f1f0d76dd6 159 /* Codes_SRS_CODEFIRST_99_087:[In order to release the device handle, CodeFirst_DestroyDevice shall call Device_Destroy.] */
XinZhangMS 0:f7f1f0d76dd6 160
XinZhangMS 0:f7f1f0d76dd6 161 Device_Destroy(deviceHeader->DeviceHandle);
XinZhangMS 0:f7f1f0d76dd6 162 free(deviceHeader->data);
XinZhangMS 0:f7f1f0d76dd6 163 free(deviceHeader);
XinZhangMS 0:f7f1f0d76dd6 164 }
XinZhangMS 0:f7f1f0d76dd6 165
XinZhangMS 0:f7f1f0d76dd6 166 static CODEFIRST_RESULT buildStructTypes(SCHEMA_HANDLE schemaHandle, const REFLECTED_DATA_FROM_DATAPROVIDER* reflectedData)
XinZhangMS 0:f7f1f0d76dd6 167 {
XinZhangMS 0:f7f1f0d76dd6 168 CODEFIRST_RESULT result = CODEFIRST_OK;
XinZhangMS 0:f7f1f0d76dd6 169
XinZhangMS 0:f7f1f0d76dd6 170 const REFLECTED_SOMETHING* something;
XinZhangMS 0:f7f1f0d76dd6 171 for (something = reflectedData->reflectedData; something != NULL; something = something->next)
XinZhangMS 0:f7f1f0d76dd6 172 {
XinZhangMS 0:f7f1f0d76dd6 173 if (something->type == REFLECTION_STRUCT_TYPE)
XinZhangMS 0:f7f1f0d76dd6 174 {
XinZhangMS 0:f7f1f0d76dd6 175 SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle;
XinZhangMS 0:f7f1f0d76dd6 176 structTypeHandle = Schema_CreateStructType(schemaHandle, something->what.structure.name);
XinZhangMS 0:f7f1f0d76dd6 177
XinZhangMS 0:f7f1f0d76dd6 178 if (structTypeHandle == NULL)
XinZhangMS 0:f7f1f0d76dd6 179 {
XinZhangMS 0:f7f1f0d76dd6 180 /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
XinZhangMS 0:f7f1f0d76dd6 181 result = CODEFIRST_SCHEMA_ERROR;
XinZhangMS 0:f7f1f0d76dd6 182 LogError("create struct failed %s", ENUM_TO_STRING(CODEFIRST_RESULT, result));
XinZhangMS 0:f7f1f0d76dd6 183 break;
XinZhangMS 0:f7f1f0d76dd6 184 }
XinZhangMS 0:f7f1f0d76dd6 185 else
XinZhangMS 0:f7f1f0d76dd6 186 {
XinZhangMS 0:f7f1f0d76dd6 187 const REFLECTED_SOMETHING* maybeField;
XinZhangMS 0:f7f1f0d76dd6 188 /*look for the field... */
XinZhangMS 0:f7f1f0d76dd6 189 for (maybeField = reflectedData->reflectedData; maybeField != NULL; maybeField = maybeField->next)
XinZhangMS 0:f7f1f0d76dd6 190 {
XinZhangMS 0:f7f1f0d76dd6 191 if (maybeField->type == REFLECTION_FIELD_TYPE)
XinZhangMS 0:f7f1f0d76dd6 192 {
XinZhangMS 0:f7f1f0d76dd6 193 if (strcmp(maybeField->what.field.structName, something->what.structure.name) == 0)
XinZhangMS 0:f7f1f0d76dd6 194 {
XinZhangMS 0:f7f1f0d76dd6 195 if (Schema_AddStructTypeProperty(structTypeHandle, maybeField->what.field.fieldName, maybeField->what.field.fieldType) != SCHEMA_OK)
XinZhangMS 0:f7f1f0d76dd6 196 {
XinZhangMS 0:f7f1f0d76dd6 197 /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
XinZhangMS 0:f7f1f0d76dd6 198 result = CODEFIRST_SCHEMA_ERROR;
XinZhangMS 0:f7f1f0d76dd6 199 LogError("add struct property failed %s", ENUM_TO_STRING(CODEFIRST_RESULT, result));
XinZhangMS 0:f7f1f0d76dd6 200 break;
XinZhangMS 0:f7f1f0d76dd6 201 }
XinZhangMS 0:f7f1f0d76dd6 202 }
XinZhangMS 0:f7f1f0d76dd6 203 }
XinZhangMS 0:f7f1f0d76dd6 204 }
XinZhangMS 0:f7f1f0d76dd6 205 }
XinZhangMS 0:f7f1f0d76dd6 206 }
XinZhangMS 0:f7f1f0d76dd6 207 }
XinZhangMS 0:f7f1f0d76dd6 208
XinZhangMS 0:f7f1f0d76dd6 209 return result;
XinZhangMS 0:f7f1f0d76dd6 210 }
XinZhangMS 0:f7f1f0d76dd6 211
XinZhangMS 0:f7f1f0d76dd6 212 static CODEFIRST_RESULT buildModel(SCHEMA_HANDLE schemaHandle, const REFLECTED_DATA_FROM_DATAPROVIDER* reflectedData, const REFLECTED_SOMETHING* modelReflectedData)
XinZhangMS 0:f7f1f0d76dd6 213 {
XinZhangMS 0:f7f1f0d76dd6 214 CODEFIRST_RESULT result = CODEFIRST_OK;
XinZhangMS 0:f7f1f0d76dd6 215 const REFLECTED_SOMETHING* something;
XinZhangMS 0:f7f1f0d76dd6 216 SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle;
XinZhangMS 0:f7f1f0d76dd6 217
XinZhangMS 0:f7f1f0d76dd6 218 modelTypeHandle = Schema_GetModelByName(schemaHandle, modelReflectedData->what.model.name);
XinZhangMS 0:f7f1f0d76dd6 219 if (modelTypeHandle == NULL)
XinZhangMS 0:f7f1f0d76dd6 220 {
XinZhangMS 0:f7f1f0d76dd6 221 /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
XinZhangMS 0:f7f1f0d76dd6 222 result = CODEFIRST_SCHEMA_ERROR;
XinZhangMS 0:f7f1f0d76dd6 223 LogError("cannot get model %s %s", modelReflectedData->what.model.name, ENUM_TO_STRING(CODEFIRST_RESULT, result));
XinZhangMS 0:f7f1f0d76dd6 224 goto out;
XinZhangMS 0:f7f1f0d76dd6 225 }
XinZhangMS 0:f7f1f0d76dd6 226
XinZhangMS 0:f7f1f0d76dd6 227 for (something = reflectedData->reflectedData; something != NULL; something = something->next)
XinZhangMS 0:f7f1f0d76dd6 228 {
XinZhangMS 0:f7f1f0d76dd6 229 /* looking for all elements that belong to a model: properties and actions */
XinZhangMS 0:f7f1f0d76dd6 230 if ((something->type == REFLECTION_PROPERTY_TYPE) &&
XinZhangMS 0:f7f1f0d76dd6 231 (strcmp(something->what.property.modelName, modelReflectedData->what.model.name) == 0))
XinZhangMS 0:f7f1f0d76dd6 232 {
XinZhangMS 0:f7f1f0d76dd6 233 SCHEMA_MODEL_TYPE_HANDLE childModelHande = Schema_GetModelByName(schemaHandle, something->what.property.type);
XinZhangMS 0:f7f1f0d76dd6 234
XinZhangMS 0:f7f1f0d76dd6 235 /* if this is a model type use the appropriate APIs for it */
XinZhangMS 0:f7f1f0d76dd6 236 if (childModelHande != NULL)
XinZhangMS 0:f7f1f0d76dd6 237 {
XinZhangMS 0:f7f1f0d76dd6 238 if (Schema_AddModelModel(modelTypeHandle, something->what.property.name, childModelHande, something->what.property.offset, NULL) != SCHEMA_OK)
XinZhangMS 0:f7f1f0d76dd6 239 {
XinZhangMS 0:f7f1f0d76dd6 240 /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
XinZhangMS 0:f7f1f0d76dd6 241 result = CODEFIRST_SCHEMA_ERROR;
XinZhangMS 0:f7f1f0d76dd6 242 LogError("add model failed %s", ENUM_TO_STRING(CODEFIRST_RESULT, result));
XinZhangMS 0:f7f1f0d76dd6 243 goto out;
XinZhangMS 0:f7f1f0d76dd6 244 }
XinZhangMS 0:f7f1f0d76dd6 245 }
XinZhangMS 0:f7f1f0d76dd6 246 else
XinZhangMS 0:f7f1f0d76dd6 247 {
XinZhangMS 0:f7f1f0d76dd6 248 if (Schema_AddModelProperty(modelTypeHandle, something->what.property.name, something->what.property.type) != SCHEMA_OK)
XinZhangMS 0:f7f1f0d76dd6 249 {
XinZhangMS 0:f7f1f0d76dd6 250 /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
XinZhangMS 0:f7f1f0d76dd6 251 result = CODEFIRST_SCHEMA_ERROR;
XinZhangMS 0:f7f1f0d76dd6 252 LogError("add property failed %s", ENUM_TO_STRING(CODEFIRST_RESULT, result));
XinZhangMS 0:f7f1f0d76dd6 253 goto out;
XinZhangMS 0:f7f1f0d76dd6 254 }
XinZhangMS 0:f7f1f0d76dd6 255 }
XinZhangMS 0:f7f1f0d76dd6 256 }
XinZhangMS 0:f7f1f0d76dd6 257
XinZhangMS 0:f7f1f0d76dd6 258 if ((something->type == REFLECTION_REPORTED_PROPERTY_TYPE) &&
XinZhangMS 0:f7f1f0d76dd6 259 (strcmp(something->what.reportedProperty.modelName, modelReflectedData->what.model.name) == 0))
XinZhangMS 0:f7f1f0d76dd6 260 {
XinZhangMS 0:f7f1f0d76dd6 261 SCHEMA_MODEL_TYPE_HANDLE childModelHande = Schema_GetModelByName(schemaHandle, something->what.reportedProperty.type);
XinZhangMS 0:f7f1f0d76dd6 262
XinZhangMS 0:f7f1f0d76dd6 263 /* if this is a model type use the appropriate APIs for it */
XinZhangMS 0:f7f1f0d76dd6 264 if (childModelHande != NULL)
XinZhangMS 0:f7f1f0d76dd6 265 {
XinZhangMS 0:f7f1f0d76dd6 266 if (Schema_AddModelModel(modelTypeHandle, something->what.reportedProperty.name, childModelHande, something->what.reportedProperty.offset, NULL) != SCHEMA_OK)
XinZhangMS 0:f7f1f0d76dd6 267 {
XinZhangMS 0:f7f1f0d76dd6 268 /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
XinZhangMS 0:f7f1f0d76dd6 269 result = CODEFIRST_SCHEMA_ERROR;
XinZhangMS 0:f7f1f0d76dd6 270 LogError("add model failed %s", ENUM_TO_STRING(CODEFIRST_RESULT, result));
XinZhangMS 0:f7f1f0d76dd6 271 goto out;
XinZhangMS 0:f7f1f0d76dd6 272 }
XinZhangMS 0:f7f1f0d76dd6 273 }
XinZhangMS 0:f7f1f0d76dd6 274 else
XinZhangMS 0:f7f1f0d76dd6 275 {
XinZhangMS 0:f7f1f0d76dd6 276 if (Schema_AddModelReportedProperty(modelTypeHandle, something->what.reportedProperty.name, something->what.reportedProperty.type) != SCHEMA_OK)
XinZhangMS 0:f7f1f0d76dd6 277 {
XinZhangMS 0:f7f1f0d76dd6 278 /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
XinZhangMS 0:f7f1f0d76dd6 279 result = CODEFIRST_SCHEMA_ERROR;
XinZhangMS 0:f7f1f0d76dd6 280 LogError("add reported property failed %s", ENUM_TO_STRING(CODEFIRST_RESULT, result));
XinZhangMS 0:f7f1f0d76dd6 281 goto out;
XinZhangMS 0:f7f1f0d76dd6 282 }
XinZhangMS 0:f7f1f0d76dd6 283 }
XinZhangMS 0:f7f1f0d76dd6 284 }
XinZhangMS 0:f7f1f0d76dd6 285
XinZhangMS 0:f7f1f0d76dd6 286 if ((something->type == REFLECTION_DESIRED_PROPERTY_TYPE) &&
XinZhangMS 0:f7f1f0d76dd6 287 (strcmp(something->what.desiredProperty.modelName, modelReflectedData->what.model.name) == 0))
XinZhangMS 0:f7f1f0d76dd6 288 {
XinZhangMS 0:f7f1f0d76dd6 289 SCHEMA_MODEL_TYPE_HANDLE childModelHande = Schema_GetModelByName(schemaHandle, something->what.desiredProperty.type);
XinZhangMS 0:f7f1f0d76dd6 290
XinZhangMS 0:f7f1f0d76dd6 291 /* if this is a model type use the appropriate APIs for it */
XinZhangMS 0:f7f1f0d76dd6 292 if (childModelHande != NULL)
XinZhangMS 0:f7f1f0d76dd6 293 {
XinZhangMS 0:f7f1f0d76dd6 294 if (Schema_AddModelModel(modelTypeHandle, something->what.desiredProperty.name, childModelHande, something->what.desiredProperty.offset, something->what.desiredProperty.onDesiredProperty) != SCHEMA_OK)
XinZhangMS 0:f7f1f0d76dd6 295 {
XinZhangMS 0:f7f1f0d76dd6 296 /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
XinZhangMS 0:f7f1f0d76dd6 297 result = CODEFIRST_SCHEMA_ERROR;
XinZhangMS 0:f7f1f0d76dd6 298 LogError("add model failed %s", ENUM_TO_STRING(CODEFIRST_RESULT, result));
XinZhangMS 0:f7f1f0d76dd6 299 goto out;
XinZhangMS 0:f7f1f0d76dd6 300 }
XinZhangMS 0:f7f1f0d76dd6 301 }
XinZhangMS 0:f7f1f0d76dd6 302 else
XinZhangMS 0:f7f1f0d76dd6 303 {
XinZhangMS 0:f7f1f0d76dd6 304 if (Schema_AddModelDesiredProperty(modelTypeHandle,
XinZhangMS 0:f7f1f0d76dd6 305 something->what.desiredProperty.name,
XinZhangMS 0:f7f1f0d76dd6 306 something->what.desiredProperty.type,
XinZhangMS 0:f7f1f0d76dd6 307 something->what.desiredProperty.FromAGENT_DATA_TYPE,
XinZhangMS 0:f7f1f0d76dd6 308 something->what.desiredProperty.desiredPropertInitialize,
XinZhangMS 0:f7f1f0d76dd6 309 something->what.desiredProperty.desiredPropertDeinitialize,
XinZhangMS 0:f7f1f0d76dd6 310 something->what.desiredProperty.offset,
XinZhangMS 0:f7f1f0d76dd6 311 something->what.desiredProperty.onDesiredProperty) != SCHEMA_OK)
XinZhangMS 0:f7f1f0d76dd6 312 {
XinZhangMS 0:f7f1f0d76dd6 313 /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
XinZhangMS 0:f7f1f0d76dd6 314 result = CODEFIRST_SCHEMA_ERROR;
XinZhangMS 0:f7f1f0d76dd6 315 LogError("add desired property failed %s", ENUM_TO_STRING(CODEFIRST_RESULT, result));
XinZhangMS 0:f7f1f0d76dd6 316 goto out;
XinZhangMS 0:f7f1f0d76dd6 317 }
XinZhangMS 0:f7f1f0d76dd6 318 }
XinZhangMS 0:f7f1f0d76dd6 319 }
XinZhangMS 0:f7f1f0d76dd6 320
XinZhangMS 0:f7f1f0d76dd6 321 if ((something->type == REFLECTION_ACTION_TYPE) &&
XinZhangMS 0:f7f1f0d76dd6 322 (strcmp(something->what.action.modelName, modelReflectedData->what.model.name) == 0))
XinZhangMS 0:f7f1f0d76dd6 323 {
XinZhangMS 0:f7f1f0d76dd6 324 SCHEMA_ACTION_HANDLE actionHandle;
XinZhangMS 0:f7f1f0d76dd6 325 size_t i;
XinZhangMS 0:f7f1f0d76dd6 326
XinZhangMS 0:f7f1f0d76dd6 327 if ((actionHandle = Schema_CreateModelAction(modelTypeHandle, something->what.action.name)) == NULL)
XinZhangMS 0:f7f1f0d76dd6 328 {
XinZhangMS 0:f7f1f0d76dd6 329 /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
XinZhangMS 0:f7f1f0d76dd6 330 result = CODEFIRST_SCHEMA_ERROR;
XinZhangMS 0:f7f1f0d76dd6 331 LogError("add model action failed %s", ENUM_TO_STRING(CODEFIRST_RESULT, result));
XinZhangMS 0:f7f1f0d76dd6 332 goto out;
XinZhangMS 0:f7f1f0d76dd6 333 }
XinZhangMS 0:f7f1f0d76dd6 334
XinZhangMS 0:f7f1f0d76dd6 335 for (i = 0; i < something->what.action.nArguments; i++)
XinZhangMS 0:f7f1f0d76dd6 336 {
XinZhangMS 0:f7f1f0d76dd6 337 if (Schema_AddModelActionArgument(actionHandle, something->what.action.arguments[i].name, something->what.action.arguments[i].type) != SCHEMA_OK)
XinZhangMS 0:f7f1f0d76dd6 338 {
XinZhangMS 0:f7f1f0d76dd6 339 /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
XinZhangMS 0:f7f1f0d76dd6 340 result = CODEFIRST_SCHEMA_ERROR;
XinZhangMS 0:f7f1f0d76dd6 341 LogError("add model action argument failed %s", ENUM_TO_STRING(CODEFIRST_RESULT, result));
XinZhangMS 0:f7f1f0d76dd6 342 goto out;
XinZhangMS 0:f7f1f0d76dd6 343 }
XinZhangMS 0:f7f1f0d76dd6 344 }
XinZhangMS 0:f7f1f0d76dd6 345 }
XinZhangMS 0:f7f1f0d76dd6 346
XinZhangMS 0:f7f1f0d76dd6 347 if ((something->type == REFLECTION_METHOD_TYPE) &&
XinZhangMS 0:f7f1f0d76dd6 348 (strcmp(something->what.method.modelName, modelReflectedData->what.model.name) == 0))
XinZhangMS 0:f7f1f0d76dd6 349 {
XinZhangMS 0:f7f1f0d76dd6 350 SCHEMA_METHOD_HANDLE methodHandle;
XinZhangMS 0:f7f1f0d76dd6 351 size_t i;
XinZhangMS 0:f7f1f0d76dd6 352
XinZhangMS 0:f7f1f0d76dd6 353 if ((methodHandle = Schema_CreateModelMethod(modelTypeHandle, something->what.method.name)) == NULL)
XinZhangMS 0:f7f1f0d76dd6 354 {
XinZhangMS 0:f7f1f0d76dd6 355 /*Codes_SRS_CODEFIRST_99_076: [ If any Schema APIs fail, CodeFirst_RegisterSchema shall return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 356 result = CODEFIRST_SCHEMA_ERROR;
XinZhangMS 0:f7f1f0d76dd6 357 LogError("add model method failed %s", ENUM_TO_STRING(CODEFIRST_RESULT, result));
XinZhangMS 0:f7f1f0d76dd6 358 goto out;
XinZhangMS 0:f7f1f0d76dd6 359 }
XinZhangMS 0:f7f1f0d76dd6 360
XinZhangMS 0:f7f1f0d76dd6 361 for (i = 0; i < something->what.method.nArguments; i++)
XinZhangMS 0:f7f1f0d76dd6 362 {
XinZhangMS 0:f7f1f0d76dd6 363 if (Schema_AddModelMethodArgument(methodHandle, something->what.method.arguments[i].name, something->what.method.arguments[i].type) != SCHEMA_OK)
XinZhangMS 0:f7f1f0d76dd6 364 {
XinZhangMS 0:f7f1f0d76dd6 365 /*Codes_SRS_CODEFIRST_99_076: [ If any Schema APIs fail, CodeFirst_RegisterSchema shall return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 366 result = CODEFIRST_SCHEMA_ERROR;
XinZhangMS 0:f7f1f0d76dd6 367 LogError("add model method argument failed %s", ENUM_TO_STRING(CODEFIRST_RESULT, result));
XinZhangMS 0:f7f1f0d76dd6 368 goto out;
XinZhangMS 0:f7f1f0d76dd6 369 }
XinZhangMS 0:f7f1f0d76dd6 370 }
XinZhangMS 0:f7f1f0d76dd6 371 }
XinZhangMS 0:f7f1f0d76dd6 372 }
XinZhangMS 0:f7f1f0d76dd6 373
XinZhangMS 0:f7f1f0d76dd6 374 out:
XinZhangMS 0:f7f1f0d76dd6 375 return result;
XinZhangMS 0:f7f1f0d76dd6 376 }
XinZhangMS 0:f7f1f0d76dd6 377
XinZhangMS 0:f7f1f0d76dd6 378 static CODEFIRST_RESULT buildModelTypes(SCHEMA_HANDLE schemaHandle, const REFLECTED_DATA_FROM_DATAPROVIDER* reflectedData)
XinZhangMS 0:f7f1f0d76dd6 379 {
XinZhangMS 0:f7f1f0d76dd6 380 CODEFIRST_RESULT result = CODEFIRST_OK;
XinZhangMS 0:f7f1f0d76dd6 381 const REFLECTED_SOMETHING* something;
XinZhangMS 0:f7f1f0d76dd6 382
XinZhangMS 0:f7f1f0d76dd6 383 /* first have a pass and add all the model types */
XinZhangMS 0:f7f1f0d76dd6 384 for (something = reflectedData->reflectedData; something != NULL; something = something->next)
XinZhangMS 0:f7f1f0d76dd6 385 {
XinZhangMS 0:f7f1f0d76dd6 386 if (something->type == REFLECTION_MODEL_TYPE)
XinZhangMS 0:f7f1f0d76dd6 387 {
XinZhangMS 0:f7f1f0d76dd6 388 if (Schema_CreateModelType(schemaHandle, something->what.model.name) == NULL)
XinZhangMS 0:f7f1f0d76dd6 389 {
XinZhangMS 0:f7f1f0d76dd6 390 /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
XinZhangMS 0:f7f1f0d76dd6 391 result = CODEFIRST_SCHEMA_ERROR;
XinZhangMS 0:f7f1f0d76dd6 392 LogError("create model failed %s", ENUM_TO_STRING(CODEFIRST_RESULT, result));
XinZhangMS 0:f7f1f0d76dd6 393 goto out;
XinZhangMS 0:f7f1f0d76dd6 394 }
XinZhangMS 0:f7f1f0d76dd6 395 }
XinZhangMS 0:f7f1f0d76dd6 396 }
XinZhangMS 0:f7f1f0d76dd6 397
XinZhangMS 0:f7f1f0d76dd6 398 for (something = reflectedData->reflectedData; something != NULL; something = something->next)
XinZhangMS 0:f7f1f0d76dd6 399 {
XinZhangMS 0:f7f1f0d76dd6 400 if (something->type == REFLECTION_MODEL_TYPE)
XinZhangMS 0:f7f1f0d76dd6 401 {
XinZhangMS 0:f7f1f0d76dd6 402 result = buildModel(schemaHandle, reflectedData, something);
XinZhangMS 0:f7f1f0d76dd6 403 if (result != CODEFIRST_OK)
XinZhangMS 0:f7f1f0d76dd6 404 {
XinZhangMS 0:f7f1f0d76dd6 405 break;
XinZhangMS 0:f7f1f0d76dd6 406 }
XinZhangMS 0:f7f1f0d76dd6 407 }
XinZhangMS 0:f7f1f0d76dd6 408 }
XinZhangMS 0:f7f1f0d76dd6 409
XinZhangMS 0:f7f1f0d76dd6 410 out:
XinZhangMS 0:f7f1f0d76dd6 411 return result;
XinZhangMS 0:f7f1f0d76dd6 412 }
XinZhangMS 0:f7f1f0d76dd6 413
XinZhangMS 0:f7f1f0d76dd6 414 static CODEFIRST_RESULT CodeFirst_Init_impl(const char* overrideSchemaNamespace, bool calledFromCodeFirst_Init)
XinZhangMS 0:f7f1f0d76dd6 415 {
XinZhangMS 0:f7f1f0d76dd6 416 /*shall build the default EntityContainer*/
XinZhangMS 0:f7f1f0d76dd6 417 CODEFIRST_RESULT result;
XinZhangMS 0:f7f1f0d76dd6 418
XinZhangMS 0:f7f1f0d76dd6 419 if (g_state != CODEFIRST_STATE_NOT_INIT)
XinZhangMS 0:f7f1f0d76dd6 420 {
XinZhangMS 0:f7f1f0d76dd6 421 /*Codes_SRS_CODEFIRST_99_003:[ If the module is already initialized, the initialization shall fail and the return value shall be CODEFIRST_ALREADY_INIT.]*/
XinZhangMS 0:f7f1f0d76dd6 422 result = CODEFIRST_ALREADY_INIT;
XinZhangMS 0:f7f1f0d76dd6 423 if(calledFromCodeFirst_Init) /*do not log this error when APIs attempt lazy init*/
XinZhangMS 0:f7f1f0d76dd6 424 {
XinZhangMS 0:f7f1f0d76dd6 425 LogError("CodeFirst was already init %s", ENUM_TO_STRING(CODEFIRST_RESULT, result));
XinZhangMS 0:f7f1f0d76dd6 426 }
XinZhangMS 0:f7f1f0d76dd6 427 }
XinZhangMS 0:f7f1f0d76dd6 428 else
XinZhangMS 0:f7f1f0d76dd6 429 {
XinZhangMS 0:f7f1f0d76dd6 430 g_DeviceCount = 0;
XinZhangMS 0:f7f1f0d76dd6 431 g_OverrideSchemaNamespace = overrideSchemaNamespace;
XinZhangMS 0:f7f1f0d76dd6 432 g_Devices = NULL;
XinZhangMS 0:f7f1f0d76dd6 433
XinZhangMS 0:f7f1f0d76dd6 434 /*Codes_SRS_CODEFIRST_99_002:[ CodeFirst_Init shall initialize the CodeFirst module. If initialization is successful, it shall return CODEFIRST_OK.]*/
XinZhangMS 0:f7f1f0d76dd6 435 g_state = calledFromCodeFirst_Init? CODEFIRST_STATE_INIT_BY_INIT: CODEFIRST_STATE_INIT_BY_API;
XinZhangMS 0:f7f1f0d76dd6 436 result = CODEFIRST_OK;
XinZhangMS 0:f7f1f0d76dd6 437 }
XinZhangMS 0:f7f1f0d76dd6 438 return result;
XinZhangMS 0:f7f1f0d76dd6 439 }
XinZhangMS 0:f7f1f0d76dd6 440
XinZhangMS 0:f7f1f0d76dd6 441 /*Codes_SRS_CODEFIRST_99_002:[ CodeFirst_Init shall initialize the CodeFirst module. If initialization is successful, it shall return CODEFIRST_OK.]*/
XinZhangMS 0:f7f1f0d76dd6 442 CODEFIRST_RESULT CodeFirst_Init(const char* overrideSchemaNamespace)
XinZhangMS 0:f7f1f0d76dd6 443 {
XinZhangMS 0:f7f1f0d76dd6 444 return CodeFirst_Init_impl(overrideSchemaNamespace, true);
XinZhangMS 0:f7f1f0d76dd6 445 }
XinZhangMS 0:f7f1f0d76dd6 446
XinZhangMS 0:f7f1f0d76dd6 447 void CodeFirst_Deinit(void)
XinZhangMS 0:f7f1f0d76dd6 448 {
XinZhangMS 0:f7f1f0d76dd6 449 /*Codes_SRS_CODEFIRST_99_006:[If the module is not previously initialed, CodeFirst_Deinit shall do nothing.]*/
XinZhangMS 0:f7f1f0d76dd6 450 if (g_state != CODEFIRST_STATE_INIT_BY_INIT)
XinZhangMS 0:f7f1f0d76dd6 451 {
XinZhangMS 0:f7f1f0d76dd6 452 LogError("CodeFirst_Deinit called when CodeFirst was not initialized by CodeFirst_Init");
XinZhangMS 0:f7f1f0d76dd6 453 }
XinZhangMS 0:f7f1f0d76dd6 454 else
XinZhangMS 0:f7f1f0d76dd6 455 {
XinZhangMS 0:f7f1f0d76dd6 456 size_t i;
XinZhangMS 0:f7f1f0d76dd6 457
XinZhangMS 0:f7f1f0d76dd6 458 /*Codes_SRS_CODEFIRST_99_005:[ CodeFirst_Deinit shall deinitialize the module, freeing all the resources and placing the module in an uninitialized state.]*/
XinZhangMS 0:f7f1f0d76dd6 459 for (i = 0; i < g_DeviceCount; i++)
XinZhangMS 0:f7f1f0d76dd6 460 {
XinZhangMS 0:f7f1f0d76dd6 461 DestroyDevice(g_Devices[i]);
XinZhangMS 0:f7f1f0d76dd6 462 }
XinZhangMS 0:f7f1f0d76dd6 463
XinZhangMS 0:f7f1f0d76dd6 464 free(g_Devices);
XinZhangMS 0:f7f1f0d76dd6 465 g_Devices = NULL;
XinZhangMS 0:f7f1f0d76dd6 466 g_DeviceCount = 0;
XinZhangMS 0:f7f1f0d76dd6 467
XinZhangMS 0:f7f1f0d76dd6 468 g_state = CODEFIRST_STATE_NOT_INIT;
XinZhangMS 0:f7f1f0d76dd6 469 }
XinZhangMS 0:f7f1f0d76dd6 470 }
XinZhangMS 0:f7f1f0d76dd6 471
XinZhangMS 0:f7f1f0d76dd6 472 static const REFLECTED_SOMETHING* FindModelInCodeFirstMetadata(const REFLECTED_SOMETHING* reflectedData, const char* modelName)
XinZhangMS 0:f7f1f0d76dd6 473 {
XinZhangMS 0:f7f1f0d76dd6 474 const REFLECTED_SOMETHING* result;
XinZhangMS 0:f7f1f0d76dd6 475
XinZhangMS 0:f7f1f0d76dd6 476 for (result = reflectedData; result != NULL; result = result->next)
XinZhangMS 0:f7f1f0d76dd6 477 {
XinZhangMS 0:f7f1f0d76dd6 478 if ((result->type == REFLECTION_MODEL_TYPE) &&
XinZhangMS 0:f7f1f0d76dd6 479 (strcmp(result->what.model.name, modelName) == 0))
XinZhangMS 0:f7f1f0d76dd6 480 {
XinZhangMS 0:f7f1f0d76dd6 481 /* found model type */
XinZhangMS 0:f7f1f0d76dd6 482 break;
XinZhangMS 0:f7f1f0d76dd6 483 }
XinZhangMS 0:f7f1f0d76dd6 484 }
XinZhangMS 0:f7f1f0d76dd6 485
XinZhangMS 0:f7f1f0d76dd6 486 return result;
XinZhangMS 0:f7f1f0d76dd6 487 }
XinZhangMS 0:f7f1f0d76dd6 488
XinZhangMS 0:f7f1f0d76dd6 489 static const REFLECTED_SOMETHING* FindChildModelInCodeFirstMetadata(const REFLECTED_SOMETHING* reflectedData, const REFLECTED_SOMETHING* startModel, const char* relativePath, size_t* offset)
XinZhangMS 0:f7f1f0d76dd6 490 {
XinZhangMS 0:f7f1f0d76dd6 491 const REFLECTED_SOMETHING* result = startModel;
XinZhangMS 0:f7f1f0d76dd6 492 *offset = 0;
XinZhangMS 0:f7f1f0d76dd6 493
XinZhangMS 0:f7f1f0d76dd6 494 /* Codes_SRS_CODEFIRST_99_139:[If the relativeActionPath is empty then the action shall be looked up in the device model.] */
XinZhangMS 0:f7f1f0d76dd6 495 while ((*relativePath != 0) && (result != NULL))
XinZhangMS 0:f7f1f0d76dd6 496 {
XinZhangMS 0:f7f1f0d76dd6 497 /* Codes_SRS_CODEFIRST_99_142:[The relativeActionPath argument shall be in the format "childModel1/childModel2/.../childModelN".] */
XinZhangMS 0:f7f1f0d76dd6 498 const REFLECTED_SOMETHING* childModelProperty;
XinZhangMS 0:f7f1f0d76dd6 499 size_t propertyNameLength;
XinZhangMS 0:f7f1f0d76dd6 500 const char* slashPos = strchr(relativePath, '/');
XinZhangMS 0:f7f1f0d76dd6 501 if (slashPos == NULL)
XinZhangMS 0:f7f1f0d76dd6 502 {
XinZhangMS 0:f7f1f0d76dd6 503 slashPos = &relativePath[strlen(relativePath)];
XinZhangMS 0:f7f1f0d76dd6 504 }
XinZhangMS 0:f7f1f0d76dd6 505
XinZhangMS 0:f7f1f0d76dd6 506 propertyNameLength = slashPos - relativePath;
XinZhangMS 0:f7f1f0d76dd6 507
XinZhangMS 0:f7f1f0d76dd6 508 for (childModelProperty = reflectedData; childModelProperty != NULL; childModelProperty = childModelProperty->next)
XinZhangMS 0:f7f1f0d76dd6 509 {
XinZhangMS 0:f7f1f0d76dd6 510 if ((childModelProperty->type == REFLECTION_PROPERTY_TYPE) &&
XinZhangMS 0:f7f1f0d76dd6 511 (strcmp(childModelProperty->what.property.modelName, result->what.model.name) == 0) &&
XinZhangMS 0:f7f1f0d76dd6 512 (strncmp(childModelProperty->what.property.name, relativePath, propertyNameLength) == 0) &&
XinZhangMS 0:f7f1f0d76dd6 513 (strlen(childModelProperty->what.property.name) == propertyNameLength))
XinZhangMS 0:f7f1f0d76dd6 514 {
XinZhangMS 0:f7f1f0d76dd6 515 /* property found, now let's find the model */
XinZhangMS 0:f7f1f0d76dd6 516 /* Codes_SRS_CODEFIRST_99_140:[CodeFirst_InvokeAction shall pass to the action wrapper that it calls a pointer to the model where the action is defined.] */
XinZhangMS 0:f7f1f0d76dd6 517 *offset += childModelProperty->what.property.offset;
XinZhangMS 0:f7f1f0d76dd6 518 break;
XinZhangMS 0:f7f1f0d76dd6 519 }
XinZhangMS 0:f7f1f0d76dd6 520 }
XinZhangMS 0:f7f1f0d76dd6 521
XinZhangMS 0:f7f1f0d76dd6 522 if (childModelProperty == NULL)
XinZhangMS 0:f7f1f0d76dd6 523 {
XinZhangMS 0:f7f1f0d76dd6 524 /* not found */
XinZhangMS 0:f7f1f0d76dd6 525 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 526 }
XinZhangMS 0:f7f1f0d76dd6 527 else
XinZhangMS 0:f7f1f0d76dd6 528 {
XinZhangMS 0:f7f1f0d76dd6 529 result = FindModelInCodeFirstMetadata(reflectedData, childModelProperty->what.property.type);
XinZhangMS 0:f7f1f0d76dd6 530 }
XinZhangMS 0:f7f1f0d76dd6 531
XinZhangMS 0:f7f1f0d76dd6 532 relativePath = slashPos;
XinZhangMS 0:f7f1f0d76dd6 533 }
XinZhangMS 0:f7f1f0d76dd6 534
XinZhangMS 0:f7f1f0d76dd6 535 return result;
XinZhangMS 0:f7f1f0d76dd6 536 }
XinZhangMS 0:f7f1f0d76dd6 537
XinZhangMS 0:f7f1f0d76dd6 538 EXECUTE_COMMAND_RESULT CodeFirst_InvokeAction(DEVICE_HANDLE deviceHandle, void* callbackUserContext, const char* relativeActionPath, const char* actionName, size_t parameterCount, const AGENT_DATA_TYPE* parameterValues)
XinZhangMS 0:f7f1f0d76dd6 539 {
XinZhangMS 0:f7f1f0d76dd6 540 EXECUTE_COMMAND_RESULT result;
XinZhangMS 0:f7f1f0d76dd6 541 DEVICE_HEADER_DATA* deviceHeader = (DEVICE_HEADER_DATA*)callbackUserContext;
XinZhangMS 0:f7f1f0d76dd6 542
XinZhangMS 0:f7f1f0d76dd6 543 /*Codes_SRS_CODEFIRST_99_068:[ If the function is called before CodeFirst is initialized then EXECUTE_COMMAND_ERROR shall be returned.] */
XinZhangMS 0:f7f1f0d76dd6 544 if (g_state == CODEFIRST_STATE_NOT_INIT)
XinZhangMS 0:f7f1f0d76dd6 545 {
XinZhangMS 0:f7f1f0d76dd6 546 result = EXECUTE_COMMAND_ERROR;
XinZhangMS 0:f7f1f0d76dd6 547 LogError("CodeFirst_InvokeAction called before init has an error %s ", ENUM_TO_STRING(EXECUTE_COMMAND_RESULT, result));
XinZhangMS 0:f7f1f0d76dd6 548 }
XinZhangMS 0:f7f1f0d76dd6 549 /*Codes_SRS_CODEFIRST_99_066:[ If actionName, relativeActionPath or deviceHandle is NULL then EXECUTE_COMMAND_ERROR shall be returned*/
XinZhangMS 0:f7f1f0d76dd6 550 else if ((actionName == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 551 (deviceHandle == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 552 (relativeActionPath == NULL))
XinZhangMS 0:f7f1f0d76dd6 553 {
XinZhangMS 0:f7f1f0d76dd6 554 result = EXECUTE_COMMAND_ERROR;
XinZhangMS 0:f7f1f0d76dd6 555 LogError("action Name is NULL %s ", ENUM_TO_STRING(EXECUTE_COMMAND_RESULT, result));
XinZhangMS 0:f7f1f0d76dd6 556 }
XinZhangMS 0:f7f1f0d76dd6 557 /*Codes_SRS_CODEFIRST_99_067:[ If parameterCount is greater than zero and parameterValues is NULL then EXECUTE_COMMAND_ERROR shall be returned.]*/
XinZhangMS 0:f7f1f0d76dd6 558 else if ((parameterCount > 0) && (parameterValues == NULL))
XinZhangMS 0:f7f1f0d76dd6 559 {
XinZhangMS 0:f7f1f0d76dd6 560 result = EXECUTE_COMMAND_ERROR;
XinZhangMS 0:f7f1f0d76dd6 561 LogError("parameterValues error %s ", ENUM_TO_STRING(EXECUTE_COMMAND_RESULT, result));
XinZhangMS 0:f7f1f0d76dd6 562 }
XinZhangMS 0:f7f1f0d76dd6 563 else
XinZhangMS 0:f7f1f0d76dd6 564 {
XinZhangMS 0:f7f1f0d76dd6 565 const REFLECTED_SOMETHING* something;
XinZhangMS 0:f7f1f0d76dd6 566 const REFLECTED_SOMETHING* childModel;
XinZhangMS 0:f7f1f0d76dd6 567 const char* modelName;
XinZhangMS 0:f7f1f0d76dd6 568 size_t offset;
XinZhangMS 0:f7f1f0d76dd6 569
XinZhangMS 0:f7f1f0d76dd6 570 modelName = Schema_GetModelName(deviceHeader->ModelHandle);
XinZhangMS 0:f7f1f0d76dd6 571
XinZhangMS 0:f7f1f0d76dd6 572 if (((childModel = FindModelInCodeFirstMetadata(deviceHeader->ReflectedData->reflectedData, modelName)) == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 573 /* Codes_SRS_CODEFIRST_99_138:[The relativeActionPath argument shall be used by CodeFirst_InvokeAction to find the child model where the action is declared.] */
XinZhangMS 0:f7f1f0d76dd6 574 ((childModel = FindChildModelInCodeFirstMetadata(deviceHeader->ReflectedData->reflectedData, childModel, relativeActionPath, &offset)) == NULL))
XinZhangMS 0:f7f1f0d76dd6 575 {
XinZhangMS 0:f7f1f0d76dd6 576 /*Codes_SRS_CODEFIRST_99_141:[If a child model specified in the relativeActionPath argument cannot be found by CodeFirst_InvokeAction, it shall return EXECUTE_COMMAND_ERROR.] */
XinZhangMS 0:f7f1f0d76dd6 577 result = EXECUTE_COMMAND_ERROR;
XinZhangMS 0:f7f1f0d76dd6 578 LogError("action %s was not found %s ", actionName, ENUM_TO_STRING(EXECUTE_COMMAND_RESULT, result));
XinZhangMS 0:f7f1f0d76dd6 579 }
XinZhangMS 0:f7f1f0d76dd6 580 else
XinZhangMS 0:f7f1f0d76dd6 581 {
XinZhangMS 0:f7f1f0d76dd6 582 /* Codes_SRS_CODEFIRST_99_062:[ When CodeFirst_InvokeAction is called it shall look through the codefirst metadata associated with a specific device for a previously declared action (function) named actionName.]*/
XinZhangMS 0:f7f1f0d76dd6 583 /* Codes_SRS_CODEFIRST_99_078:[If such a function is not found then the function shall return EXECUTE_COMMAND_ERROR.]*/
XinZhangMS 0:f7f1f0d76dd6 584 result = EXECUTE_COMMAND_ERROR;
XinZhangMS 0:f7f1f0d76dd6 585 for (something = deviceHeader->ReflectedData->reflectedData; something != NULL; something = something->next)
XinZhangMS 0:f7f1f0d76dd6 586 {
XinZhangMS 0:f7f1f0d76dd6 587 if ((something->type == REFLECTION_ACTION_TYPE) &&
XinZhangMS 0:f7f1f0d76dd6 588 (strcmp(actionName, something->what.action.name) == 0) &&
XinZhangMS 0:f7f1f0d76dd6 589 (strcmp(childModel->what.model.name, something->what.action.modelName) == 0))
XinZhangMS 0:f7f1f0d76dd6 590 {
XinZhangMS 0:f7f1f0d76dd6 591 /*Codes_SRS_CODEFIRST_99_063:[ If the function is found, then CodeFirst shall call the wrapper of the found function inside the data provider. The wrapper is linked in the reflected data to the function name. The wrapper shall be called with the same arguments as CodeFirst_InvokeAction has been called.]*/
XinZhangMS 0:f7f1f0d76dd6 592 /*Codes_SRS_CODEFIRST_99_064:[ If the wrapper call succeeds then CODEFIRST_OK shall be returned. ]*/
XinZhangMS 0:f7f1f0d76dd6 593 /*Codes_SRS_CODEFIRST_99_065:[ For all the other return values CODEFIRST_ACTION_EXECUTION_ERROR shall be returned.]*/
XinZhangMS 0:f7f1f0d76dd6 594 /* Codes_SRS_CODEFIRST_99_140:[CodeFirst_InvokeAction shall pass to the action wrapper that it calls a pointer to the model where the action is defined.] */
XinZhangMS 0:f7f1f0d76dd6 595 /*Codes_SRS_CODEFIRST_02_013: [The wrapper's return value shall be returned.]*/
XinZhangMS 0:f7f1f0d76dd6 596 result = something->what.action.wrapper(deviceHeader->data + offset, parameterCount, parameterValues);
XinZhangMS 0:f7f1f0d76dd6 597 break;
XinZhangMS 0:f7f1f0d76dd6 598 }
XinZhangMS 0:f7f1f0d76dd6 599 }
XinZhangMS 0:f7f1f0d76dd6 600 }
XinZhangMS 0:f7f1f0d76dd6 601 }
XinZhangMS 0:f7f1f0d76dd6 602
XinZhangMS 0:f7f1f0d76dd6 603 if (result == EXECUTE_COMMAND_ERROR)
XinZhangMS 0:f7f1f0d76dd6 604 {
XinZhangMS 0:f7f1f0d76dd6 605 LogError(" %s ", ENUM_TO_STRING(EXECUTE_COMMAND_RESULT, result));
XinZhangMS 0:f7f1f0d76dd6 606 }
XinZhangMS 0:f7f1f0d76dd6 607 return result;
XinZhangMS 0:f7f1f0d76dd6 608 }
XinZhangMS 0:f7f1f0d76dd6 609
XinZhangMS 0:f7f1f0d76dd6 610 METHODRETURN_HANDLE CodeFirst_InvokeMethod(DEVICE_HANDLE deviceHandle, void* callbackUserContext, const char* relativeMethodPath, const char* methodName, size_t parameterCount, const AGENT_DATA_TYPE* parameterValues)
XinZhangMS 0:f7f1f0d76dd6 611 {
XinZhangMS 0:f7f1f0d76dd6 612 METHODRETURN_HANDLE result;
XinZhangMS 0:f7f1f0d76dd6 613 DEVICE_HEADER_DATA* deviceHeader = (DEVICE_HEADER_DATA*)callbackUserContext;
XinZhangMS 0:f7f1f0d76dd6 614
XinZhangMS 0:f7f1f0d76dd6 615 if (g_state == CODEFIRST_STATE_NOT_INIT)
XinZhangMS 0:f7f1f0d76dd6 616 {
XinZhangMS 0:f7f1f0d76dd6 617 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 618 LogError("CodeFirst_InvokeMethod called before CodeFirst_Init");
XinZhangMS 0:f7f1f0d76dd6 619 }
XinZhangMS 0:f7f1f0d76dd6 620 else if ((methodName == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 621 (deviceHandle == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 622 (relativeMethodPath == NULL))
XinZhangMS 0:f7f1f0d76dd6 623 {
XinZhangMS 0:f7f1f0d76dd6 624 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 625 LogError("invalid args: DEVICE_HANDLE deviceHandle=%p, void* callbackUserContext=%p, const char* relativeMethodPath=%p, const char* methodName=%p, size_t parameterCount=%lu, const AGENT_DATA_TYPE* parameterValues=%p",
XinZhangMS 0:f7f1f0d76dd6 626 deviceHandle, callbackUserContext, relativeMethodPath, methodName, parameterCount, parameterValues);
XinZhangMS 0:f7f1f0d76dd6 627 }
XinZhangMS 0:f7f1f0d76dd6 628 else if ((parameterCount > 0) && (parameterValues == NULL))
XinZhangMS 0:f7f1f0d76dd6 629 {
XinZhangMS 0:f7f1f0d76dd6 630 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 631 LogError("parameterValues error ");
XinZhangMS 0:f7f1f0d76dd6 632 }
XinZhangMS 0:f7f1f0d76dd6 633 else
XinZhangMS 0:f7f1f0d76dd6 634 {
XinZhangMS 0:f7f1f0d76dd6 635 const REFLECTED_SOMETHING* something;
XinZhangMS 0:f7f1f0d76dd6 636 const REFLECTED_SOMETHING* childModel;
XinZhangMS 0:f7f1f0d76dd6 637 const char* modelName;
XinZhangMS 0:f7f1f0d76dd6 638 size_t offset;
XinZhangMS 0:f7f1f0d76dd6 639
XinZhangMS 0:f7f1f0d76dd6 640 modelName = Schema_GetModelName(deviceHeader->ModelHandle);
XinZhangMS 0:f7f1f0d76dd6 641
XinZhangMS 0:f7f1f0d76dd6 642 if (((childModel = FindModelInCodeFirstMetadata(deviceHeader->ReflectedData->reflectedData, modelName)) == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 643 ((childModel = FindChildModelInCodeFirstMetadata(deviceHeader->ReflectedData->reflectedData, childModel, relativeMethodPath, &offset)) == NULL))
XinZhangMS 0:f7f1f0d76dd6 644 {
XinZhangMS 0:f7f1f0d76dd6 645 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 646 LogError("method %s was not found", methodName);
XinZhangMS 0:f7f1f0d76dd6 647 }
XinZhangMS 0:f7f1f0d76dd6 648 else
XinZhangMS 0:f7f1f0d76dd6 649 {
XinZhangMS 0:f7f1f0d76dd6 650 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 651 for (something = deviceHeader->ReflectedData->reflectedData; something != NULL; something = something->next)
XinZhangMS 0:f7f1f0d76dd6 652 {
XinZhangMS 0:f7f1f0d76dd6 653 if ((something->type == REFLECTION_METHOD_TYPE) &&
XinZhangMS 0:f7f1f0d76dd6 654 (strcmp(methodName, something->what.method.name) == 0) &&
XinZhangMS 0:f7f1f0d76dd6 655 (strcmp(childModel->what.model.name, something->what.method.modelName) == 0))
XinZhangMS 0:f7f1f0d76dd6 656 {
XinZhangMS 0:f7f1f0d76dd6 657 break; /*found...*/
XinZhangMS 0:f7f1f0d76dd6 658 }
XinZhangMS 0:f7f1f0d76dd6 659 }
XinZhangMS 0:f7f1f0d76dd6 660
XinZhangMS 0:f7f1f0d76dd6 661 if (something == NULL)
XinZhangMS 0:f7f1f0d76dd6 662 {
XinZhangMS 0:f7f1f0d76dd6 663 LogError("method \"%s\" not found", methodName);
XinZhangMS 0:f7f1f0d76dd6 664 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 665 }
XinZhangMS 0:f7f1f0d76dd6 666 else
XinZhangMS 0:f7f1f0d76dd6 667 {
XinZhangMS 0:f7f1f0d76dd6 668 result = something->what.method.wrapper(deviceHeader->data + offset, parameterCount, parameterValues);
XinZhangMS 0:f7f1f0d76dd6 669 if (result == NULL)
XinZhangMS 0:f7f1f0d76dd6 670 {
XinZhangMS 0:f7f1f0d76dd6 671 LogError("method \"%s\" execution error (returned NULL)", methodName);
XinZhangMS 0:f7f1f0d76dd6 672 }
XinZhangMS 0:f7f1f0d76dd6 673 }
XinZhangMS 0:f7f1f0d76dd6 674 }
XinZhangMS 0:f7f1f0d76dd6 675 }
XinZhangMS 0:f7f1f0d76dd6 676 return result;
XinZhangMS 0:f7f1f0d76dd6 677 }
XinZhangMS 0:f7f1f0d76dd6 678
XinZhangMS 0:f7f1f0d76dd6 679
XinZhangMS 0:f7f1f0d76dd6 680 /* Codes_SRS_CODEFIRST_99_002:[ CodeFirst_RegisterSchema shall create the schema information and give it to the Schema module for one schema, identified by the metadata argument. On success, it shall return a handle to the schema.] */
XinZhangMS 0:f7f1f0d76dd6 681 SCHEMA_HANDLE CodeFirst_RegisterSchema(const char* schemaNamespace, const REFLECTED_DATA_FROM_DATAPROVIDER* metadata)
XinZhangMS 0:f7f1f0d76dd6 682 {
XinZhangMS 0:f7f1f0d76dd6 683 SCHEMA_HANDLE result;
XinZhangMS 0:f7f1f0d76dd6 684 /*Codes_SRS_CODEFIRST_02_048: [ If schemaNamespace is NULL then CodeFirst_RegisterSchema shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 685 /*Codes_SRS_CODEFIRST_02_049: [ If metadata is NULL then CodeFirst_RegisterSchema shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 686 if (
XinZhangMS 0:f7f1f0d76dd6 687 (schemaNamespace == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 688 (metadata == NULL)
XinZhangMS 0:f7f1f0d76dd6 689 )
XinZhangMS 0:f7f1f0d76dd6 690 {
XinZhangMS 0:f7f1f0d76dd6 691 LogError("invalid arg const char* schemaNamespace=%p, const REFLECTED_DATA_FROM_DATAPROVIDER* metadata=%p", schemaNamespace, metadata);
XinZhangMS 0:f7f1f0d76dd6 692 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 693 }
XinZhangMS 0:f7f1f0d76dd6 694 else
XinZhangMS 0:f7f1f0d76dd6 695 {
XinZhangMS 0:f7f1f0d76dd6 696 if (g_OverrideSchemaNamespace != NULL)
XinZhangMS 0:f7f1f0d76dd6 697 {
XinZhangMS 0:f7f1f0d76dd6 698 schemaNamespace = g_OverrideSchemaNamespace;
XinZhangMS 0:f7f1f0d76dd6 699 }
XinZhangMS 0:f7f1f0d76dd6 700
XinZhangMS 0:f7f1f0d76dd6 701 /* Codes_SRS_CODEFIRST_99_121:[If the schema has already been registered, CodeFirst_RegisterSchema shall return its handle.] */
XinZhangMS 0:f7f1f0d76dd6 702 result = Schema_GetSchemaByNamespace(schemaNamespace);
XinZhangMS 0:f7f1f0d76dd6 703 if (result == NULL)
XinZhangMS 0:f7f1f0d76dd6 704 {
XinZhangMS 0:f7f1f0d76dd6 705 if ((result = Schema_Create(schemaNamespace, (void*)metadata)) == NULL)
XinZhangMS 0:f7f1f0d76dd6 706 {
XinZhangMS 0:f7f1f0d76dd6 707 /* Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CodeFirst_RegisterSchema shall return NULL.] */
XinZhangMS 0:f7f1f0d76dd6 708 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 709 LogError("schema init failed %s", ENUM_TO_STRING(CODEFIRST_RESULT, CODEFIRST_SCHEMA_ERROR));
XinZhangMS 0:f7f1f0d76dd6 710 }
XinZhangMS 0:f7f1f0d76dd6 711 else
XinZhangMS 0:f7f1f0d76dd6 712 {
XinZhangMS 0:f7f1f0d76dd6 713 if ((buildStructTypes(result, metadata) != CODEFIRST_OK) ||
XinZhangMS 0:f7f1f0d76dd6 714 (buildModelTypes(result, metadata) != CODEFIRST_OK))
XinZhangMS 0:f7f1f0d76dd6 715 {
XinZhangMS 0:f7f1f0d76dd6 716 Schema_Destroy(result);
XinZhangMS 0:f7f1f0d76dd6 717 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 718 }
XinZhangMS 0:f7f1f0d76dd6 719 else
XinZhangMS 0:f7f1f0d76dd6 720 {
XinZhangMS 0:f7f1f0d76dd6 721 /* do nothing, everything is OK */
XinZhangMS 0:f7f1f0d76dd6 722 }
XinZhangMS 0:f7f1f0d76dd6 723 }
XinZhangMS 0:f7f1f0d76dd6 724 }
XinZhangMS 0:f7f1f0d76dd6 725 }
XinZhangMS 0:f7f1f0d76dd6 726
XinZhangMS 0:f7f1f0d76dd6 727 return result;
XinZhangMS 0:f7f1f0d76dd6 728 }
XinZhangMS 0:f7f1f0d76dd6 729
XinZhangMS 0:f7f1f0d76dd6 730 AGENT_DATA_TYPE_TYPE CodeFirst_GetPrimitiveType(const char* typeName)
XinZhangMS 0:f7f1f0d76dd6 731 {
XinZhangMS 0:f7f1f0d76dd6 732 #ifndef NO_FLOATS
XinZhangMS 0:f7f1f0d76dd6 733 if (strcmp(typeName, "double") == 0)
XinZhangMS 0:f7f1f0d76dd6 734 {
XinZhangMS 0:f7f1f0d76dd6 735 return EDM_DOUBLE_TYPE;
XinZhangMS 0:f7f1f0d76dd6 736 }
XinZhangMS 0:f7f1f0d76dd6 737 else if (strcmp(typeName, "float") == 0)
XinZhangMS 0:f7f1f0d76dd6 738 {
XinZhangMS 0:f7f1f0d76dd6 739 return EDM_SINGLE_TYPE;
XinZhangMS 0:f7f1f0d76dd6 740 }
XinZhangMS 0:f7f1f0d76dd6 741 else
XinZhangMS 0:f7f1f0d76dd6 742 #endif
XinZhangMS 0:f7f1f0d76dd6 743 if (strcmp(typeName, "int") == 0)
XinZhangMS 0:f7f1f0d76dd6 744 {
XinZhangMS 0:f7f1f0d76dd6 745 return EDM_INT32_TYPE;
XinZhangMS 0:f7f1f0d76dd6 746 }
XinZhangMS 0:f7f1f0d76dd6 747 else if (strcmp(typeName, "long") == 0)
XinZhangMS 0:f7f1f0d76dd6 748 {
XinZhangMS 0:f7f1f0d76dd6 749 return EDM_INT64_TYPE;
XinZhangMS 0:f7f1f0d76dd6 750 }
XinZhangMS 0:f7f1f0d76dd6 751 else if (strcmp(typeName, "int8_t") == 0)
XinZhangMS 0:f7f1f0d76dd6 752 {
XinZhangMS 0:f7f1f0d76dd6 753 return EDM_SBYTE_TYPE;
XinZhangMS 0:f7f1f0d76dd6 754 }
XinZhangMS 0:f7f1f0d76dd6 755 else if (strcmp(typeName, "uint8_t") == 0)
XinZhangMS 0:f7f1f0d76dd6 756 {
XinZhangMS 0:f7f1f0d76dd6 757 return EDM_BYTE_TYPE;
XinZhangMS 0:f7f1f0d76dd6 758 }
XinZhangMS 0:f7f1f0d76dd6 759 else if (strcmp(typeName, "int16_t") == 0)
XinZhangMS 0:f7f1f0d76dd6 760 {
XinZhangMS 0:f7f1f0d76dd6 761 return EDM_INT16_TYPE;
XinZhangMS 0:f7f1f0d76dd6 762 }
XinZhangMS 0:f7f1f0d76dd6 763 else if (strcmp(typeName, "int32_t") == 0)
XinZhangMS 0:f7f1f0d76dd6 764 {
XinZhangMS 0:f7f1f0d76dd6 765 return EDM_INT32_TYPE;
XinZhangMS 0:f7f1f0d76dd6 766 }
XinZhangMS 0:f7f1f0d76dd6 767 else if (strcmp(typeName, "int64_t") == 0)
XinZhangMS 0:f7f1f0d76dd6 768 {
XinZhangMS 0:f7f1f0d76dd6 769 return EDM_INT64_TYPE;
XinZhangMS 0:f7f1f0d76dd6 770 }
XinZhangMS 0:f7f1f0d76dd6 771 else if (
XinZhangMS 0:f7f1f0d76dd6 772 (strcmp(typeName, "_Bool") == 0) ||
XinZhangMS 0:f7f1f0d76dd6 773 (strcmp(typeName, "bool") == 0)
XinZhangMS 0:f7f1f0d76dd6 774 )
XinZhangMS 0:f7f1f0d76dd6 775 {
XinZhangMS 0:f7f1f0d76dd6 776 return EDM_BOOLEAN_TYPE;
XinZhangMS 0:f7f1f0d76dd6 777 }
XinZhangMS 0:f7f1f0d76dd6 778 else if (strcmp(typeName, "ascii_char_ptr") == 0)
XinZhangMS 0:f7f1f0d76dd6 779 {
XinZhangMS 0:f7f1f0d76dd6 780 return EDM_STRING_TYPE;
XinZhangMS 0:f7f1f0d76dd6 781 }
XinZhangMS 0:f7f1f0d76dd6 782 else if (strcmp(typeName, "ascii_char_ptr_no_quotes") == 0)
XinZhangMS 0:f7f1f0d76dd6 783 {
XinZhangMS 0:f7f1f0d76dd6 784 return EDM_STRING_NO_QUOTES_TYPE;
XinZhangMS 0:f7f1f0d76dd6 785 }
XinZhangMS 0:f7f1f0d76dd6 786 else if (strcmp(typeName, "EDM_DATE_TIME_OFFSET") == 0)
XinZhangMS 0:f7f1f0d76dd6 787 {
XinZhangMS 0:f7f1f0d76dd6 788 return EDM_DATE_TIME_OFFSET_TYPE;
XinZhangMS 0:f7f1f0d76dd6 789 }
XinZhangMS 0:f7f1f0d76dd6 790 else if (strcmp(typeName, "EDM_GUID") == 0)
XinZhangMS 0:f7f1f0d76dd6 791 {
XinZhangMS 0:f7f1f0d76dd6 792 return EDM_GUID_TYPE;
XinZhangMS 0:f7f1f0d76dd6 793 }
XinZhangMS 0:f7f1f0d76dd6 794 else if (strcmp(typeName, "EDM_BINARY") == 0)
XinZhangMS 0:f7f1f0d76dd6 795 {
XinZhangMS 0:f7f1f0d76dd6 796 return EDM_BINARY_TYPE;
XinZhangMS 0:f7f1f0d76dd6 797 }
XinZhangMS 0:f7f1f0d76dd6 798 else
XinZhangMS 0:f7f1f0d76dd6 799 {
XinZhangMS 0:f7f1f0d76dd6 800 return EDM_NO_TYPE;
XinZhangMS 0:f7f1f0d76dd6 801 }
XinZhangMS 0:f7f1f0d76dd6 802 }
XinZhangMS 0:f7f1f0d76dd6 803
XinZhangMS 0:f7f1f0d76dd6 804 static void initializeDesiredProperties(SCHEMA_MODEL_TYPE_HANDLE model, void* destination)
XinZhangMS 0:f7f1f0d76dd6 805 {
XinZhangMS 0:f7f1f0d76dd6 806 /*this function assumes that at the address given by destination there is an instance of a model*/
XinZhangMS 0:f7f1f0d76dd6 807 /*some constituents of the model need to be initialized - ascii_char_ptr for example should be set to NULL*/
XinZhangMS 0:f7f1f0d76dd6 808
XinZhangMS 0:f7f1f0d76dd6 809 size_t nDesiredProperties;
XinZhangMS 0:f7f1f0d76dd6 810 if (Schema_GetModelDesiredPropertyCount(model, &nDesiredProperties) != SCHEMA_OK)
XinZhangMS 0:f7f1f0d76dd6 811 {
XinZhangMS 0:f7f1f0d76dd6 812 LogError("unexpected error in Schema_GetModelDesiredPropertyCount");
XinZhangMS 0:f7f1f0d76dd6 813 }
XinZhangMS 0:f7f1f0d76dd6 814 else
XinZhangMS 0:f7f1f0d76dd6 815 {
XinZhangMS 0:f7f1f0d76dd6 816 size_t nProcessedDesiredProperties = 0;
XinZhangMS 0:f7f1f0d76dd6 817 for (size_t i = 0;i < nDesiredProperties;i++)
XinZhangMS 0:f7f1f0d76dd6 818 {
XinZhangMS 0:f7f1f0d76dd6 819 SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle = Schema_GetModelDesiredPropertyByIndex(model, i);
XinZhangMS 0:f7f1f0d76dd6 820 if (desiredPropertyHandle == NULL)
XinZhangMS 0:f7f1f0d76dd6 821 {
XinZhangMS 0:f7f1f0d76dd6 822 LogError("unexpected error in Schema_GetModelDesiredPropertyByIndex");
XinZhangMS 0:f7f1f0d76dd6 823 i = nDesiredProperties;
XinZhangMS 0:f7f1f0d76dd6 824 }
XinZhangMS 0:f7f1f0d76dd6 825 else
XinZhangMS 0:f7f1f0d76dd6 826 {
XinZhangMS 0:f7f1f0d76dd6 827 pfDesiredPropertyInitialize desiredPropertyInitialize = Schema_GetModelDesiredProperty_pfDesiredPropertyInitialize(desiredPropertyHandle);
XinZhangMS 0:f7f1f0d76dd6 828 if (desiredPropertyInitialize == NULL)
XinZhangMS 0:f7f1f0d76dd6 829 {
XinZhangMS 0:f7f1f0d76dd6 830 LogError("unexpected error in Schema_GetModelDesiredProperty_pfDesiredPropertyInitialize");
XinZhangMS 0:f7f1f0d76dd6 831 i = nDesiredProperties;
XinZhangMS 0:f7f1f0d76dd6 832 }
XinZhangMS 0:f7f1f0d76dd6 833 else
XinZhangMS 0:f7f1f0d76dd6 834 {
XinZhangMS 0:f7f1f0d76dd6 835 /*Codes_SRS_CODEFIRST_02_036: [ CodeFirst_CreateDevice shall initialize all the desired properties to their default values. ]*/
XinZhangMS 0:f7f1f0d76dd6 836 size_t offset = Schema_GetModelDesiredProperty_offset(desiredPropertyHandle);
XinZhangMS 0:f7f1f0d76dd6 837 desiredPropertyInitialize((char*)destination + offset);
XinZhangMS 0:f7f1f0d76dd6 838 nProcessedDesiredProperties++;
XinZhangMS 0:f7f1f0d76dd6 839 }
XinZhangMS 0:f7f1f0d76dd6 840 }
XinZhangMS 0:f7f1f0d76dd6 841 }
XinZhangMS 0:f7f1f0d76dd6 842
XinZhangMS 0:f7f1f0d76dd6 843 if (nDesiredProperties == nProcessedDesiredProperties)
XinZhangMS 0:f7f1f0d76dd6 844 {
XinZhangMS 0:f7f1f0d76dd6 845 /*recursively go in the model and initialize the other fields*/
XinZhangMS 0:f7f1f0d76dd6 846 size_t nModelInModel;
XinZhangMS 0:f7f1f0d76dd6 847 if (Schema_GetModelModelCount(model, &nModelInModel) != SCHEMA_OK)
XinZhangMS 0:f7f1f0d76dd6 848 {
XinZhangMS 0:f7f1f0d76dd6 849 LogError("unexpected error in Schema_GetModelModelCount");
XinZhangMS 0:f7f1f0d76dd6 850 }
XinZhangMS 0:f7f1f0d76dd6 851 else
XinZhangMS 0:f7f1f0d76dd6 852 {
XinZhangMS 0:f7f1f0d76dd6 853 size_t nProcessedModelInModel = 0;
XinZhangMS 0:f7f1f0d76dd6 854 for (size_t i = 0; i < nModelInModel;i++)
XinZhangMS 0:f7f1f0d76dd6 855 {
XinZhangMS 0:f7f1f0d76dd6 856 SCHEMA_MODEL_TYPE_HANDLE modelInModel = Schema_GetModelModelyByIndex(model, i);
XinZhangMS 0:f7f1f0d76dd6 857 if (modelInModel == NULL)
XinZhangMS 0:f7f1f0d76dd6 858 {
XinZhangMS 0:f7f1f0d76dd6 859 LogError("unexpected failure in Schema_GetModelModelyByIndex");
XinZhangMS 0:f7f1f0d76dd6 860 i = nModelInModel;
XinZhangMS 0:f7f1f0d76dd6 861 }
XinZhangMS 0:f7f1f0d76dd6 862 else
XinZhangMS 0:f7f1f0d76dd6 863 {
XinZhangMS 0:f7f1f0d76dd6 864 size_t offset = Schema_GetModelModelByIndex_Offset(model, i);
XinZhangMS 0:f7f1f0d76dd6 865 initializeDesiredProperties(modelInModel, (char*)destination + offset);
XinZhangMS 0:f7f1f0d76dd6 866 nProcessedModelInModel++;
XinZhangMS 0:f7f1f0d76dd6 867 }
XinZhangMS 0:f7f1f0d76dd6 868 }
XinZhangMS 0:f7f1f0d76dd6 869
XinZhangMS 0:f7f1f0d76dd6 870 if (nProcessedModelInModel == nModelInModel)
XinZhangMS 0:f7f1f0d76dd6 871 {
XinZhangMS 0:f7f1f0d76dd6 872 /*all is fine... */
XinZhangMS 0:f7f1f0d76dd6 873 }
XinZhangMS 0:f7f1f0d76dd6 874 }
XinZhangMS 0:f7f1f0d76dd6 875 }
XinZhangMS 0:f7f1f0d76dd6 876 }
XinZhangMS 0:f7f1f0d76dd6 877 }
XinZhangMS 0:f7f1f0d76dd6 878
XinZhangMS 0:f7f1f0d76dd6 879 /* Codes_SRS_CODEFIRST_99_079:[CodeFirst_CreateDevice shall create a device and allocate a memory block that should hold the device data.] */
XinZhangMS 0:f7f1f0d76dd6 880 void* CodeFirst_CreateDevice(SCHEMA_MODEL_TYPE_HANDLE model, const REFLECTED_DATA_FROM_DATAPROVIDER* metadata, size_t dataSize, bool includePropertyPath)
XinZhangMS 0:f7f1f0d76dd6 881 {
XinZhangMS 0:f7f1f0d76dd6 882 void* result;
XinZhangMS 0:f7f1f0d76dd6 883 DEVICE_HEADER_DATA* deviceHeader;
XinZhangMS 0:f7f1f0d76dd6 884
XinZhangMS 0:f7f1f0d76dd6 885 /* Codes_SRS_CODEFIRST_99_080:[If CodeFirst_CreateDevice is invoked with a NULL model, it shall return NULL.]*/
XinZhangMS 0:f7f1f0d76dd6 886 if (model == NULL)
XinZhangMS 0:f7f1f0d76dd6 887 {
XinZhangMS 0:f7f1f0d76dd6 888 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 889 LogError(" %s ", ENUM_TO_STRING(CODEFIRST_RESULT, CODEFIRST_INVALID_ARG));
XinZhangMS 0:f7f1f0d76dd6 890 }
XinZhangMS 0:f7f1f0d76dd6 891 else
XinZhangMS 0:f7f1f0d76dd6 892 {
XinZhangMS 0:f7f1f0d76dd6 893 /*Codes_SRS_CODEFIRST_02_037: [ CodeFirst_CreateDevice shall call CodeFirst_Init, passing NULL for overrideSchemaNamespace. ]*/
XinZhangMS 0:f7f1f0d76dd6 894 (void)CodeFirst_Init_impl(NULL, false); /*lazy init*/
XinZhangMS 0:f7f1f0d76dd6 895
XinZhangMS 0:f7f1f0d76dd6 896 if ((deviceHeader = (DEVICE_HEADER_DATA*)malloc(sizeof(DEVICE_HEADER_DATA))) == NULL)
XinZhangMS 0:f7f1f0d76dd6 897 {
XinZhangMS 0:f7f1f0d76dd6 898 /* Codes_SRS_CODEFIRST_99_102:[On any other errors, Device_Create shall return NULL.] */
XinZhangMS 0:f7f1f0d76dd6 899 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 900 LogError(" %s ", ENUM_TO_STRING(CODEFIRST_RESULT, CODEFIRST_ERROR));
XinZhangMS 0:f7f1f0d76dd6 901 }
XinZhangMS 0:f7f1f0d76dd6 902 /* Codes_SRS_CODEFIRST_99_081:[CodeFirst_CreateDevice shall use Device_Create to create a device handle.] */
XinZhangMS 0:f7f1f0d76dd6 903 /* Codes_SRS_CODEFIRST_99_082: [ CodeFirst_CreateDevice shall pass to Device_Create the function CodeFirst_InvokeAction, action callback argument and the CodeFirst_InvokeMethod ] */
XinZhangMS 0:f7f1f0d76dd6 904 else
XinZhangMS 0:f7f1f0d76dd6 905 {
XinZhangMS 0:f7f1f0d76dd6 906 if ((deviceHeader->data = malloc(dataSize)) == NULL)
XinZhangMS 0:f7f1f0d76dd6 907 {
XinZhangMS 0:f7f1f0d76dd6 908 free(deviceHeader);
XinZhangMS 0:f7f1f0d76dd6 909 deviceHeader = NULL;
XinZhangMS 0:f7f1f0d76dd6 910 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 911 LogError(" %s ", ENUM_TO_STRING(CODEFIRST_RESULT, CODEFIRST_ERROR));
XinZhangMS 0:f7f1f0d76dd6 912 }
XinZhangMS 0:f7f1f0d76dd6 913 else
XinZhangMS 0:f7f1f0d76dd6 914 {
XinZhangMS 0:f7f1f0d76dd6 915 DEVICE_HEADER_DATA** newDevices;
XinZhangMS 0:f7f1f0d76dd6 916
XinZhangMS 0:f7f1f0d76dd6 917 initializeDesiredProperties(model, deviceHeader->data);
XinZhangMS 0:f7f1f0d76dd6 918
XinZhangMS 0:f7f1f0d76dd6 919 if (Device_Create(model, CodeFirst_InvokeAction, deviceHeader, CodeFirst_InvokeMethod, deviceHeader,
XinZhangMS 0:f7f1f0d76dd6 920 includePropertyPath, &deviceHeader->DeviceHandle) != DEVICE_OK)
XinZhangMS 0:f7f1f0d76dd6 921 {
XinZhangMS 0:f7f1f0d76dd6 922 free(deviceHeader->data);
XinZhangMS 0:f7f1f0d76dd6 923 free(deviceHeader);
XinZhangMS 0:f7f1f0d76dd6 924
XinZhangMS 0:f7f1f0d76dd6 925 /* Codes_SRS_CODEFIRST_99_084:[If Device_Create fails, CodeFirst_CreateDevice shall return NULL.] */
XinZhangMS 0:f7f1f0d76dd6 926 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 927 LogError(" %s ", ENUM_TO_STRING(CODEFIRST_RESULT, CODEFIRST_DEVICE_FAILED));
XinZhangMS 0:f7f1f0d76dd6 928 }
XinZhangMS 0:f7f1f0d76dd6 929 else if ((newDevices = (DEVICE_HEADER_DATA**)realloc(g_Devices, sizeof(DEVICE_HEADER_DATA*) * (g_DeviceCount + 1))) == NULL)
XinZhangMS 0:f7f1f0d76dd6 930 {
XinZhangMS 0:f7f1f0d76dd6 931 Device_Destroy(deviceHeader->DeviceHandle);
XinZhangMS 0:f7f1f0d76dd6 932 free(deviceHeader->data);
XinZhangMS 0:f7f1f0d76dd6 933 free(deviceHeader);
XinZhangMS 0:f7f1f0d76dd6 934
XinZhangMS 0:f7f1f0d76dd6 935 /* Codes_SRS_CODEFIRST_99_102:[On any other errors, Device_Create shall return NULL.] */
XinZhangMS 0:f7f1f0d76dd6 936 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 937 LogError(" %s ", ENUM_TO_STRING(CODEFIRST_RESULT, CODEFIRST_ERROR));
XinZhangMS 0:f7f1f0d76dd6 938 }
XinZhangMS 0:f7f1f0d76dd6 939 else
XinZhangMS 0:f7f1f0d76dd6 940 {
XinZhangMS 0:f7f1f0d76dd6 941 SCHEMA_RESULT schemaResult;
XinZhangMS 0:f7f1f0d76dd6 942 deviceHeader->ReflectedData = metadata;
XinZhangMS 0:f7f1f0d76dd6 943 deviceHeader->DataSize = dataSize;
XinZhangMS 0:f7f1f0d76dd6 944 deviceHeader->ModelHandle = model;
XinZhangMS 0:f7f1f0d76dd6 945 schemaResult = Schema_AddDeviceRef(model);
XinZhangMS 0:f7f1f0d76dd6 946 if (schemaResult != SCHEMA_OK)
XinZhangMS 0:f7f1f0d76dd6 947 {
XinZhangMS 0:f7f1f0d76dd6 948 Device_Destroy(deviceHeader->DeviceHandle);
XinZhangMS 0:f7f1f0d76dd6 949 free(deviceHeader->data);
XinZhangMS 0:f7f1f0d76dd6 950 free(deviceHeader);
XinZhangMS 0:f7f1f0d76dd6 951
XinZhangMS 0:f7f1f0d76dd6 952 /* Codes_SRS_CODEFIRST_99_102:[On any other errors, Device_Create shall return NULL.] */
XinZhangMS 0:f7f1f0d76dd6 953 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 954 }
XinZhangMS 0:f7f1f0d76dd6 955 else
XinZhangMS 0:f7f1f0d76dd6 956 {
XinZhangMS 0:f7f1f0d76dd6 957 g_Devices = newDevices;
XinZhangMS 0:f7f1f0d76dd6 958 g_Devices[g_DeviceCount] = deviceHeader;
XinZhangMS 0:f7f1f0d76dd6 959 g_DeviceCount++;
XinZhangMS 0:f7f1f0d76dd6 960
XinZhangMS 0:f7f1f0d76dd6 961 /* Codes_SRS_CODEFIRST_99_101:[On success, CodeFirst_CreateDevice shall return a non NULL pointer to the device data.] */
XinZhangMS 0:f7f1f0d76dd6 962 result = deviceHeader->data;
XinZhangMS 0:f7f1f0d76dd6 963 }
XinZhangMS 0:f7f1f0d76dd6 964 }
XinZhangMS 0:f7f1f0d76dd6 965 }
XinZhangMS 0:f7f1f0d76dd6 966 }
XinZhangMS 0:f7f1f0d76dd6 967
XinZhangMS 0:f7f1f0d76dd6 968 }
XinZhangMS 0:f7f1f0d76dd6 969
XinZhangMS 0:f7f1f0d76dd6 970 return result;
XinZhangMS 0:f7f1f0d76dd6 971 }
XinZhangMS 0:f7f1f0d76dd6 972
XinZhangMS 0:f7f1f0d76dd6 973 void CodeFirst_DestroyDevice(void* device)
XinZhangMS 0:f7f1f0d76dd6 974 {
XinZhangMS 0:f7f1f0d76dd6 975 /* Codes_SRS_CODEFIRST_99_086:[If the argument is NULL, CodeFirst_DestroyDevice shall do nothing.] */
XinZhangMS 0:f7f1f0d76dd6 976 if (device != NULL)
XinZhangMS 0:f7f1f0d76dd6 977 {
XinZhangMS 0:f7f1f0d76dd6 978 size_t i;
XinZhangMS 0:f7f1f0d76dd6 979
XinZhangMS 0:f7f1f0d76dd6 980 for (i = 0; i < g_DeviceCount; i++)
XinZhangMS 0:f7f1f0d76dd6 981 {
XinZhangMS 0:f7f1f0d76dd6 982 if (g_Devices[i]->data == device)
XinZhangMS 0:f7f1f0d76dd6 983 {
XinZhangMS 0:f7f1f0d76dd6 984 deinitializeDesiredProperties(g_Devices[i]->ModelHandle, g_Devices[i]->data);
XinZhangMS 0:f7f1f0d76dd6 985 Schema_ReleaseDeviceRef(g_Devices[i]->ModelHandle);
XinZhangMS 0:f7f1f0d76dd6 986
XinZhangMS 0:f7f1f0d76dd6 987 // Delete the Created Schema if all the devices are unassociated
XinZhangMS 0:f7f1f0d76dd6 988 Schema_DestroyIfUnused(g_Devices[i]->ModelHandle);
XinZhangMS 0:f7f1f0d76dd6 989
XinZhangMS 0:f7f1f0d76dd6 990 DestroyDevice(g_Devices[i]);
XinZhangMS 0:f7f1f0d76dd6 991 (void)memcpy(&g_Devices[i], &g_Devices[i + 1], (g_DeviceCount - i - 1) * sizeof(DEVICE_HEADER_DATA*));
XinZhangMS 0:f7f1f0d76dd6 992 g_DeviceCount--;
XinZhangMS 0:f7f1f0d76dd6 993 break;
XinZhangMS 0:f7f1f0d76dd6 994 }
XinZhangMS 0:f7f1f0d76dd6 995 }
XinZhangMS 0:f7f1f0d76dd6 996
XinZhangMS 0:f7f1f0d76dd6 997 /*Codes_SRS_CODEFIRST_02_039: [ If the current device count is zero then CodeFirst_DestroyDevice shall deallocate all other used resources. ]*/
XinZhangMS 0:f7f1f0d76dd6 998 if ((g_state == CODEFIRST_STATE_INIT_BY_API) && (g_DeviceCount == 0))
XinZhangMS 0:f7f1f0d76dd6 999 {
XinZhangMS 0:f7f1f0d76dd6 1000 free(g_Devices);
XinZhangMS 0:f7f1f0d76dd6 1001 g_Devices = NULL;
XinZhangMS 0:f7f1f0d76dd6 1002 g_state = CODEFIRST_STATE_NOT_INIT;
XinZhangMS 0:f7f1f0d76dd6 1003 }
XinZhangMS 0:f7f1f0d76dd6 1004 }
XinZhangMS 0:f7f1f0d76dd6 1005 }
XinZhangMS 0:f7f1f0d76dd6 1006
XinZhangMS 0:f7f1f0d76dd6 1007 static DEVICE_HEADER_DATA* FindDevice(void* value)
XinZhangMS 0:f7f1f0d76dd6 1008 {
XinZhangMS 0:f7f1f0d76dd6 1009 size_t i;
XinZhangMS 0:f7f1f0d76dd6 1010 DEVICE_HEADER_DATA* result = NULL;
XinZhangMS 0:f7f1f0d76dd6 1011
XinZhangMS 0:f7f1f0d76dd6 1012 for (i = 0; i < g_DeviceCount; i++)
XinZhangMS 0:f7f1f0d76dd6 1013 {
XinZhangMS 0:f7f1f0d76dd6 1014 if ((g_Devices[i]->data <= (unsigned char*)value) &&
XinZhangMS 0:f7f1f0d76dd6 1015 (g_Devices[i]->data + g_Devices[i]->DataSize > (unsigned char*)value))
XinZhangMS 0:f7f1f0d76dd6 1016 {
XinZhangMS 0:f7f1f0d76dd6 1017 result = g_Devices[i];
XinZhangMS 0:f7f1f0d76dd6 1018 break;
XinZhangMS 0:f7f1f0d76dd6 1019 }
XinZhangMS 0:f7f1f0d76dd6 1020 }
XinZhangMS 0:f7f1f0d76dd6 1021
XinZhangMS 0:f7f1f0d76dd6 1022 return result;
XinZhangMS 0:f7f1f0d76dd6 1023 }
XinZhangMS 0:f7f1f0d76dd6 1024
XinZhangMS 0:f7f1f0d76dd6 1025 static const REFLECTED_SOMETHING* FindValue(DEVICE_HEADER_DATA* deviceHeader, void* value, const char* modelName, size_t startOffset, STRING_HANDLE valuePath)
XinZhangMS 0:f7f1f0d76dd6 1026 {
XinZhangMS 0:f7f1f0d76dd6 1027 const REFLECTED_SOMETHING* result;
XinZhangMS 0:f7f1f0d76dd6 1028 size_t valueOffset = (size_t)((unsigned char*)value - (unsigned char*)deviceHeader->data) - startOffset;
XinZhangMS 0:f7f1f0d76dd6 1029
XinZhangMS 0:f7f1f0d76dd6 1030 for (result = deviceHeader->ReflectedData->reflectedData; result != NULL; result = result->next)
XinZhangMS 0:f7f1f0d76dd6 1031 {
XinZhangMS 0:f7f1f0d76dd6 1032 if (result->type == REFLECTION_PROPERTY_TYPE &&
XinZhangMS 0:f7f1f0d76dd6 1033 (strcmp(result->what.property.modelName, modelName) == 0) &&
XinZhangMS 0:f7f1f0d76dd6 1034 (result->what.property.offset <= valueOffset) &&
XinZhangMS 0:f7f1f0d76dd6 1035 (result->what.property.offset + result->what.property.size > valueOffset))
XinZhangMS 0:f7f1f0d76dd6 1036 {
XinZhangMS 0:f7f1f0d76dd6 1037 if (startOffset != 0)
XinZhangMS 0:f7f1f0d76dd6 1038 {
XinZhangMS 0:f7f1f0d76dd6 1039 STRING_concat(valuePath, "/");
XinZhangMS 0:f7f1f0d76dd6 1040 }
XinZhangMS 0:f7f1f0d76dd6 1041
XinZhangMS 0:f7f1f0d76dd6 1042 STRING_concat(valuePath, result->what.property.name);
XinZhangMS 0:f7f1f0d76dd6 1043 break;
XinZhangMS 0:f7f1f0d76dd6 1044 }
XinZhangMS 0:f7f1f0d76dd6 1045 }
XinZhangMS 0:f7f1f0d76dd6 1046
XinZhangMS 0:f7f1f0d76dd6 1047 if (result != NULL)
XinZhangMS 0:f7f1f0d76dd6 1048 {
XinZhangMS 0:f7f1f0d76dd6 1049 /* Codes_SRS_CODEFIRST_99_133:[CodeFirst_SendAsync shall allow sending of properties that are part of a child model.] */
XinZhangMS 0:f7f1f0d76dd6 1050 if (result->what.property.offset < valueOffset)
XinZhangMS 0:f7f1f0d76dd6 1051 {
XinZhangMS 0:f7f1f0d76dd6 1052 /* find recursively the property in the inner model, if there is one */
XinZhangMS 0:f7f1f0d76dd6 1053 result = FindValue(deviceHeader, value, result->what.property.type, startOffset + result->what.property.offset, valuePath);
XinZhangMS 0:f7f1f0d76dd6 1054 }
XinZhangMS 0:f7f1f0d76dd6 1055 }
XinZhangMS 0:f7f1f0d76dd6 1056
XinZhangMS 0:f7f1f0d76dd6 1057 return result;
XinZhangMS 0:f7f1f0d76dd6 1058 }
XinZhangMS 0:f7f1f0d76dd6 1059
XinZhangMS 0:f7f1f0d76dd6 1060 static const REFLECTED_SOMETHING* FindReportedProperty(DEVICE_HEADER_DATA* deviceHeader, void* value, const char* modelName, size_t startOffset, STRING_HANDLE valuePath)
XinZhangMS 0:f7f1f0d76dd6 1061 {
XinZhangMS 0:f7f1f0d76dd6 1062 const REFLECTED_SOMETHING* result;
XinZhangMS 0:f7f1f0d76dd6 1063 size_t valueOffset = (size_t)((unsigned char*)value - (unsigned char*)deviceHeader->data) - startOffset;
XinZhangMS 0:f7f1f0d76dd6 1064
XinZhangMS 0:f7f1f0d76dd6 1065 for (result = deviceHeader->ReflectedData->reflectedData; result != NULL; result = result->next)
XinZhangMS 0:f7f1f0d76dd6 1066 {
XinZhangMS 0:f7f1f0d76dd6 1067 if (result->type == REFLECTION_REPORTED_PROPERTY_TYPE &&
XinZhangMS 0:f7f1f0d76dd6 1068 (strcmp(result->what.reportedProperty.modelName, modelName) == 0) &&
XinZhangMS 0:f7f1f0d76dd6 1069 (result->what.reportedProperty.offset <= valueOffset) &&
XinZhangMS 0:f7f1f0d76dd6 1070 (result->what.reportedProperty.offset + result->what.reportedProperty.size > valueOffset))
XinZhangMS 0:f7f1f0d76dd6 1071 {
XinZhangMS 0:f7f1f0d76dd6 1072 if (startOffset != 0)
XinZhangMS 0:f7f1f0d76dd6 1073 {
XinZhangMS 0:f7f1f0d76dd6 1074 if (STRING_concat(valuePath, "/") != 0)
XinZhangMS 0:f7f1f0d76dd6 1075 {
XinZhangMS 0:f7f1f0d76dd6 1076 LogError("unable to STRING_concat");
XinZhangMS 0:f7f1f0d76dd6 1077 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 1078 break;
XinZhangMS 0:f7f1f0d76dd6 1079 }
XinZhangMS 0:f7f1f0d76dd6 1080 }
XinZhangMS 0:f7f1f0d76dd6 1081
XinZhangMS 0:f7f1f0d76dd6 1082 if (STRING_concat(valuePath, result->what.reportedProperty.name) != 0)
XinZhangMS 0:f7f1f0d76dd6 1083 {
XinZhangMS 0:f7f1f0d76dd6 1084 LogError("unable to STRING_concat");
XinZhangMS 0:f7f1f0d76dd6 1085 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 1086 break;
XinZhangMS 0:f7f1f0d76dd6 1087 }
XinZhangMS 0:f7f1f0d76dd6 1088 break;
XinZhangMS 0:f7f1f0d76dd6 1089 }
XinZhangMS 0:f7f1f0d76dd6 1090 }
XinZhangMS 0:f7f1f0d76dd6 1091
XinZhangMS 0:f7f1f0d76dd6 1092 if (result != NULL)
XinZhangMS 0:f7f1f0d76dd6 1093 {
XinZhangMS 0:f7f1f0d76dd6 1094 /* Codes_SRS_CODEFIRST_99_133:[CodeFirst_SendAsync shall allow sending of properties that are part of a child model.] */
XinZhangMS 0:f7f1f0d76dd6 1095 if (result->what.reportedProperty.offset < valueOffset)
XinZhangMS 0:f7f1f0d76dd6 1096 {
XinZhangMS 0:f7f1f0d76dd6 1097 /* find recursively the property in the inner model, if there is one */
XinZhangMS 0:f7f1f0d76dd6 1098 result = FindReportedProperty(deviceHeader, value, result->what.reportedProperty.type, startOffset + result->what.reportedProperty.offset, valuePath);
XinZhangMS 0:f7f1f0d76dd6 1099 }
XinZhangMS 0:f7f1f0d76dd6 1100 }
XinZhangMS 0:f7f1f0d76dd6 1101
XinZhangMS 0:f7f1f0d76dd6 1102 return result;
XinZhangMS 0:f7f1f0d76dd6 1103 }
XinZhangMS 0:f7f1f0d76dd6 1104
XinZhangMS 0:f7f1f0d76dd6 1105 /* Codes_SRS_CODEFIRST_99_130:[If a pointer to the beginning of a device block is passed to CodeFirst_SendAsync instead of a pointer to a property, CodeFirst_SendAsync shall send all the properties that belong to that device.] */
XinZhangMS 0:f7f1f0d76dd6 1106 /* Codes_SRS_CODEFIRST_99_131:[The properties shall be given to Device as one transaction, as if they were all passed as individual arguments to Code_First.] */
XinZhangMS 0:f7f1f0d76dd6 1107 static CODEFIRST_RESULT SendAllDeviceProperties(DEVICE_HEADER_DATA* deviceHeader, TRANSACTION_HANDLE transaction)
XinZhangMS 0:f7f1f0d76dd6 1108 {
XinZhangMS 0:f7f1f0d76dd6 1109 const char* modelName = Schema_GetModelName(deviceHeader->ModelHandle);
XinZhangMS 0:f7f1f0d76dd6 1110 const REFLECTED_SOMETHING* something;
XinZhangMS 0:f7f1f0d76dd6 1111 unsigned char* deviceAddress = (unsigned char*)deviceHeader->data;
XinZhangMS 0:f7f1f0d76dd6 1112 CODEFIRST_RESULT result = CODEFIRST_OK;
XinZhangMS 0:f7f1f0d76dd6 1113
XinZhangMS 0:f7f1f0d76dd6 1114 for (something = deviceHeader->ReflectedData->reflectedData; something != NULL; something = something->next)
XinZhangMS 0:f7f1f0d76dd6 1115 {
XinZhangMS 0:f7f1f0d76dd6 1116 if ((something->type == REFLECTION_PROPERTY_TYPE) &&
XinZhangMS 0:f7f1f0d76dd6 1117 (strcmp(something->what.property.modelName, modelName) == 0))
XinZhangMS 0:f7f1f0d76dd6 1118 {
XinZhangMS 0:f7f1f0d76dd6 1119 AGENT_DATA_TYPE agentDataType;
XinZhangMS 0:f7f1f0d76dd6 1120
XinZhangMS 0:f7f1f0d76dd6 1121 /* Codes_SRS_CODEFIRST_99_097:[For each value marshalling to AGENT_DATA_TYPE shall be performed.] */
XinZhangMS 0:f7f1f0d76dd6 1122 /* Codes_SRS_CODEFIRST_99_098:[The marshalling shall be done by calling the Create_AGENT_DATA_TYPE_from_Ptr function associated with the property.] */
XinZhangMS 0:f7f1f0d76dd6 1123 if (something->what.property.Create_AGENT_DATA_TYPE_from_Ptr(deviceAddress + something->what.property.offset, &agentDataType) != AGENT_DATA_TYPES_OK)
XinZhangMS 0:f7f1f0d76dd6 1124 {
XinZhangMS 0:f7f1f0d76dd6 1125 /* Codes_SRS_CODEFIRST_99_099:[If Create_AGENT_DATA_TYPE_from_Ptr fails, CodeFirst_SendAsync shall return CODEFIRST_AGENT_DATA_TYPE_ERROR.] */
XinZhangMS 0:f7f1f0d76dd6 1126 result = CODEFIRST_AGENT_DATA_TYPE_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1127 LOG_CODEFIRST_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1128 break;
XinZhangMS 0:f7f1f0d76dd6 1129 }
XinZhangMS 0:f7f1f0d76dd6 1130 else
XinZhangMS 0:f7f1f0d76dd6 1131 {
XinZhangMS 0:f7f1f0d76dd6 1132 /* Codes_SRS_CODEFIRST_99_092:[CodeFirst shall publish each value by using Device_PublishTransacted.] */
XinZhangMS 0:f7f1f0d76dd6 1133 if (Device_PublishTransacted(transaction, something->what.property.name, &agentDataType) != DEVICE_OK)
XinZhangMS 0:f7f1f0d76dd6 1134 {
XinZhangMS 0:f7f1f0d76dd6 1135 Destroy_AGENT_DATA_TYPE(&agentDataType);
XinZhangMS 0:f7f1f0d76dd6 1136
XinZhangMS 0:f7f1f0d76dd6 1137 /* Codes_SRS_CODEFIRST_99_094:[If any Device API fail, CodeFirst_SendAsync shall return CODEFIRST_DEVICE_PUBLISH_FAILED.] */
XinZhangMS 0:f7f1f0d76dd6 1138 result = CODEFIRST_DEVICE_PUBLISH_FAILED;
XinZhangMS 0:f7f1f0d76dd6 1139 LOG_CODEFIRST_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1140 break;
XinZhangMS 0:f7f1f0d76dd6 1141 }
XinZhangMS 0:f7f1f0d76dd6 1142
XinZhangMS 0:f7f1f0d76dd6 1143 Destroy_AGENT_DATA_TYPE(&agentDataType);
XinZhangMS 0:f7f1f0d76dd6 1144 }
XinZhangMS 0:f7f1f0d76dd6 1145 }
XinZhangMS 0:f7f1f0d76dd6 1146 }
XinZhangMS 0:f7f1f0d76dd6 1147
XinZhangMS 0:f7f1f0d76dd6 1148 return result;
XinZhangMS 0:f7f1f0d76dd6 1149 }
XinZhangMS 0:f7f1f0d76dd6 1150
XinZhangMS 0:f7f1f0d76dd6 1151 static CODEFIRST_RESULT SendAllDeviceReportedProperties(DEVICE_HEADER_DATA* deviceHeader, REPORTED_PROPERTIES_TRANSACTION_HANDLE transaction)
XinZhangMS 0:f7f1f0d76dd6 1152 {
XinZhangMS 0:f7f1f0d76dd6 1153 const char* modelName = Schema_GetModelName(deviceHeader->ModelHandle);
XinZhangMS 0:f7f1f0d76dd6 1154 const REFLECTED_SOMETHING* something;
XinZhangMS 0:f7f1f0d76dd6 1155 unsigned char* deviceAddress = (unsigned char*)deviceHeader->data;
XinZhangMS 0:f7f1f0d76dd6 1156 CODEFIRST_RESULT result = CODEFIRST_OK;
XinZhangMS 0:f7f1f0d76dd6 1157
XinZhangMS 0:f7f1f0d76dd6 1158 for (something = deviceHeader->ReflectedData->reflectedData; something != NULL; something = something->next)
XinZhangMS 0:f7f1f0d76dd6 1159 {
XinZhangMS 0:f7f1f0d76dd6 1160 if ((something->type == REFLECTION_REPORTED_PROPERTY_TYPE) &&
XinZhangMS 0:f7f1f0d76dd6 1161 (strcmp(something->what.reportedProperty.modelName, modelName) == 0))
XinZhangMS 0:f7f1f0d76dd6 1162 {
XinZhangMS 0:f7f1f0d76dd6 1163 AGENT_DATA_TYPE agentDataType;
XinZhangMS 0:f7f1f0d76dd6 1164
XinZhangMS 0:f7f1f0d76dd6 1165 if (something->what.reportedProperty.Create_AGENT_DATA_TYPE_from_Ptr(deviceAddress + something->what.reportedProperty.offset, &agentDataType) != AGENT_DATA_TYPES_OK)
XinZhangMS 0:f7f1f0d76dd6 1166 {
XinZhangMS 0:f7f1f0d76dd6 1167 result = CODEFIRST_AGENT_DATA_TYPE_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1168 LOG_CODEFIRST_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1169 break;
XinZhangMS 0:f7f1f0d76dd6 1170 }
XinZhangMS 0:f7f1f0d76dd6 1171 else
XinZhangMS 0:f7f1f0d76dd6 1172 {
XinZhangMS 0:f7f1f0d76dd6 1173 if (Device_PublishTransacted_ReportedProperty(transaction, something->what.reportedProperty.name, &agentDataType) != DEVICE_OK)
XinZhangMS 0:f7f1f0d76dd6 1174 {
XinZhangMS 0:f7f1f0d76dd6 1175 Destroy_AGENT_DATA_TYPE(&agentDataType);
XinZhangMS 0:f7f1f0d76dd6 1176 result = CODEFIRST_DEVICE_PUBLISH_FAILED;
XinZhangMS 0:f7f1f0d76dd6 1177 LOG_CODEFIRST_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1178 break;
XinZhangMS 0:f7f1f0d76dd6 1179 }
XinZhangMS 0:f7f1f0d76dd6 1180
XinZhangMS 0:f7f1f0d76dd6 1181 Destroy_AGENT_DATA_TYPE(&agentDataType);
XinZhangMS 0:f7f1f0d76dd6 1182 }
XinZhangMS 0:f7f1f0d76dd6 1183 }
XinZhangMS 0:f7f1f0d76dd6 1184 }
XinZhangMS 0:f7f1f0d76dd6 1185
XinZhangMS 0:f7f1f0d76dd6 1186 return result;
XinZhangMS 0:f7f1f0d76dd6 1187 }
XinZhangMS 0:f7f1f0d76dd6 1188
XinZhangMS 0:f7f1f0d76dd6 1189
XinZhangMS 0:f7f1f0d76dd6 1190 /* Codes_SRS_CODEFIRST_99_088:[CodeFirst_SendAsync shall send to the Device module a set of properties, a destination and a destinationSize.]*/
XinZhangMS 0:f7f1f0d76dd6 1191 CODEFIRST_RESULT CodeFirst_SendAsync(unsigned char** destination, size_t* destinationSize, size_t numProperties, ...)
XinZhangMS 0:f7f1f0d76dd6 1192 {
XinZhangMS 0:f7f1f0d76dd6 1193 CODEFIRST_RESULT result;
XinZhangMS 0:f7f1f0d76dd6 1194 va_list ap;
XinZhangMS 0:f7f1f0d76dd6 1195
XinZhangMS 0:f7f1f0d76dd6 1196 if (
XinZhangMS 0:f7f1f0d76dd6 1197 (numProperties == 0) ||
XinZhangMS 0:f7f1f0d76dd6 1198 (destination == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 1199 (destinationSize == NULL)
XinZhangMS 0:f7f1f0d76dd6 1200 )
XinZhangMS 0:f7f1f0d76dd6 1201 {
XinZhangMS 0:f7f1f0d76dd6 1202 /* Codes_SRS_CODEFIRST_04_002: [If CodeFirst_SendAsync receives destination or destinationSize NULL, CodeFirst_SendAsync shall return Invalid Argument.]*/
XinZhangMS 0:f7f1f0d76dd6 1203 /* Codes_SRS_CODEFIRST_99_103:[If CodeFirst_SendAsync is called with numProperties being zero, CODEFIRST_INVALID_ARG shall be returned.] */
XinZhangMS 0:f7f1f0d76dd6 1204 result = CODEFIRST_INVALID_ARG;
XinZhangMS 0:f7f1f0d76dd6 1205 LOG_CODEFIRST_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1206 }
XinZhangMS 0:f7f1f0d76dd6 1207 else
XinZhangMS 0:f7f1f0d76dd6 1208 {
XinZhangMS 0:f7f1f0d76dd6 1209 /*Codes_SRS_CODEFIRST_02_040: [ CodeFirst_SendAsync shall call CodeFirst_Init, passing NULL for overrideSchemaNamespace. ]*/
XinZhangMS 0:f7f1f0d76dd6 1210 (void)CodeFirst_Init_impl(NULL, false); /*lazy init*/
XinZhangMS 0:f7f1f0d76dd6 1211
XinZhangMS 0:f7f1f0d76dd6 1212 DEVICE_HEADER_DATA* deviceHeader = NULL;
XinZhangMS 0:f7f1f0d76dd6 1213 size_t i;
XinZhangMS 0:f7f1f0d76dd6 1214 TRANSACTION_HANDLE transaction = NULL;
XinZhangMS 0:f7f1f0d76dd6 1215 result = CODEFIRST_OK;
XinZhangMS 0:f7f1f0d76dd6 1216
XinZhangMS 0:f7f1f0d76dd6 1217 /* Codes_SRS_CODEFIRST_99_105:[The properties are passed as pointers to the memory locations where the data exists in the device block allocated by CodeFirst_CreateDevice.] */
XinZhangMS 0:f7f1f0d76dd6 1218 va_start(ap, numProperties);
XinZhangMS 0:f7f1f0d76dd6 1219
XinZhangMS 0:f7f1f0d76dd6 1220 /* Codes_SRS_CODEFIRST_99_089:[The numProperties argument shall indicate how many properties are to be sent.] */
XinZhangMS 0:f7f1f0d76dd6 1221 for (i = 0; i < numProperties; i++)
XinZhangMS 0:f7f1f0d76dd6 1222 {
XinZhangMS 0:f7f1f0d76dd6 1223 void* value = (void*)va_arg(ap, void*);
XinZhangMS 0:f7f1f0d76dd6 1224
XinZhangMS 0:f7f1f0d76dd6 1225 /* Codes_SRS_CODEFIRST_99_095:[For each value passed to it, CodeFirst_SendAsync shall look up to which device the value belongs.] */
XinZhangMS 0:f7f1f0d76dd6 1226 DEVICE_HEADER_DATA* currentValueDeviceHeader = FindDevice(value);
XinZhangMS 0:f7f1f0d76dd6 1227 if (currentValueDeviceHeader == NULL)
XinZhangMS 0:f7f1f0d76dd6 1228 {
XinZhangMS 0:f7f1f0d76dd6 1229 /* Codes_SRS_CODEFIRST_99_104:[If a property cannot be associated with a device, CodeFirst_SendAsync shall return CODEFIRST_INVALID_ARG.] */
XinZhangMS 0:f7f1f0d76dd6 1230 result = CODEFIRST_INVALID_ARG;
XinZhangMS 0:f7f1f0d76dd6 1231 LOG_CODEFIRST_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1232 break;
XinZhangMS 0:f7f1f0d76dd6 1233 }
XinZhangMS 0:f7f1f0d76dd6 1234 else if ((deviceHeader != NULL) &&
XinZhangMS 0:f7f1f0d76dd6 1235 (currentValueDeviceHeader != deviceHeader))
XinZhangMS 0:f7f1f0d76dd6 1236 {
XinZhangMS 0:f7f1f0d76dd6 1237 /* Codes_SRS_CODEFIRST_99_096:[All values have to belong to the same device, otherwise CodeFirst_SendAsync shall return CODEFIRST_VALUES_FROM_DIFFERENT_DEVICES_ERROR.] */
XinZhangMS 0:f7f1f0d76dd6 1238 result = CODEFIRST_VALUES_FROM_DIFFERENT_DEVICES_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1239 LOG_CODEFIRST_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1240 break;
XinZhangMS 0:f7f1f0d76dd6 1241 }
XinZhangMS 0:f7f1f0d76dd6 1242 /* Codes_SRS_CODEFIRST_99_090:[All the properties shall be sent together by using the transacted APIs of the device.] */
XinZhangMS 0:f7f1f0d76dd6 1243 /* Codes_SRS_CODEFIRST_99_091:[CodeFirst_SendAsync shall start a transaction by calling Device_StartTransaction.] */
XinZhangMS 0:f7f1f0d76dd6 1244 else if ((deviceHeader == NULL) &&
XinZhangMS 0:f7f1f0d76dd6 1245 ((transaction = Device_StartTransaction(currentValueDeviceHeader->DeviceHandle)) == NULL))
XinZhangMS 0:f7f1f0d76dd6 1246 {
XinZhangMS 0:f7f1f0d76dd6 1247 /* Codes_SRS_CODEFIRST_99_094:[If any Device API fail, CodeFirst_SendAsync shall return CODEFIRST_DEVICE_PUBLISH_FAILED.] */
XinZhangMS 0:f7f1f0d76dd6 1248 result = CODEFIRST_DEVICE_PUBLISH_FAILED;
XinZhangMS 0:f7f1f0d76dd6 1249 LOG_CODEFIRST_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1250 break;
XinZhangMS 0:f7f1f0d76dd6 1251 }
XinZhangMS 0:f7f1f0d76dd6 1252 else
XinZhangMS 0:f7f1f0d76dd6 1253 {
XinZhangMS 0:f7f1f0d76dd6 1254 deviceHeader = currentValueDeviceHeader;
XinZhangMS 0:f7f1f0d76dd6 1255
XinZhangMS 0:f7f1f0d76dd6 1256 if (value == ((unsigned char*)deviceHeader->data))
XinZhangMS 0:f7f1f0d76dd6 1257 {
XinZhangMS 0:f7f1f0d76dd6 1258 /* we got a full device, send all its state data */
XinZhangMS 0:f7f1f0d76dd6 1259 result = SendAllDeviceProperties(deviceHeader, transaction);
XinZhangMS 0:f7f1f0d76dd6 1260 if (result != CODEFIRST_OK)
XinZhangMS 0:f7f1f0d76dd6 1261 {
XinZhangMS 0:f7f1f0d76dd6 1262 LOG_CODEFIRST_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1263 break;
XinZhangMS 0:f7f1f0d76dd6 1264 }
XinZhangMS 0:f7f1f0d76dd6 1265 }
XinZhangMS 0:f7f1f0d76dd6 1266 else
XinZhangMS 0:f7f1f0d76dd6 1267 {
XinZhangMS 0:f7f1f0d76dd6 1268 const REFLECTED_SOMETHING* propertyReflectedData;
XinZhangMS 0:f7f1f0d76dd6 1269 const char* modelName;
XinZhangMS 0:f7f1f0d76dd6 1270 STRING_HANDLE valuePath;
XinZhangMS 0:f7f1f0d76dd6 1271
XinZhangMS 0:f7f1f0d76dd6 1272 if ((valuePath = STRING_new()) == NULL)
XinZhangMS 0:f7f1f0d76dd6 1273 {
XinZhangMS 0:f7f1f0d76dd6 1274 /* Codes_SRS_CODEFIRST_99_134:[If CodeFirst_Notify fails for any other reason it shall return CODEFIRST_ERROR.] */
XinZhangMS 0:f7f1f0d76dd6 1275 result = CODEFIRST_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1276 LOG_CODEFIRST_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1277 break;
XinZhangMS 0:f7f1f0d76dd6 1278 }
XinZhangMS 0:f7f1f0d76dd6 1279 else
XinZhangMS 0:f7f1f0d76dd6 1280 {
XinZhangMS 0:f7f1f0d76dd6 1281 if ((modelName = Schema_GetModelName(deviceHeader->ModelHandle)) == NULL)
XinZhangMS 0:f7f1f0d76dd6 1282 {
XinZhangMS 0:f7f1f0d76dd6 1283 /* Codes_SRS_CODEFIRST_99_134:[If CodeFirst_Notify fails for any other reason it shall return CODEFIRST_ERROR.] */
XinZhangMS 0:f7f1f0d76dd6 1284 result = CODEFIRST_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1285 LOG_CODEFIRST_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1286 STRING_delete(valuePath);
XinZhangMS 0:f7f1f0d76dd6 1287 break;
XinZhangMS 0:f7f1f0d76dd6 1288 }
XinZhangMS 0:f7f1f0d76dd6 1289 else if ((propertyReflectedData = FindValue(deviceHeader, value, modelName, 0, valuePath)) == NULL)
XinZhangMS 0:f7f1f0d76dd6 1290 {
XinZhangMS 0:f7f1f0d76dd6 1291 /* Codes_SRS_CODEFIRST_99_104:[If a property cannot be associated with a device, CodeFirst_SendAsync shall return CODEFIRST_INVALID_ARG.] */
XinZhangMS 0:f7f1f0d76dd6 1292 result = CODEFIRST_INVALID_ARG;
XinZhangMS 0:f7f1f0d76dd6 1293 LOG_CODEFIRST_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1294 STRING_delete(valuePath);
XinZhangMS 0:f7f1f0d76dd6 1295 break;
XinZhangMS 0:f7f1f0d76dd6 1296 }
XinZhangMS 0:f7f1f0d76dd6 1297 else
XinZhangMS 0:f7f1f0d76dd6 1298 {
XinZhangMS 0:f7f1f0d76dd6 1299 AGENT_DATA_TYPE agentDataType;
XinZhangMS 0:f7f1f0d76dd6 1300
XinZhangMS 0:f7f1f0d76dd6 1301 /* Codes_SRS_CODEFIRST_99_097:[For each value marshalling to AGENT_DATA_TYPE shall be performed.] */
XinZhangMS 0:f7f1f0d76dd6 1302 /* Codes_SRS_CODEFIRST_99_098:[The marshalling shall be done by calling the Create_AGENT_DATA_TYPE_from_Ptr function associated with the property.] */
XinZhangMS 0:f7f1f0d76dd6 1303 if (propertyReflectedData->what.property.Create_AGENT_DATA_TYPE_from_Ptr(value, &agentDataType) != AGENT_DATA_TYPES_OK)
XinZhangMS 0:f7f1f0d76dd6 1304 {
XinZhangMS 0:f7f1f0d76dd6 1305 /* Codes_SRS_CODEFIRST_99_099:[If Create_AGENT_DATA_TYPE_from_Ptr fails, CodeFirst_SendAsync shall return CODEFIRST_AGENT_DATA_TYPE_ERROR.] */
XinZhangMS 0:f7f1f0d76dd6 1306 result = CODEFIRST_AGENT_DATA_TYPE_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1307 LOG_CODEFIRST_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1308 STRING_delete(valuePath);
XinZhangMS 0:f7f1f0d76dd6 1309 break;
XinZhangMS 0:f7f1f0d76dd6 1310 }
XinZhangMS 0:f7f1f0d76dd6 1311 else
XinZhangMS 0:f7f1f0d76dd6 1312 {
XinZhangMS 0:f7f1f0d76dd6 1313 /* Codes_SRS_CODEFIRST_99_092:[CodeFirst shall publish each value by using Device_PublishTransacted.] */
XinZhangMS 0:f7f1f0d76dd6 1314 /* Codes_SRS_CODEFIRST_99_136:[CodeFirst_SendAsync shall build the full path for each property and then pass it to Device_PublishTransacted.] */
XinZhangMS 0:f7f1f0d76dd6 1315 if (Device_PublishTransacted(transaction, STRING_c_str(valuePath), &agentDataType) != DEVICE_OK)
XinZhangMS 0:f7f1f0d76dd6 1316 {
XinZhangMS 0:f7f1f0d76dd6 1317 Destroy_AGENT_DATA_TYPE(&agentDataType);
XinZhangMS 0:f7f1f0d76dd6 1318
XinZhangMS 0:f7f1f0d76dd6 1319 /* Codes_SRS_CODEFIRST_99_094:[If any Device API fail, CodeFirst_SendAsync shall return CODEFIRST_DEVICE_PUBLISH_FAILED.] */
XinZhangMS 0:f7f1f0d76dd6 1320 result = CODEFIRST_DEVICE_PUBLISH_FAILED;
XinZhangMS 0:f7f1f0d76dd6 1321 LOG_CODEFIRST_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1322 STRING_delete(valuePath);
XinZhangMS 0:f7f1f0d76dd6 1323 break;
XinZhangMS 0:f7f1f0d76dd6 1324 }
XinZhangMS 0:f7f1f0d76dd6 1325 else
XinZhangMS 0:f7f1f0d76dd6 1326 {
XinZhangMS 0:f7f1f0d76dd6 1327 STRING_delete(valuePath); /*anyway*/
XinZhangMS 0:f7f1f0d76dd6 1328 }
XinZhangMS 0:f7f1f0d76dd6 1329
XinZhangMS 0:f7f1f0d76dd6 1330 Destroy_AGENT_DATA_TYPE(&agentDataType);
XinZhangMS 0:f7f1f0d76dd6 1331 }
XinZhangMS 0:f7f1f0d76dd6 1332 }
XinZhangMS 0:f7f1f0d76dd6 1333 }
XinZhangMS 0:f7f1f0d76dd6 1334 }
XinZhangMS 0:f7f1f0d76dd6 1335 }
XinZhangMS 0:f7f1f0d76dd6 1336 }
XinZhangMS 0:f7f1f0d76dd6 1337
XinZhangMS 0:f7f1f0d76dd6 1338 if (i < numProperties)
XinZhangMS 0:f7f1f0d76dd6 1339 {
XinZhangMS 0:f7f1f0d76dd6 1340 if (transaction != NULL)
XinZhangMS 0:f7f1f0d76dd6 1341 {
XinZhangMS 0:f7f1f0d76dd6 1342 (void)Device_CancelTransaction(transaction);
XinZhangMS 0:f7f1f0d76dd6 1343 }
XinZhangMS 0:f7f1f0d76dd6 1344 }
XinZhangMS 0:f7f1f0d76dd6 1345 /* Codes_SRS_CODEFIRST_99_093:[After all values have been published, Device_EndTransaction shall be called.] */
XinZhangMS 0:f7f1f0d76dd6 1346 else if (Device_EndTransaction(transaction, destination, destinationSize) != DEVICE_OK)
XinZhangMS 0:f7f1f0d76dd6 1347 {
XinZhangMS 0:f7f1f0d76dd6 1348 /* Codes_SRS_CODEFIRST_99_094:[If any Device API fail, CodeFirst_SendAsync shall return CODEFIRST_DEVICE_PUBLISH_FAILED.] */
XinZhangMS 0:f7f1f0d76dd6 1349 result = CODEFIRST_DEVICE_PUBLISH_FAILED;
XinZhangMS 0:f7f1f0d76dd6 1350 LOG_CODEFIRST_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1351 }
XinZhangMS 0:f7f1f0d76dd6 1352 else
XinZhangMS 0:f7f1f0d76dd6 1353 {
XinZhangMS 0:f7f1f0d76dd6 1354 /* Codes_SRS_CODEFIRST_99_117:[On success, CodeFirst_SendAsync shall return CODEFIRST_OK.] */
XinZhangMS 0:f7f1f0d76dd6 1355 result = CODEFIRST_OK;
XinZhangMS 0:f7f1f0d76dd6 1356 }
XinZhangMS 0:f7f1f0d76dd6 1357
XinZhangMS 0:f7f1f0d76dd6 1358 va_end(ap);
XinZhangMS 0:f7f1f0d76dd6 1359
XinZhangMS 0:f7f1f0d76dd6 1360 }
XinZhangMS 0:f7f1f0d76dd6 1361
XinZhangMS 0:f7f1f0d76dd6 1362 return result;
XinZhangMS 0:f7f1f0d76dd6 1363 }
XinZhangMS 0:f7f1f0d76dd6 1364
XinZhangMS 0:f7f1f0d76dd6 1365 CODEFIRST_RESULT CodeFirst_SendAsyncReported(unsigned char** destination, size_t* destinationSize, size_t numReportedProperties, ...)
XinZhangMS 0:f7f1f0d76dd6 1366 {
XinZhangMS 0:f7f1f0d76dd6 1367 CODEFIRST_RESULT result;
XinZhangMS 0:f7f1f0d76dd6 1368 if ((destination == NULL) || (destinationSize == NULL) || numReportedProperties == 0)
XinZhangMS 0:f7f1f0d76dd6 1369 {
XinZhangMS 0:f7f1f0d76dd6 1370 /*Codes_SRS_CODEFIRST_02_018: [ If parameter destination, destinationSize or any of the values passed through va_args is NULL then CodeFirst_SendAsyncReported shall fail and return CODEFIRST_INVALID_ARG. ]*/
XinZhangMS 0:f7f1f0d76dd6 1371 LogError("invalid argument unsigned char** destination=%p, size_t* destinationSize=%p, size_t numReportedProperties=%lu", destination, destinationSize, numReportedProperties);
XinZhangMS 0:f7f1f0d76dd6 1372 result = CODEFIRST_INVALID_ARG;
XinZhangMS 0:f7f1f0d76dd6 1373 }
XinZhangMS 0:f7f1f0d76dd6 1374 else
XinZhangMS 0:f7f1f0d76dd6 1375 {
XinZhangMS 0:f7f1f0d76dd6 1376 /*Codes_SRS_CODEFIRST_02_046: [ CodeFirst_SendAsyncReported shall call CodeFirst_Init, passing NULL for overrideSchemaNamespace. ]*/
XinZhangMS 0:f7f1f0d76dd6 1377 (void)CodeFirst_Init_impl(NULL, false);/*lazy init*/
XinZhangMS 0:f7f1f0d76dd6 1378
XinZhangMS 0:f7f1f0d76dd6 1379 DEVICE_HEADER_DATA* deviceHeader = NULL;
XinZhangMS 0:f7f1f0d76dd6 1380 size_t i;
XinZhangMS 0:f7f1f0d76dd6 1381 REPORTED_PROPERTIES_TRANSACTION_HANDLE transaction = NULL;
XinZhangMS 0:f7f1f0d76dd6 1382 va_list ap;
XinZhangMS 0:f7f1f0d76dd6 1383 result = CODEFIRST_ACTION_EXECUTION_ERROR; /*this initialization squelches a false warning about result not being initialized*/
XinZhangMS 0:f7f1f0d76dd6 1384
XinZhangMS 0:f7f1f0d76dd6 1385 va_start(ap, numReportedProperties);
XinZhangMS 0:f7f1f0d76dd6 1386
XinZhangMS 0:f7f1f0d76dd6 1387 for (i = 0; i < numReportedProperties; i++)
XinZhangMS 0:f7f1f0d76dd6 1388 {
XinZhangMS 0:f7f1f0d76dd6 1389 void* value = (void*)va_arg(ap, void*);
XinZhangMS 0:f7f1f0d76dd6 1390 /*Codes_SRS_CODEFIRST_02_018: [ If parameter destination, destinationSize or any of the values passed through va_args is NULL then CodeFirst_SendAsyncReported shall fail and return CODEFIRST_INVALID_ARG. ]*/
XinZhangMS 0:f7f1f0d76dd6 1391 if (value == NULL)
XinZhangMS 0:f7f1f0d76dd6 1392 {
XinZhangMS 0:f7f1f0d76dd6 1393 LogError("argument number %lu passed through variable arguments is NULL", i);
XinZhangMS 0:f7f1f0d76dd6 1394 result = CODEFIRST_INVALID_ARG;
XinZhangMS 0:f7f1f0d76dd6 1395 break;
XinZhangMS 0:f7f1f0d76dd6 1396 }
XinZhangMS 0:f7f1f0d76dd6 1397 else
XinZhangMS 0:f7f1f0d76dd6 1398 {
XinZhangMS 0:f7f1f0d76dd6 1399 DEVICE_HEADER_DATA* currentValueDeviceHeader = FindDevice(value);
XinZhangMS 0:f7f1f0d76dd6 1400 if (currentValueDeviceHeader == NULL)
XinZhangMS 0:f7f1f0d76dd6 1401 {
XinZhangMS 0:f7f1f0d76dd6 1402 result = CODEFIRST_INVALID_ARG;
XinZhangMS 0:f7f1f0d76dd6 1403 LOG_CODEFIRST_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1404 break;
XinZhangMS 0:f7f1f0d76dd6 1405 }
XinZhangMS 0:f7f1f0d76dd6 1406 /*Codes_SRS_CODEFIRST_02_019: [ If values passed through va_args do not belong to the same device then CodeFirst_SendAsyncReported shall fail and return CODEFIRST_VALUES_FROM_DIFFERENT_DEVICES_ERROR. ]*/
XinZhangMS 0:f7f1f0d76dd6 1407 else if ((deviceHeader != NULL) &&
XinZhangMS 0:f7f1f0d76dd6 1408 (currentValueDeviceHeader != deviceHeader))
XinZhangMS 0:f7f1f0d76dd6 1409 {
XinZhangMS 0:f7f1f0d76dd6 1410 result = CODEFIRST_VALUES_FROM_DIFFERENT_DEVICES_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1411 LOG_CODEFIRST_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1412 break;
XinZhangMS 0:f7f1f0d76dd6 1413 }
XinZhangMS 0:f7f1f0d76dd6 1414 /*Codes_SRS_CODEFIRST_02_022: [ CodeFirst_SendAsyncReported shall start a transaction by calling Device_CreateTransaction_ReportedProperties. ]*/
XinZhangMS 0:f7f1f0d76dd6 1415 else if ((deviceHeader == NULL) &&
XinZhangMS 0:f7f1f0d76dd6 1416 ((transaction = Device_CreateTransaction_ReportedProperties(currentValueDeviceHeader->DeviceHandle)) == NULL))
XinZhangMS 0:f7f1f0d76dd6 1417 {
XinZhangMS 0:f7f1f0d76dd6 1418 result = CODEFIRST_DEVICE_PUBLISH_FAILED;
XinZhangMS 0:f7f1f0d76dd6 1419 LOG_CODEFIRST_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1420 break;
XinZhangMS 0:f7f1f0d76dd6 1421 }
XinZhangMS 0:f7f1f0d76dd6 1422 else
XinZhangMS 0:f7f1f0d76dd6 1423 {
XinZhangMS 0:f7f1f0d76dd6 1424 deviceHeader = currentValueDeviceHeader;
XinZhangMS 0:f7f1f0d76dd6 1425 if (value == ((unsigned char*)deviceHeader->data))
XinZhangMS 0:f7f1f0d76dd6 1426 {
XinZhangMS 0:f7f1f0d76dd6 1427 /*Codes_SRS_CODEFIRST_02_021: [ If the value passed through va_args is a complete model instance, then CodeFirst_SendAsyncReported shall send all the reported properties of that device. ]*/
XinZhangMS 0:f7f1f0d76dd6 1428 result = SendAllDeviceReportedProperties(deviceHeader, transaction);
XinZhangMS 0:f7f1f0d76dd6 1429 if (result != CODEFIRST_OK)
XinZhangMS 0:f7f1f0d76dd6 1430 {
XinZhangMS 0:f7f1f0d76dd6 1431 LOG_CODEFIRST_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1432 break;
XinZhangMS 0:f7f1f0d76dd6 1433 }
XinZhangMS 0:f7f1f0d76dd6 1434 }
XinZhangMS 0:f7f1f0d76dd6 1435 else
XinZhangMS 0:f7f1f0d76dd6 1436 {
XinZhangMS 0:f7f1f0d76dd6 1437 /*Codes_SRS_CODEFIRST_02_020: [ If values passed through va_args are not all of type REFLECTED_REPORTED_PROPERTY then CodeFirst_SendAsyncReported shall fail and return CODEFIRST_INVALID_ARG. ]*/
XinZhangMS 0:f7f1f0d76dd6 1438 const REFLECTED_SOMETHING* propertyReflectedData;
XinZhangMS 0:f7f1f0d76dd6 1439 const char* modelName;
XinZhangMS 0:f7f1f0d76dd6 1440
XinZhangMS 0:f7f1f0d76dd6 1441 STRING_HANDLE valuePath;
XinZhangMS 0:f7f1f0d76dd6 1442 if ((valuePath = STRING_new()) == NULL)
XinZhangMS 0:f7f1f0d76dd6 1443 {
XinZhangMS 0:f7f1f0d76dd6 1444 result = CODEFIRST_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1445 LOG_CODEFIRST_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1446 break;
XinZhangMS 0:f7f1f0d76dd6 1447 }
XinZhangMS 0:f7f1f0d76dd6 1448 else
XinZhangMS 0:f7f1f0d76dd6 1449 {
XinZhangMS 0:f7f1f0d76dd6 1450 modelName = Schema_GetModelName(deviceHeader->ModelHandle);
XinZhangMS 0:f7f1f0d76dd6 1451
XinZhangMS 0:f7f1f0d76dd6 1452 /*Codes_SRS_CODEFIRST_02_025: [ CodeFirst_SendAsyncReported shall compute for every AGENT_DATA_TYPE the valuePath. ]*/
XinZhangMS 0:f7f1f0d76dd6 1453 if ((propertyReflectedData = FindReportedProperty(deviceHeader, value, modelName, 0, valuePath)) == NULL)
XinZhangMS 0:f7f1f0d76dd6 1454 {
XinZhangMS 0:f7f1f0d76dd6 1455 result = CODEFIRST_INVALID_ARG;
XinZhangMS 0:f7f1f0d76dd6 1456 LOG_CODEFIRST_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1457 STRING_delete(valuePath);
XinZhangMS 0:f7f1f0d76dd6 1458 break;
XinZhangMS 0:f7f1f0d76dd6 1459 }
XinZhangMS 0:f7f1f0d76dd6 1460 else
XinZhangMS 0:f7f1f0d76dd6 1461 {
XinZhangMS 0:f7f1f0d76dd6 1462 AGENT_DATA_TYPE agentDataType;
XinZhangMS 0:f7f1f0d76dd6 1463 /*Codes_SRS_CODEFIRST_02_023: [ CodeFirst_SendAsyncReported shall convert all REPORTED_PROPERTY model components to AGENT_DATA_TYPE. ]*/
XinZhangMS 0:f7f1f0d76dd6 1464 if (propertyReflectedData->what.reportedProperty.Create_AGENT_DATA_TYPE_from_Ptr(value, &agentDataType) != AGENT_DATA_TYPES_OK)
XinZhangMS 0:f7f1f0d76dd6 1465 {
XinZhangMS 0:f7f1f0d76dd6 1466 result = CODEFIRST_AGENT_DATA_TYPE_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1467 LOG_CODEFIRST_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1468 STRING_delete(valuePath);
XinZhangMS 0:f7f1f0d76dd6 1469 break;
XinZhangMS 0:f7f1f0d76dd6 1470 }
XinZhangMS 0:f7f1f0d76dd6 1471 else
XinZhangMS 0:f7f1f0d76dd6 1472 {
XinZhangMS 0:f7f1f0d76dd6 1473 /*Codes_SRS_CODEFIRST_02_024: [ CodeFirst_SendAsyncReported shall call Device_PublishTransacted_ReportedProperty for every AGENT_DATA_TYPE converted from REPORTED_PROPERTY. ]*/
XinZhangMS 0:f7f1f0d76dd6 1474 if (Device_PublishTransacted_ReportedProperty(transaction, STRING_c_str(valuePath), &agentDataType) != DEVICE_OK)
XinZhangMS 0:f7f1f0d76dd6 1475 {
XinZhangMS 0:f7f1f0d76dd6 1476 Destroy_AGENT_DATA_TYPE(&agentDataType);
XinZhangMS 0:f7f1f0d76dd6 1477 result = CODEFIRST_DEVICE_PUBLISH_FAILED;
XinZhangMS 0:f7f1f0d76dd6 1478 LOG_CODEFIRST_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1479 STRING_delete(valuePath);
XinZhangMS 0:f7f1f0d76dd6 1480 break;
XinZhangMS 0:f7f1f0d76dd6 1481 }
XinZhangMS 0:f7f1f0d76dd6 1482 else
XinZhangMS 0:f7f1f0d76dd6 1483 {
XinZhangMS 0:f7f1f0d76dd6 1484 STRING_delete(valuePath);
XinZhangMS 0:f7f1f0d76dd6 1485 }
XinZhangMS 0:f7f1f0d76dd6 1486 Destroy_AGENT_DATA_TYPE(&agentDataType);
XinZhangMS 0:f7f1f0d76dd6 1487 }
XinZhangMS 0:f7f1f0d76dd6 1488 }
XinZhangMS 0:f7f1f0d76dd6 1489 }
XinZhangMS 0:f7f1f0d76dd6 1490 }
XinZhangMS 0:f7f1f0d76dd6 1491 }
XinZhangMS 0:f7f1f0d76dd6 1492 }
XinZhangMS 0:f7f1f0d76dd6 1493 }
XinZhangMS 0:f7f1f0d76dd6 1494
XinZhangMS 0:f7f1f0d76dd6 1495 /*Codes_SRS_CODEFIRST_02_027: [ If any error occurs, CodeFirst_SendAsyncReported shall fail and return CODEFIRST_ERROR. ]*/
XinZhangMS 0:f7f1f0d76dd6 1496 if (i < numReportedProperties)
XinZhangMS 0:f7f1f0d76dd6 1497 {
XinZhangMS 0:f7f1f0d76dd6 1498 if (transaction != NULL)
XinZhangMS 0:f7f1f0d76dd6 1499 {
XinZhangMS 0:f7f1f0d76dd6 1500 Device_DestroyTransaction_ReportedProperties(transaction);
XinZhangMS 0:f7f1f0d76dd6 1501 }
XinZhangMS 0:f7f1f0d76dd6 1502 }
XinZhangMS 0:f7f1f0d76dd6 1503 /*Codes_SRS_CODEFIRST_02_026: [ CodeFirst_SendAsyncReported shall call Device_CommitTransaction_ReportedProperties to commit the transaction. ]*/
XinZhangMS 0:f7f1f0d76dd6 1504 else
XinZhangMS 0:f7f1f0d76dd6 1505 {
XinZhangMS 0:f7f1f0d76dd6 1506 if (Device_CommitTransaction_ReportedProperties(transaction, destination, destinationSize) != DEVICE_OK)
XinZhangMS 0:f7f1f0d76dd6 1507 {
XinZhangMS 0:f7f1f0d76dd6 1508 result = CODEFIRST_DEVICE_PUBLISH_FAILED;
XinZhangMS 0:f7f1f0d76dd6 1509 LOG_CODEFIRST_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1510 }
XinZhangMS 0:f7f1f0d76dd6 1511 else
XinZhangMS 0:f7f1f0d76dd6 1512 {
XinZhangMS 0:f7f1f0d76dd6 1513 /*Codes_SRS_CODEFIRST_02_028: [ CodeFirst_SendAsyncReported shall return CODEFIRST_OK when it succeeds. ]*/
XinZhangMS 0:f7f1f0d76dd6 1514 result = CODEFIRST_OK;
XinZhangMS 0:f7f1f0d76dd6 1515 }
XinZhangMS 0:f7f1f0d76dd6 1516
XinZhangMS 0:f7f1f0d76dd6 1517 /*Codes_SRS_CODEFIRST_02_029: [ CodeFirst_SendAsyncReported shall call Device_DestroyTransaction_ReportedProperties to destroy the transaction. ]*/
XinZhangMS 0:f7f1f0d76dd6 1518 Device_DestroyTransaction_ReportedProperties(transaction);
XinZhangMS 0:f7f1f0d76dd6 1519 }
XinZhangMS 0:f7f1f0d76dd6 1520
XinZhangMS 0:f7f1f0d76dd6 1521 va_end(ap);
XinZhangMS 0:f7f1f0d76dd6 1522 }
XinZhangMS 0:f7f1f0d76dd6 1523 return result;
XinZhangMS 0:f7f1f0d76dd6 1524 }
XinZhangMS 0:f7f1f0d76dd6 1525
XinZhangMS 0:f7f1f0d76dd6 1526 EXECUTE_COMMAND_RESULT CodeFirst_ExecuteCommand(void* device, const char* command)
XinZhangMS 0:f7f1f0d76dd6 1527 {
XinZhangMS 0:f7f1f0d76dd6 1528 EXECUTE_COMMAND_RESULT result;
XinZhangMS 0:f7f1f0d76dd6 1529 /*Codes_SRS_CODEFIRST_02_014: [If parameter device or command is NULL then CodeFirst_ExecuteCommand shall return EXECUTE_COMMAND_ERROR.] */
XinZhangMS 0:f7f1f0d76dd6 1530 if (
XinZhangMS 0:f7f1f0d76dd6 1531 (device == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 1532 (command == NULL)
XinZhangMS 0:f7f1f0d76dd6 1533 )
XinZhangMS 0:f7f1f0d76dd6 1534 {
XinZhangMS 0:f7f1f0d76dd6 1535 result = EXECUTE_COMMAND_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1536 LogError("invalid argument (NULL) passed to CodeFirst_ExecuteCommand void* device = %p, const char* command = %p", device, command);
XinZhangMS 0:f7f1f0d76dd6 1537 }
XinZhangMS 0:f7f1f0d76dd6 1538 else
XinZhangMS 0:f7f1f0d76dd6 1539 {
XinZhangMS 0:f7f1f0d76dd6 1540 /*Codes_SRS_CODEFIRST_02_015: [CodeFirst_ExecuteCommand shall find the device.]*/
XinZhangMS 0:f7f1f0d76dd6 1541 DEVICE_HEADER_DATA* deviceHeader = FindDevice(device);
XinZhangMS 0:f7f1f0d76dd6 1542 if(deviceHeader == NULL)
XinZhangMS 0:f7f1f0d76dd6 1543 {
XinZhangMS 0:f7f1f0d76dd6 1544 /*Codes_SRS_CODEFIRST_02_016: [If finding the device fails, then CodeFirst_ExecuteCommand shall return EXECUTE_COMMAND_ERROR.]*/
XinZhangMS 0:f7f1f0d76dd6 1545 result = EXECUTE_COMMAND_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1546 LogError("unable to find the device given by address %p", device);
XinZhangMS 0:f7f1f0d76dd6 1547 }
XinZhangMS 0:f7f1f0d76dd6 1548 else
XinZhangMS 0:f7f1f0d76dd6 1549 {
XinZhangMS 0:f7f1f0d76dd6 1550 /*Codes_SRS_CODEFIRST_02_017: [Otherwise CodeFirst_ExecuteCommand shall call Device_ExecuteCommand and return what Device_ExecuteCommand is returning.] */
XinZhangMS 0:f7f1f0d76dd6 1551 result = Device_ExecuteCommand(deviceHeader->DeviceHandle, command);
XinZhangMS 0:f7f1f0d76dd6 1552 }
XinZhangMS 0:f7f1f0d76dd6 1553 }
XinZhangMS 0:f7f1f0d76dd6 1554 return result;
XinZhangMS 0:f7f1f0d76dd6 1555 }
XinZhangMS 0:f7f1f0d76dd6 1556
XinZhangMS 0:f7f1f0d76dd6 1557 METHODRETURN_HANDLE CodeFirst_ExecuteMethod(void* device, const char* methodName, const char* methodPayload)
XinZhangMS 0:f7f1f0d76dd6 1558 {
XinZhangMS 0:f7f1f0d76dd6 1559 METHODRETURN_HANDLE result;
XinZhangMS 0:f7f1f0d76dd6 1560 if (
XinZhangMS 0:f7f1f0d76dd6 1561 (device == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 1562 (methodName== NULL) /*methodPayload can be NULL*/
XinZhangMS 0:f7f1f0d76dd6 1563 )
XinZhangMS 0:f7f1f0d76dd6 1564 {
XinZhangMS 0:f7f1f0d76dd6 1565 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 1566 LogError("invalid argument (NULL) passed to CodeFirst_ExecuteMethod void* device = %p, const char* methodName = %p", device, methodName);
XinZhangMS 0:f7f1f0d76dd6 1567 }
XinZhangMS 0:f7f1f0d76dd6 1568 else
XinZhangMS 0:f7f1f0d76dd6 1569 {
XinZhangMS 0:f7f1f0d76dd6 1570 DEVICE_HEADER_DATA* deviceHeader = FindDevice(device);
XinZhangMS 0:f7f1f0d76dd6 1571 if (deviceHeader == NULL)
XinZhangMS 0:f7f1f0d76dd6 1572 {
XinZhangMS 0:f7f1f0d76dd6 1573 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 1574 LogError("unable to find the device given by address %p", device);
XinZhangMS 0:f7f1f0d76dd6 1575 }
XinZhangMS 0:f7f1f0d76dd6 1576 else
XinZhangMS 0:f7f1f0d76dd6 1577 {
XinZhangMS 0:f7f1f0d76dd6 1578 result = Device_ExecuteMethod(deviceHeader->DeviceHandle, methodName, methodPayload);
XinZhangMS 0:f7f1f0d76dd6 1579 }
XinZhangMS 0:f7f1f0d76dd6 1580 }
XinZhangMS 0:f7f1f0d76dd6 1581 return result;
XinZhangMS 0:f7f1f0d76dd6 1582 }
XinZhangMS 0:f7f1f0d76dd6 1583
XinZhangMS 0:f7f1f0d76dd6 1584 CODEFIRST_RESULT CodeFirst_IngestDesiredProperties(void* device, const char* jsonPayload, bool parseDesiredNode)
XinZhangMS 0:f7f1f0d76dd6 1585 {
XinZhangMS 0:f7f1f0d76dd6 1586 CODEFIRST_RESULT result;
XinZhangMS 0:f7f1f0d76dd6 1587 /*Codes_SRS_CODEFIRST_02_030: [ If argument device is NULL then CodeFirst_IngestDesiredProperties shall fail and return CODEFIRST_INVALID_ARG. ]*/
XinZhangMS 0:f7f1f0d76dd6 1588 /*Codes_SRS_CODEFIRST_02_031: [ If argument jsonPayload is NULL then CodeFirst_IngestDesiredProperties shall fail and return CODEFIRST_INVALID_ARG. ]*/
XinZhangMS 0:f7f1f0d76dd6 1589 if (
XinZhangMS 0:f7f1f0d76dd6 1590 (device == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 1591 (jsonPayload == NULL)
XinZhangMS 0:f7f1f0d76dd6 1592 )
XinZhangMS 0:f7f1f0d76dd6 1593 {
XinZhangMS 0:f7f1f0d76dd6 1594 LogError("invalid argument void* device=%p, const char* jsonPayload=%p", device, jsonPayload);
XinZhangMS 0:f7f1f0d76dd6 1595 result = CODEFIRST_INVALID_ARG;
XinZhangMS 0:f7f1f0d76dd6 1596 }
XinZhangMS 0:f7f1f0d76dd6 1597 else
XinZhangMS 0:f7f1f0d76dd6 1598 {
XinZhangMS 0:f7f1f0d76dd6 1599 /*Codes_SRS_CODEFIRST_02_032: [ CodeFirst_IngestDesiredProperties shall locate the device associated with device. ]*/
XinZhangMS 0:f7f1f0d76dd6 1600 DEVICE_HEADER_DATA* deviceHeader = FindDevice(device);
XinZhangMS 0:f7f1f0d76dd6 1601 if (deviceHeader == NULL)
XinZhangMS 0:f7f1f0d76dd6 1602 {
XinZhangMS 0:f7f1f0d76dd6 1603 /*Codes_SRS_CODEFIRST_02_034: [ If there is any failure, then CodeFirst_IngestDesiredProperties shall fail and return CODEFIRST_ERROR. ]*/
XinZhangMS 0:f7f1f0d76dd6 1604 LogError("unable to find a device having this memory address %p", device);
XinZhangMS 0:f7f1f0d76dd6 1605 result = CODEFIRST_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1606 }
XinZhangMS 0:f7f1f0d76dd6 1607 else
XinZhangMS 0:f7f1f0d76dd6 1608 {
XinZhangMS 0:f7f1f0d76dd6 1609 /*Codes_SRS_CODEFIRST_02_033: [ CodeFirst_IngestDesiredProperties shall call Device_IngestDesiredProperties. ]*/
XinZhangMS 0:f7f1f0d76dd6 1610 if (Device_IngestDesiredProperties(device, deviceHeader->DeviceHandle, jsonPayload, parseDesiredNode) != DEVICE_OK)
XinZhangMS 0:f7f1f0d76dd6 1611 {
XinZhangMS 0:f7f1f0d76dd6 1612 LogError("failure in Device_IngestDesiredProperties");
XinZhangMS 0:f7f1f0d76dd6 1613 result = CODEFIRST_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1614 }
XinZhangMS 0:f7f1f0d76dd6 1615 else
XinZhangMS 0:f7f1f0d76dd6 1616 {
XinZhangMS 0:f7f1f0d76dd6 1617 /*Codes_SRS_CODEFIRST_02_035: [ Otherwise, CodeFirst_IngestDesiredProperties shall return CODEFIRST_OK. ]*/
XinZhangMS 0:f7f1f0d76dd6 1618 result = CODEFIRST_OK;
XinZhangMS 0:f7f1f0d76dd6 1619 }
XinZhangMS 0:f7f1f0d76dd6 1620 }
XinZhangMS 0:f7f1f0d76dd6 1621 }
XinZhangMS 0:f7f1f0d76dd6 1622 return result;
XinZhangMS 0:f7f1f0d76dd6 1623 }
XinZhangMS 0:f7f1f0d76dd6 1624
XinZhangMS 0:f7f1f0d76dd6 1625