GCC Code Coverage Report


Directory: src/gate/
File: src/gate/tech/cxx_microservices.cpp
Date: 2026-02-03 22:06:38
Exec Total Coverage
Lines: 226 455 49.7%
Functions: 54 96 56.2%
Branches: 98 378 25.9%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2026, 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.hpp"
30
31 namespace gate
32 {
33 namespace tech
34 {
35
36 /******************************
37 * MicroHost implementation *
38 ******************************/
39
40 1 MicroHost::MicroHost(gate_microhost_t* host) noexcept
41 1 : object_impl_t(host)
42 {
43 1 }
44
45 1 MicroHost::~MicroHost() noexcept
46 {
47
48 1 }
49
50 void MicroHost::publishMessage(String const& sourceAddress, String const& destinationAddress, String const& msgId, String const& message)
51 {
52 result_t result = gate_microhost_publish_message(this->c_impl(),
53 sourceAddress.c_impl(), destinationAddress.c_impl(),
54 msgId.c_impl(), message.c_impl());
55 GATEXX_CHECK_EXCEPTION(result);
56 }
57 void MicroHost::publishObject(String const& sourceAddress, String const& destinationAddress, String const& objId, Object& obj)
58 {
59 result_t result = gate_microhost_publish_object(this->c_impl(),
60 sourceAddress.c_impl(), destinationAddress.c_impl(),
61 objId.c_impl(), obj.c_impl());
62 GATEXX_CHECK_EXCEPTION(result);
63 }
64
65 void MicroHost::subscribeMessages(String const& sourceAddress, String const& destinationAddress, String const& msgId, MicroService& obj, void* userData)
66 {
67 result_t result = gate_microhost_subscribe_messages(this->c_impl(),
68 sourceAddress.c_impl(), destinationAddress.c_impl(),
69 msgId.c_impl(), obj.c_impl(), userData);
70 GATEXX_CHECK_EXCEPTION(result);
71 }
72 void MicroHost::unsubscribeMessages(String const& sourceAddress, String const& destinationAddress, String const& msgId, MicroService& obj, void* userData)
73 {
74 result_t result = gate_microhost_unsubscribe_messages(this->c_impl(),
75 sourceAddress.c_impl(), destinationAddress.c_impl(),
76 msgId.c_impl(), obj.c_impl(), userData);
77 GATEXX_CHECK_EXCEPTION(result);
78 }
79
80 void MicroHost::subscribeObjects(String const& sourceAddress, String const& destinationAddress, String const& objId, MicroService& obj, void* userData)
81 {
82 result_t result = gate_microhost_subscribe_objects(this->c_impl(),
83 sourceAddress.c_impl(), destinationAddress.c_impl(),
84 objId.c_impl(), obj.c_impl(), userData);
85 GATEXX_CHECK_EXCEPTION(result);
86 }
87 void MicroHost::unsubscribeObjects(String const& sourceAddress, String const& destinationAddress, String const& objId, MicroService& obj, void* userData)
88 {
89 result_t result = gate_microhost_unsubscribe_objects(this->c_impl(),
90 sourceAddress.c_impl(), destinationAddress.c_impl(),
91 objId.c_impl(), obj.c_impl(), userData);
92 GATEXX_CHECK_EXCEPTION(result);
93 }
94
95 void MicroHost::remoteInvoke(String const& destinationAddress, String const& method, ConstStruct& inputData, MutableStruct& outputData)
96 {
97 result_t result = gate_microhost_remote_invoke(this->c_impl(),
98 destinationAddress.c_impl(), method.c_impl(),
99 inputData.c_impl(), outputData.c_impl());
100 GATEXX_CHECK_EXCEPTION(result);
101 }
102
103 void MicroHost::log(uint32_t logType, result_t resultCode, int32_t nativeCode, String const& origin, String const& message)
104 {
105 result_t result = gate_microhost_log(this->c_impl(),
106 logType, resultCode, nativeCode,
107 origin.c_impl(), message.c_impl());
108 GATEXX_CHECK_EXCEPTION(result);
109 }
110
111
112
113
114 /*********************************
115 * MicroService implementation *
116 *********************************/
117
118 2 MicroService::MicroService(gate_microservice_t* service) noexcept
119 2 : Startable((gate_startable_t*)service)
120 {
121 2 }
122
123 35 gate_microservice_t* MicroService::c_impl() const noexcept
124 {
125 35 return reinterpret_cast<gate_microservice_t*>(Startable::c_impl());
126 }
127
128
129 void MicroService::setup(String const& instanceAddress, MicroHost& host)
130 {
131 result_t result = gate_microservice_setup(this->c_impl(), instanceAddress.c_impl(), host.c_impl());
132 GATEXX_CHECK_EXCEPTION(result);
133 }
134 String MicroService::getAddress()
135 {
136 gate_string_t tmp;
137 result_t result = gate_microservice_get_address(this->c_impl(), &tmp);
138 GATEXX_CHECK_ERROR(result);
139 return String::createFrom(tmp);
140 }
141 1 enumint_t MicroService::getConditionBits()
142 {
143 1 enumint_t condition = 0;
144
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 result_t result = gate_microservice_get_condition_bits(this->c_impl(), &condition);
145
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_ERROR(result);
146 1 return condition;
147 }
148
149 1 Array<String> MicroService::getParameterNames()
150 {
151 1 Array<String> ret;
152 gate_array_t tmp;
153
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 result_t result = gate_microservice_get_parameter_names(this->c_impl(), &tmp);
154
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_ERROR(result);
155
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 return util::createStringArray(tmp).toArray();
156 }
157 4 Property::TypeEnum MicroService::getParameterType(String const& paramName)
158 {
159 4 uint32_t type = 0;
160
1/2
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
4 result_t result = gate_microservice_get_parameter_type(this->c_impl(), paramName.c_impl(), &type);
161
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
4 GATEXX_CHECK_EXCEPTION(result);
162 4 return (Property::TypeEnum)type;
163 }
164 4 Property MicroService::getParameter(String const& paramName)
165 {
166 gate_property_t tmp;
167
1/2
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
4 result_t result = gate_microservice_get_parameter(this->c_impl(), paramName.c_impl(), &tmp);
168
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
4 GATEXX_CHECK_EXCEPTION(result);
169
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
8 return Property::createFrom(tmp);
170 }
171 7 void MicroService::setParameter(String const& paramName, Property const& value)
172 {
173 7 result_t result = gate_microservice_set_parameter(this->c_impl(), paramName.c_impl(), value.c_impl());
174
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 GATEXX_CHECK_EXCEPTION(result);
175 7 }
176
177
178
179
180 2 MicroServiceActivities::~MicroServiceActivities() noexcept
181 {
182 2 }
183
184 /*************************************
185 * MicroServiceBase implementation *
186 *************************************/
187
188
189 1 MicroServiceBase::MicroServiceBase(String const& serviceName)
190 : impl(),
191 name(serviceName),
192 status(MicroService::Status_Offline),
193 conditionBits(0),
194 host(NULL),
195
2/4
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
1 genericParameters(Property::object_members_t())
196 {
197 static GATE_INTERFACE_VTBL(gate_microservice) local_vtbl = {
198 &MicroServiceBase::msi_get_interface_name,
199 &MicroServiceBase::msi_release,
200 &MicroServiceBase::msi_retain,
201 &MicroServiceBase::msi_start,
202 &MicroServiceBase::msi_stop,
203 &MicroServiceBase::msi_get_status,
204 &MicroServiceBase::msi_setup,
205 &MicroServiceBase::msi_get_address,
206 &MicroServiceBase::msi_get_condition_bits,
207 &MicroServiceBase::msi_process_message,
208 &MicroServiceBase::msi_process_object,
209 &MicroServiceBase::msi_invoke,
210 &MicroServiceBase::msi_get_parameter_names,
211 &MicroServiceBase::msi_get_parameter_type,
212 &MicroServiceBase::msi_get_parameter,
213 &MicroServiceBase::msi_set_parameter
214 };
215
216 1 this->impl.vtbl = &local_vtbl;
217
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 gate_atomic_int_init(&this->impl.refcounter, 0);
218 1 this->impl.parent = this;
219 1 }
220
221 2 MicroServiceBase::~MicroServiceBase() noexcept
222 {
223 try
224 {
225 2 this->onDestroy();
226 }
227 catch (...)
228 {
229 }
230 2 }
231
232 1 MicroService MicroServiceBase::getInstance()
233 {
234 1 MicroService service(&this->impl);
235
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 gate_object_retain(&this->impl);
236 1 return service;
237 }
238
239
240 1 MicroServiceBase::StatusEnum MicroServiceBase::getStatus()
241 {
242 1 return this->onReadStatus();
243 }
244 1 enumint_t MicroServiceBase::getConditionBits()
245 {
246 1 return this->onReadConditionBits();
247 }
248 void MicroServiceBase::setup(String const& instanceAddress, MicroHost& hostInterface)
249 {
250 if (!this->updateStatus(MicroService::Status_Offline, MicroService::Status_Configure))
251 {
252 GATEXX_RAISE_EXCEPTION(results::InvalidState, "Service not in offline state", 0);
253 }
254
255 try
256 {
257 this->address = instanceAddress;
258 this->host = hostInterface;
259 }
260 catch (...)
261 {
262 this->updateStatus(MicroService::Status_Offline);
263 throw;
264 }
265 this->updateStatus(MicroService::Status_Offline);
266 }
267 void MicroServiceBase::start()
268 {
269 if (!this->updateStatus(MicroService::Status_Offline, MicroService::Status_Starting))
270 {
271 GATEXX_RAISE_EXCEPTION(results::InvalidState, "Service not in offline state", 0);
272 }
273
274 try
275 {
276 this->onStart();
277 }
278 catch (...)
279 {
280 this->updateStatus(MicroService::Status_Offline);
281 throw;
282 }
283
284 this->updateStatus(MicroService::Status_Online);
285 }
286
287 void MicroServiceBase::stop()
288 {
289 if (!this->updateStatus(MicroService::Status_Online, MicroService::Status_Stopping))
290 {
291 GATEXX_RAISE_EXCEPTION(results::InvalidState, "Service not in line state", 0);
292 }
293 try
294 {
295 this->onStop();
296 }
297 catch (...)
298 {
299 //this->updateStatus(MicroService::Status_Online);
300 this->updateStatus(MicroService::Status_Error);
301 }
302 this->updateStatus(MicroService::Status_Offline);
303 }
304
305 template<class KEY, class VALUE, class COMP>
306 8 void addMapKeysToArrayList(Map<KEY, VALUE, COMP> const& mapping, ArrayList<KEY>& keys)
307 {
308 8 Enumerator<KEY const> e = mapping.enumerateKeys();
309
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
16 for(; e.valid(); e.next())
310 {
311
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
8 keys.add(*e);
312 }
313 8 }
314
315 template<class KEY, class VALUE, class COMP>
316 60 VALUE getMappedValue(Map<KEY, VALUE, COMP> const& mapping, KEY const& key)
317 {
318 typedef typename Map<KEY, VALUE, COMP>::const_iterator iter_t;
319 120 iter_t const iter = mapping.get(key);
320
2/2
✓ Branch 3 taken 18 times.
✓ Branch 4 taken 12 times.
60 if(iter == mapping.end())
321 {
322 36 return NULL;
323 }
324 else
325 {
326 24 return iter.value();
327 }
328 }
329
330 1 Array<String> MicroServiceBase::getParameterNames()
331 {
332 1 StringArray names;
333
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 this->onListParameterNames(names);
334 1 return names;
335 }
336 4 Property::TypeEnum MicroServiceBase::getParameterType(String const& paramName)
337 {
338 4 Property::TypeEnum propType = Property::Type_Empty;
339
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 this->onReadParameterType(paramName, propType);
340 4 return propType;
341 }
342 4 Property MicroServiceBase::getParameter(String const& paramName)
343 {
344 4 Property prop;
345
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 this->onReadParameterValue(paramName, prop);
346 4 return prop;
347 }
348 4 void MicroServiceBase::setParameter(String const& paramName, Property const& value)
349 {
350 4 this->onWriteParameterValue(paramName, value);
351 4 }
352
353 1 MicroServiceBase::StatusEnum MicroServiceBase::onReadStatus()
354 {
355 1 return static_cast<MicroServiceBase::StatusEnum>(this->status.get());
356 }
357 1 enumint_t MicroServiceBase::onReadConditionBits()
358 {
359 1 return static_cast<enumint_t>(this->conditionBits.get());
360 }
361
362 void MicroServiceBase::onStart()
363 {
364 // override by derived class
365 }
366 void MicroServiceBase::onStop()
367 {
368 // override by derived class
369 }
370 2 void MicroServiceBase::onDestroy()
371 {
372 // override by derived class
373 2 }
374 void MicroServiceBase::onMessageReceived(String const& source, String const& destination, String const& msgId, String const& message)
375 {
376 GATE_UNUSED_ARG(source);
377 GATE_UNUSED_ARG(destination);
378 GATE_UNUSED_ARG(msgId);
379 GATE_UNUSED_ARG(message);
380 // override by derived class
381 }
382 void MicroServiceBase::onObjectReceived(String const& source, String const& destination, String const& objId, Object& obj)
383 {
384 GATE_UNUSED_ARG(source);
385 GATE_UNUSED_ARG(destination);
386 GATE_UNUSED_ARG(objId);
387 GATE_UNUSED_ARG(obj);
388 // override by derived class
389 }
390 void MicroServiceBase::onInvoke(String const& method, ConstStruct const& request, MutableStruct& response)
391 {
392 GATE_UNUSED_ARG(method);
393 GATE_UNUSED_ARG(request);
394 GATE_UNUSED_ARG(response);
395 // override by derived class
396 }
397
398 1 void MicroServiceBase::registerParameter(String const& name, bool_t& value)
399 {
400
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 this->boolParameters.add(name, &value);
401 1 }
402 1 void MicroServiceBase::registerParameter(String const& name, int64_t& value)
403 {
404
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 this->intParameters.add(name, &value);
405 1 }
406 1 void MicroServiceBase::registerParameter(String const& name, real64_t& value)
407 {
408
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 this->realParameters.add(name, &value);
409 1 }
410 1 void MicroServiceBase::registerParameter(String const& name, String& value)
411 {
412
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 this->stringParameters.add(name, &value);
413 1 }
414
415
416 1 void MicroServiceBase::onListParameterNames(Array<String>& names)
417 {
418
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 ArrayList<String> keys;
419
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 addMapKeysToArrayList(this->boolParameters, keys);
420
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 addMapKeysToArrayList(this->intParameters, keys);
421
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 addMapKeysToArrayList(this->realParameters, keys);
422
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 addMapKeysToArrayList(this->stringParameters, keys);
423
424
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 Array<String> const genericKeys = this->genericParameters.getObjectMemberNames();
425
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 keys.addItems(genericKeys.begin(), genericKeys.end());
426
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 names = keys.toArray();
427 1 }
428 4 void MicroServiceBase::onReadParameterType(String const& paramName, TypeEnum& type)
429 {
430
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3 times.
4 if(NULL != getMappedValue(this->boolParameters, paramName))
431 {
432 1 type = Property::Type_Bool;
433 }
434
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
3 else if(NULL != getMappedValue(this->intParameters, paramName))
435 {
436 1 type = Property::Type_Int;
437 }
438
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
2 else if(NULL != getMappedValue(this->realParameters, paramName))
439 {
440 1 type = Property::Type_Real;
441 }
442
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 else if(NULL != getMappedValue(this->stringParameters, paramName))
443 {
444 1 type = Property::Type_String;
445 }
446 else
447 {
448 Property prop = this->genericParameters.getObjectMember(paramName);
449 type = prop.getType();
450 }
451 4 }
452 4 void MicroServiceBase::onReadParameterValue(String const& paramName, Property& value)
453 {
454 4 bool_t* const ptrBool = getMappedValue(this->boolParameters, paramName);
455
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (ptrBool)
456 {
457
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 value = Property(*ptrBool);
458 1 return;
459 }
460
461 3 int64_t* const ptrInt = getMappedValue(this->intParameters, paramName);
462
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (ptrInt)
463 {
464
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 value = Property(*ptrInt);
465 1 return;
466 }
467
468 2 real64_t* const ptrReal = getMappedValue(this->realParameters, paramName);
469
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (ptrReal)
470 {
471
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 value = Property(*ptrReal);
472 1 return;
473 }
474
475 1 String* const ptrStr = getMappedValue(this->stringParameters, paramName);
476
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptrStr)
477 {
478
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 value = Property(*ptrStr);
479 1 return;
480 }
481
482 value = this->genericParameters.getObjectMember(paramName);
483 }
484 4 void MicroServiceBase::onWriteParameterValue(String const& paramName, Property const& value)
485 {
486 4 bool_t* const ptrBool = getMappedValue(this->boolParameters, paramName);
487
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (ptrBool)
488 {
489 1 *ptrBool = value.getBool();
490 1 return;
491 }
492
493 3 int64_t* const ptrInt = getMappedValue(this->intParameters, paramName);
494
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (ptrInt)
495 {
496 1 *ptrInt = value.getInt();
497 1 return;
498 }
499
500 2 real64_t* const ptrReal = getMappedValue(this->realParameters, paramName);
501
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (ptrReal)
502 {
503 1 *ptrReal = value.getReal();
504 1 return;
505 }
506
507 1 String* const ptrStr = getMappedValue(this->stringParameters, paramName);
508
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptrStr)
509 {
510 1 *ptrStr = value.getString();
511 1 return;
512 }
513
514 this->genericParameters.addObjectMember(paramName, value);
515 }
516
517
518 String MicroServiceBase::getAddress() const
519 {
520 return this->address;
521 }
522 void MicroServiceBase::publishMessage(String const& destinationAddress, String const& msgId, String const& message)
523 {
524 if (!this->updateStatus(MicroService::Status_Online, MicroService::Status_Online))
525 {
526 GATEXX_RAISE_EXCEPTION(results::InvalidState, "Service not in online state", 0);
527 }
528 this->host.publishMessage(this->getAddress(), destinationAddress, msgId, message);
529 }
530 void MicroServiceBase::publishObject(String const& destinationAddress, String const& objId, Object& obj)
531 {
532 if (!this->updateStatus(MicroService::Status_Online, MicroService::Status_Online))
533 {
534 GATEXX_RAISE_EXCEPTION(results::InvalidState, "Service not in online state", 0);
535 }
536 this->host.publishObject(this->getAddress(), destinationAddress, objId, obj);
537 }
538 void MicroServiceBase::subscribeMessages(String const& sourceAddress, String const& destAddress, String const& msgId)
539 {
540 if (!this->updateStatus(MicroService::Status_Online, MicroService::Status_Online))
541 {
542 GATEXX_RAISE_EXCEPTION(results::InvalidState, "Service not in online state", 0);
543 }
544 MicroService instance = this->getInstance();
545 this->host.subscribeMessages(sourceAddress, destAddress, msgId, instance, this);
546 }
547 void MicroServiceBase::unsubscribeMessages(String const& sourceAddress, String const& destAddress, String const& msgId)
548 {
549 if (!this->updateStatus(MicroService::Status_Online, MicroService::Status_Online))
550 {
551 GATEXX_RAISE_EXCEPTION(results::InvalidState, "Service not in online state", 0);
552 }
553 MicroService instance = this->getInstance();
554 this->host.unsubscribeMessages(sourceAddress, destAddress, msgId, instance, this);
555 }
556 void MicroServiceBase::subscribeObjects(String const& sourceAddress, String const& destAddress, String const& objId)
557 {
558 if (!this->updateStatus(MicroService::Status_Online, MicroService::Status_Online))
559 {
560 GATEXX_RAISE_EXCEPTION(results::InvalidState, "Service not in online state", 0);
561 }
562 MicroService instance = this->getInstance();
563 this->host.subscribeMessages(sourceAddress, destAddress, objId, instance, this);
564 }
565 void MicroServiceBase::unsubscribeObjects(String const& sourceAddress, String const& destAddress, String const& objId)
566 {
567 if (!this->updateStatus(MicroService::Status_Online, MicroService::Status_Online))
568 {
569 GATEXX_RAISE_EXCEPTION(results::InvalidState, "Service not in online state", 0);
570 }
571 MicroService instance = this->getInstance();
572 this->host.unsubscribeMessages(sourceAddress, destAddress, objId, instance, this);
573 }
574 void MicroServiceBase::log(LogTypeEnum type, result_t resultCode, String const& message, int32_t nativeCode)
575 {
576 if (!this->host.empty())
577 {
578 this->host.log(type, resultCode, nativeCode, this->address, message);
579 }
580 }
581 void MicroServiceBase::updateStatus(MicroService::StatusEnum newStatus)
582 {
583 this->status.set(static_cast<int32_t>(newStatus));
584 }
585 bool_t MicroServiceBase::updateStatus(MicroService::StatusEnum fromStatus, MicroService::StatusEnum toStatus)
586 {
587 MicroService::StatusEnum oldStatus = static_cast<MicroService::StatusEnum>(
588 this->status.changeIf(static_cast<int32_t>(fromStatus), static_cast<int32_t>(toStatus)));
589 return (oldStatus == fromStatus);
590 }
591 bool_t MicroServiceBase::setConditionBits(uint32_t bits)
592 {
593 int32_t addBits = static_cast<int32_t>(bits);
594 int32_t oldBits, newBits;
595 do
596 {
597 oldBits = this->conditionBits.get();
598 newBits = oldBits | addBits;
599 } while (oldBits != this->conditionBits.changeIf(oldBits, newBits));
600 return true;
601 }
602 bool_t MicroServiceBase::clearConditionBits(uint32_t bits)
603 {
604 int32_t delBits = static_cast<int32_t>(bits);
605 int32_t oldBits, newBits;
606 do
607 {
608 oldBits = this->conditionBits.get();
609 newBits = oldBits & (~delBits);
610 } while (oldBits != this->conditionBits.changeIf(oldBits, newBits));
611 return true;
612 }
613
614
615 1 char const* MicroServiceBase::msi_get_interface_name(void* thisptr)
616 {
617 1 return GATE_INTERFACE_NAME_MICROSERVICE;
618 }
619 1 void MicroServiceBase::msi_release(void* thisptr)
620 {
621 1 microservice_impl* self = (microservice_impl*)thisptr;
622
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (gate_atomic_int_dec(&self->refcounter) == 0)
623 {
624 1 MicroServiceBase* ms = self->parent;
625 1 self->parent = NULL;
626
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ms)
627 {
628 try
629 {
630
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 ms->onDestroy();
631 }
632 catch (...)
633 {
634 }
635
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 delete ms;
636 }
637 }
638 1 }
639 1 int MicroServiceBase::msi_retain(void* thisptr)
640 {
641 1 microservice_impl* self = (microservice_impl*)thisptr;
642 1 return gate_atomic_int_inc(&self->refcounter);
643 }
644
645 #define MICROSERVICEBASE_CALL(thisptr, func_call) \
646 microservice_impl* self = (microservice_impl*)thisptr; \
647 if(!self->parent) return GATE_RESULT_INVALIDSTATE; \
648 try { \
649 self->parent-> func_call ; \
650 } \
651 catch(gate::Throwable const& xcpt) { \
652 return xcpt.getResult(); \
653 } \
654 catch(...) { \
655 return GATE_RESULT_UNKNOWNEXCEPTION; \
656 }
657
658 #define MICROSERVICEBASE_CALL_RET(thisptr, ret_var, func_call) \
659 microservice_impl* self = (microservice_impl*)thisptr; \
660 if(!self->parent) return GATE_RESULT_INVALIDSTATE; \
661 try { \
662 ret_var = self->parent-> func_call ; \
663 } \
664 catch(gate::Throwable const& xcpt) { \
665 return xcpt.getResult(); \
666 } \
667 catch(...) { \
668 return GATE_RESULT_UNKNOWNEXCEPTION; \
669 }
670
671
672 gate_result_t MicroServiceBase::msi_start(void* thisptr)
673 {
674 MICROSERVICEBASE_CALL(thisptr, onStart());
675 return GATE_RESULT_OK;
676 }
677 gate_result_t MicroServiceBase::msi_stop(void* thisptr)
678 {
679 MICROSERVICEBASE_CALL(thisptr, onStop());
680 return GATE_RESULT_OK;
681 }
682 1 gate_enumint_t MicroServiceBase::msi_get_status(void* thisptr)
683 {
684 1 microservice_impl* self = (microservice_impl*)thisptr;
685
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!self->parent) return GATE_RESULT_INVALIDSTATE;
686 1 return (gate_enumint_t)self->parent->getStatus();
687 }
688
689 gate_result_t MicroServiceBase::msi_setup(void* thisptr, gate_string_t const* instance_address, gate_microhost_t* host)
690 {
691 String address(*instance_address);
692 MicroHost microhost(host);
693 gate_object_retain(host);
694
695 MICROSERVICEBASE_CALL(thisptr, setup(address, microhost));
696 return GATE_RESULT_OK;
697 }
698 gate_result_t MicroServiceBase::msi_get_address(void* thisptr, gate_string_t* ptr_output_address)
699 {
700 String address;
701 MICROSERVICEBASE_CALL_RET(thisptr, address, getAddress());
702 if (ptr_output_address)
703 {
704 gate_string_clone(ptr_output_address, address.c_impl());
705 }
706 return GATE_RESULT_OK;
707 }
708 1 gate_result_t MicroServiceBase::msi_get_condition_bits(void* thisptr, gate_enumint_t* ptr_bits)
709 {
710 1 enumint_t stat = 0;
711
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 MICROSERVICEBASE_CALL_RET(thisptr, stat, getConditionBits());
712
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_bits)
713 {
714 1 *ptr_bits = stat;
715 }
716 1 return GATE_RESULT_OK;
717 }
718
719 gate_result_t MicroServiceBase::msi_process_message(void* thisptr,
720 gate_string_t const* source_service_address, gate_string_t const* publish_channel,
721 gate_string_t const* msg_id, gate_string_t const* message, void* user_param)
722 {
723 String source(*source_service_address);
724 String channel(*publish_channel);
725 String id(*msg_id);
726 String msg(*message);
727
728 MICROSERVICEBASE_CALL(thisptr, onMessageReceived(source, channel, id, msg));
729 return GATE_RESULT_OK;
730 }
731
732 gate_result_t MicroServiceBase::msi_process_object(void* thisptr,
733 gate_string_t const* source_service_address, gate_string_t const* publish_channel,
734 gate_string_t const* obj_id, gate_object_t* ptr_object, void* user_param)
735 {
736 String source(*source_service_address);
737 String channel(*publish_channel);
738 String id(*obj_id);
739 Object obj(ptr_object);
740 gate_object_retain(ptr_object);
741
742 MICROSERVICEBASE_CALL(thisptr, onObjectReceived(source, channel, id, obj));
743 return GATE_RESULT_OK;
744 }
745
746 gate_result_t MicroServiceBase::msi_invoke(void* thisptr,
747 gate_string_t const* method, gate_struct_t const* request, gate_struct_t* response)
748 {
749 String methodName(*method);
750 ConstStruct requestStruct(request);
751 MutableStruct responseStruct(response);
752
753 MICROSERVICEBASE_CALL(thisptr, onInvoke(methodName, requestStruct, responseStruct));
754 return GATE_RESULT_OK;
755 }
756
757 1 gate_result_t MicroServiceBase::msi_get_parameter_names(void* thisptr, gate_array_t* ptr_output_names)
758 {
759 2 StringArray names;
760
761
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
1 MICROSERVICEBASE_CALL_RET(thisptr, names, getParameterNames());
762
763
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_output_names)
764 {
765
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 gate_array_duplicate(ptr_output_names, names.c_impl());
766 }
767 1 return GATE_RESULT_OK;
768 }
769
770 4 gate_result_t MicroServiceBase::msi_get_parameter_type(void* thisptr, gate_string_t const* name, gate_uint32_t* ptr_output_type)
771 {
772
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
8 String const paramName(*name);
773 4 Property::TypeEnum paramType = Property::Type_Empty;
774
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
4 MICROSERVICEBASE_CALL_RET(thisptr, paramType, getParameterType(paramName));
775
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (ptr_output_type)
776 {
777 4 *ptr_output_type = (gate_enumint_t)paramType;
778 }
779
780 4 return GATE_RESULT_OK;
781 }
782
783 4 gate_result_t MicroServiceBase::msi_get_parameter(void* thisptr, gate_string_t const* name, gate_property_t* ptr_output_value)
784 {
785
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
8 String const paramName(*name);
786
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
8 Property prop;
787
3/8
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
4 MICROSERVICEBASE_CALL_RET(thisptr, prop, getParameter(paramName));
788
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (ptr_output_value)
789 {
790
3/6
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
4 if (NULL == gate_property_copy(ptr_output_value, prop.c_impl()))
791 {
792 return GATE_RESULT_OUTOFMEMORY;
793 }
794 }
795 4 return GATE_RESULT_OK;
796 }
797
798 4 gate_result_t MicroServiceBase::msi_set_parameter(void* thisptr, gate_string_t const* name, gate_property_t const* value)
799 {
800
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
8 String const paramName(*name);
801
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
8 Property prop;
802
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (value != NULL)
803 {
804
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
4 prop = Property(*value);
805 }
806
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
4 MICROSERVICEBASE_CALL(thisptr, setParameter(paramName, prop));
807 4 return GATE_RESULT_OK;
808 }
809
810
811 /*********************************
812 * MicroFactory implementation *
813 *********************************/
814
815 2 MicroFactory::MicroFactory(gate_microfactory_t* impl) noexcept
816 2 : object_impl_t(impl)
817 {
818 2 }
819
820 2 MicroFactory::~MicroFactory() noexcept
821 {
822 2 }
823
824 Array<String> MicroFactory::getSupportedServiceNames()
825 {
826 Array<String> ret;
827 gate_array_t names = GATE_INIT_EMPTY;
828 result_t result = gate_microfactory_supported_service_names(this->c_impl(), &names);
829 GATEXX_CHECK_ERROR(result);
830 return util::createStringArray(names).toArray();
831 }
832
833 MicroService MicroFactory::createService(String const& serviceName)
834 {
835 gate_microservice_t* ptr_service = NULL;
836 result_t result = gate_microfactory_create_service(this->c_impl(), serviceName.c_impl(), &ptr_service);
837 GATEXX_CHECK_EXCEPTION(result);
838 return MicroService(ptr_service);
839 }
840
841
842
843
844 /*************************************
845 * MicroFactoryBase implementation *
846 *************************************/
847
848 1 MicroFactoryBase::MicroFactoryBase()
849 {
850 static GATE_INTERFACE_VTBL(gate_microfactory) local_vtbl = {
851 &MicroFactoryBase::mf_get_interface_name,
852 &MicroFactoryBase::mf_release,
853 &MicroFactoryBase::mf_retain,
854 &MicroFactoryBase::mf_supported_service_names,
855 &MicroFactoryBase::mf_create_service
856 };
857
858 1 this->impl.vtbl = &local_vtbl;
859 1 gate_atomic_int_init(&this->impl.refcounter, 0);
860 1 this->impl.parent = this;
861 1 }
862 2 MicroFactoryBase::~MicroFactoryBase() noexcept
863 {
864 2 }
865
866 1 MicroFactory MicroFactoryBase::getInstance()
867 {
868 1 MicroFactory factory(&this->impl);
869
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 gate_object_retain(&this->impl);
870 1 return factory;
871 }
872
873 char const* MicroFactoryBase::mf_get_interface_name(void* thisptr)
874 {
875 return GATE_INTERFACE_NAME_MICROFACTORY;
876 }
877 2 void MicroFactoryBase::mf_release(void* thisptr)
878 {
879 2 microfactory_impl* impl = (microfactory_impl*)thisptr;
880
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
2 if (gate_atomic_int_dec(&impl->refcounter) == 0)
881 {
882 1 MicroFactoryBase* ptr = impl->parent;
883 1 impl->parent = NULL;
884
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 delete ptr;
885 }
886 2 }
887 2 int MicroFactoryBase::mf_retain(void* thisptr)
888 {
889 2 microfactory_impl* impl = (microfactory_impl*)thisptr;
890 2 return gate_atomic_int_inc(&impl->refcounter);
891 }
892
893 gate_result_t MicroFactoryBase::mf_supported_service_names(void* thisptr, gate_array_t* ptr_output_names)
894 {
895 microfactory_impl* impl = (microfactory_impl*)thisptr;
896 MicroFactoryBase* ptr = impl->parent;
897 if (!ptr)
898 {
899 return GATE_RESULT_INVALIDSTATE;
900 }
901 StringArray names;
902 try
903 {
904 names = ptr->getSupportedServiceNames();
905 }
906 catch (Throwable const& xcpt)
907 {
908 return xcpt.getResult();
909 }
910 catch (...)
911 {
912 return GATE_RESULT_FAILED;
913 }
914 gate_arraylist_t names_list = gate::util::convertStringArray(names);
915 if (NULL == names_list)
916 {
917 return GATE_RESULT_OUTOFMEMORY;
918 }
919 gate_result_t ret = GATE_RESULT_OK;
920 if (ptr_output_names)
921 {
922 if (NULL == gate_array_create(ptr_output_names, names_list))
923 {
924 ret = GATE_RESULT_OUTOFMEMORY;
925 }
926 }
927 gate_arraylist_release(names_list);
928 return ret;
929 }
930
931 gate_result_t MicroFactoryBase::mf_create_service(void* thisptr, gate_string_t const* service_name, gate_microservice_t** ptr_service)
932 {
933 microfactory_impl* impl = (microfactory_impl*)thisptr;
934 MicroFactoryBase* ptr = impl->parent;
935 if (!ptr)
936 {
937 return GATE_RESULT_INVALIDSTATE;
938 }
939
940 gate_result_t ret = GATE_RESULT_FAILED;
941 try
942 {
943 String name(*service_name);
944 MicroService svc = ptr->createService(name);
945
946 if (ptr_service)
947 {
948 *ptr_service = svc.c_impl();
949 gate_object_retain(*ptr_service);
950 }
951 ret = GATE_RESULT_OK;
952 }
953 catch (Throwable const& xcpt)
954 {
955 ret = xcpt.getResult();
956 }
957 catch (...)
958 {
959 ret = GATE_RESULT_FAILED;
960 }
961 return ret;
962 }
963
964
965 } // end of namespace tech
966 } // end of namespace gate
967