| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* GATE PROJECT LICENSE: | ||
| 2 | +----------------------------------------------------------------------------+ | ||
| 3 | | Copyright(c) 2018-2025, Stefan Meislinger | | ||
| 4 | | All rights reserved. | | ||
| 5 | | | | ||
| 6 | | Redistribution and use in source and binary forms, with or without | | ||
| 7 | | modification, are permitted provided that the following conditions are met:| | ||
| 8 | | | | ||
| 9 | | 1. Redistributions of source code must retain the above copyright notice, | | ||
| 10 | | this list of conditions and the following disclaimer. | | ||
| 11 | | 2. Redistributions in binary form must reproduce the above copyright | | ||
| 12 | | notice, this list of conditions and the following disclaimer in the | | ||
| 13 | | documentation and/or other materials provided with the distribution. | | ||
| 14 | | | | ||
| 15 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"| | ||
| 16 | | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | ||
| 17 | | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | ||
| 18 | | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | | ||
| 19 | | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | ||
| 20 | | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | ||
| 21 | | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | ||
| 22 | | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | ||
| 23 | | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | ||
| 24 | | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | | ||
| 25 | | THE POSSIBILITY OF SUCH DAMAGE. | | ||
| 26 | +----------------------------------------------------------------------------+ | ||
| 27 | */ | ||
| 28 | |||
| 29 | #include "gate/tech/microservices.h" | ||
| 30 | #include "gate/properties.h" | ||
| 31 | #include "gate/results.h" | ||
| 32 | #include "gate/threading.h" | ||
| 33 | |||
| 34 | |||
| 35 | ✗ | static void msb_destroy(gate_microservice_base_t* self) | |
| 36 | { | ||
| 37 | ✗ | if (self->on_release) | |
| 38 | { | ||
| 39 | ✗ | self->on_release(self); | |
| 40 | } | ||
| 41 | ✗ | gate_property_destroy(&self->parameters); | |
| 42 | |||
| 43 | ✗ | gate_string_release(&self->address); | |
| 44 | |||
| 45 | ✗ | if (NULL != self->host) | |
| 46 | { | ||
| 47 | ✗ | gate_object_release(self->host); | |
| 48 | ✗ | self->host = NULL; | |
| 49 | } | ||
| 50 | |||
| 51 | ✗ | gate_mem_dealloc(self); | |
| 52 | ✗ | } | |
| 53 | |||
| 54 | ✗ | static char const* msb_get_interface_name(void* thisptr) | |
| 55 | { | ||
| 56 | (void)thisptr; | ||
| 57 | ✗ | return GATE_INTERFACE_NAME_MICROSERVICE; | |
| 58 | } | ||
| 59 | ✗ | static void msb_release(void* thisptr) | |
| 60 | { | ||
| 61 | ✗ | gate_microservice_base_t* self = (gate_microservice_base_t*)thisptr; | |
| 62 | ✗ | if (gate_atomic_int_dec(&self->ref_counter) == 0) | |
| 63 | { | ||
| 64 | ✗ | msb_destroy(self); | |
| 65 | } | ||
| 66 | ✗ | } | |
| 67 | ✗ | static int msb_retain(void* thisptr) | |
| 68 | { | ||
| 69 | ✗ | gate_microservice_base_t* self = (gate_microservice_base_t*)thisptr; | |
| 70 | ✗ | return gate_atomic_int_inc(&self->ref_counter); | |
| 71 | } | ||
| 72 | |||
| 73 | ✗ | static gate_bool_t msb_update_state(gate_microservice_base_t* self, gate_int32_t from_state, gate_int32_t to_state) | |
| 74 | { | ||
| 75 | ✗ | return from_state == gate_atomic_int_xchg_if(&self->status, from_state, to_state); | |
| 76 | } | ||
| 77 | ✗ | static void msb_set_state(gate_microservice_base_t* self, gate_int32_t state) | |
| 78 | { | ||
| 79 | ✗ | gate_atomic_int_set(&self->status, state); | |
| 80 | ✗ | } | |
| 81 | |||
| 82 | ✗ | static gate_result_t msb_setup(void* thisptr, gate_string_t const* instance_address, gate_microhost_t* host) | |
| 83 | { | ||
| 84 | ✗ | gate_microservice_base_t* self = (gate_microservice_base_t*)thisptr; | |
| 85 | |||
| 86 | ✗ | gate_result_t ret = GATE_RESULT_FAILED; | |
| 87 | ✗ | gate_microhost_t* old_host = NULL; | |
| 88 | gate_string_t tmp; | ||
| 89 | |||
| 90 | do | ||
| 91 | { | ||
| 92 | ✗ | if (!msb_update_state(self, GATE_MICROSERVICE_STATUS_OFFLINE, GATE_MICROSERVICE_STATUS_CONFIGURE)) | |
| 93 | { | ||
| 94 | ✗ | return GATE_RESULT_INVALIDSTATE; | |
| 95 | } | ||
| 96 | |||
| 97 | ✗ | if (instance_address) | |
| 98 | { | ||
| 99 | ✗ | if (NULL == gate_string_clone(&tmp, instance_address)) | |
| 100 | { | ||
| 101 | ✗ | ret = GATE_RESULT_OUTOFMEMORY; | |
| 102 | ✗ | break; | |
| 103 | } | ||
| 104 | ✗ | gate_string_release(&self->address); | |
| 105 | ✗ | gate_mem_copy(&self->address, &tmp, sizeof(tmp)); | |
| 106 | } | ||
| 107 | |||
| 108 | ✗ | old_host = self->host; | |
| 109 | ✗ | self->host = host; | |
| 110 | ✗ | if (self->host) | |
| 111 | { | ||
| 112 | ✗ | gate_object_retain(self->host); | |
| 113 | } | ||
| 114 | |||
| 115 | ✗ | ret = GATE_RESULT_OK; | |
| 116 | } while (0); | ||
| 117 | |||
| 118 | ✗ | if (old_host) | |
| 119 | { | ||
| 120 | ✗ | gate_object_release(old_host); | |
| 121 | } | ||
| 122 | |||
| 123 | ✗ | msb_set_state(self, GATE_MICROSERVICE_STATUS_OFFLINE); | |
| 124 | ✗ | return ret; | |
| 125 | } | ||
| 126 | |||
| 127 | ✗ | static gate_result_t msb_get_address(void* thisptr, gate_string_t* ptr_output_address) | |
| 128 | { | ||
| 129 | ✗ | gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED; | |
| 130 | ✗ | gate_microservice_base_t* self = (gate_microservice_base_t*)thisptr; | |
| 131 | |||
| 132 | do | ||
| 133 | { | ||
| 134 | ✗ | if (NULL == gate_string_clone(ptr_output_address, &self->address)) | |
| 135 | { | ||
| 136 | ✗ | ret = GATE_RESULT_OUTOFMEMORY; | |
| 137 | ✗ | break; | |
| 138 | } | ||
| 139 | ✗ | ret = GATE_RESULT_OK; | |
| 140 | } while (0); | ||
| 141 | |||
| 142 | ✗ | return ret; | |
| 143 | } | ||
| 144 | ✗ | static gate_enumint_t msb_get_status(void* thisptr) | |
| 145 | { | ||
| 146 | ✗ | gate_microservice_base_t* self = (gate_microservice_base_t*)thisptr; | |
| 147 | ✗ | gate_uint32_t ret = (gate_uint32_t)gate_atomic_int_get(&self->status); | |
| 148 | ✗ | return ret; | |
| 149 | } | ||
| 150 | ✗ | static gate_result_t msb_get_condition_bits(void* thisptr, gate_enumint_t* ptr_bits) | |
| 151 | { | ||
| 152 | ✗ | gate_microservice_base_t* self = (gate_microservice_base_t*)thisptr; | |
| 153 | ✗ | gate_int32_t bits = gate_atomic_int_get(&self->condition_bits); | |
| 154 | ✗ | if (ptr_bits) | |
| 155 | { | ||
| 156 | ✗ | *ptr_bits = (gate_enumint_t)bits; | |
| 157 | ✗ | return GATE_RESULT_OK; | |
| 158 | } | ||
| 159 | else | ||
| 160 | { | ||
| 161 | ✗ | return GATE_RESULT_INVALIDARG; | |
| 162 | } | ||
| 163 | } | ||
| 164 | |||
| 165 | ✗ | static gate_result_t msb_start(void* thisptr) | |
| 166 | { | ||
| 167 | ✗ | gate_result_t ret = GATE_RESULT_FAILED; | |
| 168 | ✗ | gate_microservice_base_t* self = (gate_microservice_base_t*)thisptr; | |
| 169 | |||
| 170 | do | ||
| 171 | { | ||
| 172 | ✗ | if (!msb_update_state(self, GATE_MICROSERVICE_STATUS_OFFLINE, GATE_MICROSERVICE_STATUS_STARTING)) | |
| 173 | { | ||
| 174 | ✗ | return GATE_RESULT_INVALIDSTATE; | |
| 175 | } | ||
| 176 | |||
| 177 | ✗ | if (self->host == NULL) | |
| 178 | { | ||
| 179 | ✗ | ret = GATE_RESULT_NOTREADY; | |
| 180 | ✗ | break; | |
| 181 | } | ||
| 182 | |||
| 183 | ✗ | if (self->on_start) | |
| 184 | { | ||
| 185 | ✗ | ret = self->on_start(self); | |
| 186 | } | ||
| 187 | else | ||
| 188 | { | ||
| 189 | ✗ | ret = GATE_RESULT_OK; | |
| 190 | } | ||
| 191 | |||
| 192 | } while (0); | ||
| 193 | |||
| 194 | |||
| 195 | ✗ | if (GATE_FAILED(ret)) | |
| 196 | { | ||
| 197 | ✗ | msb_set_state(self, GATE_MICROSERVICE_STATUS_OFFLINE); | |
| 198 | } | ||
| 199 | else | ||
| 200 | { | ||
| 201 | ✗ | msb_set_state(self, GATE_MICROSERVICE_STATUS_ONLINE); | |
| 202 | } | ||
| 203 | |||
| 204 | ✗ | return ret; | |
| 205 | } | ||
| 206 | ✗ | static gate_result_t msb_stop(void* thisptr) | |
| 207 | { | ||
| 208 | ✗ | gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED; | |
| 209 | ✗ | gate_microservice_base_t* self = (gate_microservice_base_t*)thisptr; | |
| 210 | |||
| 211 | do | ||
| 212 | { | ||
| 213 | ✗ | if (!msb_update_state(self, GATE_MICROSERVICE_STATUS_ONLINE, GATE_MICROSERVICE_STATUS_STOPPING)) | |
| 214 | { | ||
| 215 | ✗ | ret = GATE_RESULT_INVALIDSTATE; | |
| 216 | ✗ | break; | |
| 217 | } | ||
| 218 | |||
| 219 | ✗ | if (self->on_stop) | |
| 220 | { | ||
| 221 | ✗ | ret = self->on_stop(self); | |
| 222 | } | ||
| 223 | else | ||
| 224 | { | ||
| 225 | ✗ | ret = GATE_RESULT_OK; | |
| 226 | } | ||
| 227 | |||
| 228 | ✗ | if (GATE_FAILED(ret)) | |
| 229 | { | ||
| 230 | ✗ | msb_set_state(self, GATE_MICROSERVICE_STATUS_ERROR); | |
| 231 | } | ||
| 232 | else | ||
| 233 | { | ||
| 234 | ✗ | msb_set_state(self, GATE_MICROSERVICE_STATUS_OFFLINE); | |
| 235 | } | ||
| 236 | |||
| 237 | } while (0); | ||
| 238 | |||
| 239 | ✗ | return ret; | |
| 240 | } | ||
| 241 | |||
| 242 | ✗ | static gate_result_t msb_process_message(void* thisptr, gate_string_t const* source, gate_string_t const* destination, | |
| 243 | gate_string_t const* msg_id, gate_string_t const* message, void* user_param) | ||
| 244 | { | ||
| 245 | ✗ | gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED; | |
| 246 | ✗ | gate_microservice_base_t* self = (gate_microservice_base_t*)thisptr; | |
| 247 | (void)user_param; | ||
| 248 | do | ||
| 249 | { | ||
| 250 | ✗ | if (self->on_message_received) | |
| 251 | { | ||
| 252 | ✗ | ret = self->on_message_received(self, source, destination, msg_id, message); | |
| 253 | } | ||
| 254 | |||
| 255 | } while (0); | ||
| 256 | |||
| 257 | ✗ | return ret; | |
| 258 | } | ||
| 259 | |||
| 260 | ✗ | static gate_result_t msb_process_object(void* thisptr, gate_string_t const* source, gate_string_t const* destination, | |
| 261 | gate_string_t const* obj_id, gate_object_t* ptr_object, void* user_param) | ||
| 262 | { | ||
| 263 | ✗ | gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED; | |
| 264 | ✗ | gate_microservice_base_t* self = (gate_microservice_base_t*)thisptr; | |
| 265 | (void)user_param; | ||
| 266 | do | ||
| 267 | { | ||
| 268 | ✗ | if (self->on_object_received) | |
| 269 | { | ||
| 270 | ✗ | ret = self->on_object_received(self, source, destination, obj_id, ptr_object); | |
| 271 | } | ||
| 272 | |||
| 273 | } while (0); | ||
| 274 | |||
| 275 | ✗ | return ret; | |
| 276 | } | ||
| 277 | ✗ | static gate_result_t msb_invoke(void* thisptr, gate_string_t const* method, gate_struct_t const* request, | |
| 278 | gate_struct_t* response) | ||
| 279 | { | ||
| 280 | ✗ | gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED; | |
| 281 | ✗ | gate_microservice_base_t* self = (gate_microservice_base_t*)thisptr; | |
| 282 | |||
| 283 | do | ||
| 284 | { | ||
| 285 | ✗ | if (self->on_invoke) | |
| 286 | { | ||
| 287 | ✗ | ret = self->on_invoke(self, method, request, response); | |
| 288 | } | ||
| 289 | |||
| 290 | } while (0); | ||
| 291 | |||
| 292 | ✗ | return ret; | |
| 293 | } | ||
| 294 | |||
| 295 | ✗ | static gate_result_t msb_get_parameter_names(void* thisptr, gate_array_t* ptr_output_names) | |
| 296 | { | ||
| 297 | ✗ | gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED; | |
| 298 | ✗ | gate_microservice_base_t* self = (gate_microservice_base_t*)thisptr; | |
| 299 | |||
| 300 | do | ||
| 301 | { | ||
| 302 | ✗ | if (gate_property_get_type(&self->parameters) == GATE_PROPERTY_TYPE_OBJECT) | |
| 303 | { | ||
| 304 | ✗ | if (NULL == gate_property_member_names(&self->parameters, ptr_output_names)) | |
| 305 | { | ||
| 306 | ✗ | ret = GATE_RESULT_OUTOFMEMORY; | |
| 307 | } | ||
| 308 | else | ||
| 309 | { | ||
| 310 | ✗ | ret = GATE_RESULT_OK; | |
| 311 | } | ||
| 312 | } | ||
| 313 | else | ||
| 314 | { | ||
| 315 | ✗ | if (NULL == gate_array_create_empty(ptr_output_names)) | |
| 316 | { | ||
| 317 | ✗ | ret = GATE_RESULT_OUTOFMEMORY; | |
| 318 | } | ||
| 319 | else | ||
| 320 | { | ||
| 321 | ✗ | ret = GATE_RESULT_OK; | |
| 322 | } | ||
| 323 | } | ||
| 324 | } while (0); | ||
| 325 | |||
| 326 | ✗ | return ret; | |
| 327 | } | ||
| 328 | ✗ | static gate_result_t msb_get_parameter_type(void* thisptr, gate_string_t const* name, gate_uint32_t* ptr_output_type) | |
| 329 | { | ||
| 330 | ✗ | gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED; | |
| 331 | ✗ | gate_microservice_base_t* const self = (gate_microservice_base_t*)thisptr; | |
| 332 | |||
| 333 | do | ||
| 334 | { | ||
| 335 | ✗ | gate_property_t const* prop = gate_property_member_get(&self->parameters, name); | |
| 336 | ✗ | if (prop) | |
| 337 | { | ||
| 338 | ✗ | if (ptr_output_type) | |
| 339 | { | ||
| 340 | ✗ | *ptr_output_type = gate_property_get_type(prop); | |
| 341 | } | ||
| 342 | ✗ | ret = GATE_RESULT_OK; | |
| 343 | } | ||
| 344 | else | ||
| 345 | { | ||
| 346 | ✗ | ret = GATE_RESULT_NOMATCH; | |
| 347 | } | ||
| 348 | } while (0); | ||
| 349 | |||
| 350 | ✗ | return ret; | |
| 351 | } | ||
| 352 | ✗ | static gate_result_t msb_get_parameter(void* thisptr, gate_string_t const* name, gate_property_t* ptr_output_value) | |
| 353 | { | ||
| 354 | ✗ | gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED; | |
| 355 | ✗ | gate_microservice_base_t* const self = (gate_microservice_base_t*)thisptr; | |
| 356 | |||
| 357 | do | ||
| 358 | { | ||
| 359 | ✗ | gate_property_t const* const prop = gate_property_member_get(&self->parameters, name); | |
| 360 | ✗ | if (prop) | |
| 361 | { | ||
| 362 | ✗ | if (ptr_output_value) | |
| 363 | { | ||
| 364 | ✗ | if (NULL == gate_property_copy(ptr_output_value, prop)) | |
| 365 | { | ||
| 366 | ✗ | ret = GATE_RESULT_OUTOFMEMORY; | |
| 367 | ✗ | break; | |
| 368 | } | ||
| 369 | } | ||
| 370 | ✗ | ret = GATE_RESULT_OK; | |
| 371 | } | ||
| 372 | else | ||
| 373 | { | ||
| 374 | ✗ | ret = GATE_RESULT_NOMATCH; | |
| 375 | } | ||
| 376 | } while (0); | ||
| 377 | |||
| 378 | ✗ | return ret; | |
| 379 | } | ||
| 380 | ✗ | static gate_result_t msb_set_parameter(void* thisptr, gate_string_t const* name, gate_property_t const* value) | |
| 381 | { | ||
| 382 | ✗ | gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED; | |
| 383 | ✗ | gate_microservice_base_t* self = (gate_microservice_base_t*)thisptr; | |
| 384 | |||
| 385 | do | ||
| 386 | { | ||
| 387 | ✗ | gate_property_t const* prop = gate_property_member_get(&self->parameters, name); | |
| 388 | ✗ | if (prop) | |
| 389 | { | ||
| 390 | ✗ | if (gate_property_get_type(prop) == gate_property_get_type(value)) | |
| 391 | { | ||
| 392 | ✗ | if (NULL == gate_property_member_add(&self->parameters, name, value)) | |
| 393 | { | ||
| 394 | ✗ | ret = GATE_RESULT_OUTOFMEMORY; | |
| 395 | } | ||
| 396 | else | ||
| 397 | { | ||
| 398 | ✗ | ret = GATE_RESULT_OK; | |
| 399 | } | ||
| 400 | } | ||
| 401 | else | ||
| 402 | { | ||
| 403 | ✗ | ret = GATE_RESULT_INCORRECTTYPE; | |
| 404 | } | ||
| 405 | } | ||
| 406 | else | ||
| 407 | { | ||
| 408 | ✗ | ret = GATE_RESULT_NOMATCH; | |
| 409 | } | ||
| 410 | } while (0); | ||
| 411 | |||
| 412 | ✗ | return ret; | |
| 413 | } | ||
| 414 | |||
| 415 | |||
| 416 | static GATE_INTERFACE_VTBL(gate_microservice) gate_msb_vtbl; | ||
| 417 | ✗ | static void gate_init_msb_vtbl(void) | |
| 418 | { | ||
| 419 | ✗ | if (!gate_msb_vtbl.get_interface_name) | |
| 420 | { | ||
| 421 | GATE_INTERFACE_VTBL(gate_microservice) const local_vtbl = | ||
| 422 | { | ||
| 423 | &msb_get_interface_name, | ||
| 424 | &msb_release, | ||
| 425 | &msb_retain, | ||
| 426 | |||
| 427 | &msb_start, | ||
| 428 | &msb_stop, | ||
| 429 | &msb_get_status, | ||
| 430 | |||
| 431 | &msb_setup, | ||
| 432 | &msb_get_address, | ||
| 433 | &msb_get_condition_bits, | ||
| 434 | |||
| 435 | &msb_process_message, | ||
| 436 | &msb_process_object, | ||
| 437 | &msb_invoke, | ||
| 438 | |||
| 439 | &msb_get_parameter_names, | ||
| 440 | &msb_get_parameter_type, | ||
| 441 | &msb_get_parameter, | ||
| 442 | &msb_set_parameter | ||
| 443 | }; | ||
| 444 | ✗ | gate_msb_vtbl = local_vtbl; | |
| 445 | } | ||
| 446 | ✗ | } | |
| 447 | |||
| 448 | |||
| 449 | ✗ | gate_microservice_base_t* gate_microservice_base_create(gate_size_t data_size, void* user_param) | |
| 450 | { | ||
| 451 | ✗ | gate_microservice_base_t* ret = NULL; | |
| 452 | ✗ | gate_microservice_base_t* impl = NULL; | |
| 453 | do | ||
| 454 | { | ||
| 455 | ✗ | impl = (gate_microservice_base_t*)gate_mem_alloc(sizeof(gate_microservice_base_t) + data_size); | |
| 456 | ✗ | if (impl == NULL) | |
| 457 | { | ||
| 458 | ✗ | break; | |
| 459 | } | ||
| 460 | |||
| 461 | ✗ | gate_mem_clear(impl, sizeof(gate_microservice_base_t) + data_size); | |
| 462 | ✗ | gate_init_msb_vtbl(); | |
| 463 | ✗ | impl->vtbl = &gate_msb_vtbl; | |
| 464 | |||
| 465 | ✗ | gate_atomic_int_init(&impl->ref_counter, 1); | |
| 466 | ✗ | impl->user_param = user_param; | |
| 467 | ✗ | gate_atomic_int_init(&impl->status, GATE_MICROSERVICE_STATUS_OFFLINE); | |
| 468 | |||
| 469 | ✗ | gate_string_create_empty(&impl->address); | |
| 470 | ✗ | impl->host = NULL; | |
| 471 | ✗ | if (NULL == gate_property_create_object(&impl->parameters)) | |
| 472 | { | ||
| 473 | /* error */ | ||
| 474 | ✗ | break; | |
| 475 | } | ||
| 476 | |||
| 477 | ✗ | impl->data_ptr = &impl->custom_data; | |
| 478 | |||
| 479 | ✗ | ret = impl; | |
| 480 | ✗ | impl = NULL; | |
| 481 | } while (0); | ||
| 482 | |||
| 483 | ✗ | if (impl != NULL) | |
| 484 | { | ||
| 485 | ✗ | msb_destroy(impl); | |
| 486 | } | ||
| 487 | |||
| 488 | ✗ | return ret; | |
| 489 | } | ||
| 490 | |||
| 491 | ✗ | gate_result_t gate_microservice_encode_address(gate_string_t const* name, gate_string_t const* instance, gate_string_t* output_address) | |
| 492 | { | ||
| 493 | ✗ | gate_result_t ret = GATE_RESULT_FAILED; | |
| 494 | ✗ | gate_strbuilder_t builder = GATE_INIT_EMPTY; | |
| 495 | do | ||
| 496 | { | ||
| 497 | ✗ | gate_strbuilder_create(&builder, gate_string_length(name) + gate_string_length(instance) + 4); | |
| 498 | ✗ | gate_strbuilder_append_string(&builder, name); | |
| 499 | ✗ | gate_strbuilder_append_cstr(&builder, "."); | |
| 500 | ✗ | gate_strbuilder_append_string(&builder, instance); | |
| 501 | |||
| 502 | ✗ | if (NULL == gate_strbuilder_to_string(&builder, output_address)) | |
| 503 | { | ||
| 504 | ✗ | ret = GATE_RESULT_OUTOFMEMORY; | |
| 505 | ✗ | break; | |
| 506 | } | ||
| 507 | ✗ | ret = GATE_RESULT_OK; | |
| 508 | } while (0); | ||
| 509 | |||
| 510 | ✗ | gate_strbuilder_release(&builder); | |
| 511 | ✗ | return ret; | |
| 512 | } | ||
| 513 | |||
| 514 | ✗ | gate_result_t gate_microservice_decode_address(gate_string_t const* address, gate_string_t* output_name, gate_string_t* output_instance) | |
| 515 | { | ||
| 516 | ✗ | gate_size_t pos = gate_string_char_pos(address, '.', 0); | |
| 517 | ✗ | if (pos == GATE_STR_NPOS) | |
| 518 | { | ||
| 519 | ✗ | return GATE_RESULT_INVALIDINPUT; | |
| 520 | } | ||
| 521 | else | ||
| 522 | { | ||
| 523 | ✗ | if (output_name) | |
| 524 | { | ||
| 525 | ✗ | if (NULL == gate_string_substr(output_name, address, 0, pos)) | |
| 526 | { | ||
| 527 | ✗ | return GATE_RESULT_OUTOFMEMORY; | |
| 528 | } | ||
| 529 | } | ||
| 530 | ✗ | if (output_instance) | |
| 531 | { | ||
| 532 | ✗ | if (NULL == gate_string_substr(output_instance, address, pos + 1, GATE_STR_NPOS)) | |
| 533 | { | ||
| 534 | ✗ | if (output_name) | |
| 535 | { | ||
| 536 | ✗ | gate_string_release(output_name); | |
| 537 | } | ||
| 538 | ✗ | return GATE_RESULT_OUTOFMEMORY; | |
| 539 | } | ||
| 540 | } | ||
| 541 | ✗ | return GATE_RESULT_OK; | |
| 542 | } | ||
| 543 | } | ||
| 544 | |||
| 545 | ✗ | gate_result_t gate_microservice_base_set_condition_bits(gate_microservice_base_t* service, gate_uint32_t bits) | |
| 546 | { | ||
| 547 | ✗ | gate_int32_t add_bits = (gate_int32_t)bits; | |
| 548 | ✗ | unsigned retry_counter = 32; | |
| 549 | ✗ | if (!service) | |
| 550 | { | ||
| 551 | ✗ | return GATE_RESULT_INVALIDARG; | |
| 552 | } | ||
| 553 | ✗ | while (retry_counter-- != 0) | |
| 554 | { | ||
| 555 | ✗ | gate_int32_t old_bits = gate_atomic_int_get(&service->condition_bits); | |
| 556 | ✗ | gate_int32_t new_bits = old_bits | add_bits; | |
| 557 | ✗ | if (old_bits == gate_atomic_int_xchg_if(&service->condition_bits, old_bits, new_bits)) | |
| 558 | { | ||
| 559 | ✗ | return GATE_RESULT_OK; | |
| 560 | } | ||
| 561 | |||
| 562 | /* atomic concurrency issue detected, bits were changed by another thread */ | ||
| 563 | ✗ | gate_thread_yield(); | |
| 564 | } | ||
| 565 | ✗ | return GATE_RESULT_FAILED; | |
| 566 | } | ||
| 567 | |||
| 568 | ✗ | gate_result_t gate_microservice_base_clear_condition_bits(gate_microservice_base_t* service, gate_uint32_t bits) | |
| 569 | { | ||
| 570 | ✗ | gate_int32_t del_bits = (gate_int32_t)bits; | |
| 571 | ✗ | unsigned retry_counter = 32; | |
| 572 | ✗ | if (!service) | |
| 573 | { | ||
| 574 | ✗ | return GATE_RESULT_INVALIDARG; | |
| 575 | } | ||
| 576 | ✗ | while (retry_counter-- != 0) | |
| 577 | { | ||
| 578 | ✗ | gate_int32_t old_bits = gate_atomic_int_get(&service->condition_bits); | |
| 579 | ✗ | gate_int32_t new_bits = old_bits & (~del_bits); | |
| 580 | ✗ | if (old_bits == gate_atomic_int_xchg_if(&service->condition_bits, old_bits, new_bits)) | |
| 581 | { | ||
| 582 | ✗ | return GATE_RESULT_OK; | |
| 583 | } | ||
| 584 | |||
| 585 | /* atomic concurrency issue detected, bits were changed by another thread */ | ||
| 586 | ✗ | gate_thread_yield(); | |
| 587 | } | ||
| 588 | ✗ | return GATE_RESULT_FAILED; | |
| 589 | } | ||
| 590 |