From 7194274c67f7bfff5838d9581211a861698beabe Mon Sep 17 00:00:00 2001 From: rex-schilasky <49162693+rex-schilasky@users.noreply.github.com> Date: Thu, 9 Jan 2025 15:29:07 +0100 Subject: [PATCH] single fields req_type, req_desc, resp_type and resp_desc removed from SMethodMon ugly logic added to make new service server implementation compatible to old v5 API (where AddDescription may be called any time separately) python API extended with datatype information for pub/sub and server/client --- ecal/core/include/ecal/types/monitoring.h | 5 -- .../src/monitoring/ecal_monitoring_impl.cpp | 11 +-- .../ecal_serialize_monitoring.cpp | 9 -- .../src/service/ecal_service_server_impl.cpp | 88 ++++++++++++++----- .../src/monitoring_compare.cpp | 8 -- .../src/monitoring_generate.cpp | 7 +- lang/python/core/src/ecal_wrap.cxx | 43 ++++++--- 7 files changed, 103 insertions(+), 68 deletions(-) diff --git a/ecal/core/include/ecal/types/monitoring.h b/ecal/core/include/ecal/types/monitoring.h index ba7051c8a5..d90d33d049 100644 --- a/ecal/core/include/ecal/types/monitoring.h +++ b/ecal/core/include/ecal/types/monitoring.h @@ -135,11 +135,6 @@ namespace eCAL { std::string mname; //second.method.req_type = method_info_.request_type.name; - iter->second.method.req_desc = method_info_.request_type.descriptor; - iter->second.method.resp_type = method_info_.response_type.name; - iter->second.method.resp_desc = method_info_.response_type.descriptor; - - // new type and descriptor fields + Logging::Log(log_level_warning, "CServiceServerImpl::SetMethodCallback: Method already exists, updating attributes and callback: " + method_); + +#if 0 // this is how it should look like if we do not use the old type and descriptor fields + // update data type and callback iter->second.method.req_datatype = method_info_.request_type; iter->second.method.resp_datatype = method_info_.response_type; + iter->second.callback = callback_; +#else + ///////////////////////////////////////////// + // old types and descriptors + ///////////////////////////////////////////// + iter->second.method.req_type = method_info_.request_type.name; + iter->second.method.resp_type = method_info_.response_type.name; + + // we need to check these fields, because the v5 implementation is using SetMethodCallback with partially filled fields + if (!method_info_.request_type.descriptor.empty()) iter->second.method.req_desc = method_info_.request_type.descriptor; + if (!method_info_.response_type.descriptor.empty()) iter->second.method.resp_desc = method_info_.response_type.descriptor; - // callback - iter->second.callback = callback_; + ///////////////////////////////////////////// + // new types, encodings and descriptors + ///////////////////////////////////////////// + iter->second.method.req_datatype.name = method_info_.request_type.name; + iter->second.method.resp_datatype.name = method_info_.response_type.name; + + // we need to check these fields, because the v5 implementation is using SetMethodCallback with partially filled fields + if (!method_info_.request_type.encoding.empty()) iter->second.method.req_datatype.encoding = method_info_.request_type.encoding; + if (!method_info_.response_type.encoding.empty()) iter->second.method.resp_datatype.encoding = method_info_.response_type.encoding; + if (!method_info_.request_type.descriptor.empty()) iter->second.method.req_datatype.descriptor = method_info_.request_type.descriptor; + if (!method_info_.response_type.descriptor.empty()) iter->second.method.resp_datatype.descriptor = method_info_.response_type.descriptor; + + // we need to do this ugly hack here, because the v5 implementation is using SetMethodCallback with nullptr to update descriptions (AddDescription) + if (callback_ != nullptr) + { + iter->second.callback = callback_; + } +#endif } else { @@ -99,19 +121,43 @@ namespace eCAL SMethod method; // method name method.method.mname = method_; - - // old type and descriptor fields - method.method.req_type = method_info_.request_type.name; - method.method.req_desc = method_info_.request_type.descriptor; - method.method.resp_type = method_info_.response_type.name; - method.method.resp_desc = method_info_.response_type.descriptor; - // new type and descriptor fields +#if 0 // this is how it should look like if we do not use the old type and descriptor fields + // set data type and callback method.method.req_datatype = method_info_.request_type; method.method.resp_datatype = method_info_.response_type; - - // callback - method.callback = callback_; + method.callback = callback_; +#else +#endif + ///////////////////////////////////////////// + // old types and descriptors + ///////////////////////////////////////////// + method.method.req_type = method_info_.request_type.name; + method.method.resp_type = method_info_.response_type.name; + + // we need to check these fields, because the v5 implementation is using SetMethodCallback with partially filled fields + if (!method_info_.request_type.descriptor.empty()) method.method.req_desc = method_info_.request_type.descriptor; + if (!method_info_.response_type.descriptor.empty()) method.method.resp_desc = method_info_.response_type.descriptor; + + ///////////////////////////////////////////// + // new types, encodings and descriptors + ///////////////////////////////////////////// + method.method.req_datatype.name = method_info_.request_type.name; + method.method.resp_datatype.name = method_info_.response_type.name; + + // we need to check these fields, because the v5 implementation is using SetMethodCallback with partially filled fields + if (!method_info_.request_type.encoding.empty()) method.method.req_datatype.encoding = method_info_.request_type.encoding; + if (!method_info_.response_type.encoding.empty()) method.method.resp_datatype.encoding = method_info_.response_type.encoding; + if (!method_info_.request_type.descriptor.empty()) method.method.req_datatype.descriptor = method_info_.request_type.descriptor; + if (!method_info_.response_type.descriptor.empty()) method.method.resp_datatype.descriptor = method_info_.response_type.descriptor; + + // we need to do this ugly hack here, because the v5 implementation is using SetMethodCallback with nullptr to update descriptions (AddDescription) + if (callback_ != nullptr) + { + method.callback = callback_; + } + + // apply new method m_method_map[method_] = method; } diff --git a/ecal/tests/cpp/serialization_test/src/monitoring_compare.cpp b/ecal/tests/cpp/serialization_test/src/monitoring_compare.cpp index c744f447a1..21913181b3 100644 --- a/ecal/tests/cpp/serialization_test/src/monitoring_compare.cpp +++ b/ecal/tests/cpp/serialization_test/src/monitoring_compare.cpp @@ -147,10 +147,6 @@ namespace eCAL for (size_t j = 0; j < monitoring1.server[i].methods.size(); ++j) { if (monitoring1.server[i].methods[j].mname != monitoring2.server[i].methods[j].mname || - monitoring1.server[i].methods[j].req_type != monitoring2.server[i].methods[j].req_type || - monitoring1.server[i].methods[j].req_desc != monitoring2.server[i].methods[j].req_desc || - monitoring1.server[i].methods[j].resp_type != monitoring2.server[i].methods[j].resp_type || - monitoring1.server[i].methods[j].resp_desc != monitoring2.server[i].methods[j].resp_desc || monitoring1.server[i].methods[j].req_datatype != monitoring2.server[i].methods[j].req_datatype || monitoring1.server[i].methods[j].resp_datatype != monitoring2.server[i].methods[j].resp_datatype || monitoring1.server[i].methods[j].call_count != monitoring2.server[i].methods[j].call_count) @@ -184,10 +180,6 @@ namespace eCAL for (size_t j = 0; j < monitoring1.clients[i].methods.size(); ++j) { if (monitoring1.clients[i].methods[j].mname != monitoring2.clients[i].methods[j].mname || - monitoring1.clients[i].methods[j].req_type != monitoring2.clients[i].methods[j].req_type || - monitoring1.clients[i].methods[j].req_desc != monitoring2.clients[i].methods[j].req_desc || - monitoring1.clients[i].methods[j].resp_type != monitoring2.clients[i].methods[j].resp_type || - monitoring1.clients[i].methods[j].resp_desc != monitoring2.clients[i].methods[j].resp_desc || monitoring1.clients[i].methods[j].req_datatype != monitoring2.clients[i].methods[j].req_datatype || monitoring1.clients[i].methods[j].resp_datatype != monitoring2.clients[i].methods[j].resp_datatype || monitoring1.clients[i].methods[j].call_count != monitoring2.clients[i].methods[j].call_count) diff --git a/ecal/tests/cpp/serialization_test/src/monitoring_generate.cpp b/ecal/tests/cpp/serialization_test/src/monitoring_generate.cpp index 0d50929924..c0590e8817 100644 --- a/ecal/tests/cpp/serialization_test/src/monitoring_generate.cpp +++ b/ecal/tests/cpp/serialization_test/src/monitoring_generate.cpp @@ -79,12 +79,7 @@ namespace eCAL SMethodMon GenerateServiceMethod() { SMethodMon method; - method.mname = GenerateString(8); - - method.req_type = GenerateString(8); // deprecated - method.req_desc = GenerateString(10); // deprecated - method.resp_type = GenerateString(8); // deprecated - method.resp_desc = GenerateString(10); // deprecated + method.mname = GenerateString(8); method.req_datatype = eCAL::Registration::GenerateDataTypeInformation(); method.resp_datatype = eCAL::Registration::GenerateDataTypeInformation(); diff --git a/lang/python/core/src/ecal_wrap.cxx b/lang/python/core/src/ecal_wrap.cxx index 999cd232c6..a269be22b5 100644 --- a/lang/python/core/src/ecal_wrap.cxx +++ b/lang/python/core/src/ecal_wrap.cxx @@ -1021,7 +1021,14 @@ namespace val = Py_BuildValue("s", topic.direction.c_str()); PyDict_SetItemString(topicDict, "direction", val); Py_DECREF(val); - // TODO: SDataTypeInformation tdatatype + val = Py_BuildValue("s", topic.tdatatype.name.c_str()); + PyDict_SetItemString(topicDict, "tdatatype_name", val); Py_DECREF(val); + + val = Py_BuildValue("s", topic.tdatatype.encoding.c_str()); + PyDict_SetItemString(topicDict, "tdatatype_encoding", val); Py_DECREF(val); + + val = Py_BuildValue("y#", topic.tdatatype.descriptor.c_str(), topic.tdatatype.descriptor.length()); + PyDict_SetItemString(topicDict, "tdatatype_descriptor", val); Py_DECREF(val); // TODO: std::vector tlayer @@ -1165,15 +1172,23 @@ PyObject* mon_monitoring(PyObject* /*self*/, PyObject* /*args*/) val = Py_BuildValue("s", method.mname.c_str()); PyDict_SetItemString(methodsDict, "mname", val); Py_DECREF(val); - val = Py_BuildValue("s", method.req_type.c_str()); + val = Py_BuildValue("s", method.req_datatype.name.c_str()); PyDict_SetItemString(methodsDict, "req_type", val); Py_DECREF(val); - // TODO: std::string req_desc + val = Py_BuildValue("s", method.req_datatype.encoding.c_str()); + PyDict_SetItemString(methodsDict, "req_encoding", val); Py_DECREF(val); - val = Py_BuildValue("s", method.resp_type.c_str()); + val = Py_BuildValue("y#", method.req_datatype.descriptor.c_str(), method.req_datatype.descriptor.length()); + PyDict_SetItemString(methodsDict, "req_descriptor", val); Py_DECREF(val); + + val = Py_BuildValue("s", method.resp_datatype.name.c_str()); PyDict_SetItemString(methodsDict, "resp_type", val); Py_DECREF(val); - // TODO: std::string resp_desc + val = Py_BuildValue("s", method.resp_datatype.encoding.c_str()); + PyDict_SetItemString(methodsDict, "resp_encoding", val); Py_DECREF(val); + + val = Py_BuildValue("y#", method.resp_datatype.descriptor.c_str(), method.resp_datatype.descriptor.length()); + PyDict_SetItemString(methodsDict, "resp_descriptor", val); Py_DECREF(val); val = Py_BuildValue("i", method.call_count); PyDict_SetItemString(methodsDict, "call_count", val); Py_DECREF(val); @@ -1220,15 +1235,23 @@ PyObject* mon_monitoring(PyObject* /*self*/, PyObject* /*args*/) val = Py_BuildValue("s", method.mname.c_str()); PyDict_SetItemString(methodsDict, "mname", val); Py_DECREF(val); - val = Py_BuildValue("s", method.req_type.c_str()); + val = Py_BuildValue("s", method.req_datatype.name.c_str()); PyDict_SetItemString(methodsDict, "req_type", val); Py_DECREF(val); - // TODO: std::string req_desc - - val = Py_BuildValue("s", method.resp_type.c_str()); + val = Py_BuildValue("s", method.req_datatype.encoding.c_str()); + PyDict_SetItemString(methodsDict, "req_encoding", val); Py_DECREF(val); + + val = Py_BuildValue("y#", method.req_datatype.descriptor.c_str(), method.req_datatype.descriptor.length()); + PyDict_SetItemString(methodsDict, "req_descriptor", val); Py_DECREF(val); + + val = Py_BuildValue("s", method.resp_datatype.name.c_str()); PyDict_SetItemString(methodsDict, "resp_type", val); Py_DECREF(val); - // TODO: std::string resp_desc + val = Py_BuildValue("s", method.resp_datatype.encoding.c_str()); + PyDict_SetItemString(methodsDict, "resp_encoding", val); Py_DECREF(val); + + val = Py_BuildValue("y#", method.resp_datatype.descriptor.c_str(), method.resp_datatype.descriptor.length()); + PyDict_SetItemString(methodsDict, "resp_descriptor", val); Py_DECREF(val); val = Py_BuildValue("i", method.call_count); PyDict_SetItemString(methodsDict, "call_count", val); Py_DECREF(val);