From 3b99cc34cd3712b39a34e5789363ab497e85a75e Mon Sep 17 00:00:00 2001 From: gricciardi Date: Wed, 20 Sep 2017 15:38:21 +0200 Subject: [PATCH 1/6] Refactored serializers management --- pubsub/api/pubsub/publisher.h | 2 +- pubsub/api/pubsub/subscriber.h | 2 +- .../mp_pubsub/publisher/CMakeLists.txt | 2 +- .../mp_pubsub/subscriber/CMakeLists.txt | 8 +- .../examples/pubsub/publisher/CMakeLists.txt | 2 +- .../publisher/private/src/pubsub_publisher.c | 10 +- .../examples/pubsub/publisher2/CMakeLists.txt | 2 +- .../examples/pubsub/subscriber/CMakeLists.txt | 2 +- pubsub/pubsub_admin_udp_mc/CMakeLists.txt | 3 +- .../private/include/pubsub_admin_impl.h | 36 +- ..._service_private.h => topic_publication.h} | 14 +- .../private/include/topic_subscription.h | 9 +- .../private/src/psa_activator.c | 38 +- .../private/src/pubsub_admin_impl.c | 741 ++++++++++++------ .../private/src/topic_publication.c | 299 +++---- .../private/src/topic_subscription.c | 546 +++++++------ pubsub/pubsub_admin_zmq/CMakeLists.txt | 3 +- .../private/include/pubsub_admin_impl.h | 38 +- ..._service_private.h => topic_publication.h} | 14 +- .../private/include/topic_subscription.h | 7 +- .../private/src/psa_activator.c | 36 +- .../private/src/pubsub_admin_impl.c | 708 +++++++++++------ .../private/src/topic_publication.c | 269 +++---- .../private/src/topic_subscription.c | 502 +++++------- .../public/include/pubsub_admin.h | 22 +- .../public/include/pubsub_admin_match.h | 27 + .../public/include/pubsub_common.h | 8 +- .../public/include/pubsub_endpoint.h | 12 +- .../public/include/pubsub_serializer.h | 27 +- pubsub/pubsub_common/public/src/log_helper.c | 48 +- .../public/src/pubsub_admin_match.c | 303 +++++++ .../public/src/pubsub_endpoint.c | 184 +++-- .../private/include/pubsub_discovery_impl.h | 1 - .../private/src/etcd_common.c | 1 + .../private/src/etcd_watcher.c | 216 ++--- .../private/src/etcd_writer.c | 160 ++-- .../private/src/psd_activator.c | 2 +- .../private/src/pubsub_discovery_impl.c | 13 +- .../private/include/pubsub_serializer_impl.h | 23 +- .../private/src/ps_activator.c | 6 +- .../private/src/pubsub_serializer_impl.c | 339 ++++---- .../private/include/pubsub_topology_manager.h | 11 - .../private/src/pstm_activator.c | 64 +- .../private/src/pubsub_topology_manager.c | 526 ++++--------- 44 files changed, 2846 insertions(+), 2440 deletions(-) rename pubsub/pubsub_admin_udp_mc/private/include/{pubsub_publish_service_private.h => topic_publication.h} (80%) rename pubsub/pubsub_admin_zmq/private/include/{pubsub_publish_service_private.h => topic_publication.h} (76%) create mode 100644 pubsub/pubsub_common/public/include/pubsub_admin_match.h create mode 100644 pubsub/pubsub_common/public/src/pubsub_admin_match.c diff --git a/pubsub/api/pubsub/publisher.h b/pubsub/api/pubsub/publisher.h index 4bc6c8c60..3eec149a4 100644 --- a/pubsub/api/pubsub/publisher.h +++ b/pubsub/api/pubsub/publisher.h @@ -30,7 +30,7 @@ #include #define PUBSUB_PUBLISHER_SERVICE_NAME "pubsub.publisher" -#define PUBSUB_PUBLISHER_SERVICE_VERSION "1.0.0" +#define PUBSUB_PUBLISHER_SERVICE_VERSION "2.0.0" //properties #define PUBSUB_PUBLISHER_TOPIC "pubsub.topic" diff --git a/pubsub/api/pubsub/subscriber.h b/pubsub/api/pubsub/subscriber.h index cbbe96cf0..5d87b8a31 100644 --- a/pubsub/api/pubsub/subscriber.h +++ b/pubsub/api/pubsub/subscriber.h @@ -30,7 +30,7 @@ #include #define PUBSUB_SUBSCRIBER_SERVICE_NAME "pubsub.subscriber" -#define PUBSUB_SUBSCRIBER_SERVICE_VERSION "1.0.0" +#define PUBSUB_SUBSCRIBER_SERVICE_VERSION "2.0.0" //properties #define PUBSUB_SUBSCRIBER_TOPIC "pubsub.topic" diff --git a/pubsub/examples/mp_pubsub/publisher/CMakeLists.txt b/pubsub/examples/mp_pubsub/publisher/CMakeLists.txt index de7715605..76a01f16f 100644 --- a/pubsub/examples/mp_pubsub/publisher/CMakeLists.txt +++ b/pubsub/examples/mp_pubsub/publisher/CMakeLists.txt @@ -34,7 +34,7 @@ bundle_files(org.apache.celix.pubsub_publisher.MpPublisher ${PROJECT_SOURCE_DIR}/pubsub/examples/mp_pubsub/msg_descriptors/msg_ew.descriptor ${PROJECT_SOURCE_DIR}/pubsub/examples/mp_pubsub/msg_descriptors/msg_ide.descriptor ${PROJECT_SOURCE_DIR}/pubsub/examples/mp_pubsub/msg_descriptors/msg_kinematics.descriptor - DESTINATION "META-INF/descriptors/messages" + DESTINATION "META-INF/descriptors" ) bundle_files(org.apache.celix.pubsub_publisher.MpPublisher diff --git a/pubsub/examples/mp_pubsub/subscriber/CMakeLists.txt b/pubsub/examples/mp_pubsub/subscriber/CMakeLists.txt index 75ec6355c..a480a7320 100644 --- a/pubsub/examples/mp_pubsub/subscriber/CMakeLists.txt +++ b/pubsub/examples/mp_pubsub/subscriber/CMakeLists.txt @@ -31,10 +31,10 @@ add_bundle( org.apache.celix.pubsub_subscriber.MpSubscriber ) bundle_files( org.apache.celix.pubsub_subscriber.MpSubscriber - ${PROJECT_SOURCE_DIR}/pubsub/examples/mp_pubsub/msg_descriptors/msg_ew.descriptor - ${PROJECT_SOURCE_DIR}/pubsub/examples/mp_pubsub/msg_descriptors/msg_ide.descriptor - ${PROJECT_SOURCE_DIR}/pubsub/examples/mp_pubsub/msg_descriptors/msg_kinematics.descriptor - DESTINATION "META-INF/descriptors/messages" + ${PROJECT_SOURCE_DIR}/pubsub/examples/mp_pubsub/msg_descriptors/msg_ew.descriptor + ${PROJECT_SOURCE_DIR}/pubsub/examples/mp_pubsub/msg_descriptors/msg_ide.descriptor + ${PROJECT_SOURCE_DIR}/pubsub/examples/mp_pubsub/msg_descriptors/msg_kinematics.descriptor + DESTINATION "META-INF/descriptors" ) bundle_files(org.apache.celix.pubsub_subscriber.MpSubscriber diff --git a/pubsub/examples/pubsub/publisher/CMakeLists.txt b/pubsub/examples/pubsub/publisher/CMakeLists.txt index d932611d8..e35c137d9 100644 --- a/pubsub/examples/pubsub/publisher/CMakeLists.txt +++ b/pubsub/examples/pubsub/publisher/CMakeLists.txt @@ -32,7 +32,7 @@ add_bundle(org.apache.celix.pubsub_publisher.PoiPublisher bundle_files(org.apache.celix.pubsub_publisher.PoiPublisher ${PROJECT_SOURCE_DIR}/pubsub/examples/pubsub/msg_descriptors/msg_poi1.descriptor ${PROJECT_SOURCE_DIR}/pubsub/examples/pubsub/msg_descriptors/msg_poi2.descriptor - DESTINATION "META-INF/descriptors/messages" + DESTINATION "META-INF/descriptors" ) bundle_files(org.apache.celix.pubsub_publisher.PoiPublisher diff --git a/pubsub/examples/pubsub/publisher/private/src/pubsub_publisher.c b/pubsub/examples/pubsub/publisher/private/src/pubsub_publisher.c index 66454a067..b798ea1d0 100644 --- a/pubsub/examples/pubsub/publisher/private/src/pubsub_publisher.c +++ b/pubsub/examples/pubsub/publisher/private/src/pubsub_publisher.c @@ -77,18 +77,20 @@ static void* send_thread(void* arg){ while(stop==false){ place->position.lat = randCoordinate(MIN_LAT,MAX_LAT); place->position.lon = randCoordinate(MIN_LON,MAX_LON); - int nr_char = (int)randCoordinate(5,100000); - //int nr_char = 25; + //int nr_char = (int)randCoordinate(5,100000); + int nr_char = 32; place->data = calloc(nr_char, 1); for(int i = 0; i < (nr_char-1); i++) { place->data[i] = i%10 + '0'; } if(publish_svc->send) { - publish_svc->send(publish_svc->handle,msgId,place); + if(publish_svc->send(publish_svc->handle,msgId,place)==0){ + printf("Sent %s [%f, %f] (%s, %s) data len = %d\n",st_struct->topic, place->position.lat, place->position.lon,place->name,place->description, nr_char); + } } else { printf("No send for %s\n", st_struct->topic); } - printf("Sent %s [%f, %f] (%s, %s) data len = %d\n",st_struct->topic, place->position.lat, place->position.lon,place->name,place->description, nr_char); + free(place->data); sleep(2); } diff --git a/pubsub/examples/pubsub/publisher2/CMakeLists.txt b/pubsub/examples/pubsub/publisher2/CMakeLists.txt index c44a760aa..b83f7ddf5 100644 --- a/pubsub/examples/pubsub/publisher2/CMakeLists.txt +++ b/pubsub/examples/pubsub/publisher2/CMakeLists.txt @@ -32,7 +32,7 @@ add_bundle(org.apache.celix.pubsub_publisher.PoiPublisher2 bundle_files(org.apache.celix.pubsub_publisher.PoiPublisher2 ${PROJECT_SOURCE_DIR}/pubsub/examples/pubsub/msg_descriptors/msg_poi1.descriptor ${PROJECT_SOURCE_DIR}/pubsub/examples/pubsub/msg_descriptors/msg_poi2.descriptor - DESTINATION "META-INF/descriptors/messages" + DESTINATION "META-INF/descriptors" ) bundle_files(org.apache.celix.pubsub_publisher.PoiPublisher2 diff --git a/pubsub/examples/pubsub/subscriber/CMakeLists.txt b/pubsub/examples/pubsub/subscriber/CMakeLists.txt index da6a36249..7fd9fae2f 100644 --- a/pubsub/examples/pubsub/subscriber/CMakeLists.txt +++ b/pubsub/examples/pubsub/subscriber/CMakeLists.txt @@ -33,7 +33,7 @@ add_bundle(org.apache.celix.pubsub_subscriber.PoiSubscriber bundle_files(org.apache.celix.pubsub_subscriber.PoiSubscriber ${PROJECT_SOURCE_DIR}/pubsub/examples/pubsub/msg_descriptors/msg_poi1.descriptor ${PROJECT_SOURCE_DIR}/pubsub/examples/pubsub/msg_descriptors/msg_poi2.descriptor - DESTINATION "META-INF/descriptors/messages" + DESTINATION "META-INF/descriptors" ) bundle_files(org.apache.celix.pubsub_subscriber.PoiSubscriber diff --git a/pubsub/pubsub_admin_udp_mc/CMakeLists.txt b/pubsub/pubsub_admin_udp_mc/CMakeLists.txt index 1ac0c2dbc..86f7a472d 100644 --- a/pubsub/pubsub_admin_udp_mc/CMakeLists.txt +++ b/pubsub/pubsub_admin_udp_mc/CMakeLists.txt @@ -37,10 +37,11 @@ add_bundle(org.apache.celix.pubsub_admin.PubSubAdminUdpMc private/src/large_udp.c ${PROJECT_SOURCE_DIR}/pubsub/pubsub_common/public/src/pubsub_endpoint.c ${PROJECT_SOURCE_DIR}/pubsub/pubsub_common/public/src/log_helper.c + ${PROJECT_SOURCE_DIR}/pubsub/pubsub_common/public/src/pubsub_admin_match.c ) set_target_properties(org.apache.celix.pubsub_admin.PubSubAdminUdpMc PROPERTIES INSTALL_RPATH "$ORIGIN") -target_link_libraries(org.apache.celix.pubsub_admin.PubSubAdminUdpMc celix_framework celix_utils celix_dfi ${JANSSON_LIBRARIES}) +target_link_libraries(org.apache.celix.pubsub_admin.PubSubAdminUdpMc celix_framework celix_utils celix_dfi) install_bundle(org.apache.celix.pubsub_admin.PubSubAdminUdpMc) diff --git a/pubsub/pubsub_admin_udp_mc/private/include/pubsub_admin_impl.h b/pubsub/pubsub_admin_udp_mc/private/include/pubsub_admin_impl.h index 89e65478e..731b037d8 100644 --- a/pubsub/pubsub_admin_udp_mc/private/include/pubsub_admin_impl.h +++ b/pubsub/pubsub_admin_udp_mc/private/include/pubsub_admin_impl.h @@ -24,20 +24,23 @@ * \copyright Apache License, Version 2.0 */ -#ifndef PUBSUB_ADMIN_IMPL_H_ -#define PUBSUB_ADMIN_IMPL_H_ +#ifndef PUBSUB_ADMIN_UDP_MC_IMPL_H_ +#define PUBSUB_ADMIN_UDP_MC_IMPL_H_ #include "pubsub_admin.h" -#include "pubsub_serializer.h" #include "log_helper.h" -struct pubsub_admin { +#define PUBSUB_ADMIN_TYPE "udp_mc" - pubsub_serializer_service_t* serializerSvc; +struct pubsub_admin { bundle_context_pt bundle_context; log_helper_pt loghelper; + /* List of the available serializers */ + celix_thread_mutex_t serializerListLock; // List + array_list_pt serializerList; + celix_thread_mutex_t localPublicationsLock; hash_map_pt localPublications;// @@ -50,15 +53,24 @@ struct pubsub_admin { celix_thread_mutex_t pendingSubscriptionsLock; hash_map_pt pendingSubscriptions; //> + /* Those are used to keep track of valid subscriptions/publications that still have no valid serializer */ + celix_thread_mutex_t noSerializerPendingsLock; + array_list_pt noSerializerSubscriptions; // List + array_list_pt noSerializerPublications; // List + + celix_thread_mutex_t usedSerializersLock; + hash_map_pt topicSubscriptionsPerSerializer; // > + hash_map_pt topicPublicationsPerSerializer; // > + char* ifIpAddress; // The local interface which is used for multicast communication - char* mcIpAddress; // The multicast IP address + char* mcIpAddress; // The multicast IP address int sendSocket; + void* zmq_context; // to be removed }; celix_status_t pubsubAdmin_create(bundle_context_pt context, pubsub_admin_pt *admin); -celix_status_t pubsubAdmin_stop(pubsub_admin_pt admin); celix_status_t pubsubAdmin_destroy(pubsub_admin_pt admin); celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint_pt subEP); @@ -70,10 +82,10 @@ celix_status_t pubsubAdmin_removePublication(pubsub_admin_pt admin,pubsub_endpoi celix_status_t pubsubAdmin_closeAllPublications(pubsub_admin_pt admin,char* scope, char* topic); celix_status_t pubsubAdmin_closeAllSubscriptions(pubsub_admin_pt admin,char* scope, char* topic); -celix_status_t pubsubAdmin_matchPublisher(pubsub_admin_pt admin, pubsub_endpoint_pt pubEP, double* score); -celix_status_t pubsubAdmin_matchSubscriber(pubsub_admin_pt admin, pubsub_endpoint_pt subEP, double* score); +celix_status_t pubsubAdmin_serializerAdded(void * handle, service_reference_pt reference, void * service); +celix_status_t pubsubAdmin_serializerRemoved(void * handle, service_reference_pt reference, void * service); + +celix_status_t pubsubAdmin_matchEndpoint(pubsub_admin_pt admin, pubsub_endpoint_pt endpoint, double* score); -celix_status_t pubsubAdmin_setSerializer(pubsub_admin_pt admin, pubsub_serializer_service_t* serializerSvc); -celix_status_t pubsubAdmin_removeSerializer(pubsub_admin_pt admin, pubsub_serializer_service_t* serializerSvc); -#endif /* PUBSUB_ADMIN_IMPL_H_ */ +#endif /* PUBSUB_ADMIN_UDP_MC_IMPL_H_ */ diff --git a/pubsub/pubsub_admin_udp_mc/private/include/pubsub_publish_service_private.h b/pubsub/pubsub_admin_udp_mc/private/include/topic_publication.h similarity index 80% rename from pubsub/pubsub_admin_udp_mc/private/include/pubsub_publish_service_private.h rename to pubsub/pubsub_admin_udp_mc/private/include/topic_publication.h index b43fb085d..4363d71d1 100644 --- a/pubsub/pubsub_admin_udp_mc/private/include/pubsub_publish_service_private.h +++ b/pubsub/pubsub_admin_udp_mc/private/include/topic_publication.h @@ -17,19 +17,20 @@ *under the License. */ /* - * pubsub_publish_service_private.h + * topic_publication.h * * \date Sep 24, 2015 * \author Apache Celix Project Team * \copyright Apache License, Version 2.0 */ -#ifndef PUBSUB_PUBLISH_SERVICE_PRIVATE_H_ -#define PUBSUB_PUBLISH_SERVICE_PRIVATE_H_ +#ifndef TOPIC_PUBLICATION_H_ +#define TOPIC_PUBLICATION_H_ #include "publisher.h" #include "pubsub_endpoint.h" #include "pubsub_common.h" + #include "pubsub_serializer.h" #define UDP_BASE_PORT 49152 @@ -42,18 +43,15 @@ typedef struct pubsub_udp_msg { } pubsub_udp_msg_t; typedef struct topic_publication *topic_publication_pt; -celix_status_t pubsub_topicPublicationCreate(int sendSocket, pubsub_endpoint_pt pubEP, char* bindIP, topic_publication_pt *out); +celix_status_t pubsub_topicPublicationCreate(int sendSocket, pubsub_endpoint_pt pubEP, pubsub_serializer_service_t *best_serializer, char* bindIP, topic_publication_pt *out); celix_status_t pubsub_topicPublicationDestroy(topic_publication_pt pub); celix_status_t pubsub_topicPublicationAddPublisherEP(topic_publication_pt pub,pubsub_endpoint_pt ep); celix_status_t pubsub_topicPublicationRemovePublisherEP(topic_publication_pt pub,pubsub_endpoint_pt ep); -celix_status_t pubsub_topicPublicationSetSerializer(topic_publication_pt pub, pubsub_serializer_service_t* serializerSvc); -celix_status_t pubsub_topicPublicationRemoveSerializer(topic_publication_pt pub, pubsub_serializer_service_t* serializerSvc); - celix_status_t pubsub_topicPublicationStart(bundle_context_pt bundle_context,topic_publication_pt pub,service_factory_pt* svcFactory); celix_status_t pubsub_topicPublicationStop(topic_publication_pt pub); array_list_pt pubsub_topicPublicationGetPublisherList(topic_publication_pt pub); -#endif /* PUBSUB_PUBLISH_SERVICE_PRIVATE_H_ */ +#endif /* TOPIC_PUBLICATION_H_ */ diff --git a/pubsub/pubsub_admin_udp_mc/private/include/topic_subscription.h b/pubsub/pubsub_admin_udp_mc/private/include/topic_subscription.h index a65cb6b18..475416ae5 100644 --- a/pubsub/pubsub_admin_udp_mc/private/include/topic_subscription.h +++ b/pubsub/pubsub_admin_udp_mc/private/include/topic_subscription.h @@ -38,20 +38,21 @@ typedef struct topic_subscription* topic_subscription_pt; -celix_status_t pubsub_topicSubscriptionCreate(char* ifIp,bundle_context_pt bundle_context, pubsub_serializer_service_t* serializer, char* scope, char* topic,topic_subscription_pt* out); +celix_status_t pubsub_topicSubscriptionCreate(bundle_context_pt bundle_context, char* ifIp,char* scope, char* topic ,pubsub_serializer_service_t *best_serializer, topic_subscription_pt* out); celix_status_t pubsub_topicSubscriptionDestroy(topic_subscription_pt ts); celix_status_t pubsub_topicSubscriptionStart(topic_subscription_pt ts); celix_status_t pubsub_topicSubscriptionStop(topic_subscription_pt ts); +celix_status_t pubsub_topicSubscriptionAddConnectPublisherToPendingList(topic_subscription_pt ts, char* pubURL); +celix_status_t pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(topic_subscription_pt ts, char* pubURL); + celix_status_t pubsub_topicSubscriptionConnectPublisher(topic_subscription_pt ts, char* pubURL); celix_status_t pubsub_topicSubscriptionDisconnectPublisher(topic_subscription_pt ts, char* pubURL); celix_status_t pubsub_topicSubscriptionAddSubscriber(topic_subscription_pt ts, pubsub_endpoint_pt subEP); celix_status_t pubsub_topicSubscriptionRemoveSubscriber(topic_subscription_pt ts, pubsub_endpoint_pt subEP); -celix_status_t pubsub_topicSubscriptionSetSerializer(topic_subscription_pt ts, pubsub_serializer_service_t* serializerSvc); -celix_status_t pubsub_topicSubscriptionRemoveSerializer(topic_subscription_pt ts, pubsub_serializer_service_t* serializerSvc); - +array_list_pt pubsub_topicSubscriptionGetSubscribersList(topic_subscription_pt sub); celix_status_t pubsub_topicIncreaseNrSubscribers(topic_subscription_pt subscription); celix_status_t pubsub_topicDecreaseNrSubscribers(topic_subscription_pt subscription); unsigned int pubsub_topicGetNrSubscribers(topic_subscription_pt subscription); diff --git a/pubsub/pubsub_admin_udp_mc/private/src/psa_activator.c b/pubsub/pubsub_admin_udp_mc/private/src/psa_activator.c index cb298fe0e..cd4ee0759 100644 --- a/pubsub/pubsub_admin_udp_mc/private/src/psa_activator.c +++ b/pubsub/pubsub_admin_udp_mc/private/src/psa_activator.c @@ -28,6 +28,7 @@ #include "bundle_activator.h" #include "service_registration.h" +#include "service_tracker.h" #include "pubsub_admin_impl.h" @@ -35,6 +36,7 @@ struct activator { pubsub_admin_pt admin; pubsub_admin_service_pt adminService; service_registration_pt registration; + service_tracker_pt serializerTracker; }; celix_status_t bundleActivator_create(bundle_context_pt context, void **userData) { @@ -47,7 +49,28 @@ celix_status_t bundleActivator_create(bundle_context_pt context, void **userData } else{ *userData = activator; + status = pubsubAdmin_create(context, &(activator->admin)); + + if(status == CELIX_SUCCESS){ + service_tracker_customizer_pt customizer = NULL; + status = serviceTrackerCustomizer_create(activator->admin, + NULL, + pubsubAdmin_serializerAdded, + NULL, + pubsubAdmin_serializerRemoved, + &customizer); + if(status == CELIX_SUCCESS){ + status = serviceTracker_create(context, PUBSUB_SERIALIZER_SERVICE, customizer, &(activator->serializerTracker)); + if(status != CELIX_SUCCESS){ + serviceTrackerCustomizer_destroy(customizer); + pubsubAdmin_destroy(activator->admin); + } + } + else{ + pubsubAdmin_destroy(activator->admin); + } + } } return status; @@ -73,16 +96,14 @@ celix_status_t bundleActivator_start(void * userData, bundle_context_pt context) pubsubAdminSvc->closeAllPublications = pubsubAdmin_closeAllPublications; pubsubAdminSvc->closeAllSubscriptions = pubsubAdmin_closeAllSubscriptions; - pubsubAdminSvc->matchPublisher = pubsubAdmin_matchPublisher; - pubsubAdminSvc->matchSubscriber = pubsubAdmin_matchSubscriber; - - pubsubAdminSvc->setSerializer = pubsubAdmin_setSerializer; - pubsubAdminSvc->removeSerializer = pubsubAdmin_removeSerializer; + pubsubAdminSvc->matchEndpoint = pubsubAdmin_matchEndpoint; activator->adminService = pubsubAdminSvc; status = bundleContext_registerService(context, PUBSUB_ADMIN_SERVICE, pubsubAdminSvc, NULL, &activator->registration); + status += serviceTracker_open(activator->serializerTracker); + } @@ -93,10 +114,10 @@ celix_status_t bundleActivator_stop(void * userData, bundle_context_pt context) celix_status_t status = CELIX_SUCCESS; struct activator *activator = userData; - serviceRegistration_unregister(activator->registration); - activator->registration = NULL; + status += serviceTracker_close(activator->serializerTracker); + status += serviceRegistration_unregister(activator->registration); - pubsubAdmin_stop(activator->admin); + activator->registration = NULL; free(activator->adminService); activator->adminService = NULL; @@ -108,6 +129,7 @@ celix_status_t bundleActivator_destroy(void * userData, bundle_context_pt contex celix_status_t status = CELIX_SUCCESS; struct activator *activator = userData; + serviceTracker_destroy(activator->serializerTracker); pubsubAdmin_destroy(activator->admin); activator->admin = NULL; diff --git a/pubsub/pubsub_admin_udp_mc/private/src/pubsub_admin_impl.c b/pubsub/pubsub_admin_udp_mc/private/src/pubsub_admin_impl.c index bbb452da2..6f9427b44 100644 --- a/pubsub/pubsub_admin_udp_mc/private/src/pubsub_admin_impl.c +++ b/pubsub/pubsub_admin_udp_mc/private/src/pubsub_admin_impl.c @@ -57,9 +57,10 @@ #include "pubsub_admin_impl.h" #include "topic_subscription.h" -#include "pubsub_publish_service_private.h" +#include "topic_publication.h" #include "pubsub_endpoint.h" #include "subscriber.h" +#include "pubsub_admin_match.h" static const char *DEFAULT_MC_IP = "224.100.1.1"; static char *DEFAULT_MC_PREFIX = "224.100"; @@ -67,7 +68,10 @@ static char *DEFAULT_MC_PREFIX = "224.100"; static celix_status_t pubsubAdmin_getIpAddress(const char* interface, char** ip); static celix_status_t pubsubAdmin_addSubscriptionToPendingList(pubsub_admin_pt admin,pubsub_endpoint_pt subEP); static celix_status_t pubsubAdmin_addAnySubscription(pubsub_admin_pt admin,pubsub_endpoint_pt subEP); -static celix_status_t pubsubAdmin_match(pubsub_admin_pt admin, pubsub_endpoint_pt psEP, double* score); + +static celix_status_t pubsubAdmin_getBestSerializer(pubsub_admin_pt admin,pubsub_endpoint_pt ep, pubsub_serializer_service_t **serSvc); +static void connectTopicPubSubToSerializer(pubsub_admin_pt admin,pubsub_serializer_service_t *serializer,void *topicPubSub,bool isPublication); +static void disconnectTopicPubSubFromSerializer(pubsub_admin_pt admin,void *topicPubSub,bool isPublication); celix_status_t pubsubAdmin_create(bundle_context_pt context, pubsub_admin_pt *admin) { celix_status_t status = CELIX_SUCCESS; @@ -86,11 +90,19 @@ celix_status_t pubsubAdmin_create(bundle_context_pt context, pubsub_admin_pt *ad (*admin)->subscriptions = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL); (*admin)->pendingSubscriptions = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL); (*admin)->externalPublications = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL); + (*admin)->topicSubscriptionsPerSerializer = hashMap_create(NULL, NULL, NULL, NULL); + (*admin)->topicPublicationsPerSerializer = hashMap_create(NULL, NULL, NULL, NULL); + arrayList_create(&((*admin)->noSerializerSubscriptions)); + arrayList_create(&((*admin)->noSerializerPublications)); + arrayList_create(&((*admin)->serializerList)); celixThreadMutex_create(&(*admin)->localPublicationsLock, NULL); celixThreadMutex_create(&(*admin)->subscriptionsLock, NULL); celixThreadMutex_create(&(*admin)->pendingSubscriptionsLock, NULL); celixThreadMutex_create(&(*admin)->externalPublicationsLock, NULL); + celixThreadMutex_create(&(*admin)->noSerializerPendingsLock, NULL); + celixThreadMutex_create(&(*admin)->serializerListLock, NULL); + celixThreadMutex_create(&(*admin)->usedSerializersLock, NULL); if (logHelper_create(context, &(*admin)->loghelper) == CELIX_SUCCESS) { logHelper_start((*admin)->loghelper); @@ -104,7 +116,7 @@ celix_status_t pubsubAdmin_create(bundle_context_pt context, pubsub_admin_pt *ad if (mc_ip == NULL) { const char *mc_prefix = NULL; const char *interface = NULL; - int b0 = 224, b1 = 100, b2 = 1, b3 = 1; + int b0, b1, b2, b3; bundleContext_getProperty(context,PSA_MULTICAST_IP_PREFIX , &mc_prefix); if(mc_prefix == NULL) { mc_prefix = DEFAULT_MC_PREFIX; @@ -112,12 +124,12 @@ celix_status_t pubsubAdmin_create(bundle_context_pt context, pubsub_admin_pt *ad bundleContext_getProperty(context, PSA_ITF, &interface); if (pubsubAdmin_getIpAddress(interface, &if_ip) != CELIX_SUCCESS) { - logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_WARNING, "PSA: Could not retrieve IP address for interface %s", interface); + logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_WARNING, "PSA_UDP_MC: Could not retrieve IP address for interface %s", interface); } printf("IP Detected : %s\n", if_ip); if(if_ip && sscanf(if_ip, "%i.%i.%i.%i", &b0, &b1, &b2, &b3) != 4) { - logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_WARNING, "PSA: Could not parse IP address %s", if_ip); + logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_WARNING, "PSA_UDP_MC: Could not parse IP address %s", if_ip); b2 = 1; b3 = 1; } @@ -127,57 +139,41 @@ celix_status_t pubsubAdmin_create(bundle_context_pt context, pubsub_admin_pt *ad int sendSocket = socket(AF_INET, SOCK_DGRAM, 0); if(sendSocket == -1) { perror("pubsubAdmin_create:socket"); - status = CELIX_SERVICE_EXCEPTION; + return CELIX_SERVICE_EXCEPTION; } - else{ - char loop = 1; - if(setsockopt(sendSocket, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) != 0) { - perror("pubsubAdmin_create:setsockopt(IP_MULTICAST_LOOP)"); - status = CELIX_SERVICE_EXCEPTION; - } - - if (status == CELIX_SUCCESS){ - struct in_addr multicast_interface; - inet_aton(if_ip, &multicast_interface); - if(setsockopt(sendSocket, IPPROTO_IP, IP_MULTICAST_IF, &multicast_interface, sizeof(multicast_interface)) != 0) { - perror("pubsubAdmin_create:setsockopt(IP_MULTICAST_IF)"); - status = CELIX_SERVICE_EXCEPTION; - } - else{ - (*admin)->sendSocket = sendSocket; - } - } - - if(status!=CELIX_SUCCESS){ - close(sendSocket); - } - + char loop = 1; + if(setsockopt(sendSocket, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) != 0) { + perror("pubsubAdmin_create:setsockopt(IP_MULTICAST_LOOP)"); + return CELIX_SERVICE_EXCEPTION; } + struct in_addr multicast_interface; + inet_aton(if_ip, &multicast_interface); + if(setsockopt(sendSocket, IPPROTO_IP, IP_MULTICAST_IF, &multicast_interface, sizeof(multicast_interface)) != 0) { + perror("pubsubAdmin_create:setsockopt(IP_MULTICAST_IF)"); + return CELIX_SERVICE_EXCEPTION; + } + (*admin)->sendSocket = sendSocket; } #endif if (if_ip != NULL) { - logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_INFO, "PSA: Using %s as interface for multicast communication", if_ip); + logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_INFO, "PSA_UDP_MC: Using %s as interface for multicast communication", if_ip); (*admin)->ifIpAddress = if_ip; } else { (*admin)->ifIpAddress = strdup("127.0.0.1"); } if (mc_ip != NULL) { - logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_INFO, "PSA: Using %s for service annunciation", mc_ip); + logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_INFO, "PSA_UDP_MC: Using %s for service annunciation", mc_ip); (*admin)->mcIpAddress = mc_ip; } else { - logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_WARNING, "PSA: No IP address for service annunciation set. Using %s", DEFAULT_MC_IP); + logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_WARNING, "PSA_UDP_MC: No IP address for service annunciation set. Using %s", DEFAULT_MC_IP); (*admin)->mcIpAddress = strdup(DEFAULT_MC_IP); } - if (status != CELIX_SUCCESS){ - pubsubAdmin_destroy(*admin); - } - } return status; @@ -221,6 +217,36 @@ celix_status_t pubsubAdmin_destroy(pubsub_admin_pt admin) hashMap_destroy(admin->externalPublications,false,false); celixThreadMutex_unlock(&admin->externalPublicationsLock); + celixThreadMutex_lock(&admin->serializerListLock); + arrayList_destroy(admin->serializerList); + celixThreadMutex_unlock(&admin->serializerListLock); + + celixThreadMutex_lock(&admin->noSerializerPendingsLock); + arrayList_destroy(admin->noSerializerSubscriptions); + arrayList_destroy(admin->noSerializerPublications); + celixThreadMutex_unlock(&admin->noSerializerPendingsLock); + + celixThreadMutex_lock(&admin->usedSerializersLock); + + iter = hashMapIterator_create(admin->topicSubscriptionsPerSerializer); + while(hashMapIterator_hasNext(iter)){ + arrayList_destroy((array_list_pt)hashMapIterator_nextValue(iter)); + } + hashMapIterator_destroy(iter); + hashMap_destroy(admin->topicSubscriptionsPerSerializer,false,false); + + iter = hashMapIterator_create(admin->topicPublicationsPerSerializer); + while(hashMapIterator_hasNext(iter)){ + arrayList_destroy((array_list_pt)hashMapIterator_nextValue(iter)); + } + hashMapIterator_destroy(iter); + hashMap_destroy(admin->topicPublicationsPerSerializer,false,false); + + celixThreadMutex_unlock(&admin->usedSerializersLock); + + celixThreadMutex_destroy(&admin->usedSerializersLock); + celixThreadMutex_destroy(&admin->noSerializerPendingsLock); + celixThreadMutex_destroy(&admin->serializerListLock); celixThreadMutex_destroy(&admin->pendingSubscriptionsLock); celixThreadMutex_destroy(&admin->subscriptionsLock); celixThreadMutex_destroy(&admin->localPublicationsLock); @@ -235,12 +261,6 @@ celix_status_t pubsubAdmin_destroy(pubsub_admin_pt admin) return status; } -celix_status_t pubsubAdmin_stop(pubsub_admin_pt admin) { - celix_status_t status = CELIX_SUCCESS; - - return status; -} - static celix_status_t pubsubAdmin_addAnySubscription(pubsub_admin_pt admin,pubsub_endpoint_pt subEP){ celix_status_t status = CELIX_SUCCESS; @@ -251,52 +271,68 @@ static celix_status_t pubsubAdmin_addAnySubscription(pubsub_admin_pt admin,pubsu if(any_sub==NULL){ int i; + pubsub_serializer_service_t *best_serializer = NULL; + if( (status=pubsubAdmin_getBestSerializer(admin, subEP, &best_serializer)) == CELIX_SUCCESS){ + status = pubsub_topicSubscriptionCreate(admin->bundle_context, admin->ifIpAddress, PUBSUB_SUBSCRIBER_SCOPE_DEFAULT, PUBSUB_ANY_SUB_TOPIC, best_serializer, &any_sub); + } + else{ + printf("PSA_UDP_MC: Cannot find a serializer for subscribing topic %s. Adding it to pending list.\n",subEP->topic); + celixThreadMutex_lock(&admin->noSerializerPendingsLock); + arrayList_add(admin->noSerializerSubscriptions,subEP); + celixThreadMutex_unlock(&admin->noSerializerPendingsLock); + } - status += pubsub_topicSubscriptionCreate(admin->ifIpAddress, admin->bundle_context, admin->serializerSvc, PUBSUB_SUBSCRIBER_SCOPE_DEFAULT, PUBSUB_ANY_SUB_TOPIC,&any_sub); + if (status == CELIX_SUCCESS){ - /* Connect all internal publishers */ - celixThreadMutex_lock(&admin->localPublicationsLock); - hash_map_iterator_pt lp_iter =hashMapIterator_create(admin->localPublications); - while(hashMapIterator_hasNext(lp_iter)){ - service_factory_pt factory = (service_factory_pt)hashMapIterator_nextValue(lp_iter); - topic_publication_pt topic_pubs = (topic_publication_pt)factory->handle; - array_list_pt topic_publishers = pubsub_topicPublicationGetPublisherList(topic_pubs); - - if(topic_publishers!=NULL){ - for(i=0;iendpoint !=NULL){ - status += pubsub_topicSubscriptionConnectPublisher(any_sub,pubEP->endpoint); + /* Connect all internal publishers */ + celixThreadMutex_lock(&admin->localPublicationsLock); + hash_map_iterator_pt lp_iter =hashMapIterator_create(admin->localPublications); + while(hashMapIterator_hasNext(lp_iter)){ + service_factory_pt factory = (service_factory_pt)hashMapIterator_nextValue(lp_iter); + topic_publication_pt topic_pubs = (topic_publication_pt)factory->handle; + array_list_pt topic_publishers = pubsub_topicPublicationGetPublisherList(topic_pubs); + + if(topic_publishers!=NULL){ + for(i=0;iendpoint !=NULL){ + status += pubsub_topicSubscriptionConnectPublisher(any_sub,pubEP->endpoint); + } } + arrayList_destroy(topic_publishers); } } - } - hashMapIterator_destroy(lp_iter); - celixThreadMutex_unlock(&admin->localPublicationsLock); - - /* Connect also all external publishers */ - celixThreadMutex_lock(&admin->externalPublicationsLock); - hash_map_iterator_pt extp_iter =hashMapIterator_create(admin->externalPublications); - while(hashMapIterator_hasNext(extp_iter)){ - array_list_pt ext_pub_list = (array_list_pt)hashMapIterator_nextValue(extp_iter); - if(ext_pub_list!=NULL){ - for(i=0;iendpoint !=NULL){ - status += pubsub_topicSubscriptionConnectPublisher(any_sub,pubEP->endpoint); + hashMapIterator_destroy(lp_iter); + celixThreadMutex_unlock(&admin->localPublicationsLock); + + /* Connect also all external publishers */ + celixThreadMutex_lock(&admin->externalPublicationsLock); + hash_map_iterator_pt extp_iter =hashMapIterator_create(admin->externalPublications); + while(hashMapIterator_hasNext(extp_iter)){ + array_list_pt ext_pub_list = (array_list_pt)hashMapIterator_nextValue(extp_iter); + if(ext_pub_list!=NULL){ + for(i=0;iendpoint !=NULL){ + status += pubsub_topicSubscriptionConnectPublisher(any_sub,pubEP->endpoint); + } } } } - } - hashMapIterator_destroy(extp_iter); - celixThreadMutex_unlock(&admin->externalPublicationsLock); + hashMapIterator_destroy(extp_iter); + celixThreadMutex_unlock(&admin->externalPublicationsLock); - pubsub_topicSubscriptionAddSubscriber(any_sub,subEP); + pubsub_topicSubscriptionAddSubscriber(any_sub,subEP); - status += pubsub_topicSubscriptionStart(any_sub); + status += pubsub_topicSubscriptionStart(any_sub); + + } - hashMap_put(admin->subscriptions,strdup(PUBSUB_ANY_SUB_TOPIC),any_sub); + if (status == CELIX_SUCCESS){ + hashMap_put(admin->subscriptions,strdup(PUBSUB_ANY_SUB_TOPIC),any_sub); + connectTopicPubSubToSerializer(admin, best_serializer, any_sub, false); + } } @@ -308,16 +344,16 @@ static celix_status_t pubsubAdmin_addAnySubscription(pubsub_admin_pt admin,pubsu celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint_pt subEP){ celix_status_t status = CELIX_SUCCESS; - printf("PSA: Received subscription [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",subEP->frameworkUUID,subEP->serviceID,subEP->scope,subEP->topic); + printf("PSA_UDP_MC: Received subscription [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",subEP->frameworkUUID,subEP->serviceID,subEP->scope,subEP->topic); if(strcmp(subEP->topic,PUBSUB_ANY_SUB_TOPIC)==0){ return pubsubAdmin_addAnySubscription(admin,subEP); } - celixThreadMutex_lock(&admin->subscriptionsLock); /* Check if we already know some publisher about this topic, otherwise let's put the subscription in the pending hashmap */ celixThreadMutex_lock(&admin->localPublicationsLock); celixThreadMutex_lock(&admin->externalPublicationsLock); + char* scope_topic = createScopeTopicKey(subEP->scope,subEP->topic); service_factory_pt factory = (service_factory_pt)hashMap_get(admin->localPublications,scope_topic); @@ -330,54 +366,71 @@ celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint } else{ int i; - topic_subscription_pt subscription = hashMap_get(admin->subscriptions, scope_topic); if(subscription == NULL) { + pubsub_serializer_service_t *best_serializer = NULL; + if( (status=pubsubAdmin_getBestSerializer(admin, subEP, &best_serializer)) == CELIX_SUCCESS){ + status += pubsub_topicSubscriptionCreate(admin->bundle_context,admin->ifIpAddress, subEP->scope, subEP->topic, best_serializer, &subscription); + } + else{ + printf("PSA_UDP_MC: Cannot find a serializer for subscribing topic %s. Adding it to pending list.\n",subEP->topic); + celixThreadMutex_lock(&admin->noSerializerPendingsLock); + arrayList_add(admin->noSerializerSubscriptions,subEP); + celixThreadMutex_unlock(&admin->noSerializerPendingsLock); + } - status += pubsub_topicSubscriptionCreate(admin->ifIpAddress, admin->bundle_context, admin->serializerSvc, subEP->scope, subEP->topic,&subscription); + if (status==CELIX_SUCCESS){ - /* Try to connect internal publishers */ - if(factory!=NULL){ - topic_publication_pt topic_pubs = (topic_publication_pt)factory->handle; - array_list_pt topic_publishers = pubsub_topicPublicationGetPublisherList(topic_pubs); + /* Try to connect internal publishers */ + if(factory!=NULL){ + topic_publication_pt topic_pubs = (topic_publication_pt)factory->handle; + array_list_pt topic_publishers = pubsub_topicPublicationGetPublisherList(topic_pubs); - if(topic_publishers!=NULL){ - for(i=0;iendpoint !=NULL){ - status += pubsub_topicSubscriptionConnectPublisher(subscription,pubEP->endpoint); + if(topic_publishers!=NULL){ + for(i=0;iendpoint !=NULL){ + status += pubsub_topicSubscriptionConnectPublisher(subscription,pubEP->endpoint); + } } + arrayList_destroy(topic_publishers); } - } - } + } - /* Look also for external publishers */ - if(ext_pub_list!=NULL){ - for(i=0;iendpoint !=NULL){ - status += pubsub_topicSubscriptionConnectPublisher(subscription,pubEP->endpoint); + /* Look also for external publishers */ + if(ext_pub_list!=NULL){ + for(i=0;iendpoint !=NULL){ + status += pubsub_topicSubscriptionConnectPublisher(subscription,pubEP->endpoint); + } } } - } - pubsub_topicSubscriptionAddSubscriber(subscription,subEP); + pubsub_topicSubscriptionAddSubscriber(subscription,subEP); + + status += pubsub_topicSubscriptionStart(subscription); - status += pubsub_topicSubscriptionStart(subscription); + } if(status==CELIX_SUCCESS){ + celixThreadMutex_lock(&admin->subscriptionsLock); hashMap_put(admin->subscriptions,strdup(scope_topic),subscription); + celixThreadMutex_unlock(&admin->subscriptionsLock); + connectTopicPubSubToSerializer(admin, best_serializer, subscription, false); } } - pubsub_topicIncreaseNrSubscribers(subscription); + if (status == CELIX_SUCCESS){ + pubsub_topicIncreaseNrSubscribers(subscription); + } } + free(scope_topic); celixThreadMutex_unlock(&admin->externalPublicationsLock); celixThreadMutex_unlock(&admin->localPublicationsLock); - celixThreadMutex_unlock(&admin->subscriptionsLock); return status; @@ -386,12 +439,13 @@ celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint celix_status_t pubsubAdmin_removeSubscription(pubsub_admin_pt admin,pubsub_endpoint_pt subEP){ celix_status_t status = CELIX_SUCCESS; - printf("PSA: Removing subscription [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",subEP->frameworkUUID,subEP->serviceID,subEP->scope, subEP->topic); + printf("PSA_UDP_MC: Removing subscription [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",subEP->frameworkUUID,subEP->serviceID,subEP->scope, subEP->topic); celixThreadMutex_lock(&admin->subscriptionsLock); + char* scope_topic = createScopeTopicKey(subEP->scope, subEP->topic); topic_subscription_pt sub = (topic_subscription_pt)hashMap_get(admin->subscriptions,scope_topic); - free(scope_topic); + if(sub!=NULL){ pubsub_topicDecreaseNrSubscribers(sub); if(pubsub_topicGetNrSubscribers(sub) == 0) { @@ -399,9 +453,16 @@ celix_status_t pubsubAdmin_removeSubscription(pubsub_admin_pt admin,pubsub_endpo } } else{ - status = CELIX_ILLEGAL_STATE; + /* Maybe the endpoint was pending */ + celixThreadMutex_lock(&admin->noSerializerPendingsLock); + if(!arrayList_removeElement(admin->noSerializerSubscriptions, subEP)){ + status = CELIX_ILLEGAL_STATE; + } + celixThreadMutex_unlock(&admin->noSerializerPendingsLock); } + free(scope_topic); + celixThreadMutex_unlock(&admin->subscriptionsLock); return status; @@ -411,112 +472,120 @@ celix_status_t pubsubAdmin_removeSubscription(pubsub_admin_pt admin,pubsub_endpo celix_status_t pubsubAdmin_addPublication(pubsub_admin_pt admin,pubsub_endpoint_pt pubEP){ celix_status_t status = CELIX_SUCCESS; - printf("PSA: Received publication [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",pubEP->frameworkUUID,pubEP->serviceID,pubEP->scope, pubEP->topic); + printf("PSA_UDP_MC: Received publication [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",pubEP->frameworkUUID,pubEP->serviceID,pubEP->scope, pubEP->topic); const char* fwUUID = NULL; bundleContext_getProperty(admin->bundle_context,OSGI_FRAMEWORK_FRAMEWORK_UUID,&fwUUID); if(fwUUID==NULL){ - printf("PSA: Cannot retrieve fwUUID.\n"); + printf("PSA_UDP_MC: Cannot retrieve fwUUID.\n"); return CELIX_INVALID_BUNDLE_CONTEXT; } char* scope_topic = createScopeTopicKey(pubEP->scope, pubEP->topic); - if((strcmp(pubEP->frameworkUUID,fwUUID)==0) && (pubEP->endpoint==NULL)){ + if ((strcmp(pubEP->frameworkUUID, fwUUID) == 0) && (pubEP->endpoint == NULL)) { celixThreadMutex_lock(&admin->localPublicationsLock); - - service_factory_pt factory = (service_factory_pt)hashMap_get(admin->localPublications,scope_topic); + service_factory_pt factory = (service_factory_pt) hashMap_get(admin->localPublications, scope_topic); if (factory == NULL) { topic_publication_pt pub = NULL; - status = pubsub_topicPublicationCreate(admin->sendSocket, pubEP, admin->mcIpAddress,&pub); - pubsub_topicPublicationSetSerializer(pub, admin->serializerSvc); //TODO move back to contructor - //TODO this is certainly needed when admin are created per available serializer - if(status == CELIX_SUCCESS){ - status = pubsub_topicPublicationStart(admin->bundle_context,pub,&factory); - if(status==CELIX_SUCCESS && factory !=NULL){ - hashMap_put(admin->localPublications,strdup(scope_topic),factory); - } + pubsub_serializer_service_t *best_serializer = NULL; + if( (status=pubsubAdmin_getBestSerializer(admin, pubEP, &best_serializer)) == CELIX_SUCCESS){ + status = pubsub_topicPublicationCreate(admin->sendSocket, pubEP, best_serializer, admin->mcIpAddress, &pub); } else{ - printf("PSA: Cannot create a topicPublication for topic %s (bundle %ld).\n",pubEP->topic,pubEP->serviceID); + printf("PSA_UDP_MC: Cannot find a serializer for publishing topic %s. Adding it to pending list.\n", pubEP->topic); + celixThreadMutex_lock(&admin->noSerializerPendingsLock); + arrayList_add(admin->noSerializerPublications,pubEP); + celixThreadMutex_unlock(&admin->noSerializerPendingsLock); } - } - else{ + + if (status == CELIX_SUCCESS) { + status = pubsub_topicPublicationStart(admin->bundle_context, pub, &factory); + if (status == CELIX_SUCCESS && factory != NULL) { + hashMap_put(admin->localPublications, strdup(scope_topic), factory); + connectTopicPubSubToSerializer(admin, best_serializer, pub, true); + } + } else { + printf("PSA_UDP_MC: Cannot create a topicPublication for scope=%s, topic=%s (bundle %ld).\n", pubEP->scope, pubEP->topic, pubEP->serviceID); + } + } else { //just add the new EP to the list - topic_publication_pt pub = (topic_publication_pt)factory->handle; - pubsub_topicPublicationAddPublisherEP(pub,pubEP); + topic_publication_pt pub = (topic_publication_pt) factory->handle; + pubsub_topicPublicationAddPublisherEP(pub, pubEP); } - celixThreadMutex_unlock(&admin->localPublicationsLock); } else{ + celixThreadMutex_lock(&admin->externalPublicationsLock); - array_list_pt ext_pub_list = (array_list_pt)hashMap_get(admin->externalPublications,scope_topic); - if(ext_pub_list==NULL){ + array_list_pt ext_pub_list = (array_list_pt) hashMap_get(admin->externalPublications, scope_topic); + if (ext_pub_list == NULL) { arrayList_create(&ext_pub_list); - hashMap_put(admin->externalPublications,strdup(scope_topic),ext_pub_list); + hashMap_put(admin->externalPublications, strdup(scope_topic), ext_pub_list); } - arrayList_add(ext_pub_list,pubEP); + arrayList_add(ext_pub_list, pubEP); celixThreadMutex_unlock(&admin->externalPublicationsLock); } - /* Connect the new publisher to the subscription for his topic, if there is any */ - celixThreadMutex_lock(&admin->subscriptionsLock); - - topic_subscription_pt sub = (topic_subscription_pt)hashMap_get(admin->subscriptions,scope_topic); - if(sub!=NULL && pubEP->endpoint!=NULL){ - pubsub_topicSubscriptionConnectPublisher(sub,pubEP->endpoint); - } - - /* And check also for ANY subscription */ - topic_subscription_pt any_sub = (topic_subscription_pt)hashMap_get(admin->subscriptions,PUBSUB_ANY_SUB_TOPIC); - if(any_sub!=NULL && pubEP->endpoint!=NULL){ - pubsub_topicSubscriptionConnectPublisher(any_sub,pubEP->endpoint); - } - - celixThreadMutex_unlock(&admin->subscriptionsLock); - /* Re-evaluate the pending subscriptions */ celixThreadMutex_lock(&admin->pendingSubscriptionsLock); - hash_map_entry_pt pendingSub = hashMap_getEntry(admin->pendingSubscriptions,scope_topic); - if(pendingSub!=NULL){ //There were pending subscription for the just published topic. Let's connect them. - char* key = (char*)hashMapEntry_getKey(pendingSub); - array_list_pt pendingSubList = (array_list_pt)hashMapEntry_getValue(pendingSub); + hash_map_entry_pt pendingSub = hashMap_getEntry(admin->pendingSubscriptions, scope_topic); + if (pendingSub != NULL) { //There were pending subscription for the just published topic. Let's connect them. + char* topic = (char*) hashMapEntry_getKey(pendingSub); + array_list_pt pendingSubList = (array_list_pt) hashMapEntry_getValue(pendingSub); int i; - for(i=0;ipendingSubscriptions,key); + hashMap_remove(admin->pendingSubscriptions, scope_topic); arrayList_clear(pendingSubList); arrayList_destroy(pendingSubList); - free(key); + free(topic); } - free(scope_topic); celixThreadMutex_unlock(&admin->pendingSubscriptionsLock); + /* Connect the new publisher to the subscription for his topic, if there is any */ + celixThreadMutex_lock(&admin->subscriptionsLock); + + topic_subscription_pt sub = (topic_subscription_pt) hashMap_get(admin->subscriptions, scope_topic); + if (sub != NULL && pubEP->endpoint != NULL) { + pubsub_topicSubscriptionAddConnectPublisherToPendingList(sub, pubEP->endpoint); + } + + /* And check also for ANY subscription */ + topic_subscription_pt any_sub = (topic_subscription_pt) hashMap_get(admin->subscriptions, PUBSUB_ANY_SUB_TOPIC); + if (any_sub != NULL && pubEP->endpoint != NULL) { + pubsub_topicSubscriptionAddConnectPublisherToPendingList(any_sub, pubEP->endpoint); + } + + free(scope_topic); + + celixThreadMutex_unlock(&admin->subscriptionsLock); + return status; } celix_status_t pubsubAdmin_removePublication(pubsub_admin_pt admin,pubsub_endpoint_pt pubEP){ celix_status_t status = CELIX_SUCCESS; + int count = 0; - printf("PSA: Removing publication [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",pubEP->frameworkUUID,pubEP->serviceID,pubEP->scope, pubEP->topic); + printf("PSA_UDP_MC: Removing publication [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",pubEP->frameworkUUID,pubEP->serviceID,pubEP->scope, pubEP->topic); const char* fwUUID = NULL; bundleContext_getProperty(admin->bundle_context,OSGI_FRAMEWORK_FRAMEWORK_UUID,&fwUUID); if(fwUUID==NULL){ - printf("PSA: Cannot retrieve fwUUID.\n"); + printf("PSA_UDP_MC: Cannot retrieve fwUUID.\n"); return CELIX_INVALID_BUNDLE_CONTEXT; } char *scope_topic = createScopeTopicKey(pubEP->scope, pubEP->topic); @@ -531,7 +600,12 @@ celix_status_t pubsubAdmin_removePublication(pubsub_admin_pt admin,pubsub_endpoi pubsub_topicPublicationRemovePublisherEP(pub,pubEP); } else{ - status = CELIX_ILLEGAL_STATE; + /* Maybe the endpoint was pending */ + celixThreadMutex_lock(&admin->noSerializerPendingsLock); + if(!arrayList_removeElement(admin->noSerializerPublications, pubEP)){ + status = CELIX_ILLEGAL_STATE; + } + celixThreadMutex_unlock(&admin->noSerializerPendingsLock); } celixThreadMutex_unlock(&admin->localPublicationsLock); @@ -546,15 +620,23 @@ celix_status_t pubsubAdmin_removePublication(pubsub_admin_pt admin,pubsub_endpoi for(i=0;!found && iendpoint,p->endpoint) == 0) { + count++; + } + } + if(arrayList_size(ext_pub_list)==0){ hash_map_entry_pt entry = hashMap_getEntry(admin->externalPublications,scope_topic); char* topic = (char*)hashMapEntry_getKey(entry); array_list_pt list = (array_list_pt)hashMapEntry_getValue(entry); - hashMap_remove(admin->externalPublications,scope_topic); + hashMap_remove(admin->externalPublications,topic); arrayList_destroy(list); free(topic); } @@ -567,15 +649,16 @@ celix_status_t pubsubAdmin_removePublication(pubsub_admin_pt admin,pubsub_endpoi celixThreadMutex_lock(&admin->subscriptionsLock); topic_subscription_pt sub = (topic_subscription_pt)hashMap_get(admin->subscriptions,scope_topic); - if(sub!=NULL && pubEP->endpoint!=NULL){ - pubsub_topicSubscriptionDisconnectPublisher(sub,pubEP->endpoint); + if(sub!=NULL && pubEP->endpoint!=NULL && count == 0){ + pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(sub,pubEP->endpoint); } /* And check also for ANY subscription */ topic_subscription_pt any_sub = (topic_subscription_pt)hashMap_get(admin->subscriptions,PUBSUB_ANY_SUB_TOPIC); - if(any_sub!=NULL && pubEP->endpoint!=NULL){ - pubsub_topicSubscriptionDisconnectPublisher(any_sub,pubEP->endpoint); + if(any_sub!=NULL && pubEP->endpoint!=NULL && count == 0){ + pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(sub,pubEP->endpoint); } + free(scope_topic); celixThreadMutex_unlock(&admin->subscriptionsLock); @@ -586,7 +669,7 @@ celix_status_t pubsubAdmin_removePublication(pubsub_admin_pt admin,pubsub_endpoi celix_status_t pubsubAdmin_closeAllPublications(pubsub_admin_pt admin,char *scope, char* topic){ celix_status_t status = CELIX_SUCCESS; - printf("PSA: Closing all publications for scope=%s,topic=%s\n", scope, topic); + printf("PSA_UDP_MC: Closing all publications for scope=%s,topic=%s\n", scope, topic); celixThreadMutex_lock(&admin->localPublicationsLock); char* scope_topic =createScopeTopicKey(scope, topic); @@ -598,6 +681,7 @@ celix_status_t pubsubAdmin_closeAllPublications(pubsub_admin_pt admin,char *scop status += pubsub_topicPublicationStop(pub); status += pubsub_topicPublicationDestroy(pub); + disconnectTopicPubSubFromSerializer(admin, pub, true); hashMap_remove(admin->localPublications,scope_topic); free(key); free(factory); @@ -612,7 +696,7 @@ celix_status_t pubsubAdmin_closeAllPublications(pubsub_admin_pt admin,char *scop celix_status_t pubsubAdmin_closeAllSubscriptions(pubsub_admin_pt admin,char *scope, char* topic){ celix_status_t status = CELIX_SUCCESS; - printf("PSA: Closing all subscriptions\n"); + printf("PSA_UDP_MC: Closing all subscriptions\n"); celixThreadMutex_lock(&admin->subscriptionsLock); char* scope_topic =createScopeTopicKey(scope, topic); @@ -624,6 +708,7 @@ celix_status_t pubsubAdmin_closeAllSubscriptions(pubsub_admin_pt admin,char *sco status += pubsub_topicSubscriptionStop(ts); status += pubsub_topicSubscriptionDestroy(ts); + disconnectTopicPubSubFromSerializer(admin, ts, false); hashMap_remove(admin->subscriptions,topic); free(topic); @@ -635,92 +720,6 @@ celix_status_t pubsubAdmin_closeAllSubscriptions(pubsub_admin_pt admin,char *sco } -celix_status_t pubsubAdmin_matchPublisher(pubsub_admin_pt admin, pubsub_endpoint_pt pubEP, double* score){ - celix_status_t status = CELIX_SUCCESS; - status = pubsubAdmin_match(admin, pubEP, score); - return status; -} - -celix_status_t pubsubAdmin_matchSubscriber(pubsub_admin_pt admin, pubsub_endpoint_pt subEP, double* score){ - celix_status_t status = CELIX_SUCCESS; - status = pubsubAdmin_match(admin, subEP, score); - return status; -} - -celix_status_t pubsubAdmin_setSerializer(pubsub_admin_pt admin, pubsub_serializer_service_t* serializerSvc){ - celix_status_t status = CELIX_SUCCESS; - admin->serializerSvc = serializerSvc; - - /* Add serializer to all topic_publication_pt */ - celixThreadMutex_lock(&admin->localPublicationsLock); - hash_map_iterator_pt lp_iter = hashMapIterator_create(admin->localPublications); - while(hashMapIterator_hasNext(lp_iter)){ - service_factory_pt factory = (service_factory_pt) hashMapIterator_nextValue(lp_iter); - topic_publication_pt topic_pub = (topic_publication_pt) factory->handle; - pubsub_topicPublicationSetSerializer(topic_pub, admin->serializerSvc); - } - hashMapIterator_destroy(lp_iter); - celixThreadMutex_unlock(&admin->localPublicationsLock); - - /* Add serializer to all topic_subscription_pt */ - celixThreadMutex_lock(&admin->subscriptionsLock); - hash_map_iterator_pt subs_iter = hashMapIterator_create(admin->subscriptions); - while(hashMapIterator_hasNext(subs_iter)){ - topic_subscription_pt topic_sub = (topic_subscription_pt) hashMapIterator_nextValue(subs_iter); - pubsub_topicSubscriptionSetSerializer(topic_sub, admin->serializerSvc); - } - hashMapIterator_destroy(subs_iter); - celixThreadMutex_unlock(&admin->subscriptionsLock); - - return status; -} - -celix_status_t pubsubAdmin_removeSerializer(pubsub_admin_pt admin, pubsub_serializer_service_t* serializerSvc){ - celix_status_t status = CELIX_SUCCESS; - admin->serializerSvc = NULL; - - /* Remove serializer from all topic_publication_pt */ - celixThreadMutex_lock(&admin->localPublicationsLock); - hash_map_iterator_pt lp_iter = hashMapIterator_create(admin->localPublications); - while(hashMapIterator_hasNext(lp_iter)){ - service_factory_pt factory = (service_factory_pt) hashMapIterator_nextValue(lp_iter); - topic_publication_pt topic_pub = (topic_publication_pt) factory->handle; - pubsub_topicPublicationRemoveSerializer(topic_pub, admin->serializerSvc); - } - hashMapIterator_destroy(lp_iter); - celixThreadMutex_unlock(&admin->localPublicationsLock); - - /* Remove serializer from all topic_subscription_pt */ - celixThreadMutex_lock(&admin->subscriptionsLock); - hash_map_iterator_pt subs_iter = hashMapIterator_create(admin->subscriptions); - while(hashMapIterator_hasNext(subs_iter)){ - topic_subscription_pt topic_sub = (topic_subscription_pt) hashMapIterator_nextValue(subs_iter); - pubsub_topicSubscriptionRemoveSerializer(topic_sub, admin->serializerSvc); - } - hashMapIterator_destroy(subs_iter); - celixThreadMutex_unlock(&admin->subscriptionsLock); - - return status; -} - -static celix_status_t pubsubAdmin_match(pubsub_admin_pt admin, pubsub_endpoint_pt psEP, double* score){ - celix_status_t status = CELIX_SUCCESS; - - char topic_psa_prop[1024]; - snprintf(topic_psa_prop, 1024, "%s.psa", psEP->topic); - - const char* psa_to_use = NULL; - bundleContext_getPropertyWithDefault(admin->bundle_context, topic_psa_prop, PSA_DEFAULT, &psa_to_use); - - *score = 0; - if (strcmp(psa_to_use, "udp") == 0){ - *score += 100; - }else{ - *score += 1; - } - - return status; -} #ifndef ANDROID static celix_status_t pubsubAdmin_getIpAddress(const char* interface, char** ip) { @@ -764,11 +763,245 @@ static celix_status_t pubsubAdmin_addSubscriptionToPendingList(pubsub_admin_pt a array_list_pt pendingListPerTopic = hashMap_get(admin->pendingSubscriptions,scope_topic); if(pendingListPerTopic==NULL){ arrayList_create(&pendingListPerTopic); - hashMap_put(admin->pendingSubscriptions,scope_topic,pendingListPerTopic); - } else { - free(scope_topic); + hashMap_put(admin->pendingSubscriptions,strdup(scope_topic),pendingListPerTopic); } arrayList_add(pendingListPerTopic,subEP); + free(scope_topic); + + return status; +} + + +celix_status_t pubsubAdmin_serializerAdded(void * handle, service_reference_pt reference, void * service){ + /* Assumption: serializers are all available at startup. + * If a new (possibly better) serializer is installed and started, already created topic_publications/subscriptions will not be destroyed and recreated */ + + celix_status_t status = CELIX_SUCCESS; + int i=0; + + const char *serType = NULL; + serviceReference_getProperty(reference, PUBSUB_SERIALIZER_TYPE_KEY,&serType); + if(serType == NULL){ + printf("Serializer serviceReference %p has no pubsub_serializer.type property specified\n",reference); + return CELIX_SERVICE_EXCEPTION; + } + + pubsub_admin_pt admin = (pubsub_admin_pt)handle; + celixThreadMutex_lock(&admin->serializerListLock); + arrayList_add(admin->serializerList, reference); + celixThreadMutex_unlock(&admin->serializerListLock); + + /* Now let's re-evaluate the pending */ + celixThreadMutex_lock(&admin->noSerializerPendingsLock); + + for(i=0;inoSerializerSubscriptions);i++){ + pubsub_endpoint_pt ep = (pubsub_endpoint_pt)arrayList_get(admin->noSerializerSubscriptions,i); + pubsub_serializer_service_t *best_serializer = NULL; + pubsubAdmin_getBestSerializer(admin, ep, &best_serializer); + if(best_serializer != NULL){ /* Finally we have a valid serializer! */ + pubsubAdmin_addSubscription(admin, ep); + } + } + + for(i=0;inoSerializerPublications);i++){ + pubsub_endpoint_pt ep = (pubsub_endpoint_pt)arrayList_get(admin->noSerializerPublications,i); + pubsub_serializer_service_t *best_serializer = NULL; + pubsubAdmin_getBestSerializer(admin, ep, &best_serializer); + if(best_serializer != NULL){ /* Finally we have a valid serializer! */ + pubsubAdmin_addPublication(admin, ep); + } + } + + celixThreadMutex_unlock(&admin->noSerializerPendingsLock); + + printf("PSA_UDP_MC: %s serializer added\n",serType); return status; } + +celix_status_t pubsubAdmin_serializerRemoved(void * handle, service_reference_pt reference, void * service){ + + pubsub_admin_pt admin = (pubsub_admin_pt)handle; + int i=0, j=0; + const char *serType = NULL; + + serviceReference_getProperty(reference, PUBSUB_SERIALIZER_TYPE_KEY,&serType); + if(serType == NULL){ + printf("Serializer serviceReference %p has no pubsub_serializer.type property specified\n",reference); + return CELIX_SERVICE_EXCEPTION; + } + + celixThreadMutex_lock(&admin->serializerListLock); + celixThreadMutex_lock(&admin->usedSerializersLock); + + + /* Remove the serializer from the list */ + arrayList_removeElement(admin->serializerList, reference); + + /* Now destroy the topicPublications, but first put back the pubsub_endpoints back to the noSerializer pending list */ + array_list_pt topicPubList = (array_list_pt)hashMap_remove(admin->topicPublicationsPerSerializer, service); + if(topicPubList!=NULL){ + for(i=0;iendpoint!=NULL){ + free(pubEP->endpoint); + pubEP->endpoint = NULL; + } + /* Add the orphan endpoint to the noSerializer pending list */ + celixThreadMutex_lock(&admin->noSerializerPendingsLock); + arrayList_add(admin->noSerializerPublications,pubEP); + celixThreadMutex_unlock(&admin->noSerializerPendingsLock); + } + arrayList_destroy(pubList); + + /* Cleanup also the localPublications hashmap*/ + celixThreadMutex_lock(&admin->localPublicationsLock); + hash_map_iterator_pt iter = hashMapIterator_create(admin->localPublications); + char *key = NULL; + service_factory_pt factory = NULL; + while(hashMapIterator_hasNext(iter)){ + hash_map_entry_pt entry = hashMapIterator_nextEntry(iter); + factory = (service_factory_pt)hashMapEntry_getValue(entry); + topic_publication_pt pub = (topic_publication_pt)factory->handle; + if(pub==topicPub){ + key = (char*)hashMapEntry_getKey(entry); + break; + } + } + hashMapIterator_destroy(iter); + if(key!=NULL){ + hashMap_remove(admin->localPublications, key); + free(factory); + free(key); + } + celixThreadMutex_unlock(&admin->localPublicationsLock); + + /* Finally destroy the topicPublication */ + pubsub_topicPublicationDestroy(topicPub); + } + arrayList_destroy(topicPubList); + } + + /* Now destroy the topicSubscriptions, but first put back the pubsub_endpoints back to the noSerializer pending list */ + array_list_pt topicSubList = (array_list_pt)hashMap_remove(admin->topicSubscriptionsPerSerializer, service); + if(topicSubList!=NULL){ + for(i=0;iendpoint!=NULL){ + free(subEP->endpoint); + subEP->endpoint = NULL; + } + /* Add the orphan endpoint to the noSerializer pending list */ + celixThreadMutex_lock(&admin->noSerializerPendingsLock); + arrayList_add(admin->noSerializerSubscriptions,subEP); + celixThreadMutex_unlock(&admin->noSerializerPendingsLock); + } + + /* Cleanup also the subscriptions hashmap*/ + celixThreadMutex_lock(&admin->subscriptionsLock); + hash_map_iterator_pt iter = hashMapIterator_create(admin->subscriptions); + char *key = NULL; + while(hashMapIterator_hasNext(iter)){ + hash_map_entry_pt entry = hashMapIterator_nextEntry(iter); + topic_subscription_pt sub = (topic_subscription_pt)hashMapEntry_getValue(entry); + if(sub==topicSub){ + key = (char*)hashMapEntry_getKey(entry); + break; + } + } + hashMapIterator_destroy(iter); + if(key!=NULL){ + hashMap_remove(admin->subscriptions, key); + free(key); + } + celixThreadMutex_unlock(&admin->subscriptionsLock); + + /* Finally destroy the topicSubscription */ + pubsub_topicSubscriptionDestroy(topicSub); + } + arrayList_destroy(topicSubList); + } + + celixThreadMutex_unlock(&admin->usedSerializersLock); + celixThreadMutex_unlock(&admin->serializerListLock); + + printf("PSA_UDP_MC: %s serializer removed\n",serType); + + + return CELIX_SUCCESS; +} + +celix_status_t pubsubAdmin_matchEndpoint(pubsub_admin_pt admin, pubsub_endpoint_pt endpoint, double* score){ + celix_status_t status = CELIX_SUCCESS; + + celixThreadMutex_lock(&admin->serializerListLock); + status = pubsub_admin_match(endpoint->topic_props,PUBSUB_ADMIN_TYPE,admin->serializerList,score); + celixThreadMutex_unlock(&admin->serializerListLock); + + return status; +} + +/* This one recall the same logic as in the match function */ +static celix_status_t pubsubAdmin_getBestSerializer(pubsub_admin_pt admin,pubsub_endpoint_pt ep, pubsub_serializer_service_t **serSvc){ + + celix_status_t status = CELIX_SUCCESS; + + celixThreadMutex_lock(&admin->serializerListLock); + status = pubsub_admin_get_best_serializer(ep->topic_props, admin->serializerList, serSvc); + celixThreadMutex_unlock(&admin->serializerListLock); + + return status; + +} + +static void connectTopicPubSubToSerializer(pubsub_admin_pt admin,pubsub_serializer_service_t *serializer,void *topicPubSub,bool isPublication){ + + celixThreadMutex_lock(&admin->usedSerializersLock); + + hash_map_pt map = isPublication?admin->topicPublicationsPerSerializer:admin->topicSubscriptionsPerSerializer; + array_list_pt list = (array_list_pt)hashMap_get(map,serializer); + if(list==NULL){ + arrayList_create(&list); + hashMap_put(map,serializer,list); + } + arrayList_add(list,topicPubSub); + + celixThreadMutex_unlock(&admin->usedSerializersLock); + +} + +static void disconnectTopicPubSubFromSerializer(pubsub_admin_pt admin,void *topicPubSub,bool isPublication){ + + celixThreadMutex_lock(&admin->usedSerializersLock); + + hash_map_pt map = isPublication?admin->topicPublicationsPerSerializer:admin->topicSubscriptionsPerSerializer; + hash_map_iterator_pt iter = hashMapIterator_create(map); + while(hashMapIterator_hasNext(iter)){ + array_list_pt list = (array_list_pt)hashMapIterator_nextValue(iter); + if(arrayList_removeElement(list, topicPubSub)){ //Found it! + break; + } + } + hashMapIterator_destroy(iter); + + celixThreadMutex_unlock(&admin->usedSerializersLock); + +} diff --git a/pubsub/pubsub_admin_udp_mc/private/src/topic_publication.c b/pubsub/pubsub_admin_udp_mc/private/src/topic_publication.c index bed5dfc56..b85f0a98f 100644 --- a/pubsub/pubsub_admin_udp_mc/private/src/topic_publication.c +++ b/pubsub/pubsub_admin_udp_mc/private/src/topic_publication.c @@ -7,7 +7,7 @@ *"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 + * htPSA_UDP_MC_TP://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 @@ -41,11 +41,13 @@ #include "service_factory.h" #include "version.h" -#include "pubsub_publish_service_private.h" +#include "topic_publication.h" #include "pubsub_common.h" #include "publisher.h" #include "large_udp.h" +#include "pubsub_serializer.h" + #define EP_ADDRESS_LEN 32 #define FIRST_SEND_DELAY 2 @@ -57,28 +59,26 @@ struct topic_publication { array_list_pt pub_ep_list; //List hash_map_pt boundServices; // celix_thread_mutex_t tp_lock; + pubsub_serializer_service_t *serializer; struct sockaddr_in destAddr; - pubsub_serializer_service_t* serializerSvc; }; typedef struct publish_bundle_bound_service { topic_publication_pt parent; - pubsub_publisher_t pubSvc; + pubsub_publisher_t service; bundle_pt bundle; - char *scope; + char *scope; char *topic; + hash_map_pt msgTypes; unsigned short getCount; celix_thread_mutex_t mp_lock; - bool mp_send_in_progress; - array_list_pt mp_parts; largeUdp_pt largeUdpHandle; - pubsub_msg_serializer_map_t* map; -} publish_bundle_bound_service_t; +}* publish_bundle_bound_service_pt; typedef struct pubsub_msg{ pubsub_msg_header_pt header; char* payload; - int payloadSize; + size_t payloadSize; } pubsub_msg_t; static unsigned int rand_range(unsigned int min, unsigned int max); @@ -86,10 +86,10 @@ static unsigned int rand_range(unsigned int min, unsigned int max); static celix_status_t pubsub_topicPublicationGetService(void* handle, bundle_pt bundle, service_registration_pt registration, void **service); static celix_status_t pubsub_topicPublicationUngetService(void* handle, bundle_pt bundle, service_registration_pt registration, void **service); -static publish_bundle_bound_service_t* pubsub_createPublishBundleBoundService(topic_publication_pt tp,bundle_pt bundle); -static void pubsub_destroyPublishBundleBoundService(publish_bundle_bound_service_t* boundSvc); +static publish_bundle_bound_service_pt pubsub_createPublishBundleBoundService(topic_publication_pt tp,bundle_pt bundle); +static void pubsub_destroyPublishBundleBoundService(publish_bundle_bound_service_pt boundSvc); -static int pubsub_topicPublicationSend(void* handle, unsigned int msgTypeId, const void *msg); +static int pubsub_topicPublicationSend(void* handle,unsigned int msgTypeId, const void *msg); static int pubsub_localMsgTypeIdForUUID(void* handle, const char* msgType, unsigned int* msgTypeId); @@ -97,12 +97,12 @@ static int pubsub_localMsgTypeIdForUUID(void* handle, const char* msgType, unsig static void delay_first_send_for_late_joiners(void); -celix_status_t pubsub_topicPublicationCreate(int sendSocket, pubsub_endpoint_pt pubEP, char* bindIP, topic_publication_pt *out){ +celix_status_t pubsub_topicPublicationCreate(int sendSocket, pubsub_endpoint_pt pubEP, pubsub_serializer_service_t *best_serializer, char* bindIP, topic_publication_pt *out){ - char* ep = malloc(EP_ADDRESS_LEN); - memset(ep,0,EP_ADDRESS_LEN); - unsigned int port = pubEP->serviceID + rand_range(UDP_BASE_PORT+pubEP->serviceID+3, UDP_MAX_PORT); - snprintf(ep,EP_ADDRESS_LEN,"udp://%s:%u",bindIP,port); + char* ep = malloc(EP_ADDRESS_LEN); + memset(ep,0,EP_ADDRESS_LEN); + unsigned int port = pubEP->serviceID + rand_range(UDP_BASE_PORT+pubEP->serviceID+3, UDP_MAX_PORT); + snprintf(ep,EP_ADDRESS_LEN,"udp://%s:%u",bindIP,port); topic_publication_pt pub = calloc(1,sizeof(*pub)); @@ -116,7 +116,8 @@ celix_status_t pubsub_topicPublicationCreate(int sendSocket, pubsub_endpoint_pt pub->destAddr.sin_family = AF_INET; pub->destAddr.sin_addr.s_addr = inet_addr(bindIP); pub->destAddr.sin_port = htons(port); - pub->serializerSvc = NULL; + + pub->serializer = best_serializer; pubsub_topicPublicationAddPublisherEP(pub,pubEP); @@ -127,6 +128,7 @@ celix_status_t pubsub_topicPublicationCreate(int sendSocket, pubsub_endpoint_pt celix_status_t pubsub_topicPublicationDestroy(topic_publication_pt pub){ celix_status_t status = CELIX_SUCCESS; + celixThreadMutex_lock(&(pub->tp_lock)); free(pub->endpoint); @@ -134,14 +136,18 @@ celix_status_t pubsub_topicPublicationDestroy(topic_publication_pt pub){ hash_map_iterator_pt iter = hashMapIterator_create(pub->boundServices); while(hashMapIterator_hasNext(iter)){ - publish_bundle_bound_service_t* bound = hashMapIterator_nextValue(iter); + publish_bundle_bound_service_pt bound = hashMapIterator_nextValue(iter); pubsub_destroyPublishBundleBoundService(bound); } hashMapIterator_destroy(iter); hashMap_destroy(pub->boundServices,false,false); pub->svcFactoryReg = NULL; - status = close(pub->sendSocket); + pub->serializer = NULL; + + if(close(pub->sendSocket) != 0){ + status = CELIX_FILE_IO_EXCEPTION; + } celixThreadMutex_unlock(&(pub->tp_lock)); @@ -156,7 +162,6 @@ celix_status_t pubsub_topicPublicationStart(bundle_context_pt bundle_context,top celix_status_t status = CELIX_SUCCESS; /* Let's register the new service */ - //celixThreadMutex_lock(&(pub->tp_lock)); pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(pub->pub_ep_list,0); @@ -167,39 +172,29 @@ celix_status_t pubsub_topicPublicationStart(bundle_context_pt bundle_context,top factory->ungetService = pubsub_topicPublicationUngetService; properties_pt props = properties_create(); - properties_set(props,PUBSUB_PUBLISHER_SCOPE,pubEP->scope); + properties_set(props,PUBSUB_PUBLISHER_SCOPE,pubEP->scope); properties_set(props,PUBSUB_PUBLISHER_TOPIC,pubEP->topic); status = bundleContext_registerServiceFactory(bundle_context,PUBSUB_PUBLISHER_SERVICE_NAME,factory,props,&(pub->svcFactoryReg)); if(status != CELIX_SUCCESS){ properties_destroy(props); - printf("PSA: Cannot register ServiceFactory for topic %s, topic %s (bundle %ld).\n",pubEP->scope, pubEP->topic,pubEP->serviceID); + printf("PSA_UDP_MC_PSA_UDP_MC_TP: Cannot register ServiceFactory for topic %s, topic %s (bundle %ld).\n",pubEP->scope, pubEP->topic,pubEP->serviceID); } else{ *svcFactory = factory; } } else{ - printf("PSA: Cannot find pubsub_endpoint after adding it...Should never happen!\n"); + printf("PSA_UDP_MC_PSA_UDP_MC_TP: Cannot find pubsub_endpoint after adding it...Should never happen!\n"); status = CELIX_SERVICE_EXCEPTION; } - //celixThreadMutex_unlock(&(pub->tp_lock)); - return status; } celix_status_t pubsub_topicPublicationStop(topic_publication_pt pub){ - celix_status_t status = CELIX_SUCCESS; - - //celixThreadMutex_lock(&(pub->tp_lock)); - - status = serviceRegistration_unregister(pub->svcFactoryReg); - - //celixThreadMutex_unlock(&(pub->tp_lock)); - - return status; + return serviceRegistration_unregister(pub->svcFactoryReg); } celix_status_t pubsub_topicPublicationAddPublisherEP(topic_publication_pt pub,pubsub_endpoint_pt ep){ @@ -221,66 +216,12 @@ celix_status_t pubsub_topicPublicationRemovePublisherEP(topic_publication_pt pub return CELIX_SUCCESS; } -celix_status_t pubsub_topicPublicationSetSerializer(topic_publication_pt pub, pubsub_serializer_service_t* serializerSvc){ - celix_status_t status = CELIX_SUCCESS; - +array_list_pt pubsub_topicPublicationGetPublisherList(topic_publication_pt pub){ + array_list_pt list = NULL; celixThreadMutex_lock(&(pub->tp_lock)); - - //clear old serializer - if (pub->serializerSvc != NULL) { - hash_map_iterator_t iter = hashMapIterator_construct(pub->boundServices); //key = bundle_pt, publish_bundle_bound_service_t* - while (hashMapIterator_hasNext(&iter)) { - publish_bundle_bound_service_t* bound = hashMapIterator_nextValue(&iter); - celixThreadMutex_lock(&bound->mp_lock); - pub->serializerSvc->destroySerializerMap(pub->serializerSvc->handle, bound->map); - celixThreadMutex_unlock(&bound->mp_lock); - bound->map = NULL; - } - } - - //setup new serializer - pub->serializerSvc = serializerSvc; - if (pub->serializerSvc != NULL) { - hash_map_iterator_t iter = hashMapIterator_construct(pub->boundServices); - while (hashMapIterator_hasNext(&iter)) { - hash_map_entry_pt entry = hashMapIterator_nextEntry(&iter); - bundle_pt bundle = hashMapEntry_getKey(entry); - publish_bundle_bound_service_t *bound = hashMapEntry_getValue(entry); - celixThreadMutex_lock(&bound->mp_lock); - pub->serializerSvc->createSerializerMap(pub->serializerSvc->handle, bundle, &bound->map); - celixThreadMutex_unlock(&bound->mp_lock); - } - } - + list = arrayList_clone(pub->pub_ep_list); celixThreadMutex_unlock(&(pub->tp_lock)); - - return status; -} - -celix_status_t pubsub_topicPublicationRemoveSerializer(topic_publication_pt pub, pubsub_serializer_service_t* svc){ - celix_status_t status = CELIX_SUCCESS; - - celixThreadMutex_lock(&(pub->tp_lock)); - if (pub->serializerSvc == svc) { - hash_map_iterator_t iter = hashMapIterator_construct(pub->boundServices); - while (hashMapIterator_hasNext(&iter)) { - publish_bundle_bound_service_t* bound = hashMapIterator_nextValue(&iter); - celixThreadMutex_lock(&bound->mp_lock); - pub->serializerSvc->destroySerializerMap(pub->serializerSvc->handle, bound->map); - celixThreadMutex_unlock(&bound->mp_lock); - bound->map = NULL; - } - - pub->serializerSvc = NULL; - } - - celixThreadMutex_unlock(&(pub->tp_lock)); - - return status; -} - -array_list_pt pubsub_topicPublicationGetPublisherList(topic_publication_pt pub){ - return pub->pub_ep_list; + return list; } @@ -291,19 +232,19 @@ static celix_status_t pubsub_topicPublicationGetService(void* handle, bundle_pt celixThreadMutex_lock(&(publish->tp_lock)); - publish_bundle_bound_service_t* bound = hashMap_get(publish->boundServices, bundle); - if (bound == NULL) { - bound = pubsub_createPublishBundleBoundService(publish, bundle); - if (bound != NULL) { - hashMap_put(publish->boundServices, bundle, bound); + publish_bundle_bound_service_pt bound = (publish_bundle_bound_service_pt)hashMap_get(publish->boundServices,bundle); + if(bound==NULL){ + bound = pubsub_createPublishBundleBoundService(publish,bundle); + if(bound!=NULL){ + hashMap_put(publish->boundServices,bundle,bound); } } - else { + else{ bound->getCount++; } if (bound != NULL) { - *service = &bound->pubSvc; + *service = &bound->service; } celixThreadMutex_unlock(&(publish->tp_lock)); @@ -317,19 +258,20 @@ static celix_status_t pubsub_topicPublicationUngetService(void* handle, bundle_p celixThreadMutex_lock(&(publish->tp_lock)); - publish_bundle_bound_service_t* bound = hashMap_get(publish->boundServices, bundle); - if (bound != NULL) { + publish_bundle_bound_service_pt bound = (publish_bundle_bound_service_pt)hashMap_get(publish->boundServices,bundle); + if(bound!=NULL){ bound->getCount--; - if (bound->getCount == 0) { + if(bound->getCount==0){ pubsub_destroyPublishBundleBoundService(bound); hashMap_remove(publish->boundServices,bundle); } + } - else { + else{ long bundleId = -1; bundle_getBundleId(bundle,&bundleId); - printf("TP: Unexpected ungetService call for bundle %ld.\n", bundleId); + printf("PSA_UDP_MC_TP: Unexpected ungetService call for bundle %ld.\n", bundleId); } /* service should be never used for unget, so let's set the pointer to NULL */ @@ -340,7 +282,7 @@ static celix_status_t pubsub_topicPublicationUngetService(void* handle, bundle_p return CELIX_SUCCESS; } -static bool send_pubsub_msg(publish_bundle_bound_service_t* bound, pubsub_msg_t* msg, bool last, pubsub_release_callback_t *releaseCallback){ +static bool send_pubsub_msg(publish_bundle_bound_service_pt bound, pubsub_msg_t* msg, bool last, pubsub_release_callback_t *releaseCallback){ const int iovec_len = 3; // header + size + payload bool ret = true; @@ -357,50 +299,36 @@ static bool send_pubsub_msg(publish_bundle_bound_service_t* bound, pubsub_msg_t* delay_first_send_for_late_joiners(); if(largeUdp_sendmsg(bound->largeUdpHandle, bound->parent->sendSocket, msg_iovec, iovec_len, 0, &bound->parent->destAddr, sizeof(bound->parent->destAddr)) == -1) { - fprintf(stderr, "Socket: %d, size: %i",bound->parent->sendSocket, compiledMsgSize); - perror("send_pubsub_msg:sendSocket"); - ret = false; + fprintf(stderr, "Socket: %d, size: %i",bound->parent->sendSocket, compiledMsgSize); + perror("send_pubsub_msg:sendSocket"); + ret = false; } if(releaseCallback) { - releaseCallback->release(msg->payload, bound); + releaseCallback->release(msg->payload, bound); } return ret; -} +} -static int pubsub_topicPublicationSend(void* handle, unsigned int msgTypeId, const void *msg) { - int status = 0; - publish_bundle_bound_service_t* bound = handle; - celixThreadMutex_lock(&(bound->parent->tp_lock)); - celixThreadMutex_lock(&(bound->mp_lock)); +static int pubsub_topicPublicationSend(void* handle, unsigned int msgTypeId, const void *inMsg) { + int status = 0; + publish_bundle_bound_service_pt bound = (publish_bundle_bound_service_pt) handle; - pubsub_msg_serializer_t *msgSer = NULL; - if (bound->map != NULL) { - msgSer = hashMap_get(bound->map->serializers, (void *)(uintptr_t)msgTypeId); - } + celixThreadMutex_lock(&(bound->parent->tp_lock)); + celixThreadMutex_lock(&(bound->mp_lock)); - if (bound->map == NULL) { - printf("TP: Serializer is not set!\n"); - status = 1; - } else if (msgSer == NULL ){ - printf("TP: No msg serializer available for msg type id %d\n", msgTypeId); - hash_map_iterator_t iter = hashMapIterator_construct(bound->map->serializers); - printf("Note supported messages:\n"); - while (hashMapIterator_hasNext(&iter)) { - pubsub_msg_serializer_t *msgSer = hashMapIterator_nextValue(&iter); - printf("\tmsg %s with id %d\n", msgSer->msgName, msgSer->msgId); - } - status = 1; - } + pubsub_msg_serializer_t* msgSer = (pubsub_msg_serializer_t*)hashMap_get(bound->msgTypes, (void*)(uintptr_t)msgTypeId); - int major=0, minor=0; + if (msgSer != NULL) { + int major=0, minor=0; - if (status == 0 && msgSer != NULL) { pubsub_msg_header_pt msg_hdr = calloc(1,sizeof(struct pubsub_msg_header)); strncpy(msg_hdr->topic,bound->topic,MAX_TOPIC_LEN-1); msg_hdr->type = msgTypeId; + + if (msgSer->msgVersion != NULL){ version_getMajor(msgSer->msgVersion, &major); version_getMinor(msgSer->msgVersion, &minor); @@ -408,15 +336,16 @@ static int pubsub_topicPublicationSend(void* handle, unsigned int msgTypeId, con msg_hdr->minor = minor; } - char* serializedOutput = NULL; + void* serializedOutput = NULL; size_t serializedOutputLen = 0; - msgSer->serialize(msgSer->handle, msg, &serializedOutput, &serializedOutputLen); + msgSer->serialize(msgSer,inMsg,&serializedOutput, &serializedOutputLen); - pubsub_msg_t* msg = calloc(1,sizeof(struct pubsub_msg)); + pubsub_msg_t *msg = calloc(1,sizeof(pubsub_msg_t)); msg->header = msg_hdr; - msg->payload = serializedOutput; + msg->payload = (char *)serializedOutput; msg->payloadSize = serializedOutputLen; + if(send_pubsub_msg(bound, msg,true, NULL) == false) { status = -1; } @@ -424,38 +353,21 @@ static int pubsub_topicPublicationSend(void* handle, unsigned int msgTypeId, con free(msg); free(serializedOutput); - } - celixThreadMutex_unlock(&(bound->mp_lock)); + } else { + printf("PSA_UDP_MC_TP: No msg serializer available for msg type id %d\n", msgTypeId); + status=-1; + } + + celixThreadMutex_unlock(&(bound->mp_lock)); celixThreadMutex_unlock(&(bound->parent->tp_lock)); - return status; + return status; } -static int pubsub_localMsgTypeIdForUUID(void* handle, const char* msgType, unsigned int* out){ - publish_bundle_bound_service_t* bound = handle; - unsigned int msgTypeId = 0; - - celixThreadMutex_lock(&bound->mp_lock); - if (bound->map != NULL) { - hash_map_iterator_t iter = hashMapIterator_construct(bound->map->serializers); - while (hashMapIterator_hasNext(&iter)) { - pubsub_msg_serializer_t* msgSer = hashMapIterator_nextValue(&iter); - if (strncmp(msgType, msgSer->msgName, 1024*1024) == 0) { - msgTypeId = msgSer->msgId; - break; - } - } - } - celixThreadMutex_unlock(&bound->mp_lock); - - if (msgTypeId != 0) { - *out = msgTypeId; - return 0; - } else { - printf("TP: Cannot find msg type id for msg type %s\n", msgType); - return 1; - } +static int pubsub_localMsgTypeIdForUUID(void* handle, const char* msgType, unsigned int* msgTypeId){ + *msgTypeId = utils_stringHash(msgType); + return 0; } @@ -466,58 +378,49 @@ static unsigned int rand_range(unsigned int min, unsigned int max){ } -static publish_bundle_bound_service_t* pubsub_createPublishBundleBoundService(topic_publication_pt tp,bundle_pt bundle) { - //PRECOND lock on publish->tp_lock - publish_bundle_bound_service_t* bound = calloc(1, sizeof(*bound)); +static publish_bundle_bound_service_pt pubsub_createPublishBundleBoundService(topic_publication_pt tp,bundle_pt bundle){ + + publish_bundle_bound_service_pt bound = calloc(1, sizeof(*bound)); if (bound != NULL) { + bound->parent = tp; bound->bundle = bundle; bound->getCount = 1; - bound->mp_send_in_progress = false; celixThreadMutex_create(&bound->mp_lock,NULL); - arrayList_create(&bound->mp_parts); + + if(tp->serializer != NULL){ + tp->serializer->createSerializerMap(tp->serializer->handle,bundle,&bound->msgTypes); + } pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(bound->parent->pub_ep_list,0); bound->scope=strdup(pubEP->scope); bound->topic=strdup(pubEP->topic); bound->largeUdpHandle = largeUdp_create(1); - bound->pubSvc.handle = bound; - bound->pubSvc.localMsgTypeIdForMsgType = pubsub_localMsgTypeIdForUUID; - bound->pubSvc.send = pubsub_topicPublicationSend; - bound->pubSvc.sendMultipart = NULL; //Multipart not supported (jet) for UDP - if (tp->serializerSvc != NULL) { - tp->serializerSvc->createSerializerMap(tp->serializerSvc->handle, bundle, &bound->map); - } - } - else - { - free(bound); - return NULL; + bound->service.handle = bound; + bound->service.localMsgTypeIdForMsgType = pubsub_localMsgTypeIdForUUID; + bound->service.send = pubsub_topicPublicationSend; + bound->service.sendMultipart = NULL; //Multipart not supported for UDP + } return bound; } -static void pubsub_destroyPublishBundleBoundService(publish_bundle_bound_service_t* boundSvc) { - //PRECOND lock on publish->tp_lock - celixThreadMutex_lock(&boundSvc->mp_lock); +static void pubsub_destroyPublishBundleBoundService(publish_bundle_bound_service_pt boundSvc){ - if (boundSvc->map != NULL && boundSvc->parent->serializerSvc != NULL) { - boundSvc->parent->serializerSvc->destroySerializerMap(boundSvc->parent->serializerSvc->handle, boundSvc->map); - boundSvc->map = NULL; - } + celixThreadMutex_lock(&boundSvc->mp_lock); - if (boundSvc->mp_parts!=NULL) { - arrayList_destroy(boundSvc->mp_parts); + if(boundSvc->parent->serializer != NULL && boundSvc->msgTypes != NULL){ + boundSvc->parent->serializer->destroySerializerMap(boundSvc->parent->serializer->handle, boundSvc->msgTypes); } - if (boundSvc->scope!=NULL) { - free(boundSvc->scope); - } + if(boundSvc->scope!=NULL){ + free(boundSvc->scope); + } - if (boundSvc->topic!=NULL) { + if(boundSvc->topic!=NULL){ free(boundSvc->topic); } @@ -535,7 +438,7 @@ static void delay_first_send_for_late_joiners(){ static bool firstSend = true; if(firstSend){ - printf("TP: Delaying first send for late joiners...\n"); + printf("PSA_UDP_MC_TP: Delaying first send for late joiners...\n"); sleep(FIRST_SEND_DELAY); firstSend = false; } diff --git a/pubsub/pubsub_admin_udp_mc/private/src/topic_subscription.c b/pubsub/pubsub_admin_udp_mc/private/src/topic_subscription.c index 7a3f5a92e..58962648f 100644 --- a/pubsub/pubsub_admin_udp_mc/private/src/topic_subscription.c +++ b/pubsub/pubsub_admin_udp_mc/private/src/topic_subscription.c @@ -29,35 +29,31 @@ #include #include +#include #include +#include #include #include -#if defined(__APPLE__) && defined(__MACH__) - #include - #include -#else - #include -#endif - #include "utils.h" #include "celix_errno.h" #include "constants.h" #include "version.h" #include "topic_subscription.h" +#include "topic_publication.h" #include "subscriber.h" #include "publisher.h" -#include "pubsub_publish_service_private.h" #include "large_udp.h" +#include "pubsub_serializer.h" + #define MAX_EPOLL_EVENTS 10 #define RECV_THREAD_TIMEOUT 5 #define UDP_BUFFER_SIZE 65535 #define MAX_UDP_SESSIONS 16 -struct topic_subscription { - +struct topic_subscription{ char* ifIpAddress; service_tracker_pt tracker; array_list_pt sub_ep_list; @@ -65,25 +61,24 @@ struct topic_subscription { bool running; celix_thread_mutex_t ts_lock; bundle_context_pt context; - int topicEpollFd; // EPOLL filedescriptor where the sockets are registered. - //NOTE. using a service ptr can be dangerous, because pointer can be reused. - //ensuring that pointer are removed before new (refurbish) pionter comes along is crucial! - hash_map_pt msgSerializerMapMap; // key = service ptr, value = pubsub_msg_serializer_map_t* - hash_map_pt bundleMap; //key = service ptr, value = bundle_pt + pubsub_serializer_service_t *serializer; + int topicEpollFd; // EPOLL filedescriptor where the sockets are registered. + hash_map_pt servicesMap; // key = service, value = msg types map hash_map_pt socketMap; // key = URL, value = listen-socket + + celix_thread_mutex_t pendingConnections_lock; + array_list_pt pendingConnections; + + array_list_pt pendingDisconnections; + celix_thread_mutex_t pendingDisconnections_lock; + + //array_list_pt rawServices; unsigned int nrSubscribers; largeUdp_pt largeUdpHandle; - pubsub_serializer_service_t* serializerSvc; - }; -typedef struct mp_handle{ - hash_map_pt svc_msg_db; - hash_map_pt rcv_msg_map; -}* mp_handle_pt; - typedef struct msg_map_entry{ bool retain; void* msgInst; @@ -95,9 +90,11 @@ static void* udp_recv_thread_func(void* arg); static bool checkVersion(version_pt msgVersion,pubsub_msg_header_pt hdr); static void sigusr1_sighandler(int signo); static int pubsub_localMsgTypeIdForMsgType(void* handle, const char* msgType, unsigned int* msgTypeId); +static void connectPendingPublishers(topic_subscription_pt sub); +static void disconnectPendingPublishers(topic_subscription_pt sub); -celix_status_t pubsub_topicSubscriptionCreate(char* ifIp,bundle_context_pt bundle_context, pubsub_serializer_service_t* serializer, char* scope, char* topic,topic_subscription_pt* out){ +celix_status_t pubsub_topicSubscriptionCreate(bundle_context_pt bundle_context, char* ifIp,char* scope, char* topic ,pubsub_serializer_service_t *best_serializer, topic_subscription_pt* out){ celix_status_t status = CELIX_SUCCESS; topic_subscription_pt ts = (topic_subscription_pt) calloc(1,sizeof(*ts)); @@ -109,35 +106,39 @@ celix_status_t pubsub_topicSubscriptionCreate(char* ifIp,bundle_context_pt bundl ts->topicEpollFd = epoll_create1(0); #endif if(ts->topicEpollFd == -1) { - status += CELIX_SERVICE_EXCEPTION; + status += CELIX_SERVICE_EXCEPTION; } ts->running = false; ts->nrSubscribers = 0; - ts->serializerSvc = NULL; + ts->serializer = best_serializer; celixThreadMutex_create(&ts->ts_lock,NULL); arrayList_create(&ts->sub_ep_list); - ts->msgSerializerMapMap = hashMap_create(NULL, NULL, NULL, NULL); - ts->bundleMap = hashMap_create(NULL, NULL, NULL, NULL); + ts->servicesMap = hashMap_create(NULL, NULL, NULL, NULL); ts->socketMap = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL); + arrayList_create(&ts->pendingConnections); + arrayList_create(&ts->pendingDisconnections); + celixThreadMutex_create(&ts->pendingConnections_lock, NULL); + celixThreadMutex_create(&ts->pendingDisconnections_lock, NULL); + ts->largeUdpHandle = largeUdp_create(MAX_UDP_SESSIONS); char filter[128]; memset(filter,0,128); if(strncmp(PUBSUB_SUBSCRIBER_SCOPE_DEFAULT, scope, strlen(PUBSUB_SUBSCRIBER_SCOPE_DEFAULT)) == 0) { - // default scope, means that subscriber has not defined a scope property - snprintf(filter, 128, "(&(%s=%s)(%s=%s))", - (char*) OSGI_FRAMEWORK_OBJECTCLASS, PUBSUB_SUBSCRIBER_SERVICE_NAME, - PUBSUB_SUBSCRIBER_TOPIC,topic); - - } else { - snprintf(filter, 128, "(&(%s=%s)(%s=%s)(%s=%s))", - (char*) OSGI_FRAMEWORK_OBJECTCLASS, PUBSUB_SUBSCRIBER_SERVICE_NAME, - PUBSUB_SUBSCRIBER_TOPIC,topic, - PUBSUB_SUBSCRIBER_SCOPE,scope); - } + // default scope, means that subscriber has not defined a scope property + snprintf(filter, 128, "(&(%s=%s)(%s=%s))", + (char*) OSGI_FRAMEWORK_OBJECTCLASS, PUBSUB_SUBSCRIBER_SERVICE_NAME, + PUBSUB_SUBSCRIBER_TOPIC,topic); + + } else { + snprintf(filter, 128, "(&(%s=%s)(%s=%s)(%s=%s))", + (char*) OSGI_FRAMEWORK_OBJECTCLASS, PUBSUB_SUBSCRIBER_SERVICE_NAME, + PUBSUB_SUBSCRIBER_TOPIC,topic, + PUBSUB_SUBSCRIBER_SCOPE,scope); + } service_tracker_customizer_pt customizer = NULL; status += serviceTrackerCustomizer_create(ts,NULL,topicsub_subscriberTracked,NULL,topicsub_subscriberUntracked,&customizer); @@ -151,10 +152,9 @@ celix_status_t pubsub_topicSubscriptionCreate(char* ifIp,bundle_context_pt bundl sigaction(SIGUSR1,&actions,NULL); - if (status == CELIX_SUCCESS) { - *out=ts; - pubsub_topicSubscriptionSetSerializer(ts, serializer); - } + if (status == CELIX_SUCCESS) { + *out=ts; + } return status; } @@ -168,10 +168,20 @@ celix_status_t pubsub_topicSubscriptionDestroy(topic_subscription_pt ts){ serviceTracker_destroy(ts->tracker); arrayList_clear(ts->sub_ep_list); arrayList_destroy(ts->sub_ep_list); - hashMap_destroy(ts->msgSerializerMapMap, false, false); - hashMap_destroy(ts->bundleMap, false, false); + hashMap_destroy(ts->servicesMap,false,false); + + hashMap_destroy(ts->socketMap,true,true); + + celixThreadMutex_lock(&ts->pendingConnections_lock); + arrayList_destroy(ts->pendingConnections); + celixThreadMutex_unlock(&ts->pendingConnections_lock); + celixThreadMutex_destroy(&ts->pendingConnections_lock); + + celixThreadMutex_lock(&ts->pendingDisconnections_lock); + arrayList_destroy(ts->pendingDisconnections); + celixThreadMutex_unlock(&ts->pendingDisconnections_lock); + celixThreadMutex_destroy(&ts->pendingDisconnections_lock); - hashMap_destroy(ts->socketMap,false,false); largeUdp_destroy(ts->largeUdpHandle); #if defined(__APPLE__) && defined(__MACH__) //TODO: Use kqueue for OSX @@ -211,15 +221,16 @@ celix_status_t pubsub_topicSubscriptionStop(topic_subscription_pt ts){ celixThread_join(ts->recv_thread,NULL); - status = serviceTracker_close(ts->tracker); + status = serviceTracker_close(ts->tracker); - hash_map_iterator_pt it = hashMapIterator_create(ts->socketMap); - while(hashMapIterator_hasNext(it)) { - hash_map_entry_pt entry = hashMapIterator_nextEntry(it); - char *url = hashMapEntry_getKey(entry); - pubsub_topicSubscriptionDisconnectPublisher(ts, url); - } - hashMapIterator_destroy(it); + hash_map_iterator_pt it = hashMapIterator_create(ts->socketMap); + while(hashMapIterator_hasNext(it)) { + hash_map_entry_pt entry = hashMapIterator_nextEntry(it); + char *url = hashMapEntry_getKey(entry); + pubsub_topicSubscriptionDisconnectPublisher(ts, url); + free(url); + } + hashMapIterator_destroy(it); return status; @@ -227,108 +238,126 @@ celix_status_t pubsub_topicSubscriptionStop(topic_subscription_pt ts){ celix_status_t pubsub_topicSubscriptionConnectPublisher(topic_subscription_pt ts, char* pubURL) { - printf("pubsub_topicSubscriptionConnectPublisher : pubURL = %s\n", pubURL); + printf("pubsub_topicSubscriptionConnectPublisher : pubURL = %s\n", pubURL); - celix_status_t status = CELIX_SUCCESS; + celix_status_t status = CELIX_SUCCESS; + celixThreadMutex_lock(&ts->ts_lock); - if (!hashMap_containsKey(ts->socketMap, pubURL)){ + if(hashMap_containsKey(ts->socketMap, pubURL)){ + printf("PSA_UDM_MC_TS: PubURL %s already existing!\n",pubURL); + celixThreadMutex_unlock(&ts->ts_lock); + return CELIX_SERVICE_EXCEPTION; + } - celixThreadMutex_lock(&ts->ts_lock); + int *recvSocket = calloc(sizeof(int), 1); + *recvSocket = socket(AF_INET, SOCK_DGRAM, 0); + if (*recvSocket < 0) { + perror("pubsub_topicSubscriptionCreate:socket"); + status = CELIX_SERVICE_EXCEPTION; + } - int *recvSocket = calloc(sizeof(int), 1); - *recvSocket = socket(AF_INET, SOCK_DGRAM, 0); - if (*recvSocket < 0) { - perror("pubsub_topicSubscriptionCreate:socket"); + if (status == CELIX_SUCCESS){ + int reuse = 1; + if (setsockopt(*recvSocket, SOL_SOCKET, SO_REUSEADDR, (char*) &reuse, sizeof(reuse)) != 0) { + perror("setsockopt() SO_REUSEADDR"); + status = CELIX_SERVICE_EXCEPTION; + } + } + + if(status == CELIX_SUCCESS){ + // TODO Check if there is a better way to parse the URL to IP/Portnr + //replace ':' by spaces + char *url = strdup(pubURL); + char *pt = url; + while((pt=strchr(pt, ':')) != NULL) { + *pt = ' '; + } + char mcIp[100]; + unsigned short mcPort; + sscanf(url, "udp //%s %hu", mcIp, &mcPort); + free (url); + + printf("pubsub_topicSubscriptionConnectPublisher : IP = %s, Port = %hu\n", mcIp, mcPort); + + struct ip_mreq mc_addr; + mc_addr.imr_multiaddr.s_addr = inet_addr(mcIp); + mc_addr.imr_interface.s_addr = inet_addr(ts->ifIpAddress); + printf("Adding MC %s at interface %s\n", mcIp, ts->ifIpAddress); + if (setsockopt(*recvSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*) &mc_addr, sizeof(mc_addr)) != 0) { + perror("setsockopt() IP_ADD_MEMBERSHIP"); status = CELIX_SERVICE_EXCEPTION; } if (status == CELIX_SUCCESS){ - int reuse = 1; - if (setsockopt(*recvSocket, SOL_SOCKET, SO_REUSEADDR, (char*) &reuse, sizeof(reuse)) != 0) { - perror("setsockopt() SO_REUSEADDR"); + struct sockaddr_in mcListenAddr; + mcListenAddr.sin_family = AF_INET; + mcListenAddr.sin_addr.s_addr = INADDR_ANY; + mcListenAddr.sin_port = htons(mcPort); + if(bind(*recvSocket, (struct sockaddr*)&mcListenAddr, sizeof(mcListenAddr)) != 0) { + perror("bind()"); status = CELIX_SERVICE_EXCEPTION; } } if (status == CELIX_SUCCESS){ - // TODO Check if there is a better way to parse the URL to IP/Portnr - //replace ':' by spaces - char *url = strdup(pubURL); - char *pt = url; - while((pt=strchr(pt, ':')) != NULL) { - *pt = ' '; - } - char mcIp[100]; - unsigned short mcPort; - sscanf(url, "udp //%s %hu", mcIp, &mcPort); - free (url); - - printf("pubsub_topicSubscriptionConnectPublisher : IP = %s, Port = %hu\n", mcIp, mcPort); - - struct ip_mreq mc_addr; - mc_addr.imr_multiaddr.s_addr = inet_addr(mcIp); - mc_addr.imr_interface.s_addr = inet_addr(ts->ifIpAddress); - printf("Adding MC %s at interface %s\n", mcIp, ts->ifIpAddress); - if (setsockopt(*recvSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*) &mc_addr, sizeof(mc_addr)) != 0) { - perror("setsockopt() IP_ADD_MEMBERSHIP"); +#if defined(__APPLE__) && defined(__MACH__) + //TODO: Use kqueue for OSX +#else + struct epoll_event ev; + memset(&ev, 0, sizeof(ev)); + ev.events = EPOLLIN; + ev.data.fd = *recvSocket; + if(epoll_ctl(ts->topicEpollFd, EPOLL_CTL_ADD, *recvSocket, &ev) == -1) { + perror("epoll_ctl() EPOLL_CTL_ADD"); status = CELIX_SERVICE_EXCEPTION; } +#endif + } - if (status == CELIX_SUCCESS){ - struct sockaddr_in mcListenAddr; - mcListenAddr.sin_family = AF_INET; - mcListenAddr.sin_addr.s_addr = INADDR_ANY; - mcListenAddr.sin_port = htons(mcPort); - if(bind(*recvSocket, (struct sockaddr*)&mcListenAddr, sizeof(mcListenAddr)) != 0) { - perror("bind()"); - status = CELIX_SERVICE_EXCEPTION; - } - } - - if (status == CELIX_SUCCESS){ - #if defined(__APPLE__) && defined(__MACH__) - //TODO: Use kqueue for OSX - #else - struct epoll_event ev; - memset(&ev, 0, sizeof(ev)); - ev.events = EPOLLIN; - ev.data.fd = *recvSocket; - if(epoll_ctl(ts->topicEpollFd, EPOLL_CTL_ADD, *recvSocket, &ev) == -1) { - perror("epoll_ctl() EPOLL_CTL_ADD"); - status = CELIX_SERVICE_EXCEPTION; - } - #endif - } + } - } + if (status == CELIX_SUCCESS){ + hashMap_put(ts->socketMap, strdup(pubURL), (void*)recvSocket); + }else{ + free(recvSocket); + } - if (status == CELIX_SUCCESS){ - hashMap_put(ts->socketMap, pubURL, (void*)recvSocket); - }else{ - free(recvSocket); - } + celixThreadMutex_unlock(&ts->ts_lock); - celixThreadMutex_unlock(&ts->ts_lock); + return status; +} - } +celix_status_t pubsub_topicSubscriptionAddConnectPublisherToPendingList(topic_subscription_pt ts, char* pubURL) { + celix_status_t status = CELIX_SUCCESS; + char *url = strdup(pubURL); + celixThreadMutex_lock(&ts->pendingConnections_lock); + arrayList_add(ts->pendingConnections, url); + celixThreadMutex_unlock(&ts->pendingConnections_lock); + return status; +} - return status; +celix_status_t pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(topic_subscription_pt ts, char* pubURL) { + celix_status_t status = CELIX_SUCCESS; + char *url = strdup(pubURL); + celixThreadMutex_lock(&ts->pendingDisconnections_lock); + arrayList_add(ts->pendingDisconnections, url); + celixThreadMutex_unlock(&ts->pendingDisconnections_lock); + return status; } celix_status_t pubsub_topicSubscriptionDisconnectPublisher(topic_subscription_pt ts, char* pubURL){ - printf("pubsub_topicSubscriptionDisconnectPublisher : pubURL = %s\n", pubURL); - celix_status_t status = CELIX_SUCCESS; + printf("pubsub_topicSubscriptionDisconnectPublisher : pubURL = %s\n", pubURL); + celix_status_t status = CELIX_SUCCESS; + struct epoll_event ev; + memset(&ev, 0, sizeof(ev)); - if (hashMap_containsKey(ts->socketMap, pubURL)){ + celixThreadMutex_lock(&ts->ts_lock); + + if (hashMap_containsKey(ts->socketMap, pubURL)){ #if defined(__APPLE__) && defined(__MACH__) - //TODO: Use kqueue for OSX + //TODO: Use kqueue for OSX #else - struct epoll_event ev; - memset(&ev, 0, sizeof(ev)); - - celixThreadMutex_lock(&ts->ts_lock); - int *s = hashMap_remove(ts->socketMap, pubURL); if(epoll_ctl(ts->topicEpollFd, EPOLL_CTL_DEL, *s, &ev) == -1) { printf("in if error()\n"); @@ -336,11 +365,11 @@ celix_status_t pubsub_topicSubscriptionDisconnectPublisher(topic_subscription_pt status = CELIX_SERVICE_EXCEPTION; } free(s); - - celixThreadMutex_unlock(&ts->ts_lock); #endif - } + } + + celixThreadMutex_unlock(&ts->ts_lock); return status; } @@ -349,9 +378,7 @@ celix_status_t pubsub_topicSubscriptionAddSubscriber(topic_subscription_pt ts, p celix_status_t status = CELIX_SUCCESS; celixThreadMutex_lock(&ts->ts_lock); - arrayList_add(ts->sub_ep_list,subEP); - celixThreadMutex_unlock(&ts->ts_lock); return status; @@ -362,9 +389,7 @@ celix_status_t pubsub_topicIncreaseNrSubscribers(topic_subscription_pt ts) { celix_status_t status = CELIX_SUCCESS; celixThreadMutex_lock(&ts->ts_lock); - ts->nrSubscribers++; - celixThreadMutex_unlock(&ts->ts_lock); return status; @@ -374,22 +399,17 @@ celix_status_t pubsub_topicSubscriptionRemoveSubscriber(topic_subscription_pt ts celix_status_t status = CELIX_SUCCESS; celixThreadMutex_lock(&ts->ts_lock); - arrayList_removeElement(ts->sub_ep_list,subEP); - celixThreadMutex_unlock(&ts->ts_lock); return status; - } celix_status_t pubsub_topicDecreaseNrSubscribers(topic_subscription_pt ts) { celix_status_t status = CELIX_SUCCESS; celixThreadMutex_lock(&ts->ts_lock); - ts->nrSubscribers--; - celixThreadMutex_unlock(&ts->ts_lock); return status; @@ -399,153 +419,118 @@ unsigned int pubsub_topicGetNrSubscribers(topic_subscription_pt ts) { return ts->nrSubscribers; } -celix_status_t pubsub_topicSubscriptionSetSerializer(topic_subscription_pt ts, pubsub_serializer_service_t* serializerSvc) { - celix_status_t status = CELIX_SUCCESS; - - celixThreadMutex_lock(&ts->ts_lock); - //clear old - if (ts->serializerSvc != NULL) { - hash_map_iterator_t iter = hashMapIterator_construct(ts->msgSerializerMapMap); - while (hashMapIterator_hasNext(&iter)) { - hash_map_entry_pt entry = hashMapIterator_nextEntry(&iter); - pubsub_subscriber_t* subsvc = hashMapEntry_getKey(entry); - pubsub_msg_serializer_map_t* map = hashMapEntry_getValue(entry); - ts->serializerSvc->destroySerializerMap(ts->serializerSvc->handle, map); - hashMap_put(ts->msgSerializerMapMap, subsvc, NULL); - - } - } - ts->serializerSvc = serializerSvc; - //init new - if (ts->serializerSvc != NULL) { - hash_map_iterator_t iter = hashMapIterator_construct(ts->msgSerializerMapMap); - while (hashMapIterator_hasNext(&iter)) { - pubsub_subscriber_t* subsvc = hashMapIterator_nextKey(&iter); - bundle_pt bundle = hashMap_get(ts->bundleMap, subsvc); - pubsub_msg_serializer_map_t* map = NULL; - ts->serializerSvc->createSerializerMap(ts->serializerSvc->handle, bundle, &map); - hashMap_put(ts->msgSerializerMapMap, subsvc, map); - } - } - celixThreadMutex_unlock(&ts->ts_lock); - - return status; +array_list_pt pubsub_topicSubscriptionGetSubscribersList(topic_subscription_pt sub){ + return sub->sub_ep_list; } -celix_status_t pubsub_topicSubscriptionRemoveSerializer(topic_subscription_pt ts, pubsub_serializer_service_t* serializerSvc){ - celix_status_t status = CELIX_SUCCESS; - - celixThreadMutex_lock(&ts->ts_lock); - if (ts->serializerSvc == serializerSvc) { //only act if svc removed is services used - hash_map_iterator_t iter = hashMapIterator_construct(ts->msgSerializerMapMap); - while (hashMapIterator_hasNext(&iter)) { - hash_map_entry_pt entry = hashMapIterator_nextEntry(&iter); - pubsub_subscriber_t* subsvc = hashMapEntry_getKey(entry); - pubsub_msg_serializer_map_t* map = hashMapEntry_getValue(entry); - ts->serializerSvc->destroySerializerMap(ts->serializerSvc->handle, map); - hashMap_put(ts->msgSerializerMapMap, subsvc, NULL); - } - ts->serializerSvc = NULL; - } - celixThreadMutex_unlock(&ts->ts_lock); - - return status; -} -static celix_status_t topicsub_subscriberTracked(void * handle, service_reference_pt reference, void* svc){ +static celix_status_t topicsub_subscriberTracked(void * handle, service_reference_pt reference, void * service){ celix_status_t status = CELIX_SUCCESS; topic_subscription_pt ts = handle; celixThreadMutex_lock(&ts->ts_lock); - if (!hashMap_containsKey(ts->msgSerializerMapMap, svc)) { + if (!hashMap_containsKey(ts->servicesMap, service)) { bundle_pt bundle = NULL; + hash_map_pt msgTypes = NULL; + serviceReference_getBundle(reference, &bundle); - if (ts->serializerSvc != NULL) { - pubsub_msg_serializer_map_t* map = NULL; - ts->serializerSvc->createSerializerMap(ts->serializerSvc->handle, bundle, &map); - if (map != NULL) { - hashMap_put(ts->msgSerializerMapMap, svc, map); - hashMap_put(ts->bundleMap, svc, bundle); - } + if(ts->serializer != NULL && bundle!=NULL){ + ts->serializer->createSerializerMap(ts->serializer->handle,bundle,&msgTypes); + if(msgTypes != NULL){ + hashMap_put(ts->servicesMap, service, msgTypes); + printf("PSA_UDP_MC_TS: New subscriber registered.\n"); + } + } + else{ + printf("PSA_UDP_MC_TS: Cannot register new subscriber.\n"); + status = CELIX_SERVICE_EXCEPTION; } } celixThreadMutex_unlock(&ts->ts_lock); - printf("TS: New subscriber registered.\n"); + return status; } -static celix_status_t topicsub_subscriberUntracked(void * handle, service_reference_pt reference, void* svc){ +static celix_status_t topicsub_subscriberUntracked(void * handle, service_reference_pt reference, void * service){ celix_status_t status = CELIX_SUCCESS; topic_subscription_pt ts = handle; - - celixThreadMutex_lock(&ts->ts_lock); - if (hashMap_containsKey(ts->msgSerializerMapMap, svc)) { - pubsub_msg_serializer_map_t* map = hashMap_remove(ts->msgSerializerMapMap, svc); - if (ts->serializerSvc != NULL){ - ts->serializerSvc->destroySerializerMap(ts->serializerSvc->handle, map); - hashMap_remove(ts->bundleMap, svc); - hashMap_remove(ts->msgSerializerMapMap, svc); + celixThreadMutex_lock(&ts->ts_lock); + if (hashMap_containsKey(ts->servicesMap, service)) { + hash_map_pt msgTypes = hashMap_remove(ts->servicesMap, service); + if(msgTypes!=NULL && ts->serializer!=NULL){ + ts->serializer->destroySerializerMap(ts->serializer->handle,msgTypes); + printf("PSA_ZMQ_TS: Subscriber unregistered.\n"); + } + else{ + printf("PSA_ZMQ_TS: Cannot unregister subscriber.\n"); + status = CELIX_SERVICE_EXCEPTION; } } celixThreadMutex_unlock(&ts->ts_lock); - printf("TS: Subscriber unregistered.\n"); + printf("PSA_UDP_MC_TS: Subscriber unregistered.\n"); return status; } -static void process_msg(topic_subscription_pt sub, pubsub_udp_msg_t* msg){ +static void process_msg(topic_subscription_pt sub,pubsub_udp_msg_t *msg){ - hash_map_iterator_t iter = hashMapIterator_construct(sub->msgSerializerMapMap); celixThreadMutex_lock(&sub->ts_lock); - while (hashMapIterator_hasNext(&iter)) { - hash_map_entry_pt entry = hashMapIterator_nextEntry(&iter); + hash_map_iterator_pt iter = hashMapIterator_create(sub->servicesMap); + while (hashMapIterator_hasNext(iter)) { + hash_map_entry_pt entry = hashMapIterator_nextEntry(iter); pubsub_subscriber_pt subsvc = hashMapEntry_getKey(entry); - pubsub_msg_serializer_map_t* map = hashMapEntry_getValue(entry); - - pubsub_msg_serializer_t* msgSer = hashMap_get(map->serializers, (void *)(uintptr_t )msg->header.type); + hash_map_pt msgTypes = hashMapEntry_getValue(entry); + pubsub_msg_serializer_t *msgSer = hashMap_get(msgTypes,(void*)(uintptr_t )msg->header.type); if (msgSer == NULL) { - printf("TS: Primary message %d not supported. NOT receiving any part of the whole message.\n",msg->header.type); - } else { + printf("PSA_UDP_MC_TS: Serializer not available for message %d.\n",msg->header.type); + } + else{ void *msgInst = NULL; - bool validVersion = checkVersion(msgSer->msgVersion, &msg->header); + bool validVersion = checkVersion(msgSer->msgVersion,&msg->header); + if(validVersion){ - celix_status_t status = msgSer->deserialize(msgSer->handle, msg->payload, 0, &msgInst); + + celix_status_t status = msgSer->deserialize(msgSer, (const void *) msg->payload, 0, &msgInst); + if (status == CELIX_SUCCESS) { bool release = true; pubsub_multipart_callbacks_t mp_callbacks; - mp_callbacks.handle = map; + mp_callbacks.handle = sub; mp_callbacks.localMsgTypeIdForMsgType = pubsub_localMsgTypeIdForMsgType; mp_callbacks.getMultipart = NULL; subsvc->receive(subsvc->handle, msgSer->msgName, msg->header.type, msgInst, &mp_callbacks, &release); - if (release) { - msgSer->freeMsg(msgSer->handle, msgInst); + + if(release){ + msgSer->freeMsg(msgSer,msgInst); } } else{ - printf("TS: Cannot deserialize msgType %s.\n", msgSer->msgName); + printf("PSA_UDP_MC_TS: Cannot deserialize msgType %s.\n",msgSer->msgName); } } - else { + else{ int major=0,minor=0; - version_getMajor(msgSer->msgVersion, &major); - version_getMinor(msgSer->msgVersion, &minor); - printf("TS: Version mismatch for primary message '%s' (have %d.%d, received %u.%u). NOT sending any part of the whole message.\n", - msgSer->msgName, major, minor, msg->header.major, msg->header.minor); + version_getMajor(msgSer->msgVersion,&major); + version_getMinor(msgSer->msgVersion,&minor); + printf("PSA_UDP_MC_TS: Version mismatch for primary message '%s' (have %d.%d, received %u.%u). NOT sending any part of the whole message.\n", + msgSer->msgName,major,minor,msg->header.major,msg->header.minor); } + } } + hashMapIterator_destroy(iter); celixThreadMutex_unlock(&sub->ts_lock); } static void* udp_recv_thread_func(void * arg) { - topic_subscription_pt sub = (topic_subscription_pt) arg; + topic_subscription_pt sub = (topic_subscription_pt) arg; #if defined(__APPLE__) && defined(__MACH__) //TODO: use kqueue for OSX @@ -558,52 +543,68 @@ static void* udp_recv_thread_func(void * arg) { } } #else + struct epoll_event events[MAX_EPOLL_EVENTS]; + + while (sub->running) { + int nfds = epoll_wait(sub->topicEpollFd, events, MAX_EPOLL_EVENTS, RECV_THREAD_TIMEOUT * 1000); + int i; + for(i = 0; i < nfds; i++ ) { + unsigned int index; + unsigned int size; + if(largeUdp_dataAvailable(sub->largeUdpHandle, events[i].data.fd, &index, &size) == true) { + // Handle data + pubsub_udp_msg_t *udpMsg = NULL; + if(largeUdp_read(sub->largeUdpHandle, index, (void**)&udpMsg, size) != 0) { + printf("PSA_UDP_MC_TS: ERROR largeUdp_read with index %d\n", index); + continue; + } - struct epoll_event events[MAX_EPOLL_EVENTS]; + process_msg(sub, udpMsg); - while (sub->running) { - int nfds = epoll_wait(sub->topicEpollFd, events, MAX_EPOLL_EVENTS, RECV_THREAD_TIMEOUT * 1000); - int i; - for(i = 0; i < nfds; i++ ) { - unsigned int index; - unsigned int size; - if(largeUdp_dataAvailable(sub->largeUdpHandle, events[i].data.fd, &index, &size) == true) { - // Handle data - pubsub_udp_msg_t* udpMsg = NULL; - if(largeUdp_read(sub->largeUdpHandle, index, (void**)&udpMsg, size) != 0) { - printf("TS: ERROR largeUdp_read with index %d\n", index); - continue; - } - - if (udpMsg->header.type == 0){ - //Raw msg, since raw messages are not supported, don't do anything. - }else{ - process_msg(sub, udpMsg); - } - - free(udpMsg); - } - } - } + free(udpMsg); + } + } + connectPendingPublishers(sub); + disconnectPendingPublishers(sub); + } #endif - return NULL; + return NULL; } +static void connectPendingPublishers(topic_subscription_pt sub) { + celixThreadMutex_lock(&sub->pendingConnections_lock); + while(!arrayList_isEmpty(sub->pendingConnections)) { + char * pubEP = arrayList_remove(sub->pendingConnections, 0); + pubsub_topicSubscriptionConnectPublisher(sub, pubEP); + free(pubEP); + } + celixThreadMutex_unlock(&sub->pendingConnections_lock); +} -static void sigusr1_sighandler(int signo) { - printf("TS: Topic subscription being shut down...\n"); +static void disconnectPendingPublishers(topic_subscription_pt sub) { + celixThreadMutex_lock(&sub->pendingDisconnections_lock); + while(!arrayList_isEmpty(sub->pendingDisconnections)) { + char * pubEP = arrayList_remove(sub->pendingDisconnections, 0); + pubsub_topicSubscriptionDisconnectPublisher(sub, pubEP); + free(pubEP); + } + celixThreadMutex_unlock(&sub->pendingDisconnections_lock); +} + +static void sigusr1_sighandler(int signo){ + printf("PSA_UDP_MC_TS: Topic subscription being shut down...\n"); return; } -static bool checkVersion(version_pt msgVersion,pubsub_msg_header_pt hdr) { +static bool checkVersion(version_pt msgVersion,pubsub_msg_header_pt hdr){ bool check=false; int major=0,minor=0; - if (msgVersion!=NULL) { + if(msgVersion!=NULL){ version_getMajor(msgVersion,&major); version_getMinor(msgVersion,&minor); - if (hdr->major==((unsigned char)major)) { /* Different major means incompatible */ + if(hdr->major==((unsigned char)major)){ /* Different major means incompatible */ check = (hdr->minor>=((unsigned char)minor)); /* Compatible only if the provider has a minor equals or greater (means compatible update) */ } } @@ -611,24 +612,7 @@ static bool checkVersion(version_pt msgVersion,pubsub_msg_header_pt hdr) { return check; } -static int pubsub_localMsgTypeIdForMsgType(void* handle, const char* msgType, unsigned int* out) { - pubsub_msg_serializer_map_t* map = handle; - hash_map_iterator_t iter = hashMapIterator_construct(map->serializers); - unsigned int msgTypeId = 0; - while (hashMapIterator_hasNext(&iter)) { - pubsub_msg_serializer_t* msgSer = hashMapIterator_nextValue(&iter); - if (strncmp(msgSer->msgName, msgType, 1024 * 1024) == 0) { - msgTypeId = msgSer->msgId; - break; - } - } - - if (msgTypeId == 0) { - printf("Cannot find msg type id for msgType %s\n", msgType); - return -1; - } else { - *out = msgTypeId; - return 0; - } +static int pubsub_localMsgTypeIdForMsgType(void* handle, const char* msgType, unsigned int* msgTypeId){ + *msgTypeId = utils_stringHash(msgType); + return 0; } - diff --git a/pubsub/pubsub_admin_zmq/CMakeLists.txt b/pubsub/pubsub_admin_zmq/CMakeLists.txt index 49eba8769..8c3c727ab 100644 --- a/pubsub/pubsub_admin_zmq/CMakeLists.txt +++ b/pubsub/pubsub_admin_zmq/CMakeLists.txt @@ -53,10 +53,11 @@ if (BUILD_PUBSUB_PSA_ZMQ) ${PROJECT_SOURCE_DIR}/pubsub/pubsub_common/public/src/pubsub_endpoint.c ${PROJECT_SOURCE_DIR}/pubsub/pubsub_common/public/src/log_helper.c ${PROJECT_SOURCE_DIR}/pubsub/pubsub_common/public/src/pubsub_utils.c + ${PROJECT_SOURCE_DIR}/pubsub/pubsub_common/public/src/pubsub_admin_match.c ) set_target_properties(org.apache.celix.pubsub_admin.PubSubAdminZmq PROPERTIES INSTALL_RPATH "$ORIGIN") - target_link_libraries(org.apache.celix.pubsub_admin.PubSubAdminZmq celix_framework celix_utils celix_dfi ${ZMQ_LIBRARIES} ${CZMQ_LIBRARIES} ${JANSSON_LIBRARIES} ${OPENSSL_CRYPTO_LIBRARY}) + target_link_libraries(org.apache.celix.pubsub_admin.PubSubAdminZmq celix_framework celix_utils celix_dfi ${ZMQ_LIBRARIES} ${CZMQ_LIBRARIES} ${OPENSSL_CRYPTO_LIBRARY}) install_bundle(org.apache.celix.pubsub_admin.PubSubAdminZmq) endif() diff --git a/pubsub/pubsub_admin_zmq/private/include/pubsub_admin_impl.h b/pubsub/pubsub_admin_zmq/private/include/pubsub_admin_impl.h index 7e7ac4267..3a39a933d 100644 --- a/pubsub/pubsub_admin_zmq/private/include/pubsub_admin_impl.h +++ b/pubsub/pubsub_admin_zmq/private/include/pubsub_admin_impl.h @@ -24,8 +24,8 @@ * \copyright Apache License, Version 2.0 */ -#ifndef PUBSUB_ADMIN_IMPL_H_ -#define PUBSUB_ADMIN_IMPL_H_ +#ifndef PUBSUB_ADMIN_ZMQ_IMPL_H_ +#define PUBSUB_ADMIN_ZMQ_IMPL_H_ #include /* The following undefs prevent the collision between: @@ -38,7 +38,7 @@ #undef LOG_WARNING #include "pubsub_admin.h" -#include "pubsub_serializer.h" +#include "pubsub_admin_match.h" #include "log_helper.h" #define PSA_ZMQ_BASE_PORT "PSA_ZMQ_BASE_PORT" @@ -47,13 +47,17 @@ #define PSA_ZMQ_DEFAULT_BASE_PORT 5501 #define PSA_ZMQ_DEFAULT_MAX_PORT 6000 -struct pubsub_admin { +#define PUBSUB_ADMIN_TYPE "zmq" - pubsub_serializer_service_t* serializerSvc; +struct pubsub_admin { bundle_context_pt bundle_context; log_helper_pt loghelper; + /* List of the available serializers */ + celix_thread_mutex_t serializerListLock; // List + array_list_pt serializerList; + celix_thread_mutex_t localPublicationsLock; hash_map_pt localPublications;// @@ -64,9 +68,17 @@ struct pubsub_admin { hash_map_pt subscriptions; // celix_thread_mutex_t pendingSubscriptionsLock; - celix_thread_mutexattr_t pendingSubscriptionsAttr; hash_map_pt pendingSubscriptions; //> + /* Those are used to keep track of valid subscriptions/publications that still have no valid serializer */ + celix_thread_mutex_t noSerializerPendingsLock; + array_list_pt noSerializerSubscriptions; // List + array_list_pt noSerializerPublications; // List + + celix_thread_mutex_t usedSerializersLock; + hash_map_pt topicSubscriptionsPerSerializer; // > + hash_map_pt topicPublicationsPerSerializer; // > + char* ipAddress; zactor_t* zmq_auth; @@ -75,11 +87,6 @@ struct pubsub_admin { unsigned int maxPort; }; -/* Note: correct locking order is - * 1. subscriptionsLock - * 2. publications locks - */ - celix_status_t pubsubAdmin_create(bundle_context_pt context, pubsub_admin_pt *admin); celix_status_t pubsubAdmin_destroy(pubsub_admin_pt admin); @@ -92,10 +99,9 @@ celix_status_t pubsubAdmin_removePublication(pubsub_admin_pt admin,pubsub_endpoi celix_status_t pubsubAdmin_closeAllPublications(pubsub_admin_pt admin,char* scope, char* topic); celix_status_t pubsubAdmin_closeAllSubscriptions(pubsub_admin_pt admin,char* scope,char* topic); -celix_status_t pubsubAdmin_matchPublisher(pubsub_admin_pt admin, pubsub_endpoint_pt pubEP, double* score); -celix_status_t pubsubAdmin_matchSubscriber(pubsub_admin_pt admin, pubsub_endpoint_pt subEP, double* score); +celix_status_t pubsubAdmin_serializerAdded(void * handle, service_reference_pt reference, void * service); +celix_status_t pubsubAdmin_serializerRemoved(void * handle, service_reference_pt reference, void * service); -celix_status_t pubsubAdmin_setSerializer(pubsub_admin_pt admin, pubsub_serializer_service_t* serializerSvc); -celix_status_t pubsubAdmin_removeSerializer(pubsub_admin_pt admin, pubsub_serializer_service_t* serializerSvc); +celix_status_t pubsubAdmin_matchEndpoint(pubsub_admin_pt admin, pubsub_endpoint_pt endpoint, double* score); -#endif /* PUBSUB_ADMIN_IMPL_H_ */ +#endif /* PUBSUB_ADMIN_ZMQ_IMPL_H_ */ diff --git a/pubsub/pubsub_admin_zmq/private/include/pubsub_publish_service_private.h b/pubsub/pubsub_admin_zmq/private/include/topic_publication.h similarity index 76% rename from pubsub/pubsub_admin_zmq/private/include/pubsub_publish_service_private.h rename to pubsub/pubsub_admin_zmq/private/include/topic_publication.h index dbd2ff1c6..3457263b0 100644 --- a/pubsub/pubsub_admin_zmq/private/include/pubsub_publish_service_private.h +++ b/pubsub/pubsub_admin_zmq/private/include/topic_publication.h @@ -17,35 +17,33 @@ *under the License. */ /* - * pubsub_publish_service_private.h + * topic_publication.h * * \date Sep 24, 2015 * \author Apache Celix Project Team * \copyright Apache License, Version 2.0 */ -#ifndef PUBSUB_PUBLISH_SERVICE_PRIVATE_H_ -#define PUBSUB_PUBLISH_SERVICE_PRIVATE_H_ +#ifndef TOPIC_PUBLICATION_H_ +#define TOPIC_PUBLICATION_H_ #include "publisher.h" #include "pubsub_endpoint.h" #include "pubsub_common.h" + #include "pubsub_serializer.h" typedef struct topic_publication *topic_publication_pt; -celix_status_t pubsub_topicPublicationCreate(bundle_context_pt bundle_context,pubsub_endpoint_pt pubEP, char* bindIP, unsigned int basePort, unsigned int maxPort, topic_publication_pt *out); +celix_status_t pubsub_topicPublicationCreate(bundle_context_pt bundle_context,pubsub_endpoint_pt pubEP, pubsub_serializer_service_t *best_serializer, char* bindIP, unsigned int basePort, unsigned int maxPort, topic_publication_pt *out); celix_status_t pubsub_topicPublicationDestroy(topic_publication_pt pub); celix_status_t pubsub_topicPublicationAddPublisherEP(topic_publication_pt pub,pubsub_endpoint_pt ep); celix_status_t pubsub_topicPublicationRemovePublisherEP(topic_publication_pt pub,pubsub_endpoint_pt ep); -celix_status_t pubsub_topicPublicationSetSerializer(topic_publication_pt pub, pubsub_serializer_service_t* serializerSvc); -celix_status_t pubsub_topicPublicationRemoveSerializer(topic_publication_pt pub, pubsub_serializer_service_t* serializerSvc); - celix_status_t pubsub_topicPublicationStart(bundle_context_pt bundle_context,topic_publication_pt pub,service_factory_pt* svcFactory); celix_status_t pubsub_topicPublicationStop(topic_publication_pt pub); array_list_pt pubsub_topicPublicationGetPublisherList(topic_publication_pt pub); -#endif /* PUBSUB_PUBLISH_SERVICE_PRIVATE_H_ */ +#endif /* TOPIC_PUBLICATION_H_ */ diff --git a/pubsub/pubsub_admin_zmq/private/include/topic_subscription.h b/pubsub/pubsub_admin_zmq/private/include/topic_subscription.h index c1e78c393..726710383 100644 --- a/pubsub/pubsub_admin_zmq/private/include/topic_subscription.h +++ b/pubsub/pubsub_admin_zmq/private/include/topic_subscription.h @@ -38,22 +38,21 @@ typedef struct topic_subscription* topic_subscription_pt; -celix_status_t pubsub_topicSubscriptionCreate(bundle_context_pt bundle_context, pubsub_endpoint_pt subEP, pubsub_serializer_service_t* serializer, char* scope, char* topic,topic_subscription_pt* out); +celix_status_t pubsub_topicSubscriptionCreate(bundle_context_pt bundle_context,char* scope, char* topic, pubsub_serializer_service_t *best_serializer, topic_subscription_pt* out); celix_status_t pubsub_topicSubscriptionDestroy(topic_subscription_pt ts); celix_status_t pubsub_topicSubscriptionStart(topic_subscription_pt ts); celix_status_t pubsub_topicSubscriptionStop(topic_subscription_pt ts); celix_status_t pubsub_topicSubscriptionAddConnectPublisherToPendingList(topic_subscription_pt ts, char* pubURL); celix_status_t pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(topic_subscription_pt ts, char* pubURL); + celix_status_t pubsub_topicSubscriptionConnectPublisher(topic_subscription_pt ts, char* pubURL); celix_status_t pubsub_topicSubscriptionDisconnectPublisher(topic_subscription_pt ts, char* pubURL); celix_status_t pubsub_topicSubscriptionAddSubscriber(topic_subscription_pt ts, pubsub_endpoint_pt subEP); celix_status_t pubsub_topicSubscriptionRemoveSubscriber(topic_subscription_pt ts, pubsub_endpoint_pt subEP); -celix_status_t pubsub_topicSubscriptionSetSerializer(topic_subscription_pt ts, pubsub_serializer_service_t* serializerSvc); -celix_status_t pubsub_topicSubscriptionRemoveSerializer(topic_subscription_pt ts, pubsub_serializer_service_t* serializerSvc); - +array_list_pt pubsub_topicSubscriptionGetSubscribersList(topic_subscription_pt sub); celix_status_t pubsub_topicIncreaseNrSubscribers(topic_subscription_pt subscription); celix_status_t pubsub_topicDecreaseNrSubscribers(topic_subscription_pt subscription); unsigned int pubsub_topicGetNrSubscribers(topic_subscription_pt subscription); diff --git a/pubsub/pubsub_admin_zmq/private/src/psa_activator.c b/pubsub/pubsub_admin_zmq/private/src/psa_activator.c index cfe2c2e25..fd07310b5 100644 --- a/pubsub/pubsub_admin_zmq/private/src/psa_activator.c +++ b/pubsub/pubsub_admin_zmq/private/src/psa_activator.c @@ -28,6 +28,7 @@ #include "bundle_activator.h" #include "service_registration.h" +#include "service_tracker.h" #include "pubsub_admin_impl.h" @@ -36,6 +37,7 @@ struct activator { pubsub_admin_pt admin; pubsub_admin_service_pt adminService; service_registration_pt registration; + service_tracker_pt serializerTracker; }; celix_status_t bundleActivator_create(bundle_context_pt context, void **userData) { @@ -48,7 +50,28 @@ celix_status_t bundleActivator_create(bundle_context_pt context, void **userData } else{ *userData = activator; + status = pubsubAdmin_create(context, &(activator->admin)); + + if(status == CELIX_SUCCESS){ + service_tracker_customizer_pt customizer = NULL; + status = serviceTrackerCustomizer_create(activator->admin, + NULL, + pubsubAdmin_serializerAdded, + NULL, + pubsubAdmin_serializerRemoved, + &customizer); + if(status == CELIX_SUCCESS){ + status = serviceTracker_create(context, PUBSUB_SERIALIZER_SERVICE, customizer, &(activator->serializerTracker)); + if(status != CELIX_SUCCESS){ + serviceTrackerCustomizer_destroy(customizer); + pubsubAdmin_destroy(activator->admin); + } + } + else{ + pubsubAdmin_destroy(activator->admin); + } + } } return status; @@ -74,16 +97,14 @@ celix_status_t bundleActivator_start(void * userData, bundle_context_pt context) pubsubAdminSvc->closeAllPublications = pubsubAdmin_closeAllPublications; pubsubAdminSvc->closeAllSubscriptions = pubsubAdmin_closeAllSubscriptions; - pubsubAdminSvc->matchPublisher = pubsubAdmin_matchPublisher; - pubsubAdminSvc->matchSubscriber = pubsubAdmin_matchSubscriber; - - pubsubAdminSvc->setSerializer = pubsubAdmin_setSerializer; - pubsubAdminSvc->removeSerializer = pubsubAdmin_removeSerializer; + pubsubAdminSvc->matchEndpoint = pubsubAdmin_matchEndpoint; activator->adminService = pubsubAdminSvc; status = bundleContext_registerService(context, PUBSUB_ADMIN_SERVICE, pubsubAdminSvc, NULL, &activator->registration); + status += serviceTracker_open(activator->serializerTracker); + } @@ -94,7 +115,9 @@ celix_status_t bundleActivator_stop(void * userData, bundle_context_pt context) celix_status_t status = CELIX_SUCCESS; struct activator *activator = userData; - serviceRegistration_unregister(activator->registration); + status += serviceTracker_close(activator->serializerTracker); + status += serviceRegistration_unregister(activator->registration); + activator->registration = NULL; free(activator->adminService); @@ -107,6 +130,7 @@ celix_status_t bundleActivator_destroy(void * userData, bundle_context_pt contex celix_status_t status = CELIX_SUCCESS; struct activator *activator = userData; + serviceTracker_destroy(activator->serializerTracker); pubsubAdmin_destroy(activator->admin); activator->admin = NULL; diff --git a/pubsub/pubsub_admin_zmq/private/src/pubsub_admin_impl.c b/pubsub/pubsub_admin_zmq/private/src/pubsub_admin_impl.c index e919c9cab..931650649 100644 --- a/pubsub/pubsub_admin_zmq/private/src/pubsub_admin_impl.c +++ b/pubsub/pubsub_admin_zmq/private/src/pubsub_admin_impl.c @@ -57,7 +57,7 @@ #include "service_factory.h" #include "topic_subscription.h" -#include "pubsub_publish_service_private.h" +#include "topic_publication.h" #include "pubsub_endpoint.h" #include "pubsub_utils.h" #include "subscriber.h" @@ -66,17 +66,20 @@ static const char *DEFAULT_IP = "127.0.0.1"; -static celix_status_t pubsubAdmin_getIpAddress(const char* interface, char** ip); +static celix_status_t pubsubAdmin_getIpAdress(const char* interface, char** ip); static celix_status_t pubsubAdmin_addSubscriptionToPendingList(pubsub_admin_pt admin,pubsub_endpoint_pt subEP); static celix_status_t pubsubAdmin_addAnySubscription(pubsub_admin_pt admin,pubsub_endpoint_pt subEP); -static celix_status_t pubsubAdmin_match(pubsub_admin_pt admin, pubsub_endpoint_pt psEP, double* score); + +static celix_status_t pubsubAdmin_getBestSerializer(pubsub_admin_pt admin,pubsub_endpoint_pt ep, pubsub_serializer_service_t **serSvc); +static void connectTopicPubSubToSerializer(pubsub_admin_pt admin,pubsub_serializer_service_t *serializer,void *topicPubSub,bool isPublication); +static void disconnectTopicPubSubFromSerializer(pubsub_admin_pt admin,void *topicPubSub,bool isPublication); celix_status_t pubsubAdmin_create(bundle_context_pt context, pubsub_admin_pt *admin) { celix_status_t status = CELIX_SUCCESS; #ifdef BUILD_WITH_ZMQ_SECURITY if (!zsys_has_curve()){ - printf("PSA: zeromq curve unsupported\n"); + printf("PSA_ZMQ: zeromq curve unsupported\n"); return CELIX_SERVICE_EXCEPTION; } #endif @@ -95,14 +98,19 @@ celix_status_t pubsubAdmin_create(bundle_context_pt context, pubsub_admin_pt *ad (*admin)->subscriptions = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL); (*admin)->pendingSubscriptions = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL); (*admin)->externalPublications = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL); + (*admin)->topicSubscriptionsPerSerializer = hashMap_create(NULL, NULL, NULL, NULL); + (*admin)->topicPublicationsPerSerializer = hashMap_create(NULL, NULL, NULL, NULL); + arrayList_create(&((*admin)->noSerializerSubscriptions)); + arrayList_create(&((*admin)->noSerializerPublications)); + arrayList_create(&((*admin)->serializerList)); celixThreadMutex_create(&(*admin)->localPublicationsLock, NULL); celixThreadMutex_create(&(*admin)->subscriptionsLock, NULL); + celixThreadMutex_create(&(*admin)->pendingSubscriptionsLock, NULL); celixThreadMutex_create(&(*admin)->externalPublicationsLock, NULL); - - celixThreadMutexAttr_create(&(*admin)->pendingSubscriptionsAttr); - celixThreadMutexAttr_settype(&(*admin)->pendingSubscriptionsAttr, CELIX_THREAD_MUTEX_RECURSIVE); - celixThreadMutex_create(&(*admin)->pendingSubscriptionsLock, &(*admin)->pendingSubscriptionsAttr); + celixThreadMutex_create(&(*admin)->noSerializerPendingsLock, NULL); + celixThreadMutex_create(&(*admin)->serializerListLock, NULL); + celixThreadMutex_create(&(*admin)->usedSerializersLock, NULL); if (logHelper_create(context, &(*admin)->loghelper) == CELIX_SUCCESS) { logHelper_start((*admin)->loghelper); @@ -115,8 +123,8 @@ celix_status_t pubsubAdmin_create(bundle_context_pt context, pubsub_admin_pt *ad const char *interface = NULL; bundleContext_getProperty(context, PSA_ITF, &interface); - if (pubsubAdmin_getIpAddress(interface, &detectedIp) != CELIX_SUCCESS) { - logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_WARNING, "PSA: Could not retrieve IP adress for interface %s", interface); + if (pubsubAdmin_getIpAdress(interface, &detectedIp) != CELIX_SUCCESS) { + logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_WARNING, "PSA_ZMQ: Could not retrieve IP adress for interface %s", interface); } ip = detectedIp; @@ -124,11 +132,11 @@ celix_status_t pubsubAdmin_create(bundle_context_pt context, pubsub_admin_pt *ad #endif if (ip != NULL) { - logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_INFO, "PSA: Using %s for service annunciation", ip); + logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_INFO, "PSA_ZMQ: Using %s for service annunciation", ip); (*admin)->ipAddress = strdup(ip); } else { - logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_WARNING, "PSA: No IP address for service annunciation set. Using %s", DEFAULT_IP); + logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_WARNING, "PSA_ZMQ: No IP address for service annunciation set. Using %s", DEFAULT_IP); (*admin)->ipAddress = strdup(DEFAULT_IP); } @@ -136,24 +144,24 @@ celix_status_t pubsubAdmin_create(bundle_context_pt context, pubsub_admin_pt *ad free(detectedIp); } - const char* basePortStr = NULL; - const char* maxPortStr = NULL; - char* endptrBase = NULL; - char* endptrMax = NULL; - bundleContext_getPropertyWithDefault(context, PSA_ZMQ_BASE_PORT, "PSA_ZMQ_DEFAULT_BASE_PORT", &basePortStr); - bundleContext_getPropertyWithDefault(context, PSA_ZMQ_MAX_PORT, "PSA_ZMQ_DEFAULT_MAX_PORT", &maxPortStr); - (*admin)->basePort = strtol(basePortStr, &endptrBase, 10); - (*admin)->maxPort = strtol(maxPortStr, &endptrMax, 10); - if (*endptrBase != '\0') { - (*admin)->basePort = PSA_ZMQ_DEFAULT_BASE_PORT; - } - if (*endptrMax != '\0') { - (*admin)->maxPort = PSA_ZMQ_DEFAULT_MAX_PORT; - } - - printf("PSA Using base port %u to max port %u\n", (*admin)->basePort, (*admin)->maxPort); - - // Disable Signal Handling by CZMQ + const char* basePortStr = NULL; + const char* maxPortStr = NULL; + char* endptrBase = NULL; + char* endptrMax = NULL; + bundleContext_getPropertyWithDefault(context, PSA_ZMQ_BASE_PORT, "PSA_ZMQ_DEFAULT_BASE_PORT", &basePortStr); + bundleContext_getPropertyWithDefault(context, PSA_ZMQ_MAX_PORT, "PSA_ZMQ_DEFAULT_MAX_PORT", &maxPortStr); + (*admin)->basePort = strtol(basePortStr, &endptrBase, 10); + (*admin)->maxPort = strtol(maxPortStr, &endptrMax, 10); + if (*endptrBase != '\0') { + (*admin)->basePort = PSA_ZMQ_DEFAULT_BASE_PORT; + } + if (*endptrMax != '\0') { + (*admin)->maxPort = PSA_ZMQ_DEFAULT_MAX_PORT; + } + + printf("PSA Using base port %u to max port %u\n", (*admin)->basePort, (*admin)->maxPort); + + // Disable Signal Handling by CZMQ setenv("ZSYS_SIGHANDLER", "false", true); const char *nrZmqThreads = NULL; @@ -164,8 +172,8 @@ celix_status_t pubsubAdmin_create(bundle_context_pt context, pubsub_admin_pt *ad unsigned int nrThreads = strtoul(nrZmqThreads, &endPtr, 10); if(endPtr != nrZmqThreads && nrThreads > 0 && nrThreads < 50) { zsys_set_io_threads(nrThreads); - logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_INFO, "PSA: Using %d threads for ZMQ", nrThreads); - printf("PSA: Using %d threads for ZMQ\n", nrThreads); + logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_INFO, "PSA_ZMQ: Using %d threads for ZMQ", nrThreads); + printf("PSA_ZMQ: Using %d threads for ZMQ\n", nrThreads); } } @@ -227,8 +235,38 @@ celix_status_t pubsubAdmin_destroy(pubsub_admin_pt admin) hashMap_destroy(admin->externalPublications,false,false); celixThreadMutex_unlock(&admin->externalPublicationsLock); + celixThreadMutex_lock(&admin->serializerListLock); + arrayList_destroy(admin->serializerList); + celixThreadMutex_unlock(&admin->serializerListLock); + + celixThreadMutex_lock(&admin->noSerializerPendingsLock); + arrayList_destroy(admin->noSerializerSubscriptions); + arrayList_destroy(admin->noSerializerPublications); + celixThreadMutex_unlock(&admin->noSerializerPendingsLock); + + + celixThreadMutex_lock(&admin->usedSerializersLock); + + iter = hashMapIterator_create(admin->topicSubscriptionsPerSerializer); + while(hashMapIterator_hasNext(iter)){ + arrayList_destroy((array_list_pt)hashMapIterator_nextValue(iter)); + } + hashMapIterator_destroy(iter); + hashMap_destroy(admin->topicSubscriptionsPerSerializer,false,false); + + iter = hashMapIterator_create(admin->topicPublicationsPerSerializer); + while(hashMapIterator_hasNext(iter)){ + arrayList_destroy((array_list_pt)hashMapIterator_nextValue(iter)); + } + hashMapIterator_destroy(iter); + hashMap_destroy(admin->topicPublicationsPerSerializer,false,false); + + celixThreadMutex_unlock(&admin->usedSerializersLock); + + celixThreadMutex_destroy(&admin->usedSerializersLock); + celixThreadMutex_destroy(&admin->noSerializerPendingsLock); + celixThreadMutex_destroy(&admin->serializerListLock); celixThreadMutex_destroy(&admin->pendingSubscriptionsLock); - celixThreadMutexAttr_destroy(&admin->pendingSubscriptionsAttr); celixThreadMutex_destroy(&admin->subscriptionsLock); celixThreadMutex_destroy(&admin->localPublicationsLock); celixThreadMutex_destroy(&admin->externalPublicationsLock); @@ -258,8 +296,16 @@ static celix_status_t pubsubAdmin_addAnySubscription(pubsub_admin_pt admin,pubsu if(any_sub==NULL){ int i; - - status += pubsub_topicSubscriptionCreate(admin->bundle_context, subEP, admin->serializerSvc, PUBSUB_SUBSCRIBER_SCOPE_DEFAULT, PUBSUB_ANY_SUB_TOPIC, &any_sub); + pubsub_serializer_service_t *best_serializer = NULL; + if( (status=pubsubAdmin_getBestSerializer(admin, subEP, &best_serializer)) == CELIX_SUCCESS){ + status = pubsub_topicSubscriptionCreate(admin->bundle_context, PUBSUB_SUBSCRIBER_SCOPE_DEFAULT, PUBSUB_ANY_SUB_TOPIC, best_serializer, &any_sub); + } + else{ + printf("PSA_ZMQ: Cannot find a serializer for subscribing topic %s. Adding it to pending list.\n",subEP->topic); + celixThreadMutex_lock(&admin->noSerializerPendingsLock); + arrayList_add(admin->noSerializerSubscriptions,subEP); + celixThreadMutex_unlock(&admin->noSerializerPendingsLock); + } if (status == CELIX_SUCCESS){ @@ -278,6 +324,7 @@ static celix_status_t pubsubAdmin_addAnySubscription(pubsub_admin_pt admin,pubsu status += pubsub_topicSubscriptionConnectPublisher(any_sub,pubEP->endpoint); } } + arrayList_destroy(topic_publishers); } } hashMapIterator_destroy(lp_iter); @@ -309,6 +356,7 @@ static celix_status_t pubsubAdmin_addAnySubscription(pubsub_admin_pt admin,pubsu if (status == CELIX_SUCCESS){ hashMap_put(admin->subscriptions,strdup(PUBSUB_ANY_SUB_TOPIC),any_sub); + connectTopicPubSubToSerializer(admin, best_serializer, any_sub, false); } } @@ -321,18 +369,17 @@ static celix_status_t pubsubAdmin_addAnySubscription(pubsub_admin_pt admin,pubsu celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint_pt subEP){ celix_status_t status = CELIX_SUCCESS; - printf("PSA: Received subscription [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",subEP->frameworkUUID,subEP->serviceID,subEP->scope, subEP->topic); + printf("PSA_ZMQ: Received subscription [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",subEP->frameworkUUID,subEP->serviceID,subEP->scope, subEP->topic); if(strcmp(subEP->topic,PUBSUB_ANY_SUB_TOPIC)==0){ return pubsubAdmin_addAnySubscription(admin,subEP); } - celixThreadMutex_lock(&admin->subscriptionsLock); /* Check if we already know some publisher about this topic, otherwise let's put the subscription in the pending hashmap */ celixThreadMutex_lock(&admin->localPublicationsLock); celixThreadMutex_lock(&admin->externalPublicationsLock); - char* scope_topic = createScopeTopicKey(subEP->scope, subEP->topic); + char* scope_topic = createScopeTopicKey(subEP->scope, subEP->topic); service_factory_pt factory = (service_factory_pt)hashMap_get(admin->localPublications,scope_topic); array_list_pt ext_pub_list = (array_list_pt)hashMap_get(admin->externalPublications,scope_topic); @@ -341,12 +388,22 @@ celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint celixThreadMutex_lock(&admin->pendingSubscriptionsLock); pubsubAdmin_addSubscriptionToPendingList(admin,subEP); celixThreadMutex_unlock(&admin->pendingSubscriptionsLock); - } else { + } + else{ int i; topic_subscription_pt subscription = hashMap_get(admin->subscriptions, scope_topic); if(subscription == NULL) { - status += pubsub_topicSubscriptionCreate(admin->bundle_context, subEP, admin->serializerSvc, subEP->scope, subEP->topic, &subscription); + pubsub_serializer_service_t *best_serializer = NULL; + if( (status=pubsubAdmin_getBestSerializer(admin, subEP, &best_serializer)) == CELIX_SUCCESS){ + status += pubsub_topicSubscriptionCreate(admin->bundle_context,subEP->scope, subEP->topic, best_serializer, &subscription); + } + else{ + printf("PSA_ZMQ: Cannot find a serializer for subscribing topic %s. Adding it to pending list.\n",subEP->topic); + celixThreadMutex_lock(&admin->noSerializerPendingsLock); + arrayList_add(admin->noSerializerSubscriptions,subEP); + celixThreadMutex_unlock(&admin->noSerializerPendingsLock); + } if (status==CELIX_SUCCESS){ @@ -362,6 +419,7 @@ celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint status += pubsub_topicSubscriptionConnectPublisher(subscription,pubEP->endpoint); } } + arrayList_destroy(topic_publishers); } } @@ -383,7 +441,10 @@ celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint } if(status==CELIX_SUCCESS){ + celixThreadMutex_lock(&admin->subscriptionsLock); hashMap_put(admin->subscriptions,strdup(scope_topic),subscription); + celixThreadMutex_unlock(&admin->subscriptionsLock); + connectTopicPubSubToSerializer(admin, best_serializer, subscription, false); } } @@ -392,10 +453,9 @@ celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint } } - free(scope_topic); + free(scope_topic); celixThreadMutex_unlock(&admin->externalPublicationsLock); celixThreadMutex_unlock(&admin->localPublicationsLock); - celixThreadMutex_unlock(&admin->subscriptionsLock); return status; @@ -404,11 +464,12 @@ celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint celix_status_t pubsubAdmin_removeSubscription(pubsub_admin_pt admin,pubsub_endpoint_pt subEP){ celix_status_t status = CELIX_SUCCESS; - printf("PSA: Removing subscription [FWUUID=%s bundleID=%ld topic=%s]\n",subEP->frameworkUUID,subEP->serviceID,subEP->topic); + printf("PSA_ZMQ: Removing subscription [FWUUID=%s bundleID=%ld topic=%s]\n",subEP->frameworkUUID,subEP->serviceID,subEP->topic); celixThreadMutex_lock(&admin->subscriptionsLock); - topic_subscription_pt sub = (topic_subscription_pt)hashMap_get(admin->subscriptions,subEP->topic); + char* scope_topic = createScopeTopicKey(subEP->scope, subEP->topic); + topic_subscription_pt sub = (topic_subscription_pt)hashMap_get(admin->subscriptions,scope_topic); if(sub!=NULL){ pubsub_topicDecreaseNrSubscribers(sub); @@ -417,9 +478,16 @@ celix_status_t pubsubAdmin_removeSubscription(pubsub_admin_pt admin,pubsub_endpo } } else{ - status = CELIX_ILLEGAL_STATE; + /* Maybe the endpoint was pending */ + celixThreadMutex_lock(&admin->noSerializerPendingsLock); + if(!arrayList_removeElement(admin->noSerializerSubscriptions, subEP)){ + status = CELIX_ILLEGAL_STATE; + } + celixThreadMutex_unlock(&admin->noSerializerPendingsLock); } + free(scope_topic); + celixThreadMutex_unlock(&admin->subscriptionsLock); return status; @@ -427,114 +495,127 @@ celix_status_t pubsubAdmin_removeSubscription(pubsub_admin_pt admin,pubsub_endpo } celix_status_t pubsubAdmin_addPublication(pubsub_admin_pt admin, pubsub_endpoint_pt pubEP) { - celix_status_t status = CELIX_SUCCESS; - - printf("PSA: Received publication [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n", pubEP->frameworkUUID, pubEP->serviceID, pubEP->scope, pubEP->topic); - - const char* fwUUID = NULL; - - char *scope_topic = createScopeTopicKey(pubEP->scope, pubEP->topic); - bundleContext_getProperty(admin->bundle_context, OSGI_FRAMEWORK_FRAMEWORK_UUID, &fwUUID); - if (fwUUID == NULL) { - printf("PSA: Cannot retrieve fwUUID.\n"); - return CELIX_INVALID_BUNDLE_CONTEXT; - } - - if ((strcmp(pubEP->frameworkUUID, fwUUID) == 0) && (pubEP->endpoint == NULL)) { - - celixThreadMutex_lock(&admin->localPublicationsLock); - - service_factory_pt factory = (service_factory_pt) hashMap_get(admin->localPublications, scope_topic); - - if (factory == NULL) { - topic_publication_pt pub = NULL; - status = pubsub_topicPublicationCreate(admin->bundle_context, pubEP, admin->ipAddress, admin->basePort, admin->maxPort, &pub); - pubsub_topicPublicationSetSerializer(pub, admin->serializerSvc); //TODO serializer back to constructor. This is certainly when - //TODO admin are created for every available serializer - if (status == CELIX_SUCCESS) { - status = pubsub_topicPublicationStart(admin->bundle_context, pub, &factory); - if (status == CELIX_SUCCESS && factory != NULL) { - hashMap_put(admin->localPublications, strdup(scope_topic), factory); - } - } else { - printf("PSA: Cannot create a topicPublication for scope=%s, topic=%s (bundle %ld).\n", pubEP->scope, pubEP->topic, pubEP->serviceID); - } - } else { - //just add the new EP to the list - topic_publication_pt pub = (topic_publication_pt) factory->handle; - pubsub_topicPublicationAddPublisherEP(pub, pubEP); - } - - celixThreadMutex_unlock(&admin->localPublicationsLock); - } else { - - celixThreadMutex_lock(&admin->externalPublicationsLock); - array_list_pt ext_pub_list = (array_list_pt) hashMap_get(admin->externalPublications, scope_topic); - if (ext_pub_list == NULL) { - arrayList_create(&ext_pub_list); - hashMap_put(admin->externalPublications, strdup(scope_topic), ext_pub_list); - } - - arrayList_add(ext_pub_list, pubEP); - - celixThreadMutex_unlock(&admin->externalPublicationsLock); - } - - /* Re-evaluate the pending subscriptions */ - celixThreadMutex_lock(&admin->pendingSubscriptionsLock); - - hash_map_entry_pt pendingSub = hashMap_getEntry(admin->pendingSubscriptions, scope_topic); - if (pendingSub != NULL) { //There were pending subscription for the just published topic. Let's connect them. - char* topic = (char*) hashMapEntry_getKey(pendingSub); - array_list_pt pendingSubList = (array_list_pt) hashMapEntry_getValue(pendingSub); - int i; - for (i = 0; i < arrayList_size(pendingSubList); i++) { - pubsub_endpoint_pt subEP = (pubsub_endpoint_pt) arrayList_get(pendingSubList, i); - pubsubAdmin_addSubscription(admin, subEP); - } - hashMap_remove(admin->pendingSubscriptions, scope_topic); - arrayList_clear(pendingSubList); - arrayList_destroy(pendingSubList); - free(topic); - } - - celixThreadMutex_unlock(&admin->pendingSubscriptionsLock); - - /* Connect the new publisher to the subscription for his topic, if there is any */ - celixThreadMutex_lock(&admin->subscriptionsLock); - - topic_subscription_pt sub = (topic_subscription_pt) hashMap_get(admin->subscriptions, scope_topic); - if (sub != NULL && pubEP->endpoint != NULL) { - pubsub_topicSubscriptionAddConnectPublisherToPendingList(sub, pubEP->endpoint); - } - - /* And check also for ANY subscription */ - topic_subscription_pt any_sub = (topic_subscription_pt) hashMap_get(admin->subscriptions, PUBSUB_ANY_SUB_TOPIC); - if (any_sub != NULL && pubEP->endpoint != NULL) { - pubsub_topicSubscriptionAddConnectPublisherToPendingList(any_sub, pubEP->endpoint); - } - free(scope_topic); - - celixThreadMutex_unlock(&admin->subscriptionsLock); - - return status; + celix_status_t status = CELIX_SUCCESS; + + printf("PSA_ZMQ: Received publication [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n", pubEP->frameworkUUID, pubEP->serviceID, pubEP->scope, pubEP->topic); + + const char* fwUUID = NULL; + + bundleContext_getProperty(admin->bundle_context, OSGI_FRAMEWORK_FRAMEWORK_UUID, &fwUUID); + if (fwUUID == NULL) { + printf("PSA_ZMQ: Cannot retrieve fwUUID.\n"); + return CELIX_INVALID_BUNDLE_CONTEXT; + } + + char *scope_topic = createScopeTopicKey(pubEP->scope, pubEP->topic); + + if ((strcmp(pubEP->frameworkUUID, fwUUID) == 0) && (pubEP->endpoint == NULL)) { + + celixThreadMutex_lock(&admin->localPublicationsLock); + + service_factory_pt factory = (service_factory_pt) hashMap_get(admin->localPublications, scope_topic); + + if (factory == NULL) { + topic_publication_pt pub = NULL; + pubsub_serializer_service_t *best_serializer = NULL; + if( (status=pubsubAdmin_getBestSerializer(admin, pubEP, &best_serializer)) == CELIX_SUCCESS){ + status = pubsub_topicPublicationCreate(admin->bundle_context, pubEP, best_serializer, admin->ipAddress, admin->basePort, admin->maxPort, &pub); + } + else{ + printf("PSA_ZMQ: Cannot find a serializer for publishing topic %s. Adding it to pending list.\n", pubEP->topic); + celixThreadMutex_lock(&admin->noSerializerPendingsLock); + arrayList_add(admin->noSerializerPublications,pubEP); + celixThreadMutex_unlock(&admin->noSerializerPendingsLock); + } + + if (status == CELIX_SUCCESS) { + status = pubsub_topicPublicationStart(admin->bundle_context, pub, &factory); + if (status == CELIX_SUCCESS && factory != NULL) { + hashMap_put(admin->localPublications, strdup(scope_topic), factory); + connectTopicPubSubToSerializer(admin, best_serializer, pub, true); + } + } else { + printf("PSA_ZMQ: Cannot create a topicPublication for scope=%s, topic=%s (bundle %ld).\n", pubEP->scope, pubEP->topic, pubEP->serviceID); + } + } else { + //just add the new EP to the list + topic_publication_pt pub = (topic_publication_pt) factory->handle; + pubsub_topicPublicationAddPublisherEP(pub, pubEP); + } + + celixThreadMutex_unlock(&admin->localPublicationsLock); + } + else{ + + celixThreadMutex_lock(&admin->externalPublicationsLock); + array_list_pt ext_pub_list = (array_list_pt) hashMap_get(admin->externalPublications, scope_topic); + if (ext_pub_list == NULL) { + arrayList_create(&ext_pub_list); + hashMap_put(admin->externalPublications, strdup(scope_topic), ext_pub_list); + } + + arrayList_add(ext_pub_list, pubEP); + + celixThreadMutex_unlock(&admin->externalPublicationsLock); + } + + /* Re-evaluate the pending subscriptions */ + celixThreadMutex_lock(&admin->pendingSubscriptionsLock); + + hash_map_entry_pt pendingSub = hashMap_getEntry(admin->pendingSubscriptions, scope_topic); + if (pendingSub != NULL) { //There were pending subscription for the just published topic. Let's connect them. + char* topic = (char*) hashMapEntry_getKey(pendingSub); + array_list_pt pendingSubList = (array_list_pt) hashMapEntry_getValue(pendingSub); + int i; + for (i = 0; i < arrayList_size(pendingSubList); i++) { + pubsub_endpoint_pt subEP = (pubsub_endpoint_pt) arrayList_get(pendingSubList, i); + pubsubAdmin_addSubscription(admin, subEP); + } + hashMap_remove(admin->pendingSubscriptions, scope_topic); + arrayList_clear(pendingSubList); + arrayList_destroy(pendingSubList); + free(topic); + } + + celixThreadMutex_unlock(&admin->pendingSubscriptionsLock); + + /* Connect the new publisher to the subscription for his topic, if there is any */ + celixThreadMutex_lock(&admin->subscriptionsLock); + + topic_subscription_pt sub = (topic_subscription_pt) hashMap_get(admin->subscriptions, scope_topic); + if (sub != NULL && pubEP->endpoint != NULL) { + pubsub_topicSubscriptionAddConnectPublisherToPendingList(sub, pubEP->endpoint); + } + + /* And check also for ANY subscription */ + topic_subscription_pt any_sub = (topic_subscription_pt) hashMap_get(admin->subscriptions, PUBSUB_ANY_SUB_TOPIC); + if (any_sub != NULL && pubEP->endpoint != NULL) { + pubsub_topicSubscriptionAddConnectPublisherToPendingList(any_sub, pubEP->endpoint); + } + + free(scope_topic); + + celixThreadMutex_unlock(&admin->subscriptionsLock); + + return status; } celix_status_t pubsubAdmin_removePublication(pubsub_admin_pt admin,pubsub_endpoint_pt pubEP){ celix_status_t status = CELIX_SUCCESS; - int count = 0; + int count = 0; - printf("PSA: Removing publication [FWUUID=%s bundleID=%ld topic=%s]\n",pubEP->frameworkUUID,pubEP->serviceID,pubEP->topic); + printf("PSA_ZMQ: Removing publication [FWUUID=%s bundleID=%ld topic=%s]\n",pubEP->frameworkUUID,pubEP->serviceID,pubEP->topic); const char* fwUUID = NULL; bundleContext_getProperty(admin->bundle_context,OSGI_FRAMEWORK_FRAMEWORK_UUID,&fwUUID); if(fwUUID==NULL){ - printf("PSA: Cannot retrieve fwUUID.\n"); + printf("PSA_ZMQ: Cannot retrieve fwUUID.\n"); return CELIX_INVALID_BUNDLE_CONTEXT; } char *scope_topic = createScopeTopicKey(pubEP->scope, pubEP->topic); + if(strcmp(pubEP->frameworkUUID,fwUUID)==0){ celixThreadMutex_lock(&admin->localPublicationsLock); @@ -545,7 +626,12 @@ celix_status_t pubsubAdmin_removePublication(pubsub_admin_pt admin,pubsub_endpoi pubsub_topicPublicationRemovePublisherEP(pub,pubEP); } else{ - status = CELIX_ILLEGAL_STATE; + /* Maybe the endpoint was pending */ + celixThreadMutex_lock(&admin->noSerializerPendingsLock); + if(!arrayList_removeElement(admin->noSerializerPublications, pubEP)){ + status = CELIX_ILLEGAL_STATE; + } + celixThreadMutex_unlock(&admin->noSerializerPendingsLock); } celixThreadMutex_unlock(&admin->localPublicationsLock); @@ -561,20 +647,18 @@ celix_status_t pubsubAdmin_removePublication(pubsub_admin_pt admin,pubsub_endpoi pubsub_endpoint_pt p = (pubsub_endpoint_pt)arrayList_get(ext_pub_list,i); found = pubsubEndpoint_equals(pubEP,p); if (found){ - found = true; arrayList_remove(ext_pub_list,i); } } // Check if there are more publishers on the same endpoint (happens when 1 celix-instance with multiple bundles publish in same topic) - int ext_pub_list_size = arrayList_size(ext_pub_list); - for(i=0; iendpoint,p->endpoint) == 0) { count++; } } - if(ext_pub_list_size == 0){ + if(arrayList_size(ext_pub_list)==0){ hash_map_entry_pt entry = hashMap_getEntry(admin->externalPublications,scope_topic); char* topic = (char*)hashMapEntry_getKey(entry); array_list_pt list = (array_list_pt)hashMapEntry_getValue(entry); @@ -582,7 +666,6 @@ celix_status_t pubsubAdmin_removePublication(pubsub_admin_pt admin,pubsub_endpoi arrayList_destroy(list); free(topic); } - } celixThreadMutex_unlock(&admin->externalPublicationsLock); @@ -599,8 +682,9 @@ celix_status_t pubsubAdmin_removePublication(pubsub_admin_pt admin,pubsub_endpoi /* And check also for ANY subscription */ topic_subscription_pt any_sub = (topic_subscription_pt)hashMap_get(admin->subscriptions,PUBSUB_ANY_SUB_TOPIC); if(any_sub!=NULL && pubEP->endpoint!=NULL && count == 0){ - pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(any_sub,pubEP->endpoint); + pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(sub,pubEP->endpoint); } + free(scope_topic); celixThreadMutex_unlock(&admin->subscriptionsLock); @@ -611,20 +695,21 @@ celix_status_t pubsubAdmin_removePublication(pubsub_admin_pt admin,pubsub_endpoi celix_status_t pubsubAdmin_closeAllPublications(pubsub_admin_pt admin, char *scope, char* topic){ celix_status_t status = CELIX_SUCCESS; - printf("PSA: Closing all publications\n"); + printf("PSA_ZMQ: Closing all publications\n"); celixThreadMutex_lock(&admin->localPublicationsLock); char *scope_topic = createScopeTopicKey(scope, topic); hash_map_entry_pt pubsvc_entry = (hash_map_entry_pt)hashMap_getEntry(admin->localPublications,scope_topic); if(pubsvc_entry!=NULL){ - char* topic = (char*)hashMapEntry_getKey(pubsvc_entry); + char* key = (char*)hashMapEntry_getKey(pubsvc_entry); service_factory_pt factory= (service_factory_pt)hashMapEntry_getValue(pubsvc_entry); topic_publication_pt pub = (topic_publication_pt)factory->handle; status += pubsub_topicPublicationStop(pub); status += pubsub_topicPublicationDestroy(pub); + disconnectTopicPubSubFromSerializer(admin, pub, true); hashMap_remove(admin->localPublications,scope_topic); - free(topic); + free(key); free(factory); } free(scope_topic); @@ -637,7 +722,7 @@ celix_status_t pubsubAdmin_closeAllPublications(pubsub_admin_pt admin, char *sco celix_status_t pubsubAdmin_closeAllSubscriptions(pubsub_admin_pt admin,char* scope,char* topic){ celix_status_t status = CELIX_SUCCESS; - printf("PSA: Closing all subscriptions\n"); + printf("PSA_ZMQ: Closing all subscriptions\n"); celixThreadMutex_lock(&admin->subscriptionsLock); char *scope_topic = createScopeTopicKey(scope, topic); @@ -649,6 +734,7 @@ celix_status_t pubsubAdmin_closeAllSubscriptions(pubsub_admin_pt admin,char* sco status += pubsub_topicSubscriptionStop(ts); status += pubsub_topicSubscriptionDestroy(ts); + disconnectTopicPubSubFromSerializer(admin, ts, false); hashMap_remove(admin->subscriptions,scope_topic); free(topic); @@ -660,95 +746,9 @@ celix_status_t pubsubAdmin_closeAllSubscriptions(pubsub_admin_pt admin,char* sco } -celix_status_t pubsubAdmin_matchPublisher(pubsub_admin_pt admin, pubsub_endpoint_pt pubEP, double* score){ - celix_status_t status = CELIX_SUCCESS; - status = pubsubAdmin_match(admin, pubEP, score); - return status; -} - -celix_status_t pubsubAdmin_matchSubscriber(pubsub_admin_pt admin, pubsub_endpoint_pt subEP, double* score){ - celix_status_t status = CELIX_SUCCESS; - status = pubsubAdmin_match(admin, subEP, score); - return status; -} - -celix_status_t pubsubAdmin_setSerializer(pubsub_admin_pt admin, pubsub_serializer_service_t* serializerSvc) { - celix_status_t status = CELIX_SUCCESS; - admin->serializerSvc = serializerSvc; - - /* Add serializer to all topic_publication_pt */ - celixThreadMutex_lock(&admin->localPublicationsLock); - hash_map_iterator_pt lp_iter = hashMapIterator_create(admin->localPublications); - while(hashMapIterator_hasNext(lp_iter)){ - service_factory_pt factory = (service_factory_pt) hashMapIterator_nextValue(lp_iter); - topic_publication_pt topic_pub = (topic_publication_pt) factory->handle; - pubsub_topicPublicationSetSerializer(topic_pub, admin->serializerSvc); - } - hashMapIterator_destroy(lp_iter); - celixThreadMutex_unlock(&admin->localPublicationsLock); - - /* Add serializer to all topic_subscription_pt */ - celixThreadMutex_lock(&admin->subscriptionsLock); - hash_map_iterator_pt subs_iter = hashMapIterator_create(admin->subscriptions); - while(hashMapIterator_hasNext(subs_iter)){ - topic_subscription_pt topic_sub = (topic_subscription_pt) hashMapIterator_nextValue(subs_iter); - pubsub_topicSubscriptionSetSerializer(topic_sub, admin->serializerSvc); - } - hashMapIterator_destroy(subs_iter); - celixThreadMutex_unlock(&admin->subscriptionsLock); - - return status; -} - -celix_status_t pubsubAdmin_removeSerializer(pubsub_admin_pt admin, pubsub_serializer_service_t* serializerSvc){ - celix_status_t status = CELIX_SUCCESS; - admin->serializerSvc = NULL; - - /* Remove serializer from all topic_publication_pt */ - celixThreadMutex_lock(&admin->localPublicationsLock); - hash_map_iterator_pt lp_iter = hashMapIterator_create(admin->localPublications); - while(hashMapIterator_hasNext(lp_iter)){ - service_factory_pt factory = (service_factory_pt) hashMapIterator_nextValue(lp_iter); - topic_publication_pt topic_pub = (topic_publication_pt) factory->handle; - pubsub_topicPublicationRemoveSerializer(topic_pub, admin->serializerSvc); - } - hashMapIterator_destroy(lp_iter); - celixThreadMutex_unlock(&admin->localPublicationsLock); - - /* Remove serializer from all topic_subscription_pt */ - celixThreadMutex_lock(&admin->subscriptionsLock); - hash_map_iterator_pt subs_iter = hashMapIterator_create(admin->subscriptions); - while(hashMapIterator_hasNext(subs_iter)){ - topic_subscription_pt topic_sub = (topic_subscription_pt) hashMapIterator_nextValue(subs_iter); - pubsub_topicSubscriptionRemoveSerializer(topic_sub, admin->serializerSvc); - } - hashMapIterator_destroy(subs_iter); - celixThreadMutex_unlock(&admin->subscriptionsLock); - - return status; -} - -static celix_status_t pubsubAdmin_match(pubsub_admin_pt admin, pubsub_endpoint_pt psEP, double* score){ - celix_status_t status = CELIX_SUCCESS; - - char topic_psa_prop[1024]; - snprintf(topic_psa_prop, 1024, "%s.psa", psEP->topic); - - const char* psa_to_use = NULL; - bundleContext_getPropertyWithDefault(admin->bundle_context, topic_psa_prop, PSA_DEFAULT, &psa_to_use); - - *score = 0; - if (strcmp(psa_to_use, "zmq") == 0){ - *score += 100; - }else{ - *score += 1; - } - - return status; -} #ifndef ANDROID -static celix_status_t pubsubAdmin_getIpAddress(const char* interface, char** ip) { +static celix_status_t pubsubAdmin_getIpAdress(const char* interface, char** ip) { celix_status_t status = CELIX_BUNDLE_EXCEPTION; struct ifaddrs *ifaddr, *ifa; @@ -792,3 +792,237 @@ static celix_status_t pubsubAdmin_addSubscriptionToPendingList(pubsub_admin_pt a free(scope_topic); return status; } + +celix_status_t pubsubAdmin_serializerAdded(void * handle, service_reference_pt reference, void * service){ + /* Assumption: serializers are all available at startup. + * If a new (possibly better) serializer is installed and started, already created topic_publications/subscriptions will not be destroyed and recreated */ + + celix_status_t status = CELIX_SUCCESS; + int i=0; + + const char *serType = NULL; + serviceReference_getProperty(reference, PUBSUB_SERIALIZER_TYPE_KEY,&serType); + if(serType == NULL){ + printf("Serializer serviceReference %p has no pubsub_serializer.type property specified\n",reference); + return CELIX_SERVICE_EXCEPTION; + } + + pubsub_admin_pt admin = (pubsub_admin_pt)handle; + celixThreadMutex_lock(&admin->serializerListLock); + arrayList_add(admin->serializerList, reference); + celixThreadMutex_unlock(&admin->serializerListLock); + + /* Now let's re-evaluate the pending */ + celixThreadMutex_lock(&admin->noSerializerPendingsLock); + + for(i=0;inoSerializerSubscriptions);i++){ + pubsub_endpoint_pt ep = (pubsub_endpoint_pt)arrayList_get(admin->noSerializerSubscriptions,i); + pubsub_serializer_service_t *best_serializer = NULL; + pubsubAdmin_getBestSerializer(admin, ep, &best_serializer); + if(best_serializer != NULL){ /* Finally we have a valid serializer! */ + pubsubAdmin_addSubscription(admin, ep); + } + } + + for(i=0;inoSerializerPublications);i++){ + pubsub_endpoint_pt ep = (pubsub_endpoint_pt)arrayList_get(admin->noSerializerPublications,i); + pubsub_serializer_service_t *best_serializer = NULL; + pubsubAdmin_getBestSerializer(admin, ep, &best_serializer); + if(best_serializer != NULL){ /* Finally we have a valid serializer! */ + pubsubAdmin_addPublication(admin, ep); + } + } + + celixThreadMutex_unlock(&admin->noSerializerPendingsLock); + + printf("PSA_ZMQ: %s serializer added\n",serType); + + return status; +} + +celix_status_t pubsubAdmin_serializerRemoved(void * handle, service_reference_pt reference, void * service){ + + pubsub_admin_pt admin = (pubsub_admin_pt)handle; + int i=0, j=0; + const char *serType = NULL; + + serviceReference_getProperty(reference, PUBSUB_SERIALIZER_TYPE_KEY,&serType); + if(serType == NULL){ + printf("Serializer serviceReference %p has no pubsub_serializer.type property specified\n",reference); + return CELIX_SERVICE_EXCEPTION; + } + + celixThreadMutex_lock(&admin->serializerListLock); + celixThreadMutex_lock(&admin->usedSerializersLock); + + + /* Remove the serializer from the list */ + arrayList_removeElement(admin->serializerList, reference); + + /* Now destroy the topicPublications, but first put back the pubsub_endpoints back to the noSerializer pending list */ + array_list_pt topicPubList = (array_list_pt)hashMap_remove(admin->topicPublicationsPerSerializer, service); + if(topicPubList!=NULL){ + for(i=0;iendpoint!=NULL){ + free(pubEP->endpoint); + pubEP->endpoint = NULL; + } + /* Add the orphan endpoint to the noSerializer pending list */ + celixThreadMutex_lock(&admin->noSerializerPendingsLock); + arrayList_add(admin->noSerializerPublications,pubEP); + celixThreadMutex_unlock(&admin->noSerializerPendingsLock); + } + arrayList_destroy(pubList); + + /* Cleanup also the localPublications hashmap*/ + celixThreadMutex_lock(&admin->localPublicationsLock); + hash_map_iterator_pt iter = hashMapIterator_create(admin->localPublications); + char *key = NULL; + service_factory_pt factory = NULL; + while(hashMapIterator_hasNext(iter)){ + hash_map_entry_pt entry = hashMapIterator_nextEntry(iter); + factory = (service_factory_pt)hashMapEntry_getValue(entry); + topic_publication_pt pub = (topic_publication_pt)factory->handle; + if(pub==topicPub){ + key = (char*)hashMapEntry_getKey(entry); + break; + } + } + hashMapIterator_destroy(iter); + if(key!=NULL){ + hashMap_remove(admin->localPublications, key); + free(factory); + free(key); + } + celixThreadMutex_unlock(&admin->localPublicationsLock); + + /* Finally destroy the topicPublication */ + pubsub_topicPublicationDestroy(topicPub); + } + arrayList_destroy(topicPubList); + } + + /* Now destroy the topicSubscriptions, but first put back the pubsub_endpoints back to the noSerializer pending list */ + array_list_pt topicSubList = (array_list_pt)hashMap_remove(admin->topicSubscriptionsPerSerializer, service); + if(topicSubList!=NULL){ + for(i=0;iendpoint!=NULL){ + free(subEP->endpoint); + subEP->endpoint = NULL; + } + /* Add the orphan endpoint to the noSerializer pending list */ + celixThreadMutex_lock(&admin->noSerializerPendingsLock); + arrayList_add(admin->noSerializerSubscriptions,subEP); + celixThreadMutex_unlock(&admin->noSerializerPendingsLock); + } + + /* Cleanup also the subscriptions hashmap*/ + celixThreadMutex_lock(&admin->subscriptionsLock); + hash_map_iterator_pt iter = hashMapIterator_create(admin->subscriptions); + char *key = NULL; + while(hashMapIterator_hasNext(iter)){ + hash_map_entry_pt entry = hashMapIterator_nextEntry(iter); + topic_subscription_pt sub = (topic_subscription_pt)hashMapEntry_getValue(entry); + if(sub==topicSub){ + key = (char*)hashMapEntry_getKey(entry); + break; + } + } + hashMapIterator_destroy(iter); + if(key!=NULL){ + hashMap_remove(admin->subscriptions, key); + free(key); + } + celixThreadMutex_unlock(&admin->subscriptionsLock); + + /* Finally destroy the topicSubscription */ + pubsub_topicSubscriptionDestroy(topicSub); + } + arrayList_destroy(topicSubList); + } + + celixThreadMutex_unlock(&admin->usedSerializersLock); + celixThreadMutex_unlock(&admin->serializerListLock); + + printf("PSA_ZMQ: %s serializer removed\n",serType); + + + return CELIX_SUCCESS; +} + +celix_status_t pubsubAdmin_matchEndpoint(pubsub_admin_pt admin, pubsub_endpoint_pt endpoint, double* score){ + celix_status_t status = CELIX_SUCCESS; + + celixThreadMutex_lock(&admin->serializerListLock); + status = pubsub_admin_match(endpoint->topic_props,PUBSUB_ADMIN_TYPE,admin->serializerList,score); + celixThreadMutex_unlock(&admin->serializerListLock); + + return status; +} + +/* This one recall the same logic as in the match function */ +static celix_status_t pubsubAdmin_getBestSerializer(pubsub_admin_pt admin,pubsub_endpoint_pt ep, pubsub_serializer_service_t **serSvc){ + + celix_status_t status = CELIX_SUCCESS; + + celixThreadMutex_lock(&admin->serializerListLock); + status = pubsub_admin_get_best_serializer(ep->topic_props, admin->serializerList, serSvc); + celixThreadMutex_unlock(&admin->serializerListLock); + + return status; + +} + +static void connectTopicPubSubToSerializer(pubsub_admin_pt admin,pubsub_serializer_service_t *serializer,void *topicPubSub,bool isPublication){ + + celixThreadMutex_lock(&admin->usedSerializersLock); + + hash_map_pt map = isPublication?admin->topicPublicationsPerSerializer:admin->topicSubscriptionsPerSerializer; + array_list_pt list = (array_list_pt)hashMap_get(map,serializer); + if(list==NULL){ + arrayList_create(&list); + hashMap_put(map,serializer,list); + } + arrayList_add(list,topicPubSub); + + celixThreadMutex_unlock(&admin->usedSerializersLock); + +} + +static void disconnectTopicPubSubFromSerializer(pubsub_admin_pt admin,void *topicPubSub,bool isPublication){ + + celixThreadMutex_lock(&admin->usedSerializersLock); + + hash_map_pt map = isPublication?admin->topicPublicationsPerSerializer:admin->topicSubscriptionsPerSerializer; + hash_map_iterator_pt iter = hashMapIterator_create(map); + while(hashMapIterator_hasNext(iter)){ + array_list_pt list = (array_list_pt)hashMapIterator_nextValue(iter); + if(arrayList_removeElement(list, topicPubSub)){ //Found it! + break; + } + } + hashMapIterator_destroy(iter); + + celixThreadMutex_unlock(&admin->usedSerializersLock); + +} diff --git a/pubsub/pubsub_admin_zmq/private/src/topic_publication.c b/pubsub/pubsub_admin_zmq/private/src/topic_publication.c index 2eaad9766..b74177191 100644 --- a/pubsub/pubsub_admin_zmq/private/src/topic_publication.c +++ b/pubsub/pubsub_admin_zmq/private/src/topic_publication.c @@ -7,7 +7,7 @@ *"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 + * htPSA_ZMQ_TP://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 @@ -24,7 +24,6 @@ * \copyright Apache License, Version 2.0 */ -#include "pubsub_publish_service_private.h" #include /* The following undefs prevent the collision between: * - sys/syslog.h (which is included within czmq) @@ -50,6 +49,10 @@ #include "pubsub_utils.h" #include "publisher.h" +#include "topic_publication.h" + +#include "pubsub_serializer.h" + #ifdef BUILD_WITH_ZMQ_SECURITY #include "zmq_crypto.h" @@ -69,21 +72,21 @@ struct topic_publication { service_registration_pt svcFactoryReg; array_list_pt pub_ep_list; //List hash_map_pt boundServices; // - celix_thread_mutex_t tp_lock; // Protects topic_publication data structure - pubsub_serializer_service_t* serializerSvc; + pubsub_serializer_service_t *serializer; + celix_thread_mutex_t tp_lock; }; typedef struct publish_bundle_bound_service { topic_publication_pt parent; - pubsub_publisher_t pubSvc; + pubsub_publisher_t service; bundle_pt bundle; char *topic; - pubsub_msg_serializer_map_t* map; + hash_map_pt msgTypes; unsigned short getCount; celix_thread_mutex_t mp_lock; //Protects publish_bundle_bound_service data structure bool mp_send_in_progress; array_list_pt mp_parts; -} publish_bundle_bound_service_t; +}* publish_bundle_bound_service_pt; /* Note: correct locking order is * 1. tp_lock @@ -93,27 +96,27 @@ typedef struct publish_bundle_bound_service { * tp_lock and socket_lock are independent. */ -typedef struct pubsub_msg { +typedef struct pubsub_msg{ pubsub_msg_header_pt header; char* payload; int payloadSize; -} pubsub_msg_t; +}* pubsub_msg_pt; static unsigned int rand_range(unsigned int min, unsigned int max); static celix_status_t pubsub_topicPublicationGetService(void* handle, bundle_pt bundle, service_registration_pt registration, void **service); static celix_status_t pubsub_topicPublicationUngetService(void* handle, bundle_pt bundle, service_registration_pt registration, void **service); -static publish_bundle_bound_service_t* pubsub_createPublishBundleBoundService(topic_publication_pt tp,bundle_pt bundle); -static void pubsub_destroyPublishBundleBoundService(publish_bundle_bound_service_t* boundSvc); +static publish_bundle_bound_service_pt pubsub_createPublishBundleBoundService(topic_publication_pt tp,bundle_pt bundle); +static void pubsub_destroyPublishBundleBoundService(publish_bundle_bound_service_pt boundSvc); static int pubsub_topicPublicationSend(void* handle,unsigned int msgTypeId, const void *msg); -static int pubsub_topicPublicationSendMultipart(void *handle, unsigned int msgTypeId, const void *msg, int flags); +static int pubsub_topicPublicationSendMultipart(void *handle, unsigned int msgTypeId, const void *inMsg, int flags); static int pubsub_localMsgTypeIdForUUID(void* handle, const char* msgType, unsigned int* msgTypeId); static void delay_first_send_for_late_joiners(void); -celix_status_t pubsub_topicPublicationCreate(bundle_context_pt bundle_context, pubsub_endpoint_pt pubEP, char* bindIP, unsigned int basePort, unsigned int maxPort, topic_publication_pt *out){ +celix_status_t pubsub_topicPublicationCreate(bundle_context_pt bundle_context, pubsub_endpoint_pt pubEP, pubsub_serializer_service_t *best_serializer, char* bindIP, unsigned int basePort, unsigned int maxPort, topic_publication_pt *out){ celix_status_t status = CELIX_SUCCESS; #ifdef BUILD_WITH_ZMQ_SECURITY @@ -128,7 +131,7 @@ celix_status_t pubsub_topicPublicationCreate(bundle_context_pt bundle_context, p for (i = 0; i < secure_topics_size; i++){ char* top = arrayList_get(secure_topics_list, i); if (strcmp(pubEP->topic, top) == 0){ - printf("TP: Secure topic: '%s'\n", top); + printf("PSA_ZMQ_TP: Secure topic: '%s'\n", top); pubEP->is_secure = true; } free(top); @@ -155,12 +158,12 @@ celix_status_t pubsub_topicPublicationCreate(bundle_context_pt bundle_context, p //certificate path ".cache/bundle{id}/version0.0/./META-INF/keys/publisher/private/pub_{topic}.key" snprintf(cert_path, MAX_CERT_PATH_LENGTH, "%s/META-INF/keys/publisher/private/pub_%s.key.enc", keys_bundle_dir, pubEP->topic); free(keys_bundle_dir); - printf("TP: Loading key '%s'\n", cert_path); + printf("PSA_ZMQ_TP: Loading key '%s'\n", cert_path); pub_cert = get_zcert_from_encoded_file((char *) keys_file_path, (char *) keys_file_name, cert_path); if (pub_cert == NULL){ - printf("TP: Cannot load key '%s'\n", cert_path); - printf("TP: Topic '%s' NOT SECURED !\n", pubEP->topic); + printf("PSA_ZMQ_TP: Cannot load key '%s'\n", cert_path); + printf("PSA_ZMQ_TP: Topic '%s' NOT SECURED !\n", pubEP->topic); pubEP->is_secure = false; } } @@ -218,7 +221,7 @@ celix_status_t pubsub_topicPublicationCreate(bundle_context_pt bundle_context, p pub->endpoint = ep; pub->zmq_socket = socket; - pub->serializerSvc = NULL; + pub->serializer = best_serializer; celixThreadMutex_create(&(pub->socket_lock),NULL); @@ -245,13 +248,14 @@ celix_status_t pubsub_topicPublicationDestroy(topic_publication_pt pub){ hash_map_iterator_pt iter = hashMapIterator_create(pub->boundServices); while(hashMapIterator_hasNext(iter)){ - publish_bundle_bound_service_t* bound = hashMapIterator_nextValue(iter); + publish_bundle_bound_service_pt bound = hashMapIterator_nextValue(iter); pubsub_destroyPublishBundleBoundService(bound); } hashMapIterator_destroy(iter); hashMap_destroy(pub->boundServices,false,false); pub->svcFactoryReg = NULL; + pub->serializer = NULL; #ifdef BUILD_WITH_ZMQ_SECURITY zcert_destroy(&(pub->zmq_cert)); #endif @@ -275,7 +279,6 @@ celix_status_t pubsub_topicPublicationStart(bundle_context_pt bundle_context,top celix_status_t status = CELIX_SUCCESS; /* Let's register the new service */ - //celixThreadMutex_lock(&(pub->tp_lock)); pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(pub->pub_ep_list,0); @@ -294,30 +297,22 @@ celix_status_t pubsub_topicPublicationStart(bundle_context_pt bundle_context,top if(status != CELIX_SUCCESS){ properties_destroy(props); - printf("PSA: Cannot register ServiceFactory for topic %s (bundle %ld).\n",pubEP->topic,pubEP->serviceID); + printf("PSA_ZMQ_PSA_ZMQ_TP: Cannot register ServiceFactory for topic %s (bundle %ld).\n",pubEP->topic,pubEP->serviceID); } else{ *svcFactory = factory; } } else{ - printf("PSA: Cannot find pubsub_endpoint after adding it...Should never happen!\n"); + printf("PSA_ZMQ_PSA_ZMQ_TP: Cannot find pubsub_endpoint after adding it...Should never happen!\n"); status = CELIX_SERVICE_EXCEPTION; } - //celixThreadMutex_unlock(&(pub->tp_lock)); - return status; } celix_status_t pubsub_topicPublicationStop(topic_publication_pt pub){ - celix_status_t status = CELIX_SUCCESS; - - //celixThreadMutex_lock(&(pub->tp_lock)); - status = serviceRegistration_unregister(pub->svcFactoryReg); - //celixThreadMutex_unlock(&(pub->tp_lock)); - - return status; + return serviceRegistration_unregister(pub->svcFactoryReg); } celix_status_t pubsub_topicPublicationAddPublisherEP(topic_publication_pt pub,pubsub_endpoint_pt ep){ @@ -345,63 +340,12 @@ celix_status_t pubsub_topicPublicationRemovePublisherEP(topic_publication_pt pub return CELIX_SUCCESS; } -celix_status_t pubsub_topicPublicationSetSerializer(topic_publication_pt pub, pubsub_serializer_service_t* serializerSvc){ - celix_status_t status = CELIX_SUCCESS; - - celixThreadMutex_lock(&(pub->tp_lock)); - - //clearing pref serializer - if (pub->serializerSvc != NULL) { - hash_map_iterator_t iter = hashMapIterator_construct(pub->boundServices); - while (hashMapIterator_hasNext(&iter)) { - publish_bundle_bound_service_t* bound = hashMapIterator_nextValue(&iter); - celixThreadMutex_lock(&bound->mp_lock); - pub->serializerSvc->destroySerializerMap(pub->serializerSvc->handle, bound->map); - celixThreadMutex_unlock(&bound->mp_lock); - bound->map = NULL; - } - } - - pub->serializerSvc = serializerSvc; - if (pub->serializerSvc != NULL) { - hash_map_iterator_t iter = hashMapIterator_construct(pub->boundServices); - while (hashMapIterator_hasNext(&iter)) { - hash_map_entry_pt entry = hashMapIterator_nextEntry(&iter); - bundle_pt bundle = hashMapEntry_getKey(entry); - publish_bundle_bound_service_t* bound = hashMapEntry_getValue(entry); - celixThreadMutex_lock(&bound->mp_lock); - pub->serializerSvc->createSerializerMap(pub->serializerSvc->handle, bundle, &bound->map); - celixThreadMutex_unlock(&bound->mp_lock); - } - } - - celixThreadMutex_unlock(&(pub->tp_lock)); - - return status; -} - -celix_status_t pubsub_topicPublicationRemoveSerializer(topic_publication_pt pub, pubsub_serializer_service_t* svc){ - celix_status_t status = CELIX_SUCCESS; +array_list_pt pubsub_topicPublicationGetPublisherList(topic_publication_pt pub){ + array_list_pt list = NULL; celixThreadMutex_lock(&(pub->tp_lock)); - - if (pub->serializerSvc == svc) { - hash_map_iterator_t iter = hashMapIterator_construct(pub->boundServices); - while (hashMapIterator_hasNext(&iter)) { - publish_bundle_bound_service_t* bound = hashMapIterator_nextValue(&iter); - celixThreadMutex_lock(&bound->mp_lock); - pub->serializerSvc->destroySerializerMap(pub->serializerSvc->handle, bound->map); - celixThreadMutex_unlock(&bound->mp_lock); - bound->map = NULL; - } - pub->serializerSvc = NULL; - } - + list = arrayList_clone(pub->pub_ep_list); celixThreadMutex_unlock(&(pub->tp_lock)); - return status; -} - -array_list_pt pubsub_topicPublicationGetPublisherList(topic_publication_pt pub){ - return pub->pub_ep_list; + return list; } @@ -412,7 +356,7 @@ static celix_status_t pubsub_topicPublicationGetService(void* handle, bundle_pt celixThreadMutex_lock(&(publish->tp_lock)); - publish_bundle_bound_service_t* bound = hashMap_get(publish->boundServices,bundle); + publish_bundle_bound_service_pt bound = (publish_bundle_bound_service_pt)hashMap_get(publish->boundServices,bundle); if(bound==NULL){ bound = pubsub_createPublishBundleBoundService(publish,bundle); if(bound!=NULL){ @@ -423,9 +367,7 @@ static celix_status_t pubsub_topicPublicationGetService(void* handle, bundle_pt bound->getCount++; } - if(bound!=NULL){ - *service = &bound->pubSvc; - } + *service = &bound->service; celixThreadMutex_unlock(&(publish->tp_lock)); @@ -438,7 +380,7 @@ static celix_status_t pubsub_topicPublicationUngetService(void* handle, bundle_p celixThreadMutex_lock(&(publish->tp_lock)); - publish_bundle_bound_service_t* bound = hashMap_get(publish->boundServices,bundle); + publish_bundle_bound_service_pt bound = (publish_bundle_bound_service_pt)hashMap_get(publish->boundServices,bundle); if(bound!=NULL){ bound->getCount--; @@ -451,7 +393,7 @@ static celix_status_t pubsub_topicPublicationUngetService(void* handle, bundle_p else{ long bundleId = -1; bundle_getBundleId(bundle,&bundleId); - printf("TP: Unexpected ungetService call for bundle %ld.\n", bundleId); + printf("PSA_ZMQ_TP: Unexpected ungetService call for bundle %ld.\n", bundleId); } /* service should be never used for unget, so let's set the pointer to NULL */ @@ -462,7 +404,7 @@ static celix_status_t pubsub_topicPublicationUngetService(void* handle, bundle_p return CELIX_SUCCESS; } -static bool send_pubsub_msg(zsock_t* zmq_socket, pubsub_msg_t* msg, bool last){ +static bool send_pubsub_msg(zsock_t* zmq_socket, pubsub_msg_pt msg, bool last){ bool ret = true; @@ -502,7 +444,7 @@ static bool send_pubsub_mp_msg(zsock_t* zmq_socket, array_list_pt mp_msg_parts){ unsigned int i = 0; unsigned int mp_num = arrayList_size(mp_msg_parts); for(;imp_lock)); + publish_bundle_bound_service_pt bound = (publish_bundle_bound_service_pt) handle; + + celixThreadMutex_lock(&(bound->mp_lock)); if( (flags & PUBSUB_PUBLISHER_FIRST_MSG) && !(flags & PUBSUB_PUBLISHER_LAST_MSG) && bound->mp_send_in_progress){ //means a real mp_msg - printf("TP: Multipart send already in progress. Cannot process a new one.\n"); + printf("PSA_ZMQ_TP: Multipart send already in progress. Cannot process a new one.\n"); celixThreadMutex_unlock(&(bound->mp_lock)); return -3; - } - - pubsub_msg_serializer_t* msgSer = NULL; - if (bound->map != NULL) { - msgSer = hashMap_get(bound->map->serializers, (void*)(uintptr_t)msgTypeId); } - if (bound->map == NULL) { - printf("TP: Serializer is not set!\n"); - status = 1; - } else if (msgSer == NULL ){ - printf("TP: No msg serializer available for msg type id %d\n", msgTypeId); - hash_map_iterator_t iter = hashMapIterator_construct(bound->map->serializers); - printf("Note supported messages:\n"); - while (hashMapIterator_hasNext(&iter)) { - pubsub_msg_serializer_t *msgSer = hashMapIterator_nextValue(&iter); - printf("\tmsg %s with id %d\n", msgSer->msgName, msgSer->msgId); - } - status = 1; - } + pubsub_msg_serializer_t* msgSer = (pubsub_msg_serializer_t*)hashMap_get(bound->msgTypes, (void*)(uintptr_t)msgTypeId); + + if (msgSer!= NULL) { + int major=0, minor=0; - int major=0, minor=0; - if (status == 0 && msgSer != NULL) { pubsub_msg_header_pt msg_hdr = calloc(1,sizeof(struct pubsub_msg_header)); strncpy(msg_hdr->topic,bound->topic,MAX_TOPIC_LEN-1); msg_hdr->type = msgTypeId; + if (msgSer->msgVersion != NULL){ version_getMajor(msgSer->msgVersion, &major); version_getMinor(msgSer->msgVersion, &minor); @@ -556,23 +487,24 @@ static int pubsub_topicPublicationSendMultipart(void *handle, unsigned int msgTy msg_hdr->minor = minor; } - char* serializedOutput = NULL; + void *serializedOutput = NULL; size_t serializedOutputLen = 0; - msgSer->serialize(msgSer->handle, msg, &serializedOutput, &serializedOutputLen); - pubsub_msg_t* msg = calloc(1,sizeof(struct pubsub_msg)); + msgSer->serialize(msgSer,inMsg,&serializedOutput, &serializedOutputLen); + + pubsub_msg_pt msg = calloc(1,sizeof(struct pubsub_msg)); msg->header = msg_hdr; - msg->payload = (char *) serializedOutput; + msg->payload = (char*)serializedOutput; msg->payloadSize = serializedOutputLen; bool snd = true; - switch (flags) { + switch(flags){ case PUBSUB_PUBLISHER_FIRST_MSG: bound->mp_send_in_progress = true; arrayList_add(bound->mp_parts,msg); break; case PUBSUB_PUBLISHER_PART_MSG: if(!bound->mp_send_in_progress){ - printf("TP: ERROR: received msg part without the first part.\n"); + printf("PSA_ZMQ_TP: ERROR: received msg part without the first part.\n"); status = -4; } else{ @@ -581,72 +513,53 @@ static int pubsub_topicPublicationSendMultipart(void *handle, unsigned int msgTy break; case PUBSUB_PUBLISHER_LAST_MSG: if(!bound->mp_send_in_progress){ - printf("TP: ERROR: received end msg without the first part.\n"); + printf("PSA_ZMQ_TP: ERROR: received end msg without the first part.\n"); status = -4; } else{ arrayList_add(bound->mp_parts,msg); - celixThreadMutex_lock(&(bound->parent->socket_lock)); + celixThreadMutex_lock(&(bound->parent->tp_lock)); snd = send_pubsub_mp_msg(bound->parent->zmq_socket,bound->mp_parts); bound->mp_send_in_progress = false; - celixThreadMutex_unlock(&(bound->parent->socket_lock)); + celixThreadMutex_unlock(&(bound->parent->tp_lock)); } break; case PUBSUB_PUBLISHER_FIRST_MSG | PUBSUB_PUBLISHER_LAST_MSG: //Normal send case - celixThreadMutex_lock(&(bound->parent->socket_lock)); + celixThreadMutex_lock(&(bound->parent->tp_lock)); snd = send_pubsub_msg(bound->parent->zmq_socket,msg,true); - celixThreadMutex_unlock(&(bound->parent->socket_lock)); + celixThreadMutex_unlock(&(bound->parent->tp_lock)); break; default: - printf("TP: ERROR: Invalid MP flags combination\n"); + printf("PSA_ZMQ_TP: ERROR: Invalid MP flags combination\n"); status = -4; break; } - /* Free msg in case we got into a bad branch */ if(status==-4){ free(msg); } if(!snd){ - printf("TP: Failed to send %s message %u.\n",flags == (PUBSUB_PUBLISHER_FIRST_MSG | PUBSUB_PUBLISHER_LAST_MSG) ? "single" : "multipart", msgTypeId); + printf("PSA_ZMQ_TP: Failed to send %s message %u.\n",flags == (PUBSUB_PUBLISHER_FIRST_MSG | PUBSUB_PUBLISHER_LAST_MSG) ? "single" : "multipart", msgTypeId); } } else { - printf("TP: Message %u not supported.\n",msgTypeId); + printf("PSA_ZMQ_TP: No msg serializer available for msg type id %d\n", msgTypeId); status=-1; } celixThreadMutex_unlock(&(bound->mp_lock)); + return status; -} -static int pubsub_localMsgTypeIdForUUID(void* handle, const char* msgType, unsigned int* out){ - publish_bundle_bound_service_t* bound = handle; - unsigned int msgTypeId = 0; - - celixThreadMutex_lock(&bound->mp_lock); - if (bound->map != NULL) { - hash_map_iterator_t iter = hashMapIterator_construct(bound->map->serializers); - while (hashMapIterator_hasNext(&iter)) { - pubsub_msg_serializer_t* msgSer = hashMapIterator_nextValue(&iter); - if (strncmp(msgType, msgSer->msgName, 1024*1024) == 0) { - msgTypeId = msgSer->msgId; - break; - } - } - } - celixThreadMutex_unlock(&bound->mp_lock); +} - if (msgTypeId != 0) { - *out = msgTypeId; - return 0; - } else { - printf("TP: Cannot find msg type id for msg type %s\n", msgType); - return 1; - } +static int pubsub_localMsgTypeIdForUUID(void* handle, const char* msgType, unsigned int* msgTypeId){ + *msgTypeId = utils_stringHash(msgType); + return 0; } + static unsigned int rand_range(unsigned int min, unsigned int max){ double scaled = (double)(((double)rand())/((double)RAND_MAX)); @@ -654,10 +567,11 @@ static unsigned int rand_range(unsigned int min, unsigned int max){ } -static publish_bundle_bound_service_t* pubsub_createPublishBundleBoundService(topic_publication_pt tp,bundle_pt bundle){ +static publish_bundle_bound_service_pt pubsub_createPublishBundleBoundService(topic_publication_pt tp,bundle_pt bundle){ + //PRECOND lock on tp->lock - publish_bundle_bound_service_t* bound = calloc(1, sizeof(*bound)); + publish_bundle_bound_service_pt bound = calloc(1, sizeof(*bound)); if (bound != NULL) { @@ -667,42 +581,41 @@ static publish_bundle_bound_service_t* pubsub_createPublishBundleBoundService(to bound->mp_send_in_progress = false; celixThreadMutex_create(&bound->mp_lock,NULL); - if (tp->serializerSvc != NULL) { - tp->serializerSvc->createSerializerMap(tp->serializerSvc->handle, bundle, &bound->map); + if(tp->serializer != NULL){ + tp->serializer->createSerializerMap(tp->serializer->handle,bundle,&bound->msgTypes); } + arrayList_create(&bound->mp_parts); pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(bound->parent->pub_ep_list,0); bound->topic=strdup(pubEP->topic); - bound->pubSvc.handle = bound; - bound->pubSvc.localMsgTypeIdForMsgType = pubsub_localMsgTypeIdForUUID; - bound->pubSvc.send = pubsub_topicPublicationSend; - bound->pubSvc.sendMultipart = pubsub_topicPublicationSendMultipart; - } - else - { - free(bound); - return NULL; + bound->service.handle = bound; + bound->service.localMsgTypeIdForMsgType = pubsub_localMsgTypeIdForUUID; + bound->service.send = pubsub_topicPublicationSend; + bound->service.sendMultipart = pubsub_topicPublicationSendMultipart; + } return bound; } -static void pubsub_destroyPublishBundleBoundService(publish_bundle_bound_service_t* boundSvc){ - //PRECOND lock on publish->tp_lock +static void pubsub_destroyPublishBundleBoundService(publish_bundle_bound_service_pt boundSvc){ + + //PRECOND lock on tp->lock + celixThreadMutex_lock(&boundSvc->mp_lock); - if (boundSvc->map != NULL && boundSvc->parent->serializerSvc != NULL) { - boundSvc->parent->serializerSvc->destroySerializerMap(boundSvc->parent->serializerSvc->handle, boundSvc->map); - boundSvc->map = NULL; + + if(boundSvc->parent->serializer != NULL && boundSvc->msgTypes != NULL){ + boundSvc->parent->serializer->destroySerializerMap(boundSvc->parent->serializer->handle, boundSvc->msgTypes); } - if (boundSvc->mp_parts!=NULL) { + if(boundSvc->mp_parts!=NULL){ arrayList_destroy(boundSvc->mp_parts); } - if (boundSvc->topic!=NULL) { + if(boundSvc->topic!=NULL){ free(boundSvc->topic); } @@ -718,7 +631,7 @@ static void delay_first_send_for_late_joiners(){ static bool firstSend = true; if(firstSend){ - printf("TP: Delaying first send for late joiners...\n"); + printf("PSA_ZMQ_TP: Delaying first send for late joiners...\n"); sleep(FIRST_SEND_DELAY); firstSend = false; } diff --git a/pubsub/pubsub_admin_zmq/private/src/topic_subscription.c b/pubsub/pubsub_admin_zmq/private/src/topic_subscription.c index 409c7a5c2..cf51ed9ff 100644 --- a/pubsub/pubsub_admin_zmq/private/src/topic_subscription.c +++ b/pubsub/pubsub_admin_zmq/private/src/topic_subscription.c @@ -49,51 +49,49 @@ #include "pubsub_utils.h" #ifdef BUILD_WITH_ZMQ_SECURITY - #include "zmq_crypto.h" +#include "zmq_crypto.h" - #define MAX_CERT_PATH_LENGTH 512 +#define MAX_CERT_PATH_LENGTH 512 #endif #define POLL_TIMEOUT 250 #define ZMQ_POLL_TIMEOUT_MS_ENV "ZMQ_POLL_TIMEOUT_MS" -struct topic_subscription { +struct topic_subscription{ + zsock_t* zmq_socket; zcert_t * zmq_cert; zcert_t * zmq_pub_cert; - pthread_mutex_t socket_lock; //Protects zmq_socket access + pthread_mutex_t socket_lock; service_tracker_pt tracker; array_list_pt sub_ep_list; celix_thread_t recv_thread; bool running; - celix_thread_mutex_t ts_lock; //Protects topic_subscription data structure access + celix_thread_mutex_t ts_lock; bundle_context_pt context; - hash_map_pt msgSerializerMapMap; // key = service ptr, value = pubsub_msg_serializer_map_t* - hash_map_pt bundleMap; //key = service ptr, value = bundle_pt - array_list_pt pendingConnections; - array_list_pt pendingDisconnections; + pubsub_serializer_service_t *serializer; + + hash_map_pt servicesMap; // key = service, value = msg types map celix_thread_mutex_t pendingConnections_lock; + array_list_pt pendingConnections; + + array_list_pt pendingDisconnections; celix_thread_mutex_t pendingDisconnections_lock; + unsigned int nrSubscribers; - pubsub_serializer_service_t* serializerSvc; }; -/* Note: correct locking order is - * 1. socket_lock - * 2. ts_lock - */ - -typedef struct complete_zmq_msg { +typedef struct complete_zmq_msg{ zframe_t* header; zframe_t* payload; }* complete_zmq_msg_pt; -typedef struct mp_handle { - pubsub_msg_serializer_map_t* map; +typedef struct mp_handle{ + hash_map_pt svc_msg_db; hash_map_pt rcv_msg_map; -} mp_handle_t; +}* mp_handle_pt; typedef struct msg_map_entry{ bool retain; @@ -107,100 +105,66 @@ static bool checkVersion(version_pt msgVersion,pubsub_msg_header_pt hdr); static void sigusr1_sighandler(int signo); static int pubsub_localMsgTypeIdForMsgType(void* handle, const char* msgType, unsigned int* msgTypeId); static int pubsub_getMultipart(void *handle, unsigned int msgTypeId, bool retain, void **part); -static mp_handle_t* create_mp_handle(topic_subscription_pt sub, pubsub_msg_serializer_map_t* map, array_list_pt rcv_msg_list); -static void destroy_mp_handle(mp_handle_t* mp_handle); +static mp_handle_pt create_mp_handle(hash_map_pt svc_msg_db,array_list_pt rcv_msg_list); +static void destroy_mp_handle(mp_handle_pt mp_handle); static void connectPendingPublishers(topic_subscription_pt sub); static void disconnectPendingPublishers(topic_subscription_pt sub); -celix_status_t pubsub_topicSubscriptionCreate(bundle_context_pt bundle_context, pubsub_endpoint_pt subEP, pubsub_serializer_service_t* serializer, char* scope, char* topic,topic_subscription_pt* out){ +celix_status_t pubsub_topicSubscriptionCreate(bundle_context_pt bundle_context, char* scope, char* topic, pubsub_serializer_service_t *best_serializer, topic_subscription_pt* out){ celix_status_t status = CELIX_SUCCESS; #ifdef BUILD_WITH_ZMQ_SECURITY - if(strcmp(topic,PUBSUB_ANY_SUB_TOPIC) != 0){ - char* secure_topics = NULL; - bundleContext_getProperty(bundle_context, "SECURE_TOPICS", (const char **) &secure_topics); - - if (secure_topics){ - array_list_pt secure_topics_list = pubsub_getTopicsFromString(secure_topics); - - int i; - int secure_topics_size = arrayList_size(secure_topics_list); - for (i = 0; i < secure_topics_size; i++){ - char* top = arrayList_get(secure_topics_list, i); - if (strcmp(topic, top) == 0){ - printf("TS: Secure topic: '%s'\n", top); - subEP->is_secure = true; - } - free(top); - top = NULL; - } - - arrayList_destroy(secure_topics_list); - } + char* keys_bundle_dir = pubsub_getKeysBundleDir(bundle_context); + if (keys_bundle_dir == NULL){ + return CELIX_SERVICE_EXCEPTION; } - zcert_t* sub_cert = NULL; - zcert_t* pub_cert = NULL; - const char* pub_key = NULL; - if (subEP->is_secure){ - char* keys_bundle_dir = pubsub_getKeysBundleDir(bundle_context); - if (keys_bundle_dir == NULL){ - return CELIX_SERVICE_EXCEPTION; - } - - const char* keys_file_path = NULL; - const char* keys_file_name = NULL; - bundleContext_getProperty(bundle_context, PROPERTY_KEYS_FILE_PATH, &keys_file_path); - bundleContext_getProperty(bundle_context, PROPERTY_KEYS_FILE_NAME, &keys_file_name); + const char* keys_file_path = NULL; + const char* keys_file_name = NULL; + bundleContext_getProperty(bundle_context, PROPERTY_KEYS_FILE_PATH, &keys_file_path); + bundleContext_getProperty(bundle_context, PROPERTY_KEYS_FILE_NAME, &keys_file_name); - char sub_cert_path[MAX_CERT_PATH_LENGTH]; - char pub_cert_path[MAX_CERT_PATH_LENGTH]; + char sub_cert_path[MAX_CERT_PATH_LENGTH]; + char pub_cert_path[MAX_CERT_PATH_LENGTH]; - //certificate path ".cache/bundle{id}/version0.0/./META-INF/keys/subscriber/private/sub_{topic}.key.enc" - snprintf(sub_cert_path, MAX_CERT_PATH_LENGTH, "%s/META-INF/keys/subscriber/private/sub_%s.key.enc", keys_bundle_dir, topic); - snprintf(pub_cert_path, MAX_CERT_PATH_LENGTH, "%s/META-INF/keys/publisher/public/pub_%s.pub", keys_bundle_dir, topic); - free(keys_bundle_dir); + //certificate path ".cache/bundle{id}/version0.0/./META-INF/keys/subscriber/private/sub_{topic}.key.enc" + snprintf(sub_cert_path, MAX_CERT_PATH_LENGTH, "%s/META-INF/keys/subscriber/private/sub_%s.key.enc", keys_bundle_dir, topic); + snprintf(pub_cert_path, MAX_CERT_PATH_LENGTH, "%s/META-INF/keys/publisher/public/pub_%s.pub", keys_bundle_dir, topic); + free(keys_bundle_dir); - printf("TS: Loading subscriber key '%s'\n", sub_cert_path); - printf("TS: Loading publisher key '%s'\n", pub_cert_path); - - sub_cert = get_zcert_from_encoded_file((char *) keys_file_path, (char *) keys_file_name, sub_cert_path); - if (sub_cert == NULL){ - printf("TS: Cannot load key '%s'\n", sub_cert_path); - printf("TS: Topic '%s' NOT SECURED !\n", topic); - subEP->is_secure = false; - } + printf("PSA_ZMQ_PSA_ZMQ_TS: Loading subscriber key '%s'\n", sub_cert_path); + printf("PSA_ZMQ_PSA_ZMQ_TS: Loading publisher key '%s'\n", pub_cert_path); - pub_cert = zcert_load(pub_cert_path); - if (sub_cert != NULL && pub_cert == NULL){ - zcert_destroy(&sub_cert); - printf("TS: Cannot load key '%s'\n", pub_cert_path); - printf("TS: Topic '%s' NOT SECURED !\n", topic); - subEP->is_secure = false; - } + zcert_t* sub_cert = get_zcert_from_encoded_file((char *) keys_file_path, (char *) keys_file_name, sub_cert_path); + if (sub_cert == NULL){ + printf("PSA_ZMQ_PSA_ZMQ_TS: Cannot load key '%s'\n", sub_cert_path); + return CELIX_SERVICE_EXCEPTION; + } - pub_key = zcert_public_txt(pub_cert); + zcert_t* pub_cert = zcert_load(pub_cert_path); + if (pub_cert == NULL){ + zcert_destroy(&sub_cert); + printf("PSA_ZMQ_PSA_ZMQ_TS: Cannot load key '%s'\n", pub_cert_path); + return CELIX_SERVICE_EXCEPTION; } + + const char* pub_key = zcert_public_txt(pub_cert); #endif zsock_t* zmq_s = zsock_new (ZMQ_SUB); if(zmq_s==NULL){ - #ifdef BUILD_WITH_ZMQ_SECURITY - if (subEP->is_secure){ - zcert_destroy(&sub_cert); - zcert_destroy(&pub_cert); - } - #endif +#ifdef BUILD_WITH_ZMQ_SECURITY + zcert_destroy(&sub_cert); + zcert_destroy(&pub_cert); +#endif return CELIX_SERVICE_EXCEPTION; } - #ifdef BUILD_WITH_ZMQ_SECURITY - if (subEP->is_secure){ - zcert_apply (sub_cert, zmq_s); - zsock_set_curve_serverkey (zmq_s, pub_key); //apply key of publisher to socket of subscriber - } - #endif +#ifdef BUILD_WITH_ZMQ_SECURITY + zcert_apply (sub_cert, zmq_s); + zsock_set_curve_serverkey (zmq_s, pub_key); //apply key of publisher to socket of subscriber +#endif if(strcmp(topic,PUBSUB_ANY_SUB_TOPIC)==0){ zsock_set_subscribe (zmq_s, ""); @@ -214,20 +178,18 @@ celix_status_t pubsub_topicSubscriptionCreate(bundle_context_pt bundle_context, ts->zmq_socket = zmq_s; ts->running = false; ts->nrSubscribers = 0; - ts->serializerSvc = NULL; + ts->serializer = best_serializer; - #ifdef BUILD_WITH_ZMQ_SECURITY - if (subEP->is_secure){ - ts->zmq_cert = sub_cert; - ts->zmq_pub_cert = pub_cert; - } - #endif +#ifdef BUILD_WITH_ZMQ_SECURITY + ts->zmq_cert = sub_cert; + ts->zmq_pub_cert = pub_cert; +#endif celixThreadMutex_create(&ts->socket_lock, NULL); celixThreadMutex_create(&ts->ts_lock,NULL); arrayList_create(&ts->sub_ep_list); - ts->msgSerializerMapMap = hashMap_create(NULL, NULL, NULL, NULL); - ts->bundleMap = hashMap_create(NULL, NULL, NULL, NULL); + ts->servicesMap = hashMap_create(NULL, NULL, NULL, NULL); + arrayList_create(&ts->pendingConnections); arrayList_create(&ts->pendingDisconnections); celixThreadMutex_create(&ts->pendingConnections_lock, NULL); @@ -236,17 +198,17 @@ celix_status_t pubsub_topicSubscriptionCreate(bundle_context_pt bundle_context, char filter[128]; memset(filter,0,128); if(strncmp(PUBSUB_SUBSCRIBER_SCOPE_DEFAULT,scope,strlen(PUBSUB_SUBSCRIBER_SCOPE_DEFAULT)) == 0) { - // default scope, means that subscriber has not defined a scope property - snprintf(filter, 128, "(&(%s=%s)(%s=%s))", - (char*) OSGI_FRAMEWORK_OBJECTCLASS, PUBSUB_SUBSCRIBER_SERVICE_NAME, - PUBSUB_SUBSCRIBER_TOPIC,topic); + // default scope, means that subscriber has not defined a scope property + snprintf(filter, 128, "(&(%s=%s)(%s=%s))", + (char*) OSGI_FRAMEWORK_OBJECTCLASS, PUBSUB_SUBSCRIBER_SERVICE_NAME, + PUBSUB_SUBSCRIBER_TOPIC,topic); } else { - snprintf(filter, 128, "(&(%s=%s)(%s=%s)(%s=%s))", - (char*) OSGI_FRAMEWORK_OBJECTCLASS, PUBSUB_SUBSCRIBER_SERVICE_NAME, - PUBSUB_SUBSCRIBER_TOPIC,topic, - PUBSUB_SUBSCRIBER_SCOPE,scope); - } + snprintf(filter, 128, "(&(%s=%s)(%s=%s)(%s=%s))", + (char*) OSGI_FRAMEWORK_OBJECTCLASS, PUBSUB_SUBSCRIBER_SERVICE_NAME, + PUBSUB_SUBSCRIBER_TOPIC,topic, + PUBSUB_SUBSCRIBER_SCOPE,scope); + } service_tracker_customizer_pt customizer = NULL; status += serviceTrackerCustomizer_create(ts,NULL,topicsub_subscriberTracked,NULL,topicsub_subscriberUntracked,&customizer); status += serviceTracker_createWithFilter(bundle_context, filter, customizer, &ts->tracker); @@ -259,10 +221,7 @@ celix_status_t pubsub_topicSubscriptionCreate(bundle_context_pt bundle_context, sigaction(SIGUSR1,&actions,NULL); - if (status == CELIX_SUCCESS) { - *out=ts; - pubsub_topicSubscriptionSetSerializer(ts, serializer); - } + *out=ts; return status; } @@ -276,8 +235,8 @@ celix_status_t pubsub_topicSubscriptionDestroy(topic_subscription_pt ts){ serviceTracker_destroy(ts->tracker); arrayList_clear(ts->sub_ep_list); arrayList_destroy(ts->sub_ep_list); - hashMap_destroy(ts->msgSerializerMapMap,false,false); - hashMap_destroy(ts->bundleMap,false,false); + /* TODO: Destroy all the serializer maps? */ + hashMap_destroy(ts->servicesMap,false,false); celixThreadMutex_lock(&ts->pendingConnections_lock); arrayList_destroy(ts->pendingConnections); @@ -289,18 +248,17 @@ celix_status_t pubsub_topicSubscriptionDestroy(topic_subscription_pt ts){ celixThreadMutex_unlock(&ts->pendingDisconnections_lock); celixThreadMutex_destroy(&ts->pendingDisconnections_lock); - #ifdef BUILD_WITH_ZMQ_SECURITY - zcert_destroy(&(ts->zmq_cert)); - zcert_destroy(&(ts->zmq_pub_cert)); - #endif - - celixThreadMutex_unlock(&ts->ts_lock); - celixThreadMutex_lock(&ts->socket_lock); zsock_destroy(&(ts->zmq_socket)); +#ifdef BUILD_WITH_ZMQ_SECURITY + zcert_destroy(&(ts->zmq_cert)); + zcert_destroy(&(ts->zmq_pub_cert)); +#endif celixThreadMutex_unlock(&ts->socket_lock); celixThreadMutex_destroy(&ts->socket_lock); + celixThreadMutex_unlock(&ts->ts_lock); + free(ts); @@ -310,8 +268,6 @@ celix_status_t pubsub_topicSubscriptionDestroy(topic_subscription_pt ts){ celix_status_t pubsub_topicSubscriptionStart(topic_subscription_pt ts){ celix_status_t status = CELIX_SUCCESS; - //celixThreadMutex_lock(&ts->ts_lock); - status = serviceTracker_open(ts->tracker); ts->running = true; @@ -320,16 +276,12 @@ celix_status_t pubsub_topicSubscriptionStart(topic_subscription_pt ts){ status=celixThread_create(&ts->recv_thread,NULL,zmq_recv_thread_func,ts); } - //celixThreadMutex_unlock(&ts->ts_lock); - return status; } celix_status_t pubsub_topicSubscriptionStop(topic_subscription_pt ts){ celix_status_t status = CELIX_SUCCESS; - //celixThreadMutex_lock(&ts->ts_lock); - ts->running = false; pthread_kill(ts->recv_thread.thread,SIGUSR1); @@ -338,15 +290,13 @@ celix_status_t pubsub_topicSubscriptionStop(topic_subscription_pt ts){ status = serviceTracker_close(ts->tracker); - //celixThreadMutex_unlock(&ts->ts_lock); - return status; } celix_status_t pubsub_topicSubscriptionConnectPublisher(topic_subscription_pt ts, char* pubURL){ celix_status_t status = CELIX_SUCCESS; celixThreadMutex_lock(&ts->socket_lock); - if(!zsock_is(ts->zmq_socket) || zsock_connect(ts->zmq_socket, "%s", pubURL) != 0){ + if(!zsock_is(ts->zmq_socket) || zsock_connect(ts->zmq_socket,"%s",pubURL) != 0){ status = CELIX_SERVICE_EXCEPTION; } celixThreadMutex_unlock(&ts->socket_lock); @@ -355,28 +305,28 @@ celix_status_t pubsub_topicSubscriptionConnectPublisher(topic_subscription_pt ts } celix_status_t pubsub_topicSubscriptionAddConnectPublisherToPendingList(topic_subscription_pt ts, char* pubURL) { - celix_status_t status = CELIX_SUCCESS; - char *url = strdup(pubURL); - celixThreadMutex_lock(&ts->pendingConnections_lock); - arrayList_add(ts->pendingConnections, url); - celixThreadMutex_unlock(&ts->pendingConnections_lock); - return status; + celix_status_t status = CELIX_SUCCESS; + char *url = strdup(pubURL); + celixThreadMutex_lock(&ts->pendingConnections_lock); + arrayList_add(ts->pendingConnections, url); + celixThreadMutex_unlock(&ts->pendingConnections_lock); + return status; } celix_status_t pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(topic_subscription_pt ts, char* pubURL) { - celix_status_t status = CELIX_SUCCESS; - char *url = strdup(pubURL); - celixThreadMutex_lock(&ts->pendingDisconnections_lock); - arrayList_add(ts->pendingDisconnections, url); - celixThreadMutex_unlock(&ts->pendingDisconnections_lock); - return status; + celix_status_t status = CELIX_SUCCESS; + char *url = strdup(pubURL); + celixThreadMutex_lock(&ts->pendingDisconnections_lock); + arrayList_add(ts->pendingDisconnections, url); + celixThreadMutex_unlock(&ts->pendingDisconnections_lock); + return status; } celix_status_t pubsub_topicSubscriptionDisconnectPublisher(topic_subscription_pt ts, char* pubURL){ celix_status_t status = CELIX_SUCCESS; celixThreadMutex_lock(&ts->socket_lock); - if(!zsock_is(ts->zmq_socket) || zsock_disconnect(ts->zmq_socket, "%s", pubURL) != 0){ + if(!zsock_is(ts->zmq_socket) || zsock_disconnect(ts->zmq_socket,"%s",pubURL) != 0){ status = CELIX_SERVICE_EXCEPTION; } celixThreadMutex_unlock(&ts->socket_lock); @@ -388,9 +338,7 @@ celix_status_t pubsub_topicSubscriptionAddSubscriber(topic_subscription_pt ts, p celix_status_t status = CELIX_SUCCESS; celixThreadMutex_lock(&ts->ts_lock); - arrayList_add(ts->sub_ep_list,subEP); - celixThreadMutex_unlock(&ts->ts_lock); return status; @@ -401,9 +349,7 @@ celix_status_t pubsub_topicIncreaseNrSubscribers(topic_subscription_pt ts) { celix_status_t status = CELIX_SUCCESS; celixThreadMutex_lock(&ts->ts_lock); - ts->nrSubscribers++; - celixThreadMutex_unlock(&ts->ts_lock); return status; @@ -413,22 +359,17 @@ celix_status_t pubsub_topicSubscriptionRemoveSubscriber(topic_subscription_pt ts celix_status_t status = CELIX_SUCCESS; celixThreadMutex_lock(&ts->ts_lock); - arrayList_removeElement(ts->sub_ep_list,subEP); - celixThreadMutex_unlock(&ts->ts_lock); return status; - } celix_status_t pubsub_topicDecreaseNrSubscribers(topic_subscription_pt ts) { celix_status_t status = CELIX_SUCCESS; celixThreadMutex_lock(&ts->ts_lock); - ts->nrSubscribers--; - celixThreadMutex_unlock(&ts->ts_lock); return status; @@ -438,152 +379,114 @@ unsigned int pubsub_topicGetNrSubscribers(topic_subscription_pt ts) { return ts->nrSubscribers; } -celix_status_t pubsub_topicSubscriptionSetSerializer(topic_subscription_pt ts, pubsub_serializer_service_t* serializerSvc) { - celix_status_t status = CELIX_SUCCESS; - - celixThreadMutex_lock(&ts->ts_lock); - //clear old - if (ts->serializerSvc != NULL) { - hash_map_iterator_t iter = hashMapIterator_construct(ts->msgSerializerMapMap); - while (hashMapIterator_hasNext(&iter)) { - hash_map_entry_pt entry = hashMapIterator_nextEntry(&iter); - pubsub_subscriber_t* subsvc = hashMapEntry_getKey(entry); - pubsub_msg_serializer_map_t* map = hashMapEntry_getValue(entry); - ts->serializerSvc->destroySerializerMap(ts->serializerSvc->handle, map); - hashMap_put(ts->msgSerializerMapMap, subsvc, NULL); - - } - } - ts->serializerSvc = serializerSvc; - //init new - if (ts->serializerSvc != NULL) { - hash_map_iterator_t iter = hashMapIterator_construct(ts->msgSerializerMapMap); - while (hashMapIterator_hasNext(&iter)) { - pubsub_subscriber_t* subsvc = hashMapIterator_nextKey(&iter); - bundle_pt bundle = hashMap_get(ts->bundleMap, subsvc); - pubsub_msg_serializer_map_t* map = NULL; - ts->serializerSvc->createSerializerMap(ts->serializerSvc->handle, bundle, &map); - hashMap_put(ts->msgSerializerMapMap, subsvc, map); - } - } - celixThreadMutex_unlock(&ts->ts_lock); - - return status; +array_list_pt pubsub_topicSubscriptionGetSubscribersList(topic_subscription_pt sub){ + return sub->sub_ep_list; } -celix_status_t pubsub_topicSubscriptionRemoveSerializer(topic_subscription_pt ts, pubsub_serializer_service_t* svc){ +static celix_status_t topicsub_subscriberTracked(void * handle, service_reference_pt reference, void * service){ celix_status_t status = CELIX_SUCCESS; + topic_subscription_pt ts = handle; celixThreadMutex_lock(&ts->ts_lock); - if (ts->serializerSvc == svc) { //only act if svc removed is services used - hash_map_iterator_t iter = hashMapIterator_construct(ts->msgSerializerMapMap); - while (hashMapIterator_hasNext(&iter)) { - hash_map_entry_pt entry = hashMapIterator_nextEntry(&iter); - pubsub_subscriber_t* subsvc = hashMapEntry_getKey(entry); - pubsub_msg_serializer_map_t* map = hashMapEntry_getValue(entry); - ts->serializerSvc->destroySerializerMap(ts->serializerSvc->handle, map); - hashMap_put(ts->msgSerializerMapMap, subsvc, NULL); - } - ts->serializerSvc = NULL; - } - celixThreadMutex_unlock(&ts->ts_lock); - - return status; -} + if (!hashMap_containsKey(ts->servicesMap, service)) { + bundle_pt bundle = NULL; + hash_map_pt msgTypes = NULL; -static celix_status_t topicsub_subscriberTracked(void * handle, service_reference_pt reference, void* svc) { - celix_status_t status = CELIX_SUCCESS; - topic_subscription_pt ts = handle; + serviceReference_getBundle(reference, &bundle); - celixThreadMutex_lock(&ts->ts_lock); - if (!hashMap_containsKey(ts->msgSerializerMapMap, svc)) { - bundle_pt bundle = NULL; - serviceReference_getBundle(reference, &bundle); - - if (ts->serializerSvc != NULL) { - pubsub_msg_serializer_map_t* map = NULL; - ts->serializerSvc->createSerializerMap(ts->serializerSvc->handle, bundle, &map); - if (map != NULL) { - hashMap_put(ts->msgSerializerMapMap, svc, map); - hashMap_put(ts->bundleMap, svc, bundle); - } - } - } + if(ts->serializer != NULL && bundle!=NULL){ + ts->serializer->createSerializerMap(ts->serializer->handle,bundle,&msgTypes); + if(msgTypes != NULL){ + hashMap_put(ts->servicesMap, service, msgTypes); + printf("PSA_ZMQ_TS: New subscriber registered.\n"); + } + } + else{ + printf("PSA_ZMQ_TS: Cannot register new subscriber.\n"); + status = CELIX_SERVICE_EXCEPTION; + } + } celixThreadMutex_unlock(&ts->ts_lock); - printf("TS: New subscriber registered.\n"); - return status; + return status; } -static celix_status_t topicsub_subscriberUntracked(void * handle, service_reference_pt reference, void* svc) { +static celix_status_t topicsub_subscriberUntracked(void * handle, service_reference_pt reference, void * service){ celix_status_t status = CELIX_SUCCESS; topic_subscription_pt ts = handle; celixThreadMutex_lock(&ts->ts_lock); - if (hashMap_containsKey(ts->msgSerializerMapMap, svc)) { - pubsub_msg_serializer_map_t* map = hashMap_remove(ts->msgSerializerMapMap, svc); - if (ts->serializerSvc != NULL){ - ts->serializerSvc->destroySerializerMap(ts->serializerSvc->handle, map); - hashMap_remove(ts->bundleMap, svc); - hashMap_remove(ts->msgSerializerMapMap, svc); - } - } + if (hashMap_containsKey(ts->servicesMap, service)) { + hash_map_pt msgTypes = hashMap_remove(ts->servicesMap, service); + if(msgTypes!=NULL && ts->serializer!=NULL){ + ts->serializer->destroySerializerMap(ts->serializer->handle,msgTypes); + printf("PSA_ZMQ_TS: Subscriber unregistered.\n"); + } + else{ + printf("PSA_ZMQ_TS: Cannot unregister subscriber.\n"); + status = CELIX_SERVICE_EXCEPTION; + } + } celixThreadMutex_unlock(&ts->ts_lock); - printf("TS: Subscriber unregistered.\n"); return status; } -static void process_msg(topic_subscription_pt sub, array_list_pt msg_list) { +static void process_msg(topic_subscription_pt sub,array_list_pt msg_list){ pubsub_msg_header_pt first_msg_hdr = (pubsub_msg_header_pt)zframe_data(((complete_zmq_msg_pt)arrayList_get(msg_list,0))->header); - hash_map_iterator_t iter = hashMapIterator_construct(sub->msgSerializerMapMap); - while (hashMapIterator_hasNext(&iter)) { - hash_map_entry_pt entry = hashMapIterator_nextEntry(&iter); + hash_map_iterator_pt iter = hashMapIterator_create(sub->servicesMap); + while (hashMapIterator_hasNext(iter)) { + hash_map_entry_pt entry = hashMapIterator_nextEntry(iter); pubsub_subscriber_pt subsvc = hashMapEntry_getKey(entry); - pubsub_msg_serializer_map_t* map = hashMapEntry_getValue(entry); + hash_map_pt msgTypes = hashMapEntry_getValue(entry); - pubsub_msg_serializer_t* msgSer = hashMap_get(map->serializers, (void*)(uintptr_t )first_msg_hdr->type); + pubsub_msg_serializer_t *msgSer = hashMap_get(msgTypes,(void*)(uintptr_t )first_msg_hdr->type); if (msgSer == NULL) { - printf("TS: Primary message %d not supported. NOT sending any part of the whole message.\n", first_msg_hdr->type); - } else { + printf("PSA_ZMQ_TS: Primary message %d not supported. NOT sending any part of the whole message.\n",first_msg_hdr->type); + } + else{ void *msgInst = NULL; - bool validVersion = checkVersion(msgSer->msgVersion, first_msg_hdr); + bool validVersion = checkVersion(msgSer->msgVersion,first_msg_hdr); + if(validVersion){ - celix_status_t status = msgSer->deserialize(msgSer->handle, (const char*)zframe_data(((complete_zmq_msg_pt)arrayList_get(msg_list,0))->payload), 0, &msgInst); + + celix_status_t status = msgSer->deserialize(msgSer, (const void *) zframe_data(((complete_zmq_msg_pt)arrayList_get(msg_list,0))->payload), 0, &msgInst); if (status == CELIX_SUCCESS) { bool release = true; - - mp_handle_t* mp_handle = create_mp_handle(sub, map, msg_list); + mp_handle_pt mp_handle = create_mp_handle(msgTypes,msg_list); pubsub_multipart_callbacks_t mp_callbacks; mp_callbacks.handle = mp_handle; mp_callbacks.localMsgTypeIdForMsgType = pubsub_localMsgTypeIdForMsgType; mp_callbacks.getMultipart = pubsub_getMultipart; subsvc->receive(subsvc->handle, msgSer->msgName, first_msg_hdr->type, msgInst, &mp_callbacks, &release); - if (release) { - msgSer->freeMsg(msgSer->handle, msgInst); + if(release){ + msgSer->freeMsg(msgSer,msgInst); // pubsubSerializer_freeMsg(msgType, msgInst); } - if (mp_handle!=NULL) { + if(mp_handle!=NULL){ destroy_mp_handle(mp_handle); } } else{ - printf("TS: Cannot deserialize msgType %s.\n", msgSer->msgName); + printf("PSA_ZMQ_TS: Cannot deserialize msgType %s.\n",msgSer->msgName); } - } else { + } + else{ int major=0,minor=0; - version_getMajor(msgSer->msgVersion, &major); - version_getMinor(msgSer->msgVersion, &minor); - printf("TS: Version mismatch for primary message '%s' (have %d.%d, received %u.%u). NOT sending any part of the whole message.\n", - msgSer->msgName, major, minor, first_msg_hdr->major, first_msg_hdr->minor); + version_getMajor(msgSer->msgVersion,&major); + version_getMinor(msgSer->msgVersion,&minor); + printf("PSA_ZMQ_TS: Version mismatch for primary message '%s' (have %d.%d, received %u.%u). NOT sending any part of the whole message.\n", + msgSer->msgName,major,minor,first_msg_hdr->major,first_msg_hdr->minor); } + } } + hashMapIterator_destroy(iter); int i = 0; for(;irunning) { + while (sub->running) { - celixThreadMutex_lock(&sub->socket_lock); + celixThreadMutex_lock(&sub->socket_lock); - zframe_t* headerMsg = zframe_recv(sub->zmq_socket); - if (headerMsg == NULL) { - if (errno == EINTR) { - //It means we got a signal and we have to exit... - printf("TS: header_recv thread for topic got a signal and will exit.\n"); - } else { - perror("TS: header_recv thread"); - } - } else { + zframe_t* headerMsg = zframe_recv(sub->zmq_socket); + if (headerMsg == NULL) { + if (errno == EINTR) { + //It means we got a signal and we have to exit... + printf("PSA_ZMQ_TS: header_recv thread for topic got a signal and will exit.\n"); + } else { + perror("PSA_ZMQ_TS: header_recv thread"); + } + } else { pubsub_msg_header_pt hdr = (pubsub_msg_header_pt) zframe_data(headerMsg); @@ -622,9 +525,9 @@ static void* zmq_recv_thread_func(void * arg) { if (payloadMsg == NULL) { if (errno == EINTR) { //It means we got a signal and we have to exit... - printf("TS: payload_recv thread for topic got a signal and will exit.\n"); + printf("PSA_ZMQ_TS: payload_recv thread for topic got a signal and will exit.\n"); } else { - perror("TS: payload_recv"); + perror("PSA_ZMQ_TS: payload_recv"); } zframe_destroy(&headerMsg); } else { @@ -644,9 +547,9 @@ static void* zmq_recv_thread_func(void * arg) { if (h_msg == NULL) { if (errno == EINTR) { //It means we got a signal and we have to exit... - printf("TS: h_recv thread for topic got a signal and will exit.\n"); + printf("PSA_ZMQ_TS: h_recv thread for topic got a signal and will exit.\n"); } else { - perror("TS: h_recv"); + perror("PSA_ZMQ_TS: h_recv"); } break; } @@ -655,9 +558,9 @@ static void* zmq_recv_thread_func(void * arg) { if (p_msg == NULL) { if (errno == EINTR) { //It means we got a signal and we have to exit... - printf("TS: p_recv thread for topic got a signal and will exit.\n"); + printf("PSA_ZMQ_TS: p_recv thread for topic got a signal and will exit.\n"); } else { - perror("TS: p_recv"); + perror("PSA_ZMQ_TS: p_recv"); } zframe_destroy(&h_msg); break; @@ -682,16 +585,16 @@ static void* zmq_recv_thread_func(void * arg) { } //zframe_more(headerMsg) else { free(headerMsg); - printf("TS: received message %u for topic %s without payload!\n", hdr->type, hdr->topic); + printf("PSA_ZMQ_TS: received message %u for topic %s without payload!\n", hdr->type, hdr->topic); } - } // headerMsg != NULL - celixThreadMutex_unlock(&sub->socket_lock); - connectPendingPublishers(sub); - disconnectPendingPublishers(sub); - } // while + } // headerMsg != NULL + celixThreadMutex_unlock(&sub->socket_lock); + connectPendingPublishers(sub); + disconnectPendingPublishers(sub); + } // while - return NULL; + return NULL; } static void connectPendingPublishers(topic_subscription_pt sub) { @@ -715,7 +618,7 @@ static void disconnectPendingPublishers(topic_subscription_pt sub) { } static void sigusr1_sighandler(int signo){ - printf("TS: Topic subscription being shut down...\n"); + printf("PSA_ZMQ_TS: Topic subscription being shut down...\n"); return; } @@ -746,7 +649,7 @@ static int pubsub_getMultipart(void *handle, unsigned int msgTypeId, bool retain return -1; } - mp_handle_t* mp_handle = handle; + mp_handle_pt mp_handle = (mp_handle_pt)handle; msg_map_entry_pt entry = hashMap_get(mp_handle->rcv_msg_map,&msgTypeId); if(entry!=NULL){ entry->retain = retain; @@ -762,59 +665,66 @@ static int pubsub_getMultipart(void *handle, unsigned int msgTypeId, bool retain } -static mp_handle_t* create_mp_handle(topic_subscription_pt sub, pubsub_msg_serializer_map_t* map, array_list_pt rcv_msg_list) { +static mp_handle_pt create_mp_handle(hash_map_pt svc_msg_db,array_list_pt rcv_msg_list){ if(arrayList_size(rcv_msg_list)==1){ //Means it's not a multipart message return NULL; } - mp_handle_t* mp_handle = calloc(1,sizeof(struct mp_handle)); - mp_handle->map = map; + mp_handle_pt mp_handle = calloc(1,sizeof(struct mp_handle)); + mp_handle->svc_msg_db = svc_msg_db; mp_handle->rcv_msg_map = hashMap_create(NULL, NULL, NULL, NULL); - int i; //We skip the first message, it will be handle differently - for (i=1 ; iheader); - pubsub_msg_serializer_t* msgSer = hashMap_get(map->serializers, (void*)(uintptr_t)(header->type)); - if (msgSer != NULL) { + pubsub_msg_serializer_t* msgSer = hashMap_get(svc_msg_db, (void*)(uintptr_t)(header->type)); + + if (msgSer!= NULL) { void *msgInst = NULL; - bool validVersion = checkVersion(msgSer->msgVersion, header); + + bool validVersion = checkVersion(msgSer->msgVersion,header); + if(validVersion){ - //TODO make the getMultipart lazy? - celix_status_t status = msgSer->deserialize(msgSer->handle, (const char*)zframe_data(c_msg->payload), 0, &msgInst); + celix_status_t status = msgSer->deserialize(msgSer->handle, (const void*)zframe_data(c_msg->payload), 0, &msgInst); if(status == CELIX_SUCCESS){ msg_map_entry_pt entry = calloc(1,sizeof(struct msg_map_entry)); entry->msgInst = msgInst; - hashMap_put(mp_handle->rcv_msg_map, (void*)(uintptr_t)(header->type), entry); + hashMap_put(mp_handle->rcv_msg_map, (void*)(uintptr_t)header->type,entry); } } } } + return mp_handle; + } -static void destroy_mp_handle(mp_handle_t* mp_handle){ +static void destroy_mp_handle(mp_handle_pt mp_handle){ hash_map_iterator_pt iter = hashMapIterator_create(mp_handle->rcv_msg_map); while(hashMapIterator_hasNext(iter)){ hash_map_entry_pt entry = hashMapIterator_nextEntry(iter); unsigned int msgId = (unsigned int)(uintptr_t)hashMapEntry_getKey(entry); msg_map_entry_pt msgEntry = hashMapEntry_getValue(entry); - pubsub_msg_serializer_t* msgSer = hashMap_get(mp_handle->map->serializers, (void*)(uintptr_t)msgId); - if (msgSer != NULL) { - if (!msgEntry->retain) { - msgSer->freeMsg(msgSer->handle, msgEntry->msgInst); + pubsub_msg_serializer_t* msgSer = hashMap_get(mp_handle->svc_msg_db, (void*)(uintptr_t)msgId); + + if(msgSer!=NULL){ + if(!msgEntry->retain){ + msgSer->freeMsg(msgSer->handle,msgEntry->msgInst); } } else{ - printf("TS: ERROR: Cannot find pubsub_message_type for msg %u, so cannot destroy it!\n", msgId); + printf("PSA_ZMQ_TS: ERROR: Cannot find messageSerializer for msg %u, so cannot destroy it!\n",msgId); } + + free(msgEntry); } hashMapIterator_destroy(iter); - hashMap_destroy(mp_handle->rcv_msg_map,true,true); + hashMap_destroy(mp_handle->rcv_msg_map,false,false); free(mp_handle); } diff --git a/pubsub/pubsub_common/public/include/pubsub_admin.h b/pubsub/pubsub_common/public/include/pubsub_admin.h index f7ab7e0c0..f24d8255a 100644 --- a/pubsub/pubsub_common/public/include/pubsub_admin.h +++ b/pubsub/pubsub_common/public/include/pubsub_admin.h @@ -31,13 +31,12 @@ #include "pubsub_common.h" #include "pubsub_endpoint.h" -#include "pubsub_serializer.h" #define PSA_IP "PSA_IP" #define PSA_ITF "PSA_INTERFACE" #define PSA_MULTICAST_IP_PREFIX "PSA_MC_PREFIX" -#define PSA_DEFAULT "zmq" +#define PUBSUB_ADMIN_TYPE_KEY "pubsub_admin.type" typedef struct pubsub_admin *pubsub_admin_pt; @@ -53,12 +52,19 @@ struct pubsub_admin_service { celix_status_t (*closeAllPublications)(pubsub_admin_pt admin,char* scope, char* topic); celix_status_t (*closeAllSubscriptions)(pubsub_admin_pt admin,char* scope, char* topic); - celix_status_t (*matchPublisher)(pubsub_admin_pt admin, pubsub_endpoint_pt pubEP, double* score); - celix_status_t (*matchSubscriber)(pubsub_admin_pt admin, pubsub_endpoint_pt subEP, double* score); - - celix_status_t (*setSerializer)(pubsub_admin_pt admin, pubsub_serializer_service_t* serializerSvc); - celix_status_t (*removeSerializer)(pubsub_admin_pt admin, pubsub_serializer_service_t* serializerSvc); - + /* Match principle: + * - A full matching pubsub_admin gives 200 points + * - A full matching serializer gives 100 points + * - If QoS = sample + * - fallback pubsub_admin order of selection is: udp_mc, zmq. Points allocation is 100,75. + * - fallback serializers order of selection is: json, void. Points allocation is 30,20. + * - If QoS = control + * - fallback pubsub_admin order of selection is: zmq,udp_mc. Points allocation is 100,75. + * - fallback serializers order of selection is: json, void. Points allocation is 30,20. + * - If nothing is specified, QoS = sample is assumed, so the same score applies, just divided by two. + * + */ + celix_status_t (*matchEndpoint)(pubsub_admin_pt admin, pubsub_endpoint_pt endpoint, double* score); }; typedef struct pubsub_admin_service *pubsub_admin_service_pt; diff --git a/pubsub/pubsub_common/public/include/pubsub_admin_match.h b/pubsub/pubsub_common/public/include/pubsub_admin_match.h new file mode 100644 index 000000000..a366c340c --- /dev/null +++ b/pubsub/pubsub_common/public/include/pubsub_admin_match.h @@ -0,0 +1,27 @@ +/* + * pubsub_admin_match.h + * + * Created on: Sep 4, 2017 + * Author: dn234 + */ + +#ifndef PUBSUB_ADMIN_MATCH_H_ +#define PUBSUB_ADMIN_MATCH_H_ + +#include "celix_errno.h" +#include "properties.h" +#include "array_list.h" + +#include "pubsub_serializer.h" + +#define QOS_ATTRIBUTE_KEY "attribute.qos" +#define QOS_TYPE_SAMPLE "sample" /* A.k.a. unreliable connection */ +#define QOS_TYPE_CONTROL "control" /* A.k.a. reliable connection */ + +#define PUBSUB_ADMIN_FULL_MATCH_SCORE 200.0F +#define SERIALIZER_FULL_MATCH_SCORE 100.0F + +celix_status_t pubsub_admin_match(properties_pt endpoint_props, const char *pubsub_admin_type, array_list_pt serializerList, double *score); +celix_status_t pubsub_admin_get_best_serializer(properties_pt endpoint_props, array_list_pt serializerList, pubsub_serializer_service_t **serSvc); + +#endif /* PUBSUB_ADMIN_MATCH_H_ */ diff --git a/pubsub/pubsub_common/public/include/pubsub_common.h b/pubsub/pubsub_common/public/include/pubsub_common.h index 46abd72d1..5dfd8fdb3 100644 --- a/pubsub/pubsub_common/public/include/pubsub_common.h +++ b/pubsub/pubsub_common/public/include/pubsub_common.h @@ -32,12 +32,12 @@ #define PUBSUB_DISCOVERY_SERVICE "pubsub_discovery" #define PUBSUB_TM_ANNOUNCE_PUBLISHER_SERVICE "pubsub_tm_announce_publisher" -#define PUBSUB_ANY_SUB_TOPIC "any" +#define PUBSUB_ANY_SUB_TOPIC "any" -#define PUBSUB_BUNDLE_ID "bundle.id" +#define PUBSUB_BUNDLE_ID "bundle.id" -#define MAX_SCOPE_LEN 1024 -#define MAX_TOPIC_LEN 1024 +#define MAX_SCOPE_LEN 1024 +#define MAX_TOPIC_LEN 1024 struct pubsub_msg_header{ char topic[MAX_TOPIC_LEN]; diff --git a/pubsub/pubsub_common/public/include/pubsub_endpoint.h b/pubsub/pubsub_common/public/include/pubsub_endpoint.h index 193b3fd16..8a979eb7e 100644 --- a/pubsub/pubsub_common/public/include/pubsub_endpoint.h +++ b/pubsub/pubsub_common/public/include/pubsub_endpoint.h @@ -28,6 +28,11 @@ #define PUBSUB_ENDPOINT_H_ #include "service_reference.h" +#include "listener_hook_service.h" +#include "properties.h" + +#include "publisher.h" +#include "subscriber.h" struct pubsub_endpoint { char *frameworkUUID; @@ -36,12 +41,15 @@ struct pubsub_endpoint { long serviceID; char* endpoint; bool is_secure; + properties_pt topic_props; }; typedef struct pubsub_endpoint *pubsub_endpoint_pt; -celix_status_t pubsubEndpoint_create(const char* fwUUID, const char* scope, const char* topic, long serviceId,const char* endpoint,pubsub_endpoint_pt* psEp); -celix_status_t pubsubEndpoint_createFromServiceReference(service_reference_pt reference,pubsub_endpoint_pt* psEp); +celix_status_t pubsubEndpoint_create(const char* fwUUID, const char* scope, const char* topic, long serviceId,const char* endpoint,properties_pt topic_props,pubsub_endpoint_pt* psEp); +celix_status_t pubsubEndpoint_createFromServiceReference(service_reference_pt reference,pubsub_endpoint_pt* psEp, bool isPublisher); +celix_status_t pubsubEndpoint_createFromListenerHookInfo(listener_hook_info_pt info,pubsub_endpoint_pt* psEp, bool isPublisher); +celix_status_t pubsubEndpoint_clone(pubsub_endpoint_pt in, pubsub_endpoint_pt *out); celix_status_t pubsubEndpoint_destroy(pubsub_endpoint_pt psEp); bool pubsubEndpoint_equals(pubsub_endpoint_pt psEp1,pubsub_endpoint_pt psEp2); diff --git a/pubsub/pubsub_common/public/include/pubsub_serializer.h b/pubsub/pubsub_common/public/include/pubsub_serializer.h index e9f9f6c6b..4489fa4d4 100644 --- a/pubsub/pubsub_common/public/include/pubsub_serializer.h +++ b/pubsub/pubsub_common/public/include/pubsub_serializer.h @@ -28,9 +28,12 @@ #define PUBSUB_SERIALIZER_SERVICE_H_ #include "service_reference.h" +#include "hash_map.h" #include "pubsub_common.h" +#define PUBSUB_SERIALIZER_TYPE_KEY "pubsub_serializer.type" + /** * There should be a pubsub_serializer_t * per msg type (msg id) per bundle @@ -39,28 +42,24 @@ * a serializer_map per bundle. Potentially using * the extender pattern. */ + typedef struct pubsub_msg_serializer { - void* handle; - unsigned int msgId; - const char* msgName; - version_pt msgVersion; + void* handle; + unsigned int msgId; + const char* msgName; + version_pt msgVersion; - celix_status_t (*serialize)(void* handle, const void* input, char** out, size_t* outLen); - celix_status_t (*deserialize)(void* handle, const char* input, size_t inputLen, void** out); //note inputLen can be 0 if predefined size is not needed + celix_status_t (*serialize)(void* handle, const void* input, void** out, size_t* outLen); + celix_status_t (*deserialize)(void* handle, const void* input, size_t inputLen, void** out); //note inputLen can be 0 if predefined size is not needed + void (*freeMsg)(void* handle, void* msg); - void (*freeMsg)(void* handle, void* msg); } pubsub_msg_serializer_t; -typedef struct pubsub_msg_serializer_map { - bundle_pt bundle; - hash_map_pt serializers; //key = msg id (unsigned int), value = pubsub_serializer_t* -} pubsub_msg_serializer_map_t; - typedef struct pubsub_serializer_service { void* handle; - celix_status_t (*createSerializerMap)(void* handle, bundle_pt bundle, pubsub_msg_serializer_map_t** out); - celix_status_t (*destroySerializerMap)(void* handle, pubsub_msg_serializer_map_t* map); + celix_status_t (*createSerializerMap)(void* handle, bundle_pt bundle, hash_map_pt* serializerMap); + celix_status_t (*destroySerializerMap)(void* handle, hash_map_pt serializerMap); } pubsub_serializer_service_t; diff --git a/pubsub/pubsub_common/public/src/log_helper.c b/pubsub/pubsub_common/public/src/log_helper.c index dbd1cc3b7..7a633634e 100644 --- a/pubsub/pubsub_common/public/src/log_helper.c +++ b/pubsub/pubsub_common/public/src/log_helper.c @@ -149,6 +149,9 @@ celix_status_t logHelper_destroy(log_helper_pt* loghelper) { return status; } + + + celix_status_t logHelper_log(log_helper_pt loghelper, log_level_t level, char* message, ... ) { celix_status_t status = CELIX_SUCCESS; @@ -166,6 +169,7 @@ celix_status_t logHelper_log(log_helper_pt loghelper, log_level_t level, char* m int i = 0; for (; i < arrayList_size(loghelper->logServices); i++) { + log_service_pt logService = arrayList_get(loghelper->logServices, i); if (logService != NULL) { @@ -175,31 +179,31 @@ celix_status_t logHelper_log(log_helper_pt loghelper, log_level_t level, char* m } pthread_mutex_unlock(&loghelper->logListLock); + } - if (!logged && loghelper->stdOutFallback) { - char *levelStr = NULL; - - switch (level) { - case OSGI_LOGSERVICE_ERROR: - levelStr = "ERROR"; - break; - case OSGI_LOGSERVICE_WARNING: - levelStr = "WARNING"; - break; - case OSGI_LOGSERVICE_INFO: - levelStr = "INFO"; - break; - case OSGI_LOGSERVICE_DEBUG: - default: - levelStr = "DEBUG"; - break; - } - printf("%s: %s\n", levelStr, msg); - } - } + if (!logged && loghelper->stdOutFallback) { + char *levelStr = NULL; + + switch (level) { + case OSGI_LOGSERVICE_ERROR: + levelStr = "ERROR"; + break; + case OSGI_LOGSERVICE_WARNING: + levelStr = "WARNING"; + break; + case OSGI_LOGSERVICE_INFO: + levelStr = "INFO"; + break; + case OSGI_LOGSERVICE_DEBUG: + default: + levelStr = "DEBUG"; + break; + } + + printf("%s: %s\n", levelStr, msg); + } - va_end(listPointer); return status; } diff --git a/pubsub/pubsub_common/public/src/pubsub_admin_match.c b/pubsub/pubsub_common/public/src/pubsub_admin_match.c new file mode 100644 index 000000000..bb555b746 --- /dev/null +++ b/pubsub/pubsub_common/public/src/pubsub_admin_match.c @@ -0,0 +1,303 @@ +/* + * pubsub_admin_match.c + + * + * Created on: Sep 4, 2017 + * Author: dn234 + */ + +#include +#include "service_reference.h" + +#include "pubsub_admin.h" + +#include "pubsub_admin_match.h" + +#define KNOWN_PUBSUB_ADMIN_NUM 2 +#define KNOWN_SERIALIZER_NUM 2 + +static char* qos_sample_pubsub_admin_prio_list[KNOWN_PUBSUB_ADMIN_NUM] = {"udp_mc","zmq"}; +static char* qos_sample_serializer_prio_list[KNOWN_SERIALIZER_NUM] = {"json","void"}; + +static char* qos_control_pubsub_admin_prio_list[KNOWN_PUBSUB_ADMIN_NUM] = {"zmq","udp_mc"}; +static char* qos_control_serializer_prio_list[KNOWN_SERIALIZER_NUM] = {"json","void"}; + +static double qos_pubsub_admin_score[KNOWN_PUBSUB_ADMIN_NUM] = {100.0F,75.0F}; +static double qos_serializer_score[KNOWN_SERIALIZER_NUM] = {30.0F,20.0F}; + +static void get_serializer_type(service_reference_pt svcRef, char **serializerType); +static void manage_service_from_reference(service_reference_pt svcRef, void **svc, bool getService); + +celix_status_t pubsub_admin_match(properties_pt endpoint_props, const char *pubsub_admin_type, array_list_pt serializerList, double *score){ + + celix_status_t status = CELIX_SUCCESS; + double final_score = 0; + int i = 0, j = 0; + + const char *requested_admin_type = NULL; + const char *requested_serializer_type = NULL; + const char *requested_qos_type = NULL; + + if(endpoint_props!=NULL){ + requested_admin_type = properties_get(endpoint_props,PUBSUB_ADMIN_TYPE_KEY); + requested_serializer_type = properties_get(endpoint_props,PUBSUB_SERIALIZER_TYPE_KEY); + requested_qos_type = properties_get(endpoint_props,QOS_ATTRIBUTE_KEY); + } + + /* Analyze the pubsub_admin */ + if(requested_admin_type != NULL){ /* We got precise specification on the pubsub_admin we want */ + if(strncmp(requested_admin_type,pubsub_admin_type,strlen(pubsub_admin_type))==0){ //Full match + final_score += PUBSUB_ADMIN_FULL_MATCH_SCORE; + } + } + else if(requested_qos_type != NULL){ /* We got QoS specification that will determine the selected PSA */ + if(strncmp(requested_qos_type,QOS_TYPE_SAMPLE,strlen(QOS_TYPE_SAMPLE))==0){ + for(i=0;i = %f\n",pubsub_admin_type,serializer_type,final_score); + + return status; +} + +celix_status_t pubsub_admin_get_best_serializer(properties_pt endpoint_props, array_list_pt serializerList, pubsub_serializer_service_t **serSvc){ + celix_status_t status = CELIX_SUCCESS; + + int i = 0, j = 0; + + const char *requested_serializer_type = properties_get(endpoint_props,PUBSUB_SERIALIZER_TYPE_KEY); + const char *requested_qos_type = properties_get(endpoint_props,QOS_ATTRIBUTE_KEY); + + service_reference_pt svcRef = NULL; + void *svc = NULL; + + /* Analyze the serializers */ + if(requested_serializer_type != NULL){ /* We got precise specification on the serializer we want */ + for(i=0;iframeworkUUID = strdup(fwUUID); - } +static void pubsubEndpoint_setFields(pubsub_endpoint_pt psEp, const char* fwUUID, const char* scope, const char* topic, long serviceId,const char* endpoint,properties_pt topic_props, bool cloneProps); +static properties_pt pubsubEndpoint_getTopicProperties(bundle_pt bundle, const char *topic, bool isPublisher); - if (scope != NULL) { - psEp->scope = strdup(scope); - } +static void pubsubEndpoint_setFields(pubsub_endpoint_pt psEp, const char* fwUUID, const char* scope, const char* topic, long serviceId,const char* endpoint,properties_pt topic_props, bool cloneProps){ - if (topic != NULL) { - psEp->topic = strdup(topic); - } + if (fwUUID != NULL) { + psEp->frameworkUUID = strdup(fwUUID); + } + + if (scope != NULL) { + psEp->scope = strdup(scope); + } + + if (topic != NULL) { + psEp->topic = strdup(topic); + } + + psEp->serviceID = serviceId; + + if(endpoint != NULL) { + psEp->endpoint = strdup(endpoint); + } + + if(topic_props != NULL){ + if(cloneProps){ + properties_copy(topic_props, &(psEp->topic_props)); + } + else{ + psEp->topic_props = topic_props; + } + } +} + +static properties_pt pubsubEndpoint_getTopicProperties(bundle_pt bundle, const char *topic, bool isPublisher){ + + properties_pt topic_props = NULL; + + bool isSystemBundle = false; + bundle_isSystemBundle(bundle, &isSystemBundle); + long bundleId = -1; + bundle_isSystemBundle(bundle, &isSystemBundle); + bundle_getBundleId(bundle,&bundleId); + + if(isSystemBundle == false) { - psEp->serviceID = serviceId; + char *bundleRoot = NULL; + char* topicPropertiesPath = NULL; + bundle_getEntry(bundle, ".", &bundleRoot); - if (endpoint != NULL) { - psEp->endpoint = strdup(endpoint); - } + if(bundleRoot != NULL){ - *out = psEp; + asprintf(&topicPropertiesPath, "%s/META-INF/topics/%s/%s.properties", bundleRoot, isPublisher?"pub":"sub", topic); + topic_props = properties_load(topicPropertiesPath); + if(topic_props==NULL){ + printf("PSEP: Could not load properties for %s on topic %s, bundleId=%ld\n", isPublisher?"publication":"subscription", topic,bundleId); + } - return status; + free(topicPropertiesPath); + free(bundleRoot); + } + } + + return topic_props; +} + +celix_status_t pubsubEndpoint_create(const char* fwUUID, const char* scope, const char* topic, long serviceId,const char* endpoint,properties_pt topic_props,pubsub_endpoint_pt* psEp){ + celix_status_t status = CELIX_SUCCESS; + + *psEp = calloc(1, sizeof(**psEp)); + + pubsubEndpoint_setFields(*psEp, fwUUID, scope, topic, serviceId, endpoint, topic_props, true); + + return status; } -celix_status_t pubsubEndpoint_createFromServiceReference(service_reference_pt reference, pubsub_endpoint_pt* out){ +celix_status_t pubsubEndpoint_clone(pubsub_endpoint_pt in, pubsub_endpoint_pt *out){ celix_status_t status = CELIX_SUCCESS; - pubsub_endpoint_pt psEp = calloc(1,sizeof(*psEp)); + *out = calloc(1,sizeof(**out)); + + pubsubEndpoint_setFields(*out, in->frameworkUUID, in->scope, in->topic, in->serviceID, in->endpoint, in->topic_props, true); + + return status; + +} + +celix_status_t pubsubEndpoint_createFromServiceReference(service_reference_pt reference, pubsub_endpoint_pt* psEp, bool isPublisher){ + celix_status_t status = CELIX_SUCCESS; + + *psEp = calloc(1,sizeof(**psEp)); bundle_pt bundle = NULL; bundle_context_pt ctxt = NULL; @@ -85,49 +145,86 @@ celix_status_t pubsubEndpoint_createFromServiceReference(service_reference_pt re const char* serviceId = NULL; serviceReference_getProperty(reference,(char*)OSGI_FRAMEWORK_SERVICE_ID,&serviceId); - if(fwUUID!=NULL){ - psEp->frameworkUUID = strdup(fwUUID); - } + /* TODO: is topic_props==NULL a fatal error such that EP cannot be created? */ + properties_pt topic_props = pubsubEndpoint_getTopicProperties(bundle, topic, isPublisher); - if(scope!=NULL){ - psEp->scope = strdup(scope); - } else { - psEp->scope = strdup(PUBSUB_SUBSCRIBER_SCOPE_DEFAULT); - } + pubsubEndpoint_setFields(*psEp, fwUUID, scope!=NULL?scope:PUBSUB_SUBSCRIBER_SCOPE_DEFAULT, topic, strtol(serviceId,NULL,10), NULL, topic_props, false); - if(topic!=NULL){ - psEp->topic = strdup(topic); + if (!(*psEp)->frameworkUUID || !(*psEp)->serviceID || !(*psEp)->scope || !(*psEp)->topic) { + fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "PUBSUB_ENDPOINT: incomplete description!."); + status = CELIX_BUNDLE_EXCEPTION; } - if(serviceId!=NULL){ - psEp->serviceID = strtol(serviceId,NULL,10); - } + return status; - if (!psEp->frameworkUUID || !psEp->serviceID || !psEp->scope || !psEp->topic) { - fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "PUBSUB_ENDPOINT: incomplete description!."); - status = CELIX_BUNDLE_EXCEPTION; +} + +celix_status_t pubsubEndpoint_createFromListenerHookInfo(listener_hook_info_pt info,pubsub_endpoint_pt* psEp, bool isPublisher){ + celix_status_t status = CELIX_SUCCESS; + + const char* fwUUID=NULL; + bundleContext_getProperty(info->context,OSGI_FRAMEWORK_FRAMEWORK_UUID,&fwUUID); + + char* topic = pubsub_getTopicFromFilter(info->filter); + if(topic==NULL || fwUUID==NULL){ + return CELIX_BUNDLE_EXCEPTION; } - if (status != CELIX_SUCCESS) { - pubsubEndpoint_destroy(psEp); - } else { - *out = psEp; + *psEp = calloc(1, sizeof(**psEp)); + + char* scope = pubsub_getScopeFromFilter(info->filter); + if(scope == NULL) { + scope = strdup(PUBSUB_PUBLISHER_SCOPE_DEFAULT); } - return status; + bundle_pt bundle = NULL; + long bundleId = -1; + bundleContext_getBundle(info->context,&bundle); + bundle_getBundleId(bundle,&bundleId); + + properties_pt topic_props = pubsubEndpoint_getTopicProperties(bundle, topic, isPublisher); + + /* TODO: is topic_props==NULL a fatal error such that EP cannot be created? */ + pubsubEndpoint_setFields(*psEp, fwUUID, scope!=NULL?scope:PUBSUB_SUBSCRIBER_SCOPE_DEFAULT, topic, bundleId, NULL, topic_props, false); + + free(topic); + free(scope); + + + return status; } celix_status_t pubsubEndpoint_destroy(pubsub_endpoint_pt psEp){ - if (psEp != NULL) { + + if(psEp->frameworkUUID!=NULL){ free(psEp->frameworkUUID); + psEp->frameworkUUID = NULL; + } + + if(psEp->scope!=NULL){ free(psEp->scope); + psEp->scope = NULL; + } + + if(psEp->topic!=NULL){ free(psEp->topic); + psEp->topic = NULL; + } + + if(psEp->endpoint!=NULL){ free(psEp->endpoint); + psEp->endpoint = NULL; } + + if(psEp->topic_props != NULL){ + properties_destroy(psEp->topic_props); + } + free(psEp); return CELIX_SUCCESS; + } bool pubsubEndpoint_equals(pubsub_endpoint_pt psEp1,pubsub_endpoint_pt psEp2){ @@ -138,7 +235,6 @@ bool pubsubEndpoint_equals(pubsub_endpoint_pt psEp1,pubsub_endpoint_pt psEp2){ (psEp1->serviceID == psEp2->serviceID) /*&& ((psEp1->endpoint==NULL && psEp2->endpoint==NULL)||(strcmp(psEp1->endpoint,psEp2->endpoint)==0))*/ ); - } char *createScopeTopicKey(const char* scope, const char* topic) { diff --git a/pubsub/pubsub_discovery/private/include/pubsub_discovery_impl.h b/pubsub/pubsub_discovery/private/include/pubsub_discovery_impl.h index d5be8d61f..676a6ab53 100644 --- a/pubsub/pubsub_discovery/private/include/pubsub_discovery_impl.h +++ b/pubsub/pubsub_discovery/private/include/pubsub_discovery_impl.h @@ -58,7 +58,6 @@ celix_status_t pubsub_discovery_stop(pubsub_discovery_pt node_discovery); celix_status_t pubsub_discovery_addNode(pubsub_discovery_pt node_discovery, pubsub_endpoint_pt pubEP); celix_status_t pubsub_discovery_removeNode(pubsub_discovery_pt node_discovery, pubsub_endpoint_pt pubEP); -celix_status_t pubsub_discovery_tmPublisherAnnounceAdding(void * handle, service_reference_pt reference, void **service); celix_status_t pubsub_discovery_tmPublisherAnnounceAdded(void * handle, service_reference_pt reference, void * service); celix_status_t pubsub_discovery_tmPublisherAnnounceModified(void * handle, service_reference_pt reference, void * service); celix_status_t pubsub_discovery_tmPublisherAnnounceRemoved(void * handle, service_reference_pt reference, void * service); diff --git a/pubsub/pubsub_discovery/private/src/etcd_common.c b/pubsub/pubsub_discovery/private/src/etcd_common.c index a53a8441c..c757801a2 100644 --- a/pubsub/pubsub_discovery/private/src/etcd_common.c +++ b/pubsub/pubsub_discovery/private/src/etcd_common.c @@ -32,6 +32,7 @@ #include "pubsub_discovery.h" #include "pubsub_discovery_impl.h" + #define MAX_ROOTNODE_LENGTH 128 #define MAX_LOCALNODE_LENGTH 4096 #define MAX_FIELD_LENGTH 128 diff --git a/pubsub/pubsub_discovery/private/src/etcd_watcher.c b/pubsub/pubsub_discovery/private/src/etcd_watcher.c index 13ba3aaaa..3c3a5a85f 100644 --- a/pubsub/pubsub_discovery/private/src/etcd_watcher.c +++ b/pubsub/pubsub_discovery/private/src/etcd_watcher.c @@ -57,17 +57,17 @@ struct etcd_watcher { celix_thread_mutex_t watcherLock; celix_thread_t watcherThread; - char *scope; + char *scope; char *topic; volatile bool running; }; struct etcd_writer { - pubsub_discovery_pt pubsub_discovery; - celix_thread_mutex_t localPubsLock; - array_list_pt localPubs; - volatile bool running; - celix_thread_t writerThread; + pubsub_discovery_pt pubsub_discovery; + celix_thread_mutex_t localPubsLock; + array_list_pt localPubs; + volatile bool running; + celix_thread_t writerThread; }; @@ -77,41 +77,41 @@ static celix_status_t etcdWatcher_getTopicRootPath(bundle_context_pt context, co const char* rootPath = NULL; if (((bundleContext_getProperty(context, CFG_ETCD_ROOT_PATH, &rootPath)) != CELIX_SUCCESS) || (!rootPath)) { - snprintf(rootNode, rootNodeLen, "%s/%s/%s", DEFAULT_ETCD_ROOTPATH, scope, topic); + snprintf(rootNode, rootNodeLen, "%s/%s/%s", DEFAULT_ETCD_ROOTPATH, scope, topic); } else { - snprintf(rootNode, rootNodeLen, "%s/%s/%s", rootPath, scope, topic); + snprintf(rootNode, rootNodeLen, "%s/%s/%s", rootPath, scope, topic); } return status; } static celix_status_t etcdWatcher_getRootPath(bundle_context_pt context, char* rootNode) { - celix_status_t status = CELIX_SUCCESS; - const char* rootPath = NULL; + celix_status_t status = CELIX_SUCCESS; + const char* rootPath = NULL; - if (((bundleContext_getProperty(context, CFG_ETCD_ROOT_PATH, &rootPath)) != CELIX_SUCCESS) || (!rootPath)) { - strncpy(rootNode, DEFAULT_ETCD_ROOTPATH, MAX_ROOTNODE_LENGTH); - } else { - strncpy(rootNode, rootPath, MAX_ROOTNODE_LENGTH); - } + if (((bundleContext_getProperty(context, CFG_ETCD_ROOT_PATH, &rootPath)) != CELIX_SUCCESS) || (!rootPath)) { + strncpy(rootNode, DEFAULT_ETCD_ROOTPATH, MAX_ROOTNODE_LENGTH); + } else { + strncpy(rootNode, rootPath, MAX_ROOTNODE_LENGTH); + } - return status; + return status; } static void add_node(const char *key, const char *value, void* arg) { - pubsub_discovery_pt ps_discovery = (pubsub_discovery_pt) arg; - pubsub_endpoint_pt pubEP = NULL; - celix_status_t status = etcdWatcher_getPublisherEndpointFromKey(ps_discovery, key, value, &pubEP); - if(!status && pubEP) { - pubsub_discovery_addNode(ps_discovery, pubEP); - } + pubsub_discovery_pt ps_discovery = (pubsub_discovery_pt) arg; + pubsub_endpoint_pt pubEP = NULL; + celix_status_t status = etcdWatcher_getPublisherEndpointFromKey(ps_discovery, key, value, &pubEP); + if(!status && pubEP) { + pubsub_discovery_addNode(ps_discovery, pubEP); + } } static celix_status_t etcdWatcher_addAlreadyExistingPublishers(pubsub_discovery_pt ps_discovery, const char *rootPath, long long * highestModified) { celix_status_t status = CELIX_SUCCESS; if(etcd_get_directory(rootPath, add_node, ps_discovery, highestModified)) { - status = CELIX_ILLEGAL_ARGUMENT; + status = CELIX_ILLEGAL_ARGUMENT; } return status; } @@ -137,14 +137,14 @@ celix_status_t etcdWatcher_getPublisherEndpointFromKey(pubsub_discovery_pt pubsu asprintf(&expr, "/%s/%%[^/]/%%[^/]/%%[^/]/%%[^/].*", rootPath); if(expr) { - int foundItems = sscanf(etcdKey, expr, scope, topic, fwUUID, serviceId); - free(expr); - if (foundItems != 4) { // Could happen when a directory is removed, just don't process this. - status = CELIX_ILLEGAL_STATE; - } - else{ - status = pubsubEndpoint_create(fwUUID,scope,topic,strtol(serviceId,NULL,10),etcdValue,pubEP); - } + int foundItems = sscanf(etcdKey, expr, scope, topic, fwUUID, serviceId); + free(expr); + if (foundItems != 4) { // Could happen when a directory is removed, just don't process this. + status = CELIX_ILLEGAL_STATE; + } + else{ + status = pubsubEndpoint_create(fwUUID,scope,topic,strtol(serviceId,NULL,10),etcdValue,NULL,pubEP); + } } return status; } @@ -154,75 +154,75 @@ celix_status_t etcdWatcher_getPublisherEndpointFromKey(pubsub_discovery_pt pubsu * changing discovery endpoint information within etcd. */ static void* etcdWatcher_run(void* data) { - etcd_watcher_pt watcher = (etcd_watcher_pt) data; - time_t timeBeforeWatch = time(NULL); - char rootPath[MAX_ROOTNODE_LENGTH]; - long long highestModified = 0; - - pubsub_discovery_pt ps_discovery = watcher->pubsub_discovery; - bundle_context_pt context = ps_discovery->context; - - memset(rootPath, 0, MAX_ROOTNODE_LENGTH); - - //TODO: add topic to etcd key - etcdWatcher_getTopicRootPath(context, watcher->scope, watcher->topic, rootPath, MAX_ROOTNODE_LENGTH); - etcdWatcher_addAlreadyExistingPublishers(ps_discovery, rootPath, &highestModified); - - while ((celixThreadMutex_lock(&watcher->watcherLock) == CELIX_SUCCESS) && watcher->running) { - - char *rkey = NULL; - char *value = NULL; - char *preValue = NULL; - char *action = NULL; - long long modIndex; - - celixThreadMutex_unlock(&watcher->watcherLock); - - if (etcd_watch(rootPath, highestModified + 1, &action, &preValue, &value, &rkey, &modIndex) == 0 && action != NULL) { - pubsub_endpoint_pt pubEP = NULL; - if ((strcmp(action, "set") == 0) || (strcmp(action, "create") == 0)) { - if (etcdWatcher_getPublisherEndpointFromKey(ps_discovery, rkey, value, &pubEP) == CELIX_SUCCESS) { - pubsub_discovery_addNode(ps_discovery, pubEP); - } - } else if (strcmp(action, "delete") == 0) { - if (etcdWatcher_getPublisherEndpointFromKey(ps_discovery, rkey, preValue, &pubEP) == CELIX_SUCCESS) { - pubsub_discovery_removeNode(ps_discovery, pubEP); - } - } else if (strcmp(action, "expire") == 0) { - if (etcdWatcher_getPublisherEndpointFromKey(ps_discovery, rkey, preValue, &pubEP) == CELIX_SUCCESS) { - pubsub_discovery_removeNode(ps_discovery, pubEP); - } - } else if (strcmp(action, "update") == 0) { - if (etcdWatcher_getPublisherEndpointFromKey(ps_discovery, rkey, value, &pubEP) == CELIX_SUCCESS) { - pubsub_discovery_addNode(ps_discovery, pubEP); - } - } else { - fw_log(logger, OSGI_FRAMEWORK_LOG_INFO, "Unexpected action: %s", action); - } - highestModified = modIndex; - } else if (time(NULL) - timeBeforeWatch <= (DEFAULT_ETCD_TTL / 4)) { - sleep(DEFAULT_ETCD_TTL / 4); - } - - FREE_MEM(action); - FREE_MEM(value); - FREE_MEM(preValue); - FREE_MEM(rkey); - - /* prevent busy waiting, in case etcd_watch returns false */ - - - if (time(NULL) - timeBeforeWatch > (DEFAULT_ETCD_TTL / 4)) { - timeBeforeWatch = time(NULL); - } - - } - - if (watcher->running == false) { - celixThreadMutex_unlock(&watcher->watcherLock); - } - - return NULL; + etcd_watcher_pt watcher = (etcd_watcher_pt) data; + time_t timeBeforeWatch = time(NULL); + char rootPath[MAX_ROOTNODE_LENGTH]; + long long highestModified = 0; + + pubsub_discovery_pt ps_discovery = watcher->pubsub_discovery; + bundle_context_pt context = ps_discovery->context; + + memset(rootPath, 0, MAX_ROOTNODE_LENGTH); + + //TODO: add topic to etcd key + etcdWatcher_getTopicRootPath(context, watcher->scope, watcher->topic, rootPath, MAX_ROOTNODE_LENGTH); + etcdWatcher_addAlreadyExistingPublishers(ps_discovery, rootPath, &highestModified); + + while ((celixThreadMutex_lock(&watcher->watcherLock) == CELIX_SUCCESS) && watcher->running) { + + char *rkey = NULL; + char *value = NULL; + char *preValue = NULL; + char *action = NULL; + long long modIndex; + + celixThreadMutex_unlock(&watcher->watcherLock); + + if (etcd_watch(rootPath, highestModified + 1, &action, &preValue, &value, &rkey, &modIndex) == 0 && action != NULL) { + pubsub_endpoint_pt pubEP = NULL; + if ((strcmp(action, "set") == 0) || (strcmp(action, "create") == 0)) { + if (etcdWatcher_getPublisherEndpointFromKey(ps_discovery, rkey, value, &pubEP) == CELIX_SUCCESS) { + pubsub_discovery_addNode(ps_discovery, pubEP); + } + } else if (strcmp(action, "delete") == 0) { + if (etcdWatcher_getPublisherEndpointFromKey(ps_discovery, rkey, preValue, &pubEP) == CELIX_SUCCESS) { + pubsub_discovery_removeNode(ps_discovery, pubEP); + } + } else if (strcmp(action, "expire") == 0) { + if (etcdWatcher_getPublisherEndpointFromKey(ps_discovery, rkey, preValue, &pubEP) == CELIX_SUCCESS) { + pubsub_discovery_removeNode(ps_discovery, pubEP); + } + } else if (strcmp(action, "update") == 0) { + if (etcdWatcher_getPublisherEndpointFromKey(ps_discovery, rkey, value, &pubEP) == CELIX_SUCCESS) { + pubsub_discovery_addNode(ps_discovery, pubEP); + } + } else { + fw_log(logger, OSGI_FRAMEWORK_LOG_INFO, "Unexpected action: %s", action); + } + highestModified = modIndex; + } else if (time(NULL) - timeBeforeWatch <= (DEFAULT_ETCD_TTL / 4)) { + sleep(DEFAULT_ETCD_TTL / 4); + } + + FREE_MEM(action); + FREE_MEM(value); + FREE_MEM(preValue); + FREE_MEM(rkey); + + /* prevent busy waiting, in case etcd_watch returns false */ + + + if (time(NULL) - timeBeforeWatch > (DEFAULT_ETCD_TTL / 4)) { + timeBeforeWatch = time(NULL); + } + + } + + if (watcher->running == false) { + celixThreadMutex_unlock(&watcher->watcherLock); + } + + return NULL; } celix_status_t etcdWatcher_create(pubsub_discovery_pt pubsub_discovery, bundle_context_pt context, const char *scope, const char *topic, etcd_watcher_pt *watcher) { @@ -243,16 +243,18 @@ celix_status_t etcdWatcher_create(pubsub_discovery_pt pubsub_discovery, bundle_c (*watcher)->scope = strdup(scope); (*watcher)->topic = strdup(topic); - celixThreadMutex_create(&(*watcher)->watcherLock, NULL); - celixThreadMutex_lock(&(*watcher)->watcherLock); + celixThreadMutex_create(&(*watcher)->watcherLock, NULL); + + celixThreadMutex_lock(&(*watcher)->watcherLock); + + status = celixThread_create(&(*watcher)->watcherThread, NULL, etcdWatcher_run, *watcher); + if (status == CELIX_SUCCESS) { + (*watcher)->running = true; + } - status = celixThread_create(&(*watcher)->watcherThread, NULL, etcdWatcher_run, *watcher); - if (status == CELIX_SUCCESS) { - (*watcher)->running = true; - } + celixThreadMutex_unlock(&(*watcher)->watcherLock); - celixThreadMutex_unlock(&(*watcher)->watcherLock); return status; } diff --git a/pubsub/pubsub_discovery/private/src/etcd_writer.c b/pubsub/pubsub_discovery/private/src/etcd_writer.c index 687d8027f..1c423f3b8 100644 --- a/pubsub/pubsub_discovery/private/src/etcd_writer.c +++ b/pubsub/pubsub_discovery/private/src/etcd_writer.c @@ -47,11 +47,11 @@ #define DEFAULT_ETCD_TTL 30 struct etcd_writer { - pubsub_discovery_pt pubsub_discovery; - celix_thread_mutex_t localPubsLock; - array_list_pt localPubs; - volatile bool running; - celix_thread_t writerThread; + pubsub_discovery_pt pubsub_discovery; + celix_thread_mutex_t localPubsLock; + array_list_pt localPubs; + volatile bool running; + celix_thread_t writerThread; }; @@ -60,38 +60,38 @@ static void* etcdWriter_run(void* data); etcd_writer_pt etcdWriter_create(pubsub_discovery_pt disc) { - etcd_writer_pt writer = calloc(1, sizeof(*writer)); - if(writer) { - celixThreadMutex_create(&writer->localPubsLock, NULL); - arrayList_create(&writer->localPubs); - writer->pubsub_discovery = disc; - writer->running = true; - celixThread_create(&writer->writerThread, NULL, etcdWriter_run, writer); - } - return writer; + etcd_writer_pt writer = calloc(1, sizeof(*writer)); + if(writer) { + celixThreadMutex_create(&writer->localPubsLock, NULL); + arrayList_create(&writer->localPubs); + writer->pubsub_discovery = disc; + writer->running = true; + celixThread_create(&writer->writerThread, NULL, etcdWriter_run, writer); + } + return writer; } void etcdWriter_destroy(etcd_writer_pt writer) { - char dir[MAX_ROOTNODE_LENGTH]; - const char *rootPath = etcdWriter_getRootPath(writer->pubsub_discovery->context); - - writer->running = false; - celixThread_join(writer->writerThread, NULL); - - celixThreadMutex_lock(&writer->localPubsLock); - for(int i = 0; i < arrayList_size(writer->localPubs); i++) { - pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(writer->localPubs,i); - memset(dir,0,MAX_ROOTNODE_LENGTH); - snprintf(dir,MAX_ROOTNODE_LENGTH,"%s/%s/%s/%s",rootPath,pubEP->scope,pubEP->topic,pubEP->frameworkUUID); - etcd_del(dir); - pubsubEndpoint_destroy(pubEP); - } - arrayList_destroy(writer->localPubs); - - celixThreadMutex_unlock(&writer->localPubsLock); - celixThreadMutex_destroy(&(writer->localPubsLock)); - - free(writer); + char dir[MAX_ROOTNODE_LENGTH]; + const char *rootPath = etcdWriter_getRootPath(writer->pubsub_discovery->context); + + writer->running = false; + celixThread_join(writer->writerThread, NULL); + + celixThreadMutex_lock(&writer->localPubsLock); + for(int i = 0; i < arrayList_size(writer->localPubs); i++) { + pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(writer->localPubs,i); + memset(dir,0,MAX_ROOTNODE_LENGTH); + snprintf(dir,MAX_ROOTNODE_LENGTH,"%s/%s/%s/%s",rootPath,pubEP->scope,pubEP->topic,pubEP->frameworkUUID); + etcd_del(dir); + pubsubEndpoint_destroy(pubEP); + } + arrayList_destroy(writer->localPubs); + + celixThreadMutex_unlock(&writer->localPubsLock); + celixThreadMutex_destroy(&(writer->localPubsLock)); + + free(writer); } celix_status_t etcdWriter_addPublisherEndpoint(etcd_writer_pt writer, pubsub_endpoint_pt pubEP, bool storeEP){ @@ -101,11 +101,11 @@ celix_status_t etcdWriter_addPublisherEndpoint(etcd_writer_pt writer, pubsub_end const char *fwUUID = NULL; bundleContext_getProperty(writer->pubsub_discovery->context, OSGI_FRAMEWORK_FRAMEWORK_UUID, &fwUUID); if(fwUUID && strcmp(pubEP->frameworkUUID, fwUUID) == 0) { - celixThreadMutex_lock(&writer->localPubsLock); - pubsub_endpoint_pt p = NULL; - pubsubEndpoint_create(pubEP->frameworkUUID,pubEP->scope,pubEP->topic,pubEP->serviceID,pubEP->endpoint,&p); - arrayList_add(writer->localPubs,p); - celixThreadMutex_unlock(&writer->localPubsLock); + celixThreadMutex_lock(&writer->localPubsLock); + pubsub_endpoint_pt p = NULL; + pubsubEndpoint_clone(pubEP, &p); + arrayList_add(writer->localPubs,p); + celixThreadMutex_unlock(&writer->localPubsLock); } } @@ -138,52 +138,52 @@ celix_status_t etcdWriter_addPublisherEndpoint(etcd_writer_pt writer, pubsub_end } celix_status_t etcdWriter_deletePublisherEndpoint(etcd_writer_pt writer, pubsub_endpoint_pt pubEP) { - celix_status_t status = CELIX_SUCCESS; - char *key = NULL; - - const char *rootPath = etcdWriter_getRootPath(writer->pubsub_discovery->context); - - asprintf(&key, "%s/%s/%s/%s/%ld", rootPath, pubEP->scope, pubEP->topic, pubEP->frameworkUUID, pubEP->serviceID); - - celixThreadMutex_lock(&writer->localPubsLock); - for (unsigned int i = 0; i < arrayList_size(writer->localPubs); i++) { - pubsub_endpoint_pt ep = arrayList_get(writer->localPubs, i); - if (pubsubEndpoint_equals(ep, pubEP)) { - arrayList_remove(writer->localPubs, i); - pubsubEndpoint_destroy(ep); - break; - } - } - celixThreadMutex_unlock(&writer->localPubsLock); - - if (etcd_del(key)) { - printf("Failed to remove key %s from ETCD\n",key); - status = CELIX_ILLEGAL_ARGUMENT; - } - FREE_MEM(key); - return status; + celix_status_t status = CELIX_SUCCESS; + char *key = NULL; + + const char *rootPath = etcdWriter_getRootPath(writer->pubsub_discovery->context); + + asprintf(&key, "%s/%s/%s/%s/%ld", rootPath, pubEP->scope, pubEP->topic, pubEP->frameworkUUID, pubEP->serviceID); + + celixThreadMutex_lock(&writer->localPubsLock); + for (unsigned int i = 0; i < arrayList_size(writer->localPubs); i++) { + pubsub_endpoint_pt ep = arrayList_get(writer->localPubs, i); + if (pubsubEndpoint_equals(ep, pubEP)) { + arrayList_remove(writer->localPubs, i); + pubsubEndpoint_destroy(ep); + break; + } + } + celixThreadMutex_unlock(&writer->localPubsLock); + + if (etcd_del(key)) { + printf("Failed to remove key %s from ETCD\n",key); + status = CELIX_ILLEGAL_ARGUMENT; + } + FREE_MEM(key); + return status; } static void* etcdWriter_run(void* data) { - etcd_writer_pt writer = (etcd_writer_pt)data; - while(writer->running) { - celixThreadMutex_lock(&writer->localPubsLock); - for(int i=0; i < arrayList_size(writer->localPubs); i++) { - etcdWriter_addPublisherEndpoint(writer,(pubsub_endpoint_pt)arrayList_get(writer->localPubs,i),false); - } - celixThreadMutex_unlock(&writer->localPubsLock); - sleep(DEFAULT_ETCD_TTL / 2); - } - - return NULL; + etcd_writer_pt writer = (etcd_writer_pt)data; + while(writer->running) { + celixThreadMutex_lock(&writer->localPubsLock); + for(int i=0; i < arrayList_size(writer->localPubs); i++) { + etcdWriter_addPublisherEndpoint(writer,(pubsub_endpoint_pt)arrayList_get(writer->localPubs,i),false); + } + celixThreadMutex_unlock(&writer->localPubsLock); + sleep(DEFAULT_ETCD_TTL / 2); + } + + return NULL; } static const char* etcdWriter_getRootPath(bundle_context_pt context) { - const char* rootPath = NULL; - bundleContext_getProperty(context, CFG_ETCD_ROOT_PATH, &rootPath); - if(rootPath == NULL) { - rootPath = DEFAULT_ETCD_ROOTPATH; - } - return rootPath; + const char* rootPath = NULL; + bundleContext_getProperty(context, CFG_ETCD_ROOT_PATH, &rootPath); + if(rootPath == NULL) { + rootPath = DEFAULT_ETCD_ROOTPATH; + } + return rootPath; } diff --git a/pubsub/pubsub_discovery/private/src/psd_activator.c b/pubsub/pubsub_discovery/private/src/psd_activator.c index afbe28256..89a517d55 100644 --- a/pubsub/pubsub_discovery/private/src/psd_activator.c +++ b/pubsub/pubsub_discovery/private/src/psd_activator.c @@ -48,7 +48,7 @@ static celix_status_t createTMPublisherAnnounceTracker(struct activator *activat service_tracker_customizer_pt customizer = NULL; status = serviceTrackerCustomizer_create(activator->pubsub_discovery, - pubsub_discovery_tmPublisherAnnounceAdding, + NULL, pubsub_discovery_tmPublisherAnnounceAdded, pubsub_discovery_tmPublisherAnnounceModified, pubsub_discovery_tmPublisherAnnounceRemoved, diff --git a/pubsub/pubsub_discovery/private/src/pubsub_discovery_impl.c b/pubsub/pubsub_discovery/private/src/pubsub_discovery_impl.c index 0c7d6c4f2..94a8e11d6 100644 --- a/pubsub/pubsub_discovery/private/src/pubsub_discovery_impl.c +++ b/pubsub/pubsub_discovery/private/src/pubsub_discovery_impl.c @@ -167,7 +167,6 @@ celix_status_t pubsub_discovery_stop(pubsub_discovery_pt ps_discovery) { hashMapIterator_destroy(iter); hashMap_destroy(ps_discovery->watchers, true, true); celixThreadMutex_unlock(&ps_discovery->watchersMutex); - return status; } @@ -293,7 +292,7 @@ celix_status_t pubsub_discovery_announcePublisher(void *handle, pubsub_endpoint_ } free(pub_key); pubsub_endpoint_pt p = NULL; - pubsubEndpoint_create(pubEP->frameworkUUID,pubEP->scope,pubEP->topic,pubEP->serviceID,pubEP->endpoint,&p); + pubsubEndpoint_clone(pubEP, &p); arrayList_add(pubEP_list,p); @@ -397,16 +396,6 @@ celix_status_t pubsub_discovery_uninterestedInTopic(void *handle, const char* sc /* pubsub_topology_manager tracker callbacks */ -celix_status_t pubsub_discovery_tmPublisherAnnounceAdding(void * handle, service_reference_pt reference, void **service) { - celix_status_t status = CELIX_SUCCESS; - - pubsub_discovery_pt pubsub_discovery = (pubsub_discovery_pt)handle; - - status = bundleContext_getService(pubsub_discovery->context, reference, service); - - return status; -} - celix_status_t pubsub_discovery_tmPublisherAnnounceAdded(void * handle, service_reference_pt reference, void * service) { celix_status_t status = CELIX_SUCCESS; diff --git a/pubsub/pubsub_serializer_json/private/include/pubsub_serializer_impl.h b/pubsub/pubsub_serializer_json/private/include/pubsub_serializer_impl.h index 5299808cc..c36f20e18 100644 --- a/pubsub/pubsub_serializer_json/private/include/pubsub_serializer_impl.h +++ b/pubsub/pubsub_serializer_json/private/include/pubsub_serializer_impl.h @@ -24,8 +24,8 @@ * \copyright Apache License, Version 2.0 */ -#ifndef PUBSUB_SERIALIZER_IMPL_H_ -#define PUBSUB_SERIALIZER_IMPL_H_ +#ifndef PUBSUB_SERIALIZER_JSON_H_ +#define PUBSUB_SERIALIZER_JSON_H_ #include "dyn_common.h" #include "dyn_type.h" @@ -34,25 +34,22 @@ #include "pubsub_serializer.h" +#define PUBSUB_SERIALIZER_TYPE "json" + typedef struct pubsub_serializer { bundle_context_pt bundle_context; log_helper_pt loghelper; } pubsub_serializer_t; -typedef struct pubsub_msg_serializer_impl { - pubsub_msg_serializer_t msgSerializer; - dyn_message_type* dynMsg; -} pubsub_msg_serializer_impl_t; - celix_status_t pubsubSerializer_create(bundle_context_pt context, pubsub_serializer_t* *serializer); celix_status_t pubsubSerializer_destroy(pubsub_serializer_t* serializer); -celix_status_t pubsubSerializer_createSerializerMap(pubsub_serializer_t* serializer, bundle_pt bundle, pubsub_msg_serializer_map_t** out); -celix_status_t pubsubSerializer_destroySerializerMap(pubsub_serializer_t*, pubsub_msg_serializer_map_t* map); +celix_status_t pubsubSerializer_createSerializerMap(pubsub_serializer_t* serializer, bundle_pt bundle, hash_map_pt* serializerMap); +celix_status_t pubsubSerializer_destroySerializerMap(pubsub_serializer_t*, hash_map_pt serializerMap); /* Start of serializer specific functions */ -celix_status_t pubsubMsgSerializer_serialize(pubsub_msg_serializer_impl_t* impl, const void* msg, char** out, size_t *outLen); -celix_status_t pubsubMsgSerializer_deserialize(pubsub_msg_serializer_impl_t* impl, const char* input, size_t inputLen, void **out); -void pubsubMsgSerializer_freeMsg(pubsub_msg_serializer_impl_t* impl, void *msg); +celix_status_t pubsubMsgSerializer_serialize(pubsub_msg_serializer_t* msgSerializer, const void* msg, void** out, size_t *outLen); +celix_status_t pubsubMsgSerializer_deserialize(pubsub_msg_serializer_t* msgSerializer, const void* input, size_t inputLen, void **out); +void pubsubMsgSerializer_freeMsg(pubsub_msg_serializer_t* msgSerializer, void *msg); -#endif /* PUBSUB_SERIALIZER_IMPL_H_ */ +#endif /* PUBSUB_SERIALIZER_JSON_H_ */ diff --git a/pubsub/pubsub_serializer_json/private/src/ps_activator.c b/pubsub/pubsub_serializer_json/private/src/ps_activator.c index e0e23d49e..fec58927e 100644 --- a/pubsub/pubsub_serializer_json/private/src/ps_activator.c +++ b/pubsub/pubsub_serializer_json/private/src/ps_activator.c @@ -68,7 +68,11 @@ celix_status_t bundleActivator_start(void * userData, bundle_context_pt context) pubsubSerializerSvc->destroySerializerMap = (void*)pubsubSerializer_destroySerializerMap; activator->serializerService = pubsubSerializerSvc; - status = bundleContext_registerService(context, PUBSUB_SERIALIZER_SERVICE, pubsubSerializerSvc, NULL, &activator->registration); + /* Set serializer type */ + properties_pt props = properties_create(); + properties_set(props,PUBSUB_SERIALIZER_TYPE_KEY,PUBSUB_SERIALIZER_TYPE); + + status = bundleContext_registerService(context, PUBSUB_SERIALIZER_SERVICE, pubsubSerializerSvc, props, &activator->registration); } diff --git a/pubsub/pubsub_serializer_json/private/src/pubsub_serializer_impl.c b/pubsub/pubsub_serializer_json/private/src/pubsub_serializer_impl.c index fb46f1087..cffc8160d 100644 --- a/pubsub/pubsub_serializer_json/private/src/pubsub_serializer_impl.c +++ b/pubsub/pubsub_serializer_json/private/src/pubsub_serializer_impl.c @@ -79,206 +79,217 @@ celix_status_t pubsubSerializer_destroy(pubsub_serializer_t* serializer) { return status; } -celix_status_t pubsubSerializer_createSerializerMap(pubsub_serializer_t* serializer, bundle_pt bundle, pubsub_msg_serializer_map_t** out) { - celix_status_t status = CELIX_SUCCESS; - pubsub_msg_serializer_map_t* map = calloc(1, sizeof(*map)); - if (map != NULL) { - map->bundle = bundle; - map->serializers = hashMap_create(NULL, NULL, NULL, NULL); - pubsubSerializer_fillMsgSerializerMap(map->serializers, bundle); - } else { - logHelper_log(serializer->loghelper, OSGI_LOGSERVICE_ERROR, "Cannot allocate memory for msg map"); - status = CELIX_ENOMEM; - } - - if (status == CELIX_SUCCESS) { - *out = map; - } - return status; +celix_status_t pubsubSerializer_createSerializerMap(pubsub_serializer_t* serializer, bundle_pt bundle, hash_map_pt* serializerMap) { + celix_status_t status = CELIX_SUCCESS; + + hash_map_pt map = hashMap_create(NULL, NULL, NULL, NULL); + + if (map != NULL) { + pubsubSerializer_fillMsgSerializerMap(map, bundle); + } else { + logHelper_log(serializer->loghelper, OSGI_LOGSERVICE_ERROR, "Cannot allocate memory for msg map"); + status = CELIX_ENOMEM; + } + + if (status == CELIX_SUCCESS) { + *serializerMap = map; + } + return status; } -celix_status_t pubsubSerializer_destroySerializerMap(pubsub_serializer_t* serializer, pubsub_msg_serializer_map_t* map) { - celix_status_t status = CELIX_SUCCESS; - if (map == NULL) { - return status; - } - - hash_map_iterator_t iter = hashMapIterator_construct(map->serializers); - while (hashMapIterator_hasNext(&iter)) { - pubsub_msg_serializer_t* msgSer = hashMapIterator_nextValue(&iter); - pubsub_msg_serializer_impl_t* impl = msgSer->handle; - dynMessage_destroy(impl->dynMsg); //note msgSer->name and msgSer->version owned by dynType - free(impl); //also contains the service struct. - } - hashMap_destroy(map->serializers, false, false); - free(map); - return status; +celix_status_t pubsubSerializer_destroySerializerMap(pubsub_serializer_t* serializer, hash_map_pt serializerMap) { + celix_status_t status = CELIX_SUCCESS; + if (serializerMap == NULL) { + return CELIX_ILLEGAL_ARGUMENT; + } + + hash_map_iterator_t iter = hashMapIterator_construct(serializerMap); + while (hashMapIterator_hasNext(&iter)) { + pubsub_msg_serializer_t* msgSerializer = hashMapIterator_nextValue(&iter); + dyn_message_type *dynMsg = (dyn_message_type*)msgSerializer->handle; + dynMessage_destroy(dynMsg); //note msgSer->name and msgSer->version owned by dynType + free(msgSerializer); //also contains the service struct. + } + + hashMap_destroy(serializerMap, false, false); + + return status; } -celix_status_t pubsubMsgSerializer_serialize(pubsub_msg_serializer_impl_t* impl, const void* msg, char** out, size_t *outLen) { - celix_status_t status = CELIX_SUCCESS; +celix_status_t pubsubMsgSerializer_serialize(pubsub_msg_serializer_t* msgSerializer, const void* msg, void** out, size_t *outLen) { + celix_status_t status = CELIX_SUCCESS; + + char *jsonOutput = NULL; + dyn_type* dynType = NULL; + dyn_message_type *dynMsg = (dyn_message_type*)msgSerializer->handle; + dynMessage_getMessageType(dynMsg, &dynType); - char *jsonOutput = NULL; - dyn_type* dynType = NULL; - dynMessage_getMessageType(impl->dynMsg, &dynType); - int rc = jsonSerializer_serialize(dynType, msg, &jsonOutput); - if (rc != 0){ + if (jsonSerializer_serialize(dynType, msg, &jsonOutput) != 0){ status = CELIX_BUNDLE_EXCEPTION; } - if (status == CELIX_SUCCESS) { - *out = jsonOutput; - *outLen = strlen(jsonOutput) + 1; - } + + if (status == CELIX_SUCCESS) { + *out = jsonOutput; + *outLen = strlen(jsonOutput) + 1; + } return status; } -celix_status_t pubsubMsgSerializer_deserialize(pubsub_msg_serializer_impl_t* impl, const char* input, size_t inputLen, void **out) { - celix_status_t status = CELIX_SUCCESS; - void *msg = NULL; - dyn_type* dynType = NULL; - dynMessage_getMessageType(impl->dynMsg, &dynType); - int rc = jsonSerializer_deserialize(dynType, input, &msg); - if (rc != 0) { - status = CELIX_BUNDLE_EXCEPTION; - } - else{ - *out = msg; - } +celix_status_t pubsubMsgSerializer_deserialize(pubsub_msg_serializer_t* msgSerializer, const void* input, size_t inputLen, void **out) { + + celix_status_t status = CELIX_SUCCESS; + void *msg = NULL; + dyn_type* dynType = NULL; + dyn_message_type *dynMsg = (dyn_message_type*)msgSerializer->handle; + dynMessage_getMessageType(dynMsg, &dynType); + + if (jsonSerializer_deserialize(dynType, (const char*)input, &msg) != 0) { + status = CELIX_BUNDLE_EXCEPTION; + } + else{ + *out = msg; + } + return status; } -void pubsubMsgSerializer_freeMsg(pubsub_msg_serializer_impl_t* impl, void *msg) { - dyn_type* dynType = NULL; - dynMessage_getMessageType(impl->dynMsg, &dynType); - if (dynType != NULL) { - dynType_free(dynType, msg); - } +void pubsubMsgSerializer_freeMsg(pubsub_msg_serializer_t* msgSerializer, void *msg) { + dyn_type* dynType = NULL; + dyn_message_type *dynMsg = (dyn_message_type*)msgSerializer->handle; + dynMessage_getMessageType(dynMsg, &dynType); + if (dynType != NULL) { + dynType_free(dynType, msg); + } } static void pubsubSerializer_fillMsgSerializerMap(hash_map_pt msgSerializers, bundle_pt bundle) { - char* root = NULL; - char* metaInfPath = NULL; + char* root = NULL; + char* metaInfPath = NULL; - root = pubsubSerializer_getMsgDescriptionDir(bundle); + root = pubsubSerializer_getMsgDescriptionDir(bundle); - if(root != NULL){ - asprintf(&metaInfPath, "%s/META-INF/descriptors/messages", root); + if(root != NULL){ + asprintf(&metaInfPath, "%s/META-INF/descriptors", root); - pubsubSerializer_addMsgSerializerFromBundle(root, bundle, msgSerializers); - pubsubSerializer_addMsgSerializerFromBundle(metaInfPath, bundle, msgSerializers); + pubsubSerializer_addMsgSerializerFromBundle(root, bundle, msgSerializers); + pubsubSerializer_addMsgSerializerFromBundle(metaInfPath, bundle, msgSerializers); - free(metaInfPath); - free(root); - } + free(metaInfPath); + free(root); + } } static char* pubsubSerializer_getMsgDescriptionDir(bundle_pt bundle) { - char *root = NULL; + char *root = NULL; - bool isSystemBundle = false; - bundle_isSystemBundle(bundle, &isSystemBundle); + bool isSystemBundle = false; + bundle_isSystemBundle(bundle, &isSystemBundle); - if(isSystemBundle == true) { - bundle_context_pt context; - bundle_getContext(bundle, &context); + if(isSystemBundle == true) { + bundle_context_pt context; + bundle_getContext(bundle, &context); - const char *prop = NULL; + const char *prop = NULL; - bundleContext_getProperty(context, SYSTEM_BUNDLE_ARCHIVE_PATH, &prop); + bundleContext_getProperty(context, SYSTEM_BUNDLE_ARCHIVE_PATH, &prop); - if(prop != NULL) { - root = strdup(prop); - } else { - root = getcwd(NULL, 0); - } - } else { - bundle_getEntry(bundle, ".", &root); - } + if(prop != NULL) { + root = strdup(prop); + } else { + root = getcwd(NULL, 0); + } + } else { + bundle_getEntry(bundle, ".", &root); + } - return root; + return root; } static void pubsubSerializer_addMsgSerializerFromBundle(const char *root, bundle_pt bundle, hash_map_pt msgSerializers) { - char path[128]; - struct dirent *entry = NULL; - DIR *dir = opendir(root); - - if(dir) { - entry = readdir(dir); - } - - while (entry != NULL) { - - if (strstr(entry->d_name, ".descriptor") != NULL) { - - printf("DMU: Parsing entry '%s'\n", entry->d_name); - - memset(path,0,128); - snprintf(path, 128, "%s/%s", root, entry->d_name); - FILE *stream = fopen(path,"r"); - - if (stream != NULL){ - dyn_message_type* msgType = NULL; - - int rc = dynMessage_parse(stream, &msgType); - if (rc == 0 && msgType != NULL) { - - char* msgName = NULL; - rc += dynMessage_getName(msgType,&msgName); - - version_pt msgVersion = NULL; - rc += dynMessage_getVersion(msgType, &msgVersion); - - if(rc == 0 && msgName != NULL && msgVersion != NULL){ - - unsigned int msgId = utils_stringHash(msgName); - - pubsub_msg_serializer_impl_t* impl = calloc(1, sizeof(*impl)); - impl->dynMsg = msgType; - impl->msgSerializer.handle = impl; - impl->msgSerializer.msgId = msgId; - impl->msgSerializer.msgName = msgName; - impl->msgSerializer.msgVersion = msgVersion; - impl->msgSerializer.serialize = (void*) pubsubMsgSerializer_serialize; - impl->msgSerializer.deserialize = (void*) pubsubMsgSerializer_deserialize; - impl->msgSerializer.freeMsg = (void*) pubsubMsgSerializer_freeMsg; - - bool clash = hashMap_containsKey(msgSerializers, (void*)(uintptr_t)msgId); - if (clash) { - printf("Cannot add msg %s. clash in msg id %d!!\n", msgName, msgId); - free(impl); - dynMessage_destroy(msgType); - } else if (msgId != 0) { - hashMap_put(msgSerializers, (void*)(uintptr_t)msgId, &impl->msgSerializer); - } else { - printf("Error creating msg serializer\n"); - free(impl); - dynMessage_destroy(msgType); - } - } - else{ - printf("Cannot retrieve name and/or version from msg\n"); - } - - } else{ - printf("DMU: cannot parse message from descriptor %s\n.",path); - } - fclose(stream); - }else{ - printf("DMU: cannot open descriptor file %s\n.",path); - } - - } - entry = readdir(dir); - } - - if(dir) { - closedir(dir); - } + char path[128]; + struct dirent *entry = NULL; + DIR *dir = opendir(root); + + if(dir) { + entry = readdir(dir); + } + + while (entry != NULL) { + + if (strstr(entry->d_name, ".descriptor") != NULL) { + + printf("DMU: Parsing entry '%s'\n", entry->d_name); + + memset(path,0,128); + snprintf(path, 128, "%s/%s", root, entry->d_name); + FILE *stream = fopen(path,"r"); + + if (stream != NULL){ + dyn_message_type* msgType = NULL; + + int rc = dynMessage_parse(stream, &msgType); + if (rc == 0 && msgType != NULL) { + + char* msgName = NULL; + rc += dynMessage_getName(msgType,&msgName); + + version_pt msgVersion = NULL; + rc += dynMessage_getVersion(msgType, &msgVersion); + + if(rc == 0 && msgName != NULL && msgVersion != NULL){ + + unsigned int msgId = utils_stringHash(msgName); + + pubsub_msg_serializer_t *msgSerializer = calloc(1,sizeof(pubsub_msg_serializer_t)); + + msgSerializer->handle = msgType; + msgSerializer->msgId = msgId; + msgSerializer->msgName = msgName; + msgSerializer->msgVersion = msgVersion; + msgSerializer->serialize = (void*) pubsubMsgSerializer_serialize; + msgSerializer->deserialize = (void*) pubsubMsgSerializer_deserialize; + msgSerializer->freeMsg = (void*) pubsubMsgSerializer_freeMsg; + + bool clash = hashMap_containsKey(msgSerializers, (void*)(uintptr_t)msgId); + if (clash){ + printf("Cannot add msg %s. clash in msg id %d!!\n", msgName, msgId); + free(msgSerializer); + dynMessage_destroy(msgType); + } + else if (msgId != 0){ + printf("Adding %u : %s\n", msgId, msgName); + hashMap_put(msgSerializers, (void*)(uintptr_t)msgId, msgSerializer); + } + else{ + printf("Error creating msg serializer\n"); + free(msgSerializer); + dynMessage_destroy(msgType); + } + + } + else{ + printf("Cannot retrieve name and/or version from msg\n"); + } + + } else{ + printf("DMU: cannot parse message from descriptor %s\n.",path); + } + fclose(stream); + }else{ + printf("DMU: cannot open descriptor file %s\n.",path); + } + + } + entry = readdir(dir); + } + + if(dir) { + closedir(dir); + } } diff --git a/pubsub/pubsub_topology_manager/private/include/pubsub_topology_manager.h b/pubsub/pubsub_topology_manager/private/include/pubsub_topology_manager.h index c7cb1003a..7614e0cf6 100644 --- a/pubsub/pubsub_topology_manager/private/include/pubsub_topology_manager.h +++ b/pubsub/pubsub_topology_manager/private/include/pubsub_topology_manager.h @@ -41,9 +41,6 @@ struct pubsub_topology_manager { bundle_context_pt context; - celix_thread_mutex_t serializerListLock; - array_list_pt serializerList; - celix_thread_mutex_t psaListLock; array_list_pt psaList; @@ -65,22 +62,14 @@ celix_status_t pubsub_topologyManager_create(bundle_context_pt context, log_help celix_status_t pubsub_topologyManager_destroy(pubsub_topology_manager_pt manager); celix_status_t pubsub_topologyManager_closeImports(pubsub_topology_manager_pt manager); -celix_status_t pubsub_topologyManager_pubsubSerializerAdding(void *handle, service_reference_pt reference, void **service); -celix_status_t pubsub_topologyManager_pubsubSerializerAdded(void *handle, service_reference_pt reference, void *service); -celix_status_t pubsub_topologyManager_pubsubSerializerModified(void *handle, service_reference_pt reference, void *service); -celix_status_t pubsub_topologyManager_pubsubSerializerRemoved(void *handle, service_reference_pt reference, void *service); - -celix_status_t pubsub_topologyManager_psaAdding(void *handle, service_reference_pt reference, void **service); celix_status_t pubsub_topologyManager_psaAdded(void *handle, service_reference_pt reference, void *service); celix_status_t pubsub_topologyManager_psaModified(void *handle, service_reference_pt reference, void *service); celix_status_t pubsub_topologyManager_psaRemoved(void *handle, service_reference_pt reference, void *service); -celix_status_t pubsub_topologyManager_pubsubDiscoveryAdding(void* handle, service_reference_pt reference, void** service); celix_status_t pubsub_topologyManager_pubsubDiscoveryAdded(void* handle, service_reference_pt reference, void* service); celix_status_t pubsub_topologyManager_pubsubDiscoveryModified(void * handle, service_reference_pt reference, void* service); celix_status_t pubsub_topologyManager_pubsubDiscoveryRemoved(void * handle, service_reference_pt reference, void* service); -celix_status_t pubsub_topologyManager_subscriberAdding(void * handle, service_reference_pt reference, void **service); celix_status_t pubsub_topologyManager_subscriberAdded(void * handle, service_reference_pt reference, void * service); celix_status_t pubsub_topologyManager_subscriberModified(void * handle, service_reference_pt reference, void * service); celix_status_t pubsub_topologyManager_subscriberRemoved(void * handle, service_reference_pt reference, void * service); diff --git a/pubsub/pubsub_topology_manager/private/src/pstm_activator.c b/pubsub/pubsub_topology_manager/private/src/pstm_activator.c index c202e7a25..0ce257117 100644 --- a/pubsub/pubsub_topology_manager/private/src/pstm_activator.c +++ b/pubsub/pubsub_topology_manager/private/src/pstm_activator.c @@ -48,7 +48,6 @@ struct activator { pubsub_topology_manager_pt manager; - service_tracker_pt pubsubSerializerTracker; service_tracker_pt pubsubDiscoveryTracker; service_tracker_pt pubsubAdminTracker; service_tracker_pt pubsubSubscribersTracker; @@ -62,38 +61,19 @@ struct activator { log_helper_pt loghelper; }; -static celix_status_t bundleActivator_createPSSTracker(struct activator *activator, service_tracker_pt *tracker); + static celix_status_t bundleActivator_createPSDTracker(struct activator *activator, service_tracker_pt *tracker); static celix_status_t bundleActivator_createPSATracker(struct activator *activator, service_tracker_pt *tracker); static celix_status_t bundleActivator_createPSSubTracker(struct activator *activator, service_tracker_pt *tracker); -static celix_status_t bundleActivator_createPSSTracker(struct activator *activator, service_tracker_pt *tracker) { - celix_status_t status; - - service_tracker_customizer_pt customizer = NULL; - - status = serviceTrackerCustomizer_create(activator->manager, - pubsub_topologyManager_pubsubSerializerAdding, - pubsub_topologyManager_pubsubSerializerAdded, - pubsub_topologyManager_pubsubSerializerModified, - pubsub_topologyManager_pubsubSerializerRemoved, - &customizer); - - if (status == CELIX_SUCCESS) { - status = serviceTracker_create(activator->context, (char *) PUBSUB_SERIALIZER_SERVICE, customizer, tracker); - } - - return status; -} - static celix_status_t bundleActivator_createPSDTracker(struct activator *activator, service_tracker_pt *tracker) { celix_status_t status; service_tracker_customizer_pt customizer = NULL; status = serviceTrackerCustomizer_create(activator->manager, - pubsub_topologyManager_pubsubDiscoveryAdding, + NULL, pubsub_topologyManager_pubsubDiscoveryAdded, pubsub_topologyManager_pubsubDiscoveryModified, pubsub_topologyManager_pubsubDiscoveryRemoved, @@ -112,7 +92,7 @@ static celix_status_t bundleActivator_createPSATracker(struct activator *activat service_tracker_customizer_pt customizer = NULL; status = serviceTrackerCustomizer_create(activator->manager, - pubsub_topologyManager_psaAdding, + NULL, pubsub_topologyManager_psaAdded, pubsub_topologyManager_psaModified, pubsub_topologyManager_psaRemoved, @@ -131,7 +111,7 @@ static celix_status_t bundleActivator_createPSSubTracker(struct activator *activ service_tracker_customizer_pt customizer = NULL; status = serviceTrackerCustomizer_create(activator->manager, - pubsub_topologyManager_subscriberAdding, + NULL, pubsub_topologyManager_subscriberAdded, pubsub_topologyManager_subscriberModified, pubsub_topologyManager_subscriberRemoved, @@ -163,36 +143,15 @@ celix_status_t bundleActivator_create(bundle_context_pt context, void **userData if (status == CELIX_SUCCESS) { status = bundleActivator_createPSDTracker(activator, &activator->pubsubDiscoveryTracker); if (status == CELIX_SUCCESS) { - status = bundleActivator_createPSSTracker(activator, &activator->pubsubSerializerTracker); - if (status == CELIX_SUCCESS){ - status = bundleActivator_createPSATracker(activator, &activator->pubsubAdminTracker); + status = bundleActivator_createPSATracker(activator, &activator->pubsubAdminTracker); + if (status == CELIX_SUCCESS) { + status = bundleActivator_createPSSubTracker(activator, &activator->pubsubSubscribersTracker); if (status == CELIX_SUCCESS) { - status = bundleActivator_createPSSubTracker(activator, &activator->pubsubSubscribersTracker); - if (status == CELIX_SUCCESS) { - *userData = activator; - } - if (status != CELIX_SUCCESS){ - serviceTracker_destroy(activator->pubsubAdminTracker); - } - } - if (status != CELIX_SUCCESS){ - serviceTracker_destroy(activator->pubsubSerializerTracker); + *userData = activator; } } - if (status != CELIX_SUCCESS){ - serviceTracker_destroy(activator->pubsubDiscoveryTracker); - } - } - if (status != CELIX_SUCCESS){ - pubsub_topologyManager_destroy(activator->manager); } } - if (status != CELIX_SUCCESS){ // an exception occurred so free allocated memory - logHelper_stop(activator->loghelper); - logHelper_destroy(&activator->loghelper); - free(activator); - - } return status; } @@ -224,12 +183,13 @@ celix_status_t bundleActivator_start(void * userData, bundle_context_pt context) properties_set(props, (char *) OSGI_RSA_SERVICE_EXPORTED_INTERFACES, (char *) PUBSUB_TOPIC_INFO_SERVICE); status += bundleContext_registerService(context, (char *) PUBSUB_TOPIC_INFO_SERVICE, activator->topicInfo, props, &activator->topicInfoService); */ - - status += serviceTracker_open(activator->pubsubSerializerTracker); status += serviceTracker_open(activator->pubsubAdminTracker); + status += serviceTracker_open(activator->pubsubDiscoveryTracker); + status += serviceTracker_open(activator->pubsubSubscribersTracker); + return status; } @@ -239,7 +199,6 @@ celix_status_t bundleActivator_stop(void * userData, bundle_context_pt context) serviceTracker_close(activator->pubsubSubscribersTracker); serviceTracker_close(activator->pubsubDiscoveryTracker); - serviceTracker_close(activator->pubsubSerializerTracker); serviceTracker_close(activator->pubsubAdminTracker); serviceRegistration_unregister(activator->publisherEPDiscoverService); @@ -261,7 +220,6 @@ celix_status_t bundleActivator_destroy(void * userData, bundle_context_pt contex serviceTracker_destroy(activator->pubsubSubscribersTracker); serviceTracker_destroy(activator->pubsubDiscoveryTracker); - serviceTracker_destroy(activator->pubsubSerializerTracker); serviceTracker_destroy(activator->pubsubAdminTracker); logHelper_stop(activator->loghelper); diff --git a/pubsub/pubsub_topology_manager/private/src/pubsub_topology_manager.c b/pubsub/pubsub_topology_manager/private/src/pubsub_topology_manager.c index 0e7923bce..b4e8f46fe 100644 --- a/pubsub/pubsub_topology_manager/private/src/pubsub_topology_manager.c +++ b/pubsub/pubsub_topology_manager/private/src/pubsub_topology_manager.c @@ -23,7 +23,6 @@ * \author Apache Celix Project Team * \copyright Apache License, Version 2.0 */ - #include #include #include @@ -66,15 +65,13 @@ celix_status_t pubsub_topologyManager_create(bundle_context_pt context, log_help celixThreadMutexAttr_create(&psaAttr); celixThreadMutexAttr_settype(&psaAttr, CELIX_THREAD_MUTEX_RECURSIVE); status = celixThreadMutex_create(&(*manager)->psaListLock, &psaAttr); - celixThreadMutexAttr_destroy(&psaAttr); + celixThreadMutexAttr_destroy(&psaAttr); - status = celixThreadMutex_create(&(*manager)->publicationsLock, NULL); + status = celixThreadMutex_create(&(*manager)->publicationsLock, NULL); status = celixThreadMutex_create(&(*manager)->subscriptionsLock, NULL); status = celixThreadMutex_create(&(*manager)->discoveryListLock, NULL); - status = celixThreadMutex_create(&(*manager)->serializerListLock, NULL); arrayList_create(&(*manager)->psaList); - arrayList_create(&(*manager)->serializerList); (*manager)->discoveryList = hashMap_create(serviceReference_hashCode, NULL, serviceReference_equals2, NULL); (*manager)->publications = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL); @@ -98,11 +95,6 @@ celix_status_t pubsub_topologyManager_destroy(pubsub_topology_manager_pt manager celixThreadMutex_unlock(&manager->psaListLock); celixThreadMutex_destroy(&manager->psaListLock); - celixThreadMutex_lock(&manager->serializerListLock); - arrayList_destroy(manager->serializerList); - celixThreadMutex_unlock(&manager->serializerListLock); - celixThreadMutex_destroy(&manager->serializerListLock); - celixThreadMutex_lock(&manager->publicationsLock); hash_map_iterator_pt pubit = hashMapIterator_create(manager->publications); while(hashMapIterator_hasNext(pubit)){ @@ -138,24 +130,18 @@ celix_status_t pubsub_topologyManager_destroy(pubsub_topology_manager_pt manager return status; } - -celix_status_t pubsub_topologyManager_psaAdding(void * handle, service_reference_pt reference, void **service) { - celix_status_t status = CELIX_SUCCESS; - pubsub_topology_manager_pt manager = handle; - - status = bundleContext_getService(manager->context, reference, service); - - return status; -} - celix_status_t pubsub_topologyManager_psaAdded(void * handle, service_reference_pt reference, void * service) { celix_status_t status = CELIX_SUCCESS; pubsub_topology_manager_pt manager = handle; - int i, j; + int i; - pubsub_admin_service_pt new_psa = (pubsub_admin_service_pt) service; + pubsub_admin_service_pt psa = (pubsub_admin_service_pt) service; logHelper_log(manager->loghelper, OSGI_LOGSERVICE_INFO, "PSTM: Added PSA"); + celixThreadMutex_lock(&manager->psaListLock); + arrayList_add(manager->psaList, psa); + celixThreadMutex_unlock(&manager->psaListLock); + // Add already detected subscriptions to new PSA celixThreadMutex_lock(&manager->subscriptionsLock); hash_map_iterator_pt subscriptionsIterator = hashMapIterator_create(manager->subscriptions); @@ -163,27 +149,7 @@ celix_status_t pubsub_topologyManager_psaAdded(void * handle, service_reference_ while (hashMapIterator_hasNext(subscriptionsIterator)) { array_list_pt sub_ep_list = hashMapIterator_nextValue(subscriptionsIterator); for(i=0;imatchSubscriber(new_psa->admin, sub, &new_psa_score); - pubsub_admin_service_pt best_psa = NULL; - double highest_score = 0; - - for(j=0;jpsaList);j++){ - pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,j); - double score; - psa->matchSubscriber(psa->admin, sub, &score); - if (score > highest_score){ - highest_score = score; - best_psa = psa; - } - } - if (best_psa != NULL && (new_psa_score > highest_score)){ - best_psa->removeSubscription(best_psa->admin, sub); - } - if (new_psa_score > highest_score){ - status += new_psa->addSubscription(new_psa->admin, sub); - } + status += psa->addSubscription(psa->admin, (pubsub_endpoint_pt)arrayList_get(sub_ep_list,i)); } } @@ -198,27 +164,7 @@ celix_status_t pubsub_topologyManager_psaAdded(void * handle, service_reference_ while (hashMapIterator_hasNext(publicationsIterator)) { array_list_pt pub_ep_list = hashMapIterator_nextValue(publicationsIterator); for(i=0;imatchPublisher(new_psa->admin, pub, &new_psa_score); - pubsub_admin_service_pt best_psa = NULL; - double highest_score = 0; - - for(j=0;jpsaList);j++){ - pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,j); - double score; - psa->matchPublisher(psa->admin, pub, &score); - if (score > highest_score){ - highest_score = score; - best_psa = psa; - } - } - if (best_psa != NULL && (new_psa_score > highest_score)){ - best_psa->removePublication(best_psa->admin, pub); - } - if (new_psa_score > highest_score){ - status += new_psa->addPublication(new_psa->admin, pub); - } + status += psa->addPublication(psa->admin, (pubsub_endpoint_pt)arrayList_get(pub_ep_list,i)); } } @@ -226,20 +172,6 @@ celix_status_t pubsub_topologyManager_psaAdded(void * handle, service_reference_ celixThreadMutex_unlock(&manager->publicationsLock); - - celixThreadMutex_lock(&manager->serializerListLock); - unsigned int size = arrayList_size(manager->serializerList); - if (size > 0) { - pubsub_serializer_service_t* ser = arrayList_get(manager->serializerList, (size-1)); //last, same as result of add/remove serializer - new_psa->setSerializer(new_psa->admin, ser); - } - celixThreadMutex_unlock(&manager->serializerListLock); - - celixThreadMutex_lock(&manager->psaListLock); - arrayList_add(manager->psaList, new_psa); - celixThreadMutex_unlock(&manager->psaListLock); - - return status; } @@ -325,97 +257,13 @@ celix_status_t pubsub_topologyManager_psaRemoved(void * handle, service_referenc return status; } -celix_status_t pubsub_topologyManager_pubsubSerializerAdding(void* handle, service_reference_pt reference, void** service) { - celix_status_t status = CELIX_SUCCESS; - pubsub_topology_manager_pt manager = handle; - - bundleContext_getService(manager->context, reference, service); - - return status; -} - -celix_status_t pubsub_topologyManager_pubsubSerializerAdded(void* handle, service_reference_pt reference, void* service) { - celix_status_t status = CELIX_SUCCESS; - - pubsub_topology_manager_pt manager = handle; - pubsub_serializer_service_t* new_serializer = (pubsub_serializer_service_t*) service; - - celixThreadMutex_lock(&manager->serializerListLock); - - logHelper_log(manager->loghelper, OSGI_LOGSERVICE_INFO, "PSTM: Added pubsub serializer"); - - int i; - for(i=0; ipsaList); i++){ - pubsub_admin_service_pt psa = (pubsub_admin_service_pt) arrayList_get(manager->psaList,i); - psa->setSerializer(psa->admin, new_serializer); - } - - arrayList_add(manager->serializerList, new_serializer); - - celixThreadMutex_unlock(&manager->serializerListLock); - - return status; -} - -celix_status_t pubsub_topologyManager_pubsubSerializerModified(void * handle, service_reference_pt reference, void * service) { - celix_status_t status = CELIX_SUCCESS; - - // Nop... - - return status; -} - -celix_status_t pubsub_topologyManager_pubsubSerializerRemoved(void * handle, service_reference_pt reference, void * service) { - celix_status_t status = CELIX_SUCCESS; - - pubsub_topology_manager_pt manager = handle; - pubsub_serializer_service_t* new_serializer = (pubsub_serializer_service_t*) service; - - celixThreadMutex_lock(&manager->serializerListLock); - - logHelper_log(manager->loghelper, OSGI_LOGSERVICE_INFO, "PSTM: Removed pubsub serializer"); - - int i, j; - - for(i=0; ipsaList); i++){ - pubsub_admin_service_pt psa = (pubsub_admin_service_pt) arrayList_get(manager->psaList,i); - psa->removeSerializer(psa->admin, new_serializer); - } - - arrayList_removeElement(manager->serializerList, new_serializer); - - if (arrayList_size(manager->serializerList) > 0){ - //there is another serializer available, change the admin so it is using another serializer - pubsub_serializer_service_t* replacing_serializer = (pubsub_serializer_service_t*) arrayList_get(manager->serializerList,0); - - for(j=0; jpsaList); j++){ - pubsub_admin_service_pt psa = (pubsub_admin_service_pt) arrayList_get(manager->psaList,j); - psa->setSerializer(psa->admin, replacing_serializer); - } - } - - celixThreadMutex_unlock(&manager->serializerListLock); - - - return status; -} - -celix_status_t pubsub_topologyManager_subscriberAdding(void * handle, service_reference_pt reference, void **service) { - celix_status_t status = CELIX_SUCCESS; - pubsub_topology_manager_pt manager = handle; - - status = bundleContext_getService(manager->context, reference, service); - - return status; -} - celix_status_t pubsub_topologyManager_subscriberAdded(void * handle, service_reference_pt reference, void * service) { celix_status_t status = CELIX_SUCCESS; pubsub_topology_manager_pt manager = handle; //subscriber_service_pt subscriber = (subscriber_service_pt)service; pubsub_endpoint_pt sub = NULL; - if(pubsubEndpoint_createFromServiceReference(reference,&sub) == CELIX_SUCCESS){ + if(pubsubEndpoint_createFromServiceReference(reference,&sub,false) == CELIX_SUCCESS){ celixThreadMutex_lock(&manager->subscriptionsLock); char *sub_key = createScopeTopicKey(sub->scope, sub->topic); @@ -430,40 +278,40 @@ celix_status_t pubsub_topologyManager_subscriberAdded(void * handle, service_ref celixThreadMutex_unlock(&manager->subscriptionsLock); int j; - celixThreadMutex_lock(&manager->psaListLock); - double highest_score = -1; + double score = 0; + double best_score = 0; pubsub_admin_service_pt best_psa = NULL; - + celixThreadMutex_lock(&manager->psaListLock); for(j=0;jpsaList);j++){ pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,j); - double score; - psa->matchSubscriber(psa->admin, sub, &score); - if (score > highest_score){ - highest_score = score; + psa->matchEndpoint(psa->admin,sub,&score); + if(score>best_score){ /* We have a new winner! */ + best_score = score; best_psa = psa; } } - if (best_psa != NULL){ + + if(best_psa != NULL && best_score>0){ best_psa->addSubscription(best_psa->admin,sub); } // Inform discoveries for interest in the topic - celixThreadMutex_lock(&manager->discoveryListLock); + celixThreadMutex_lock(&manager->discoveryListLock); hash_map_iterator_pt iter = hashMapIterator_create(manager->discoveryList); - while(hashMapIterator_hasNext(iter)){ - service_reference_pt disc_sr = (service_reference_pt)hashMapIterator_nextKey(iter); - publisher_endpoint_announce_pt disc = NULL; - bundleContext_getService(manager->context, disc_sr, (void**) &disc); - disc->interestedInTopic(disc->handle, sub->scope, sub->topic); - bundleContext_ungetService(manager->context, disc_sr, NULL); - } - hashMapIterator_destroy(iter); - celixThreadMutex_unlock(&manager->discoveryListLock); + while(hashMapIterator_hasNext(iter)){ + service_reference_pt disc_sr = (service_reference_pt)hashMapIterator_nextKey(iter); + publisher_endpoint_announce_pt disc = NULL; + bundleContext_getService(manager->context, disc_sr, (void**) &disc); + disc->interestedInTopic(disc->handle, sub->scope, sub->topic); + bundleContext_ungetService(manager->context, disc_sr, NULL); + } + hashMapIterator_destroy(iter); + celixThreadMutex_unlock(&manager->discoveryListLock); celixThreadMutex_unlock(&manager->psaListLock); } else{ - status = CELIX_INVALID_BUNDLE_CONTEXT; + status=CELIX_INVALID_BUNDLE_CONTEXT; } return status; @@ -482,25 +330,25 @@ celix_status_t pubsub_topologyManager_subscriberRemoved(void * handle, service_r pubsub_topology_manager_pt manager = handle; pubsub_endpoint_pt subcmp = NULL; - if(pubsubEndpoint_createFromServiceReference(reference,&subcmp) == CELIX_SUCCESS){ + if(pubsubEndpoint_createFromServiceReference(reference,&subcmp,false) == CELIX_SUCCESS){ int j,k; // Inform discoveries that we not interested in the topic any more - celixThreadMutex_lock(&manager->discoveryListLock); - hash_map_iterator_pt iter = hashMapIterator_create(manager->discoveryList); - while(hashMapIterator_hasNext(iter)){ - service_reference_pt disc_sr = (service_reference_pt)hashMapIterator_nextKey(iter); - publisher_endpoint_announce_pt disc = NULL; - bundleContext_getService(manager->context, disc_sr, (void**) &disc); - disc->uninterestedInTopic(disc->handle, subcmp->scope, subcmp->topic); - bundleContext_ungetService(manager->context, disc_sr, NULL); - } - hashMapIterator_destroy(iter); - celixThreadMutex_unlock(&manager->discoveryListLock); - - celixThreadMutex_lock(&manager->subscriptionsLock); - celixThreadMutex_lock(&manager->psaListLock); + celixThreadMutex_lock(&manager->discoveryListLock); + hash_map_iterator_pt iter = hashMapIterator_create(manager->discoveryList); + while(hashMapIterator_hasNext(iter)){ + service_reference_pt disc_sr = (service_reference_pt)hashMapIterator_nextKey(iter); + publisher_endpoint_announce_pt disc = NULL; + bundleContext_getService(manager->context, disc_sr, (void**) &disc); + disc->uninterestedInTopic(disc->handle, subcmp->scope, subcmp->topic); + bundleContext_ungetService(manager->context, disc_sr, NULL); + } + hashMapIterator_destroy(iter); + celixThreadMutex_unlock(&manager->discoveryListLock); + + celixThreadMutex_lock(&manager->subscriptionsLock); + celixThreadMutex_lock(&manager->psaListLock); char *sub_key = createScopeTopicKey(subcmp->scope,subcmp->topic); array_list_pt sub_list_by_topic = hashMap_get(manager->subscriptions,sub_key); @@ -509,19 +357,10 @@ celix_status_t pubsub_topologyManager_subscriberRemoved(void * handle, service_r for(j=0;jpsaList);k++){ + /* No problem with invoking removal on all psa's, only the one that manage this topic will do something */ pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,k); - double score; - psa->matchSubscriber(psa->admin, sub, &score); - if (score > highest_score){ - highest_score = score; - best_psa = psa; - } - } - if (best_psa != NULL){ - best_psa->removeSubscription(best_psa->admin,sub); + psa->removeSubscription(psa->admin,sub); } } @@ -547,22 +386,13 @@ celix_status_t pubsub_topologyManager_subscriberRemoved(void * handle, service_r } else{ - status = CELIX_INVALID_BUNDLE_CONTEXT; + status=CELIX_INVALID_BUNDLE_CONTEXT; } return status; } -celix_status_t pubsub_topologyManager_pubsubDiscoveryAdding(void* handle, service_reference_pt reference, void** service) { - celix_status_t status = CELIX_SUCCESS; - pubsub_topology_manager_pt manager = handle; - - bundleContext_getService(manager->context, reference, service); - - return status; -} - celix_status_t pubsub_topologyManager_pubsubDiscoveryAdded(void* handle, service_reference_pt reference, void* service) { celix_status_t status = CELIX_SUCCESS; pubsub_topology_manager_pt manager = (pubsub_topology_manager_pt)handle; @@ -600,16 +430,16 @@ celix_status_t pubsub_topologyManager_pubsubDiscoveryAdded(void* handle, service iter = hashMapIterator_create(manager->subscriptions); while(hashMapIterator_hasNext(iter)) { - array_list_pt l = (array_list_pt)hashMapIterator_nextValue(iter); - int i; - for(i=0;iinterestedInTopic(disc->handle, subEp->scope, subEp->topic); - } + disc->interestedInTopic(disc->handle, subEp->scope, subEp->topic); + } } hashMapIterator_destroy(iter); - celixThreadMutex_unlock(&manager->subscriptionsLock); + celixThreadMutex_unlock(&manager->subscriptionsLock); return status; } @@ -654,81 +484,57 @@ celix_status_t pubsub_topologyManager_publisherTrackerAdded(void *handle, array_ listener_hook_info_pt info = arrayList_get(listeners, l_index); - const char* fwUUID=NULL; - bundleContext_getProperty(info->context,OSGI_FRAMEWORK_FRAMEWORK_UUID,&fwUUID); + pubsub_endpoint_pt pub = NULL; + if(pubsubEndpoint_createFromListenerHookInfo(info, &pub, true) == CELIX_SUCCESS){ - char* scope = pubsub_getScopeFromFilter(info->filter); - char* topic = pubsub_getTopicFromFilter(info->filter); - if(scope == NULL) { - scope = strdup(PUBSUB_PUBLISHER_SCOPE_DEFAULT); - } - - //TODO: Can we use a better serviceID?? - bundle_pt bundle = NULL; - long bundleId = -1; - bundleContext_getBundle(info->context,&bundle); - bundle_getBundleId(bundle,&bundleId); + celixThreadMutex_lock(&manager->publicationsLock); + char *pub_key = createScopeTopicKey(pub->scope, pub->topic); + array_list_pt pub_list_by_topic = hashMap_get(manager->publications, pub_key); + if(pub_list_by_topic==NULL){ + arrayList_create(&pub_list_by_topic); + hashMap_put(manager->publications,strdup(pub_key),pub_list_by_topic); + } + free(pub_key); + arrayList_add(pub_list_by_topic,pub); - if(fwUUID !=NULL && topic !=NULL){ + celixThreadMutex_unlock(&manager->publicationsLock); - pubsub_endpoint_pt pub = NULL; - if(pubsubEndpoint_create(fwUUID, scope, topic,bundleId,NULL,&pub) == CELIX_SUCCESS){ + int j; + double score = 0; + double best_score = 0; + pubsub_admin_service_pt best_psa = NULL; + celixThreadMutex_lock(&manager->psaListLock); - celixThreadMutex_lock(&manager->publicationsLock); - char *pub_key = createScopeTopicKey(scope, topic); - array_list_pt pub_list_by_topic = hashMap_get(manager->publications, pub_key); - if(pub_list_by_topic==NULL){ - arrayList_create(&pub_list_by_topic); - hashMap_put(manager->publications,strdup(pub_key),pub_list_by_topic); + for(j=0;jpsaList);j++){ + pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,j); + psa->matchEndpoint(psa->admin,pub,&score); + if(score>best_score){ /* We have a new winner! */ + best_score = score; + best_psa = psa; } - free(pub_key); - arrayList_add(pub_list_by_topic,pub); - - celixThreadMutex_unlock(&manager->publicationsLock); - - int j; - celixThreadMutex_lock(&manager->psaListLock); - - double highest_score = -1; - pubsub_admin_service_pt best_psa = NULL; + } - for(j=0;jpsaList);j++){ - pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,j); - double score; - psa->matchPublisher(psa->admin, pub, &score); - if (score > highest_score){ - highest_score = score; - best_psa = psa; + if(best_psa != NULL && best_score>0){ + status = best_psa->addPublication(best_psa->admin,pub); + if(status==CELIX_SUCCESS){ + celixThreadMutex_lock(&manager->discoveryListLock); + hash_map_iterator_pt iter = hashMapIterator_create(manager->discoveryList); + while(hashMapIterator_hasNext(iter)){ + service_reference_pt disc_sr = (service_reference_pt)hashMapIterator_nextKey(iter); + publisher_endpoint_announce_pt disc = NULL; + bundleContext_getService(manager->context, disc_sr, (void**) &disc); + disc->announcePublisher(disc->handle,pub); + bundleContext_ungetService(manager->context, disc_sr, NULL); } + hashMapIterator_destroy(iter); + celixThreadMutex_unlock(&manager->discoveryListLock); } - if (best_psa != NULL){ - status = best_psa->addPublication(best_psa->admin,pub); - if(status==CELIX_SUCCESS){ - celixThreadMutex_lock(&manager->discoveryListLock); - hash_map_iterator_pt iter = hashMapIterator_create(manager->discoveryList); - while(hashMapIterator_hasNext(iter)){ - service_reference_pt disc_sr = (service_reference_pt)hashMapIterator_nextKey(iter); - publisher_endpoint_announce_pt disc = NULL; - bundleContext_getService(manager->context, disc_sr, (void**) &disc); - disc->announcePublisher(disc->handle,pub); - bundleContext_ungetService(manager->context, disc_sr, NULL); - } - hashMapIterator_destroy(iter); - celixThreadMutex_unlock(&manager->discoveryListLock); - } - } - - celixThreadMutex_unlock(&manager->psaListLock); - } - } - else{ - status=CELIX_INVALID_BUNDLE_CONTEXT; + celixThreadMutex_unlock(&manager->psaListLock); + } - free(topic); - free(scope); } return status; @@ -746,62 +552,41 @@ celix_status_t pubsub_topologyManager_publisherTrackerRemoved(void *handle, arra listener_hook_info_pt info = arrayList_get(listeners, l_index); - char* pub_scope = pubsub_getScopeFromFilter(info->filter); - char* pub_topic = pubsub_getTopicFromFilter(info->filter); - - const char* fwUUID=NULL; - bundleContext_getProperty(info->context,OSGI_FRAMEWORK_FRAMEWORK_UUID,&fwUUID); - - //TODO: Can we use a better serviceID?? - bundle_pt bundle = NULL; - long bundleId = -1; - bundleContext_getBundle(info->context,&bundle); - bundle_getBundleId(bundle,&bundleId); - - if(bundle !=NULL && pub_topic !=NULL && bundleId>0){ - - pubsub_endpoint_pt pubcmp = NULL; - if(pubsubEndpoint_create(fwUUID, pub_scope, pub_topic,bundleId,NULL,&pubcmp) == CELIX_SUCCESS){ - - int j,k; - celixThreadMutex_lock(&manager->psaListLock); - celixThreadMutex_lock(&manager->publicationsLock); - - char *pub_key = createScopeTopicKey(pub_scope, pub_topic); - array_list_pt pub_list_by_topic = hashMap_get(manager->publications,pub_key); - if(pub_list_by_topic!=NULL){ - for(j=0;jpsaList);k++){ - pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,k); - double score; - psa->matchPublisher(psa->admin, pub, &score); - if (score > highest_score){ - highest_score = score; - best_psa = psa; + pubsub_endpoint_pt pubcmp = NULL; + if(pubsubEndpoint_createFromListenerHookInfo(info,&pubcmp,true) == CELIX_SUCCESS){ + + + int j,k; + celixThreadMutex_lock(&manager->psaListLock); + celixThreadMutex_lock(&manager->publicationsLock); + + char *pub_key = createScopeTopicKey(pubcmp->scope, pubcmp->topic); + array_list_pt pub_list_by_topic = hashMap_get(manager->publications,pub_key); + if(pub_list_by_topic!=NULL){ + for(j=0;jpsaList);k++){ + pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,k); + status = psa->removePublication(psa->admin,pub); + if(status==CELIX_SUCCESS){ /* We found the one that manages this endpoint */ + celixThreadMutex_lock(&manager->discoveryListLock); + hash_map_iterator_pt iter = hashMapIterator_create(manager->discoveryList); + while(hashMapIterator_hasNext(iter)){ + service_reference_pt disc_sr = (service_reference_pt)hashMapIterator_nextKey(iter); + publisher_endpoint_announce_pt disc = NULL; + bundleContext_getService(manager->context, disc_sr, (void**) &disc); + disc->removePublisher(disc->handle,pub); + bundleContext_ungetService(manager->context, disc_sr, NULL); } + hashMapIterator_destroy(iter); + celixThreadMutex_unlock(&manager->discoveryListLock); } - if (best_psa != NULL){ - status = best_psa->removePublication(best_psa->admin,pub); - if(status==CELIX_SUCCESS){ - celixThreadMutex_lock(&manager->discoveryListLock); - hash_map_iterator_pt iter = hashMapIterator_create(manager->discoveryList); - while(hashMapIterator_hasNext(iter)){ - service_reference_pt disc_sr = (service_reference_pt)hashMapIterator_nextKey(iter); - publisher_endpoint_announce_pt disc = NULL; - bundleContext_getService(manager->context, disc_sr, (void**) &disc); - disc->removePublisher(disc->handle,pub); - bundleContext_ungetService(manager->context, disc_sr, NULL); - } - hashMapIterator_destroy(iter); - celixThreadMutex_unlock(&manager->discoveryListLock); - } + else if(status == CELIX_ILLEGAL_ARGUMENT){ /* Not a real error, just saying this psa does not handle this endpoint */ + status = CELIX_SUCCESS; } } + //} arrayList_remove(pub_list_by_topic,j); /* If it was the last publisher for this topic, tell PSA to close the ZMQ socket and then inform the discovery */ @@ -813,26 +598,20 @@ celix_status_t pubsub_topologyManager_publisherTrackerRemoved(void *handle, arra } pubsubEndpoint_destroy(pub); - } - } - celixThreadMutex_unlock(&manager->publicationsLock); - celixThreadMutex_unlock(&manager->psaListLock); + } + } - pubsubEndpoint_destroy(pubcmp); + celixThreadMutex_unlock(&manager->publicationsLock); + celixThreadMutex_unlock(&manager->psaListLock); - free(pub_key); + free(pub_key); - } + pubsubEndpoint_destroy(pubcmp); } - else{ - status=CELIX_INVALID_BUNDLE_CONTEXT; - } - free(pub_scope); - free(pub_topic); } return status; @@ -846,8 +625,6 @@ celix_status_t pubsub_topologyManager_announcePublisher(void *handle, pubsub_end celixThreadMutex_lock(&manager->psaListLock); celixThreadMutex_lock(&manager->publicationsLock); - int i; - char *pub_key = createScopeTopicKey(pubEP->scope, pubEP->topic); array_list_pt pub_list_by_topic = hashMap_get(manager->publications,pub_key); @@ -859,23 +636,28 @@ celix_status_t pubsub_topologyManager_announcePublisher(void *handle, pubsub_end /* Shouldn't be any other duplicate, since it's filtered out by the discovery */ pubsub_endpoint_pt p = NULL; - pubsubEndpoint_create(pubEP->frameworkUUID,pubEP->scope,pubEP->topic,pubEP->serviceID,pubEP->endpoint,&p); + pubsubEndpoint_clone(pubEP, &p); arrayList_add(pub_list_by_topic,p); - double highest_score = -1; + int j; + double score = 0; + double best_score = 0; pubsub_admin_service_pt best_psa = NULL; - for(i=0;ipsaList);i++){ - pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,i); - double score; - psa->matchPublisher(psa->admin, p, &score); - if (score > highest_score){ - highest_score = score; + for(j=0;jpsaList);j++){ + pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,j); + psa->matchEndpoint(psa->admin,p,&score); + if(score>best_score){ /* We have a new winner! */ + best_score = score; best_psa = psa; } } - if (best_psa != NULL){ - status += best_psa->addPublication(best_psa->admin,p); + + if(best_psa != NULL && best_score>0){ + best_psa->addPublication(best_psa->admin,p); + } + else{ + status = CELIX_ILLEGAL_STATE; } celixThreadMutex_unlock(&manager->publicationsLock); @@ -911,20 +693,10 @@ celix_status_t pubsub_topologyManager_removePublisher(void *handle, pubsub_endpo if(found && p !=NULL){ - double highest_score = -1; - pubsub_admin_service_pt best_psa = NULL; - for(i=0;ipsaList);i++){ pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,i); - double score; - psa->matchPublisher(psa->admin, p, &score); - if (score > highest_score){ - highest_score = score; - best_psa = psa; - } - } - if (best_psa != NULL){ - status += best_psa->removePublication(best_psa->admin,p); + /* No problem with invoking removal on all psa's, only the one that manage this topic will do something */ + psa->removePublication(psa->admin,p); } arrayList_removeElement(pub_list_by_topic,p); @@ -934,7 +706,7 @@ celix_status_t pubsub_topologyManager_removePublisher(void *handle, pubsub_endpo for(i=0;ipsaList);i++){ pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,i); - status += psa->closeAllPublications(psa->admin,p->scope, p->topic); + psa->closeAllPublications(psa->admin,p->scope, p->topic); } } From fc720cf2ad5cc0d8845650cd956729e8d3fe1ec0 Mon Sep 17 00:00:00 2001 From: gricciardi Date: Wed, 20 Sep 2017 17:08:23 +0200 Subject: [PATCH 2/6] Fixed send error in PSA UDP_MC --- .../pubsub/publisher/private/src/pubsub_publisher.c | 3 +-- .../pubsub_admin_udp_mc/private/src/topic_publication.c | 9 ++++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/pubsub/examples/pubsub/publisher/private/src/pubsub_publisher.c b/pubsub/examples/pubsub/publisher/private/src/pubsub_publisher.c index b798ea1d0..b78a6c5af 100644 --- a/pubsub/examples/pubsub/publisher/private/src/pubsub_publisher.c +++ b/pubsub/examples/pubsub/publisher/private/src/pubsub_publisher.c @@ -77,8 +77,7 @@ static void* send_thread(void* arg){ while(stop==false){ place->position.lat = randCoordinate(MIN_LAT,MAX_LAT); place->position.lon = randCoordinate(MIN_LON,MAX_LON); - //int nr_char = (int)randCoordinate(5,100000); - int nr_char = 32; + int nr_char = (int)randCoordinate(5,100000); place->data = calloc(nr_char, 1); for(int i = 0; i < (nr_char-1); i++) { place->data[i] = i%10 + '0'; diff --git a/pubsub/pubsub_admin_udp_mc/private/src/topic_publication.c b/pubsub/pubsub_admin_udp_mc/private/src/topic_publication.c index b85f0a98f..982c8fcb5 100644 --- a/pubsub/pubsub_admin_udp_mc/private/src/topic_publication.c +++ b/pubsub/pubsub_admin_udp_mc/private/src/topic_publication.c @@ -75,12 +75,14 @@ typedef struct publish_bundle_bound_service { largeUdp_pt largeUdpHandle; }* publish_bundle_bound_service_pt; + typedef struct pubsub_msg{ pubsub_msg_header_pt header; char* payload; - size_t payloadSize; + unsigned int payloadSize; } pubsub_msg_t; + static unsigned int rand_range(unsigned int min, unsigned int max); static celix_status_t pubsub_topicPublicationGetService(void* handle, bundle_pt bundle, service_registration_pt registration, void **service); @@ -286,8 +288,6 @@ static bool send_pubsub_msg(publish_bundle_bound_service_pt bound, pubsub_msg_t* const int iovec_len = 3; // header + size + payload bool ret = true; - int compiledMsgSize = sizeof(pubsub_udp_msg_t) + msg->payloadSize; - struct iovec msg_iovec[iovec_len]; msg_iovec[0].iov_base = msg->header; msg_iovec[0].iov_len = sizeof(*msg->header); @@ -299,7 +299,6 @@ static bool send_pubsub_msg(publish_bundle_bound_service_pt bound, pubsub_msg_t* delay_first_send_for_late_joiners(); if(largeUdp_sendmsg(bound->largeUdpHandle, bound->parent->sendSocket, msg_iovec, iovec_len, 0, &bound->parent->destAddr, sizeof(bound->parent->destAddr)) == -1) { - fprintf(stderr, "Socket: %d, size: %i",bound->parent->sendSocket, compiledMsgSize); perror("send_pubsub_msg:sendSocket"); ret = false; } @@ -342,7 +341,7 @@ static int pubsub_topicPublicationSend(void* handle, unsigned int msgTypeId, con pubsub_msg_t *msg = calloc(1,sizeof(pubsub_msg_t)); msg->header = msg_hdr; - msg->payload = (char *)serializedOutput; + msg->payload = (char*)serializedOutput; msg->payloadSize = serializedOutputLen; From e0d33e5ae70b9383cdd5b9c6381ffc93e89bb8df Mon Sep 17 00:00:00 2001 From: gricciardi Date: Thu, 21 Sep 2017 10:42:00 +0200 Subject: [PATCH 3/6] Fixed small leak in PSA UDP_MC topic_subscription --- .../private/src/topic_subscription.c | 135 +++++++++--------- 1 file changed, 66 insertions(+), 69 deletions(-) diff --git a/pubsub/pubsub_admin_udp_mc/private/src/topic_subscription.c b/pubsub/pubsub_admin_udp_mc/private/src/topic_subscription.c index 58962648f..9bf0f8024 100644 --- a/pubsub/pubsub_admin_udp_mc/private/src/topic_subscription.c +++ b/pubsub/pubsub_admin_udp_mc/private/src/topic_subscription.c @@ -243,85 +243,82 @@ celix_status_t pubsub_topicSubscriptionConnectPublisher(topic_subscription_pt ts celix_status_t status = CELIX_SUCCESS; celixThreadMutex_lock(&ts->ts_lock); - if(hashMap_containsKey(ts->socketMap, pubURL)){ - printf("PSA_UDM_MC_TS: PubURL %s already existing!\n",pubURL); - celixThreadMutex_unlock(&ts->ts_lock); - return CELIX_SERVICE_EXCEPTION; - } - - int *recvSocket = calloc(sizeof(int), 1); - *recvSocket = socket(AF_INET, SOCK_DGRAM, 0); - if (*recvSocket < 0) { - perror("pubsub_topicSubscriptionCreate:socket"); - status = CELIX_SERVICE_EXCEPTION; - } - - if (status == CELIX_SUCCESS){ - int reuse = 1; - if (setsockopt(*recvSocket, SOL_SOCKET, SO_REUSEADDR, (char*) &reuse, sizeof(reuse)) != 0) { - perror("setsockopt() SO_REUSEADDR"); - status = CELIX_SERVICE_EXCEPTION; - } - } + if(!hashMap_containsKey(ts->socketMap, pubURL)){ - if(status == CELIX_SUCCESS){ - // TODO Check if there is a better way to parse the URL to IP/Portnr - //replace ':' by spaces - char *url = strdup(pubURL); - char *pt = url; - while((pt=strchr(pt, ':')) != NULL) { - *pt = ' '; - } - char mcIp[100]; - unsigned short mcPort; - sscanf(url, "udp //%s %hu", mcIp, &mcPort); - free (url); - - printf("pubsub_topicSubscriptionConnectPublisher : IP = %s, Port = %hu\n", mcIp, mcPort); - - struct ip_mreq mc_addr; - mc_addr.imr_multiaddr.s_addr = inet_addr(mcIp); - mc_addr.imr_interface.s_addr = inet_addr(ts->ifIpAddress); - printf("Adding MC %s at interface %s\n", mcIp, ts->ifIpAddress); - if (setsockopt(*recvSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*) &mc_addr, sizeof(mc_addr)) != 0) { - perror("setsockopt() IP_ADD_MEMBERSHIP"); + int *recvSocket = calloc(sizeof(int), 1); + *recvSocket = socket(AF_INET, SOCK_DGRAM, 0); + if (*recvSocket < 0) { + perror("pubsub_topicSubscriptionCreate:socket"); status = CELIX_SERVICE_EXCEPTION; } if (status == CELIX_SUCCESS){ - struct sockaddr_in mcListenAddr; - mcListenAddr.sin_family = AF_INET; - mcListenAddr.sin_addr.s_addr = INADDR_ANY; - mcListenAddr.sin_port = htons(mcPort); - if(bind(*recvSocket, (struct sockaddr*)&mcListenAddr, sizeof(mcListenAddr)) != 0) { - perror("bind()"); + int reuse = 1; + if (setsockopt(*recvSocket, SOL_SOCKET, SO_REUSEADDR, (char*) &reuse, sizeof(reuse)) != 0) { + perror("setsockopt() SO_REUSEADDR"); status = CELIX_SERVICE_EXCEPTION; } } - if (status == CELIX_SUCCESS){ -#if defined(__APPLE__) && defined(__MACH__) - //TODO: Use kqueue for OSX -#else - struct epoll_event ev; - memset(&ev, 0, sizeof(ev)); - ev.events = EPOLLIN; - ev.data.fd = *recvSocket; - if(epoll_ctl(ts->topicEpollFd, EPOLL_CTL_ADD, *recvSocket, &ev) == -1) { - perror("epoll_ctl() EPOLL_CTL_ADD"); + if(status == CELIX_SUCCESS){ + // TODO Check if there is a better way to parse the URL to IP/Portnr + //replace ':' by spaces + char *url = strdup(pubURL); + char *pt = url; + while((pt=strchr(pt, ':')) != NULL) { + *pt = ' '; + } + char mcIp[100]; + unsigned short mcPort; + sscanf(url, "udp //%s %hu", mcIp, &mcPort); + free(url); + + printf("pubsub_topicSubscriptionConnectPublisher : IP = %s, Port = %hu\n", mcIp, mcPort); + + struct ip_mreq mc_addr; + mc_addr.imr_multiaddr.s_addr = inet_addr(mcIp); + mc_addr.imr_interface.s_addr = inet_addr(ts->ifIpAddress); + printf("Adding MC %s at interface %s\n", mcIp, ts->ifIpAddress); + if (setsockopt(*recvSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*) &mc_addr, sizeof(mc_addr)) != 0) { + perror("setsockopt() IP_ADD_MEMBERSHIP"); status = CELIX_SERVICE_EXCEPTION; } + + if (status == CELIX_SUCCESS){ + struct sockaddr_in mcListenAddr; + mcListenAddr.sin_family = AF_INET; + mcListenAddr.sin_addr.s_addr = INADDR_ANY; + mcListenAddr.sin_port = htons(mcPort); + if(bind(*recvSocket, (struct sockaddr*)&mcListenAddr, sizeof(mcListenAddr)) != 0) { + perror("bind()"); + status = CELIX_SERVICE_EXCEPTION; + } + } + + if (status == CELIX_SUCCESS){ +#if defined(__APPLE__) && defined(__MACH__) + //TODO: Use kqueue for OSX +#else + struct epoll_event ev; + memset(&ev, 0, sizeof(ev)); + ev.events = EPOLLIN; + ev.data.fd = *recvSocket; + if(epoll_ctl(ts->topicEpollFd, EPOLL_CTL_ADD, *recvSocket, &ev) == -1) { + perror("epoll_ctl() EPOLL_CTL_ADD"); + status = CELIX_SERVICE_EXCEPTION; + } #endif - } + } - } + } - if (status == CELIX_SUCCESS){ - hashMap_put(ts->socketMap, strdup(pubURL), (void*)recvSocket); - }else{ - free(recvSocket); + if (status == CELIX_SUCCESS){ + hashMap_put(ts->socketMap, strdup(pubURL), (void*)recvSocket); + } + else{ + free(recvSocket); + } } - celixThreadMutex_unlock(&ts->ts_lock); return status; @@ -533,15 +530,15 @@ static void* udp_recv_thread_func(void * arg) { topic_subscription_pt sub = (topic_subscription_pt) arg; #if defined(__APPLE__) && defined(__MACH__) - //TODO: use kqueue for OSX - //struct kevent events[MAX_EPOLL_EVENTS]; - while (sub->running) { - int nfds = 0; + //TODO: use kqueue for OSX + //struct kevent events[MAX_EPOLL_EVENTS]; + while (sub->running) { + int nfds = 0; if(nfds > 0) { pubsub_udp_msg_t* udpMsg = NULL; process_msg(sub, udpMsg); } - } + } #else struct epoll_event events[MAX_EPOLL_EVENTS]; From d5ff9463a6f457a7b92f0fa4ca9c15dd69fe9cf5 Mon Sep 17 00:00:00 2001 From: gricciardi Date: Fri, 29 Sep 2017 14:34:28 +0200 Subject: [PATCH 4/6] Fixed uninitialized variables warning --- pubsub/pubsub_admin_udp_mc/private/src/pubsub_admin_impl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubsub/pubsub_admin_udp_mc/private/src/pubsub_admin_impl.c b/pubsub/pubsub_admin_udp_mc/private/src/pubsub_admin_impl.c index 6f9427b44..8268287b4 100644 --- a/pubsub/pubsub_admin_udp_mc/private/src/pubsub_admin_impl.c +++ b/pubsub/pubsub_admin_udp_mc/private/src/pubsub_admin_impl.c @@ -116,7 +116,7 @@ celix_status_t pubsubAdmin_create(bundle_context_pt context, pubsub_admin_pt *ad if (mc_ip == NULL) { const char *mc_prefix = NULL; const char *interface = NULL; - int b0, b1, b2, b3; + int b0 = 0, b1 = 0, b2 = 0, b3 = 0; bundleContext_getProperty(context,PSA_MULTICAST_IP_PREFIX , &mc_prefix); if(mc_prefix == NULL) { mc_prefix = DEFAULT_MC_PREFIX; From 683701a12ca961b2c091619ee49d00fed8879909 Mon Sep 17 00:00:00 2001 From: gricciardi Date: Fri, 29 Sep 2017 14:59:08 +0200 Subject: [PATCH 5/6] Added missing file during compilation --- pubsub/pubsub_admin_udp_mc/CMakeLists.txt | 1 + pubsub/pubsub_discovery/CMakeLists.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/pubsub/pubsub_admin_udp_mc/CMakeLists.txt b/pubsub/pubsub_admin_udp_mc/CMakeLists.txt index 86f7a472d..7be1ee9dd 100644 --- a/pubsub/pubsub_admin_udp_mc/CMakeLists.txt +++ b/pubsub/pubsub_admin_udp_mc/CMakeLists.txt @@ -38,6 +38,7 @@ add_bundle(org.apache.celix.pubsub_admin.PubSubAdminUdpMc ${PROJECT_SOURCE_DIR}/pubsub/pubsub_common/public/src/pubsub_endpoint.c ${PROJECT_SOURCE_DIR}/pubsub/pubsub_common/public/src/log_helper.c ${PROJECT_SOURCE_DIR}/pubsub/pubsub_common/public/src/pubsub_admin_match.c + ${PROJECT_SOURCE_DIR}/pubsub/pubsub_common/public/src/pubsub_utils.c ) set_target_properties(org.apache.celix.pubsub_admin.PubSubAdminUdpMc PROPERTIES INSTALL_RPATH "$ORIGIN") diff --git a/pubsub/pubsub_discovery/CMakeLists.txt b/pubsub/pubsub_discovery/CMakeLists.txt index f568f0c32..948da3e8a 100644 --- a/pubsub/pubsub_discovery/CMakeLists.txt +++ b/pubsub/pubsub_discovery/CMakeLists.txt @@ -36,6 +36,7 @@ add_bundle(org.apache.celix.pubsub_discovery.etcd.PubsubDiscovery private/src/etcd_watcher.c private/src/etcd_writer.c ${PROJECT_SOURCE_DIR}/pubsub/pubsub_common/public/src/pubsub_endpoint.c + ${PROJECT_SOURCE_DIR}/pubsub/pubsub_common/public/src/pubsub_utils.c ) target_link_libraries(org.apache.celix.pubsub_discovery.etcd.PubsubDiscovery celix_framework celix_utils etcdlib_static ${CURL_LIBRARIES} ${JANSSON_LIBRARIES}) From a89ca588a9399da2fb66936ae333b4f4a18faecd Mon Sep 17 00:00:00 2001 From: gricciardi Date: Fri, 29 Sep 2017 15:16:28 +0200 Subject: [PATCH 6/6] Disabled pubsub build for MacOSX --- .travis.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index fba0352d4..279e54887 100644 --- a/.travis.yml +++ b/.travis.yml @@ -72,8 +72,6 @@ before_script: -DBUILD_DEPENDENCY_MANAGER=ON \ -DBUILD_EXAMPLES=ON -DBUILD_LOG_SERVICE=ON \ -DBUILD_LOG_WRITER=ON \ - -DBUILD_PUBSUB=ON \ - -DBUILD_PUBSUB_PSA_ZMQ=ON \ -DBUILD_REMOTE_SERVICE_ADMIN=ON \ -DBUILD_RSA_DISCOVERY_CONFIGURED=ON \ -DBUILD_RSA_DISCOVERY_ETCD=ON \ @@ -85,9 +83,13 @@ before_script: -DBUILD_DEVICE_ACCESS_EXAMPLE=ON " - export BUILD_OPTIONS_LINUX=" \ -DBUILD_RSA_REMOTE_SERVICE_ADMIN_SHM=ON \ + -DBUILD_PUBSUB=ON \ + -DBUILD_PUBSUB_PSA_ZMQ=ON \ -DBUILD_RSA_DISCOVERY_SHM=ON " - export BUILD_OPTIONS_OSX=" \ -DBUILD_RSA_REMOTE_SERVICE_ADMIN_SHM=OFF \ + -DBUILD_PUBSUB=OFF \ + -DBUILD_PUBSUB_PSA_ZMQ=OFF \ -DBUILD_RSA_DISCOVERY_SHM=OFF " - export BUILD_OPTIONS_SANITIZE=" -DENABLE_ADDRESS_SANITIZER=ON"