Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Iox #1142 add service discovery c binding #1160

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/website/release-notes/iceoryx-v2-0-0.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
- Replace IPC-channel-based `findService` with pub/sub-based on [#415](https://github.com/eclipse-iceoryx/iceoryx/issues/415)
- Add `findService` method to `ServiceDiscovery` which applies a callable to all matching services [\#1105](https://github.com/eclipse-iceoryx/iceoryx/pull/1105)
- Increase limits of `ServiceRegistry` to support the maximum number of publishers and servers that are configured in `iceoryx_posh_types.hpp` [\#1074](https://github.com/eclipse-iceoryx/iceoryx/issues/1074)
- C binding for service discovery [\#1142](https://github.com/eclipse-iceoryx/iceoryx/issues/1142)

**Bugfixes:**

Expand Down
1 change: 1 addition & 0 deletions iceoryx_binding_c/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ add_library(${PROJECT_NAME}
source/cpp2c_publisher.cpp
source/cpp2c_subscriber.cpp
source/cpp2c_service_description_translation.cpp
source/c_service_discovery.cpp
)
add_library(${PROJECT_NAMESPACE}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})

Expand Down
3 changes: 2 additions & 1 deletion iceoryx_binding_c/include/iceoryx_binding_c/api.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2021 by Apex.AI Inc. All rights reserved.
// Copyright (c) 2021 - 2022 by Apex.AI Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -31,6 +31,7 @@
#include "runtime.h"
#include "server.h"
#include "service_description.h"
#include "service_discovery.h"
#include "subscriber.h"
#include "types.h"
#include "user_trigger.h"
Expand Down
13 changes: 13 additions & 0 deletions iceoryx_binding_c/include/iceoryx_binding_c/enums.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ enum iox_ChunkReceiveResult
ChunkReceiveResult_SUCCESS,
};

/// @brief describes events which can be triggered by a service discovery
enum iox_ServiceDiscoveryEvent
{
ServiceDiscoveryEvent_SERVICE_REGISTRY_CHANGED
};

/// @brief Used by consumers to request a specific behavior from the producer; describes whether a producer blocks when
/// consumer queue is full
enum iox_QueueFullPolicy
Expand Down Expand Up @@ -143,4 +149,11 @@ enum iox_ServerRequestResult
ServerRequestResult_SUCCESS
};

/// @brief used to describe the messaging pattern
enum iox_MessagingPattern
{
MessagingPattern_PUB_SUB,
MessagingPattern_REQ_RES
};

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "iceoryx_binding_c/enums.h"
#include "iceoryx_posh/popo/base_subscriber.hpp"
#include "iceoryx_posh/popo/subscriber.hpp"
#include "iceoryx_posh/runtime/service_discovery.hpp"

namespace c2cpp
{
Expand All @@ -33,6 +34,9 @@ iox::popo::ClientEvent clientEvent(const iox_ClientEvent value) noexcept;
iox::popo::ClientState clientState(const iox_ClientState value) noexcept;
iox::popo::ServerEvent serverEvent(const iox_ServerEvent value) noexcept;
iox::popo::ServerState serverState(const iox_ServerState value) noexcept;

iox::runtime::ServiceDiscoveryEvent serviceDiscoveryEvent(const iox_ServiceDiscoveryEvent value) noexcept;
iox::popo::MessagingPattern messagingPattern(const iox_MessagingPattern value) noexcept;
} // namespace c2cpp

#endif
37 changes: 37 additions & 0 deletions iceoryx_binding_c/include/iceoryx_binding_c/listener.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "iceoryx_binding_c/enums.h"
#include "iceoryx_binding_c/internal/c2cpp_binding.h"
#include "iceoryx_binding_c/server.h"
#include "iceoryx_binding_c/service_discovery.h"
#include "iceoryx_binding_c/subscriber.h"
#include "iceoryx_binding_c/types.h"
#include "iceoryx_binding_c/user_trigger.h"
Expand Down Expand Up @@ -174,4 +175,40 @@ ENUM iox_ListenerResult iox_listener_attach_server_event_with_context_data(iox_l
void iox_listener_detach_server_event(iox_listener_t const self,
iox_server_t const server,
const ENUM iox_ServerEvent serverEvent);

/// @brief Attaches a service discovery event to the listener
/// @param[in] self listener to which the event should be attached to
/// @param[in] serviceDiscovery service discovery which emits the event
/// @param[in] serviceDiscoveryEvent the event which should trigger the listener
/// @param[in] callback the callback which is called when an event triggers the listener
/// @return when successful iox_ListenerResult::ListenerResult_SUCCESS otherwise an enum which describes the error
ENUM iox_ListenerResult
iox_listener_attach_service_discovery_event(iox_listener_t const self,
iox_service_discovery_t const serviceDiscovery,
const ENUM iox_ServiceDiscoveryEvent serviceDiscoveryEvent,
void (*callback)(iox_service_discovery_t));

/// @brief Attaches a service discovery event to the listener. The callback has an additional contextData argument to
/// provide access to user defined data.
/// @param[in] self listener to which the event should be attached to
/// @param[in] serviceDiscovery service discovery which emits the event
/// @param[in] serviceDiscoveryEvent the event which should trigger the listener
/// @param[in] callback the callback which is called when an event triggers the listener
/// @param[in] contextData a void pointer which is provided as second argument to the callback
/// @return when successful iox_ListenerResult::ListenerResult_SUCCESS otherwise an enum which describes the error
ENUM iox_ListenerResult iox_listener_attach_service_discovery_event_with_context_data(
iox_listener_t const self,
iox_service_discovery_t const serviceDiscovery,
const ENUM iox_ServiceDiscoveryEvent serviceDiscoveryEvent,
void (*callback)(iox_service_discovery_t, void*),
void* const contextData);

/// @brief Detaches a service discovery event from the listener
/// @param[in] self listener from which the event should be detached
/// @param[in] serviceDiscovery the service discovery which emits the event
/// @param[in] serviceDiscoveryEvent the service discovery event which should be removed from the listener
void iox_listener_detach_service_discovery_event(iox_listener_t const self,
iox_service_discovery_t const serviceDiscovery,
const ENUM iox_ServiceDiscoveryEvent serviceDiscoveryEvent);

#endif
13 changes: 13 additions & 0 deletions iceoryx_binding_c/include/iceoryx_binding_c/notification_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "iceoryx_binding_c/client.h"
#include "iceoryx_binding_c/internal/c2cpp_binding.h"
#include "iceoryx_binding_c/server.h"
#include "iceoryx_binding_c/service_discovery.h"
#include "iceoryx_binding_c/subscriber.h"
#include "iceoryx_binding_c/user_trigger.h"

Expand Down Expand Up @@ -57,6 +58,13 @@ bool iox_notification_info_does_originate_from_client(iox_notification_info_t co
/// @return true if the notification originates from the server, otherwise false
bool iox_notification_info_does_originate_from_server(iox_notification_info_t const self, iox_server_t const server);

/// @brief does the notification originate from a certain service discovery
/// @param[in] self handle to notification info
/// @param[in] serviceDiscovery handle to serviceDiscovery in question
/// @return true if the notifiaction originates from the service discovery, otherwise false
bool iox_notification_info_does_originate_from_service_discovery(iox_notification_info_t const self,
iox_service_discovery_t const serviceDiscovery);

/// @brief acquires the handle of the subscriber origin
/// @param[in] self handle to notification info
/// @return the handle to the subscriber if the notification originated from a subscriber, otherwise NULL
Expand All @@ -77,6 +85,11 @@ iox_client_t iox_notification_info_get_client_origin(iox_notification_info_t con
/// @return the handle to the server if the notification originated from a server, otherwise NULL
iox_server_t iox_notification_info_get_server_origin(iox_notification_info_t const self);

/// @brief acquires the handle of the service discovery origin
/// @param[in] self handle to the notification info
/// @return the handle to the service discovery if the notification originated from a service discovery, otherwise NULL
iox_service_discovery_t iox_notification_info_get_service_discovery_origin(iox_notification_info_t const self);

/// @brief calls the callback of the notification
/// @param[in] self handle to notification info
void iox_notification_info_call(iox_notification_info_t const self);
Expand Down
91 changes: 91 additions & 0 deletions iceoryx_binding_c/include/iceoryx_binding_c/service_discovery.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// Copyright (c) 2022 by Apex.AI Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0

#ifndef IOX_BINDING_C_SERVICE_DISCOVERY_H
#define IOX_BINDING_C_SERVICE_DISCOVERY_H

#include "iceoryx_binding_c/enums.h"
#include "iceoryx_binding_c/internal/c2cpp_binding.h"
#include "iceoryx_binding_c/types.h"
#include "service_description.h"

/// @brief service discovery handle
typedef CLASS ServiceDiscovery* iox_service_discovery_t;

/// @brief initializes a service discovery from a storage struct pointer
/// @param[in] self pointer to raw memory which can hold a service discovery
/// @return an initialized iox_service_discovery_t
iox_service_discovery_t iox_service_discovery_init(iox_service_discovery_storage_t* self);

/// @brief after using an iox_service_discovery_t it must be cleaned up with this function
/// @param[in] self the service discovery which should be deinitialized
void iox_service_discovery_deinit(iox_service_discovery_t const self);

/// @brief Searches all services with the given messaging pattern that match the provided service description
/// @param[in] self handle of the service discovery
/// @param[in] service service string to search for, a nullptr corresponds to a wildcard
/// @param[in] instance instance string to search for, a nullptr corresponds to a wildcard
/// @param[in] event event string to search for, a nullptr corresponds to a wildcard
/// @param[in] serviceContainer preallocated memory to an array of iox_service_description_t in which the matching
/// services can be written
/// @param[in] serviceContainerCapacity the capacity of the preallocated serviceContainer
/// @param[in] missedServices if the serviceContainer has insufficient size the number of missed services which could
/// not be written into the serviceContainer are stored here
/// @param[in] pattern messaging pattern of the service to search
/// @return the number of services which were written into the serviceContainer
uint64_t iox_service_discovery_find_service(iox_service_discovery_t const self,
MatthiasKillat marked this conversation as resolved.
Show resolved Hide resolved
const char* const service,
const char* const instance,
const char* const event,
iox_service_description_t* const serviceContainer,
const uint64_t serviceContainerCapacity,
uint64_t* missedServices,
const ENUM iox_MessagingPattern pattern);

/// @brief Searches all services with the given messaging pattern that match the provided service description and
/// applies a function to each of them
/// @param[in] self handle of the service discovery
/// @param[in] service service string to search for, a nullptr corresponds to a wildcard
/// @param[in] instance instance string to search for, a nullptr corresponds to a wildcard
/// @param[in] event event string to search for, a nullptr corresponds to a wildcard
/// @param[in] callable to apply to all matching services
FerdinandSpitzschnueffler marked this conversation as resolved.
Show resolved Hide resolved
/// @param[in] pattern messaging pattern of the service to search
void iox_service_discovery_find_service_apply_callable(iox_service_discovery_t const self,
const char* const service,
const char* const instance,
const char* const event,
void (*callable)(const iox_service_description_t),
const ENUM iox_MessagingPattern pattern);

/// @brief Searches all services with the given messaging pattern that match the provided service description and
/// applies a function to each of them. A second parameter for the function can be provided as contextData.
/// @param[in] self handle of the service discovery
/// @param[in] service service string to search for, a nullptr corresponds to a wildcard
/// @param[in] instance instance string to search for, a nullptr corresponds to a wildcard
/// @param[in] event event string to search for, a nullptr corresponds to a wildcard
/// @param[in] callable to apply to all matching services
/// @param[in] contextData a void pointer which is provided as second argument to the callback
/// @param[in] pattern messaging pattern of the service to search
void iox_service_discovery_find_service_apply_callable_with_context_data(
MatthiasKillat marked this conversation as resolved.
Show resolved Hide resolved
iox_service_discovery_t const self,
const char* const service,
const char* const instance,
const char* const event,
void (*callable)(const iox_service_description_t, void*),
void* const contextData,
const ENUM iox_MessagingPattern pattern);

#endif
12 changes: 12 additions & 0 deletions iceoryx_binding_c/include/iceoryx_binding_c/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,5 +120,17 @@ typedef struct
#endif
} iox_server_storage_t;

/// @brief has exactly the size required to store the underlying object of iox_service_discovery_t
struct iox_service_discovery_storage_t
{
// the value of the array size is the result of the following formula:
// sizeof(ServiceDiscovery) / 8
#if defined(__APPLE__)
uint64_t do_not_touch_me[49175];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Appears fairly small (if it has space for 1024 Servicedescriptions each larger than 300 bytes). I am not sure something is off here. But will likely change (to something smaller) after #1151 because than we store those in dynamic memory.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got the numbers via "CI Debugging". Don't forget that you have to multiply by 8.

Copy link
Contributor

@MatthiasKillat MatthiasKillat Feb 24, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes ... it is a uint64_t. Why I do not know (it is 8 byte aligned then, machine word on 64 bit architectures). But I am not sure access is always aligned for the actual type (many architectures can compensate this). Note that placement new requires an aligned pointer, which is not generally true for the ones we pass (&do_not_touch_me).

TLDR: I think this is broken for some types (those with alignment greater than 8) but have not looked at the details (this is nothing particular to this PR). It is broken on machines that cannot enforce alignment on their own and even then the space may be insufficient.

If we do not have alignment > 8 types then it is ok, if we add those types in the future it can subtly break on some architectures.

#else
uint64_t do_not_touch_me[49172];
#endif
};
typedef struct iox_service_discovery_storage_t iox_service_discovery_storage_t;

#endif
41 changes: 41 additions & 0 deletions iceoryx_binding_c/include/iceoryx_binding_c/wait_set.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "iceoryx_binding_c/enums.h"
#include "iceoryx_binding_c/internal/c2cpp_binding.h"
#include "iceoryx_binding_c/notification_info.h"
#include "iceoryx_binding_c/service_discovery.h"
#include "iceoryx_binding_c/subscriber.h"
#include "iceoryx_binding_c/types.h"
#include "iceoryx_binding_c/user_trigger.h"
Expand Down Expand Up @@ -333,4 +334,44 @@ void iox_ws_detach_server_event(iox_ws_t const self, iox_server_t const server,
/// @param[in] server the server which should be detached
/// @param[in] serverState the state which should be detached from the server
void iox_ws_detach_server_state(iox_ws_t const self, iox_server_t const server, const ENUM iox_ServerState serverState);

/// @brief attaches a service discovery event to a waitset
/// @param[in] self handle to the waitset
/// @param[in] serviceDiscovery service discovery which emits the event
/// @param[in] serviceDiscoveryEvent the event which should be attached
/// @param[in] eventId an arbitrary id which will be tagged to the event
/// @param[in] callback a callback which is attached to the event
/// @return if the attaching was successfull it returns WaitSetResult_SUCCESS, otherwise
/// an enum which describes the error
ENUM iox_WaitSetResult iox_ws_attach_service_discovery_event(const iox_ws_t self,
const iox_service_discovery_t serviceDiscovery,
const ENUM iox_ServiceDiscoveryEvent serviceDiscoveryEvent,
const uint64_t eventId,
void (*callback)(iox_service_discovery_t));

/// @brief attaches a service discovery event to a waitset with additional context data for the callback
/// @param[in] self handle to the waitset
/// @param[in] serviceDiscovery service discovery which emits the event
/// @param[in] serviceDiscoveryEvent the event which should be attached
/// @param[in] eventId an arbitrary id which will be tagged to the event
/// @param[in] callback a callback which is attached to the event
/// @param[in] contextData a void pointer which is provided as second argument to the callback
/// @return if the attaching was successfull it returns WaitSetResult_SUCCESS, otherwise
/// an enum which describes the error
ENUM iox_WaitSetResult
iox_ws_attach_service_discovery_event_with_context_data(iox_ws_t const self,
iox_service_discovery_t const serviceDiscovery,
const ENUM iox_ServiceDiscoveryEvent serviceDiscoveryEvent,
const uint64_t eventId,
void (*callback)(iox_service_discovery_t, void*),
void* const contextData);

/// @brief detaches a service discovery event from a waitset
/// @param[in] self handle to the waitset
/// @param[in] serviceDiscovery the service discovery which should be detached
/// @param[in] serviceDiscoveryEvent the event which should be detached from the service discovery
void iox_ws_detach_service_discovery_event(iox_ws_t const self,
iox_service_discovery_t const serviceDiscovery,
const ENUM iox_ServiceDiscoveryEvent serviceDiscoveryEvent);

#endif
29 changes: 29 additions & 0 deletions iceoryx_binding_c/source/c2cpp_enum_translation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,33 @@ iox::popo::ServerState serverState(const iox_ServerState value) noexcept
errorHandler(iox::Error::kBINDING_C__C2CPP_ENUM_TRANSLATION_INVALID_SERVER_STATE_VALUE);
return iox::popo::ServerState::HAS_REQUEST;
}

iox::runtime::ServiceDiscoveryEvent serviceDiscoveryEvent(const iox_ServiceDiscoveryEvent value) noexcept
{
switch (value)
{
case ServiceDiscoveryEvent_SERVICE_REGISTRY_CHANGED:
return iox::runtime::ServiceDiscoveryEvent::SERVICE_REGISTRY_CHANGED;
}

iox::LogFatal() << "invalid iox_ServiceDiscoveryEvent value";
errorHandler(iox::Error::kBINDING_C__C2CPP_ENUM_TRANSLATION_INVALID_SERVICE_DISCOVERY_EVENT_VALUE);
return iox::runtime::ServiceDiscoveryEvent::SERVICE_REGISTRY_CHANGED;
}

iox::popo::MessagingPattern messagingPattern(const iox_MessagingPattern value) noexcept
{
switch (value)
{
case MessagingPattern_PUB_SUB:
return iox::popo::MessagingPattern::PUB_SUB;
case MessagingPattern_REQ_RES:
return iox::popo::MessagingPattern::REQ_RES;
}

iox::LogFatal() << "invalid iox_MessagingPattern value";
errorHandler(iox::Error::kBINDING_C__C2CPP_ENUM_TRANSLATION_INVALID_MESSAGING_PATTERN_VALUE);
return iox::popo::MessagingPattern::PUB_SUB;
}

} // namespace c2cpp
Loading