You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by rl...@apache.org on 2018/02/02 13:38:08 UTC
[1/4] celix git commit: Changing pubsub endpoint to store more
information in etcd
Repository: celix
Updated Branches:
refs/heads/develop a8b8410f1 -> 0a5ef69a6
Changing pubsub endpoint to store more information in etcd
Project: http://git-wip-us.apache.org/repos/asf/celix/repo
Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/9094f554
Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/9094f554
Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/9094f554
Branch: refs/heads/develop
Commit: 9094f554217e963797910306359c89b145518724
Parents: d7307ff
Author: Roy Lenferink <rl...@apache.org>
Authored: Wed Jan 31 17:26:11 2018 +0100
Committer: Roy Lenferink <rl...@apache.org>
Committed: Fri Feb 2 11:48:19 2018 +0100
----------------------------------------------------------------------
.../private/src/pubsub_admin_impl.c | 103 ++++++++++++-------
.../private/src/topic_publication.c | 15 +--
.../private/src/pubsub_admin_impl.c | 99 +++++++++++-------
.../private/src/topic_publication.c | 13 +--
.../public/include/pubsub_endpoint.h | 19 ++--
.../pubsub_common/public/src/pubsub_endpoint.c | 88 ++++++++++------
.../pubsub_discovery/private/src/etcd_watcher.c | 56 +++++++++-
.../pubsub_discovery/private/src/etcd_writer.c | 44 ++++++--
.../private/src/pubsub_discovery_impl.c | 19 ++--
.../private/src/pubsub_topology_manager.c | 40 ++++---
utils/private/src/properties.c | 5 +
utils/public/include/properties.h | 2 +
12 files changed, 343 insertions(+), 160 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/celix/blob/9094f554/pubsub/pubsub_admin_udp_mc/private/src/pubsub_admin_impl.c
----------------------------------------------------------------------
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 1fbdb08..8124950 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
@@ -311,7 +311,9 @@ static celix_status_t pubsubAdmin_addAnySubscription(pubsub_admin_pt admin,pubsu
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);
+ printf("PSA_UDP_MC: Cannot find a serializer for subscribing topic %s. Adding it to pending list.\n",
+ properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+
celixThreadMutex_lock(&admin->noSerializerPendingsLock);
arrayList_add(admin->noSerializerSubscriptions,subEP);
celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
@@ -330,8 +332,8 @@ static celix_status_t pubsubAdmin_addAnySubscription(pubsub_admin_pt admin,pubsu
if(topic_publishers!=NULL){
for(i=0;i<arrayList_size(topic_publishers);i++){
pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(topic_publishers,i);
- if(pubEP->endpoint !=NULL){
- status += pubsub_topicSubscriptionConnectPublisher(any_sub,pubEP->endpoint);
+ if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
+ status += pubsub_topicSubscriptionConnectPublisher(any_sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
}
}
arrayList_destroy(topic_publishers);
@@ -348,8 +350,8 @@ static celix_status_t pubsubAdmin_addAnySubscription(pubsub_admin_pt admin,pubsu
if(ext_pub_list!=NULL){
for(i=0;i<arrayList_size(ext_pub_list);i++){
pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(ext_pub_list,i);
- if(pubEP->endpoint !=NULL){
- status += pubsub_topicSubscriptionConnectPublisher(any_sub,pubEP->endpoint);
+ if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
+ status += pubsub_topicSubscriptionConnectPublisher(any_sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
}
}
}
@@ -379,9 +381,13 @@ 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_UDP_MC: 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",
+ properties_get(subEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
+ subEP->serviceID,
+ properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
+ properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
- if(strcmp(subEP->topic,PUBSUB_ANY_SUB_TOPIC)==0){
+ if(strcmp(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),PUBSUB_ANY_SUB_TOPIC)==0){
return pubsubAdmin_addAnySubscription(admin,subEP);
}
@@ -391,7 +397,7 @@ celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint
celixThreadMutex_lock(&admin->localPublicationsLock);
celixThreadMutex_lock(&admin->externalPublicationsLock);
- char* scope_topic = createScopeTopicKey(subEP->scope,subEP->topic);
+ char* scope_topic = createScopeTopicKey(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_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);
@@ -406,10 +412,12 @@ celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint
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);
+ status += pubsub_topicSubscriptionCreate(admin->bundle_context,admin->ifIpAddress, (char*) properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), (char*) properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_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);
+ printf("PSA_UDP_MC: Cannot find a serializer for subscribing topic %s. Adding it to pending list.\n",
+ properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+
celixThreadMutex_lock(&admin->noSerializerPendingsLock);
arrayList_add(admin->noSerializerSubscriptions,subEP);
celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
@@ -425,8 +433,8 @@ celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint
if(topic_publishers!=NULL){
for(i=0;i<arrayList_size(topic_publishers);i++){
pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(topic_publishers,i);
- if(pubEP->endpoint !=NULL){
- status += pubsub_topicSubscriptionConnectPublisher(subscription,pubEP->endpoint);
+ if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
+ status += pubsub_topicSubscriptionConnectPublisher(subscription, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
}
}
arrayList_destroy(topic_publishers);
@@ -438,8 +446,8 @@ celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint
if(ext_pub_list!=NULL){
for(i=0;i<arrayList_size(ext_pub_list);i++){
pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(ext_pub_list,i);
- if(pubEP->endpoint !=NULL){
- status += pubsub_topicSubscriptionConnectPublisher(subscription,pubEP->endpoint);
+ if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
+ status += pubsub_topicSubscriptionConnectPublisher(subscription, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
}
}
}
@@ -476,9 +484,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_UDP_MC: 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",
+ properties_get(subEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
+ subEP->serviceID,
+ properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
+ properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
- char* scope_topic = createScopeTopicKey(subEP->scope, subEP->topic);
+ char* scope_topic = createScopeTopicKey(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
celixThreadMutex_lock(&admin->subscriptionsLock);
topic_subscription_pt sub = (topic_subscription_pt)hashMap_get(admin->subscriptions,scope_topic);
@@ -510,7 +522,11 @@ 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_UDP_MC: 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",
+ properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
+ pubEP->serviceID,
+ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
+ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
const char* fwUUID = NULL;
@@ -519,9 +535,9 @@ celix_status_t pubsubAdmin_addPublication(pubsub_admin_pt admin,pubsub_endpoint_
printf("PSA_UDP_MC: Cannot retrieve fwUUID.\n");
return CELIX_INVALID_BUNDLE_CONTEXT;
}
- char* scope_topic = createScopeTopicKey(pubEP->scope, pubEP->topic);
+ char* scope_topic = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
- if ((strcmp(pubEP->frameworkUUID, fwUUID) == 0) && (pubEP->endpoint == NULL)) {
+ if ((strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID), fwUUID) == 0) && (properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) == NULL)) {
celixThreadMutex_lock(&admin->localPublicationsLock);
@@ -534,7 +550,9 @@ celix_status_t pubsubAdmin_addPublication(pubsub_admin_pt admin,pubsub_endpoint_
status = pubsub_topicPublicationCreate(admin->sendSocket, pubEP, best_serializer, admin->mcIpAddress, &pub);
}
else{
- printf("PSA_UDP_MC: Cannot find a serializer for publishing topic %s. Adding it to pending list.\n", pubEP->topic);
+ printf("PSA_UDP_MC: Cannot find a serializer for publishing topic %s. Adding it to pending list.\n",
+ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+
celixThreadMutex_lock(&admin->noSerializerPendingsLock);
arrayList_add(admin->noSerializerPublications,pubEP);
celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
@@ -547,7 +565,10 @@ celix_status_t pubsubAdmin_addPublication(pubsub_admin_pt admin,pubsub_endpoint_
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);
+ printf("PSA_UDP_MC: Cannot create a topicPublication for scope=%s, topic=%s (bundle %ld).\n",
+ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
+ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
+ pubEP->serviceID);
}
} else {
//just add the new EP to the list
@@ -595,14 +616,14 @@ celix_status_t pubsubAdmin_addPublication(pubsub_admin_pt admin,pubsub_endpoint_
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);
+ if (sub != NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) != NULL) {
+ pubsub_topicSubscriptionAddConnectPublisherToPendingList(sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
}
/* 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);
+ if (any_sub != NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) != NULL) {
+ pubsub_topicSubscriptionAddConnectPublisherToPendingList(any_sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
}
free(scope_topic);
@@ -617,7 +638,11 @@ celix_status_t pubsubAdmin_removePublication(pubsub_admin_pt admin,pubsub_endpoi
celix_status_t status = CELIX_SUCCESS;
int count = 0;
- printf("PSA_UDP_MC: 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",
+ properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
+ pubEP->serviceID,
+ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
+ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
const char* fwUUID = NULL;
@@ -626,9 +651,9 @@ celix_status_t pubsubAdmin_removePublication(pubsub_admin_pt admin,pubsub_endpoi
printf("PSA_UDP_MC: Cannot retrieve fwUUID.\n");
return CELIX_INVALID_BUNDLE_CONTEXT;
}
- char *scope_topic = createScopeTopicKey(pubEP->scope, pubEP->topic);
+ char *scope_topic = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
- if(strcmp(pubEP->frameworkUUID,fwUUID)==0){
+ if(strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),fwUUID)==0){
celixThreadMutex_lock(&admin->localPublicationsLock);
service_factory_pt factory = (service_factory_pt)hashMap_get(admin->localPublications,scope_topic);
@@ -665,7 +690,7 @@ celix_status_t pubsubAdmin_removePublication(pubsub_admin_pt admin,pubsub_endpoi
// Check if there are more publishers on the same endpoint (happens when 1 celix-instance with multiple bundles publish in same topic)
for(i=0; i<arrayList_size(ext_pub_list);i++) {
pubsub_endpoint_pt p = (pubsub_endpoint_pt)arrayList_get(ext_pub_list,i);
- if (strcmp(pubEP->endpoint,p->endpoint) == 0) {
+ if (strcmp(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL),properties_get(p->endpoint_props, PUBSUB_ENDPOINT_URL)) == 0) {
count++;
}
}
@@ -687,14 +712,14 @@ 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 && count == 0){
- pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(sub,pubEP->endpoint);
+ if(sub!=NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL && count == 0){
+ pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
}
/* 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);
+ if(any_sub!=NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL && count == 0){
+ pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(any_sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
}
free(scope_topic);
@@ -793,7 +818,7 @@ 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){
celix_status_t status = CELIX_SUCCESS;
- char* scope_topic =createScopeTopicKey(subEP->scope, subEP->topic);
+ char* scope_topic =createScopeTopicKey(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
array_list_pt pendingListPerTopic = hashMap_get(admin->pendingSubscriptions,scope_topic);
if(pendingListPerTopic==NULL){
arrayList_create(&pendingListPerTopic);
@@ -888,9 +913,8 @@ celix_status_t pubsubAdmin_serializerRemoved(void * handle, service_reference_pt
/* Remove the publication */
pubsubAdmin_removePublication(admin, pubEP);
/* Reset the endpoint field, so that will be recreated from scratch when a new serializer will be found */
- if(pubEP->endpoint!=NULL){
- free(pubEP->endpoint);
- pubEP->endpoint = NULL;
+ if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL){
+ properties_unset(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL);
}
/* Add the orphan endpoint to the noSerializer pending list */
celixThreadMutex_lock(&admin->noSerializerPendingsLock);
@@ -940,9 +964,8 @@ celix_status_t pubsubAdmin_serializerRemoved(void * handle, service_reference_pt
/* Remove the subscription */
pubsubAdmin_removeSubscription(admin, subEP);
/* Reset the endpoint field, so that will be recreated from scratch when a new serializer will be found */
- if(subEP->endpoint!=NULL){
- free(subEP->endpoint);
- subEP->endpoint = NULL;
+ if(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL){
+ properties_unset(subEP->endpoint_props, PUBSUB_ENDPOINT_URL);
}
/* Add the orphan endpoint to the noSerializer pending list */
celixThreadMutex_lock(&admin->noSerializerPendingsLock);
http://git-wip-us.apache.org/repos/asf/celix/blob/9094f554/pubsub/pubsub_admin_udp_mc/private/src/topic_publication.c
----------------------------------------------------------------------
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 e43ec29..52abeda 100644
--- a/pubsub/pubsub_admin_udp_mc/private/src/topic_publication.c
+++ b/pubsub/pubsub_admin_udp_mc/private/src/topic_publication.c
@@ -174,14 +174,17 @@ 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_TOPIC,pubEP->topic);
+ properties_set(props,PUBSUB_PUBLISHER_SCOPE,properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE));
+ properties_set(props,PUBSUB_PUBLISHER_TOPIC,properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
status = bundleContext_registerServiceFactory(bundle_context,PUBSUB_PUBLISHER_SERVICE_NAME,factory,props,&(pub->svcFactoryReg));
if(status != CELIX_SUCCESS){
properties_destroy(props);
- 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);
+ printf("PSA_UDP_MC_PSA_UDP_MC_TP: Cannot register ServiceFactory for topic %s, topic %s (bundle %ld).\n",
+ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
+ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
+ pubEP->serviceID);
}
else{
*svcFactory = factory;
@@ -202,7 +205,7 @@ celix_status_t pubsub_topicPublicationStop(topic_publication_pt pub){
celix_status_t pubsub_topicPublicationAddPublisherEP(topic_publication_pt pub,pubsub_endpoint_pt ep){
celixThreadMutex_lock(&(pub->tp_lock));
- ep->endpoint = strdup(pub->endpoint);
+ pubsubEndpoint_setField(ep, PUBSUB_ENDPOINT_URL, pub->endpoint);
arrayList_add(pub->pub_ep_list,ep);
celixThreadMutex_unlock(&(pub->tp_lock));
@@ -393,8 +396,8 @@ static publish_bundle_bound_service_pt pubsub_createPublishBundleBoundService(to
}
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->scope=strdup(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE));
+ bound->topic=strdup(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
bound->largeUdpHandle = largeUdp_create(1);
bound->service.handle = bound;
http://git-wip-us.apache.org/repos/asf/celix/blob/9094f554/pubsub/pubsub_admin_zmq/private/src/pubsub_admin_impl.c
----------------------------------------------------------------------
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 29ead0c..9a486dd 100644
--- a/pubsub/pubsub_admin_zmq/private/src/pubsub_admin_impl.c
+++ b/pubsub/pubsub_admin_zmq/private/src/pubsub_admin_impl.c
@@ -312,7 +312,8 @@ static celix_status_t pubsubAdmin_addAnySubscription(pubsub_admin_pt admin,pubsu
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);
+ printf("PSA_ZMQ: Cannot find a serializer for subscribing topic %s. Adding it to pending list.\n",
+ properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
celixThreadMutex_lock(&admin->noSerializerPendingsLock);
arrayList_add(admin->noSerializerSubscriptions,subEP);
celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
@@ -331,8 +332,8 @@ static celix_status_t pubsubAdmin_addAnySubscription(pubsub_admin_pt admin,pubsu
if(topic_publishers!=NULL){
for(i=0;i<arrayList_size(topic_publishers);i++){
pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(topic_publishers,i);
- if(pubEP->endpoint !=NULL){
- status += pubsub_topicSubscriptionConnectPublisher(any_sub,pubEP->endpoint);
+ if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
+ status += pubsub_topicSubscriptionConnectPublisher(any_sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
}
}
arrayList_destroy(topic_publishers);
@@ -349,8 +350,8 @@ static celix_status_t pubsubAdmin_addAnySubscription(pubsub_admin_pt admin,pubsu
if(ext_pub_list!=NULL){
for(i=0;i<arrayList_size(ext_pub_list);i++){
pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(ext_pub_list,i);
- if(pubEP->endpoint !=NULL){
- status += pubsub_topicSubscriptionConnectPublisher(any_sub,pubEP->endpoint);
+ if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
+ status += pubsub_topicSubscriptionConnectPublisher(any_sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
}
}
}
@@ -380,9 +381,13 @@ 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_ZMQ: 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",
+ properties_get(subEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
+ subEP->serviceID,
+ properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
+ properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
- if(strcmp(subEP->topic,PUBSUB_ANY_SUB_TOPIC)==0){
+ if(strcmp(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),PUBSUB_ANY_SUB_TOPIC)==0){
return pubsubAdmin_addAnySubscription(admin,subEP);
}
@@ -392,7 +397,7 @@ celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint
celixThreadMutex_lock(&admin->localPublicationsLock);
celixThreadMutex_lock(&admin->externalPublicationsLock);
- char* scope_topic = createScopeTopicKey(subEP->scope, subEP->topic);
+ char* scope_topic = createScopeTopicKey(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_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);
@@ -407,10 +412,11 @@ celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint
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,subEP->scope, subEP->topic, best_serializer, &subscription);
+ status += pubsub_topicSubscriptionCreate(admin->bundle_context, (char*) properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), (char*) properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC), best_serializer, &subscription);
}
else{
- printf("PSA_ZMQ: Cannot find a serializer for subscribing topic %s. Adding it to pending list.\n",subEP->topic);
+ printf("PSA_ZMQ: Cannot find a serializer for subscribing topic %s. Adding it to pending list.\n",
+ properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
celixThreadMutex_lock(&admin->noSerializerPendingsLock);
arrayList_add(admin->noSerializerSubscriptions,subEP);
celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
@@ -426,8 +432,8 @@ celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint
if(topic_publishers!=NULL){
for(i=0;i<arrayList_size(topic_publishers);i++){
pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(topic_publishers,i);
- if(pubEP->endpoint !=NULL){
- status += pubsub_topicSubscriptionConnectPublisher(subscription,pubEP->endpoint);
+ if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
+ status += pubsub_topicSubscriptionConnectPublisher(subscription,(char*)properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
}
}
arrayList_destroy(topic_publishers);
@@ -439,8 +445,8 @@ celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint
if(ext_pub_list!=NULL){
for(i=0;i<arrayList_size(ext_pub_list);i++){
pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(ext_pub_list,i);
- if(pubEP->endpoint !=NULL){
- status += pubsub_topicSubscriptionConnectPublisher(subscription,pubEP->endpoint);
+ if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
+ status += pubsub_topicSubscriptionConnectPublisher(subscription,(char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
}
}
}
@@ -477,9 +483,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_ZMQ: 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",
+ properties_get(subEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
+ subEP->serviceID,
+ properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
- char* scope_topic = createScopeTopicKey(subEP->scope, subEP->topic);
+ char* scope_topic = createScopeTopicKey(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
celixThreadMutex_lock(&admin->subscriptionsLock);
topic_subscription_pt sub = (topic_subscription_pt)hashMap_get(admin->subscriptions,scope_topic);
@@ -511,7 +520,11 @@ 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_ZMQ: Received publication [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n", pubEP->frameworkUUID, pubEP->serviceID, pubEP->scope, pubEP->topic);
+ printf("PSA_ZMQ: Received publication [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",
+ properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
+ pubEP->serviceID,
+ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
+ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
const char* fwUUID = NULL;
@@ -521,9 +534,10 @@ celix_status_t pubsubAdmin_addPublication(pubsub_admin_pt admin, pubsub_endpoint
return CELIX_INVALID_BUNDLE_CONTEXT;
}
- char *scope_topic = createScopeTopicKey(pubEP->scope, pubEP->topic);
+ char *scope_topic = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
- if ((strcmp(pubEP->frameworkUUID, fwUUID) == 0) && (pubEP->endpoint == NULL)) {
+ if ((strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID), fwUUID) == 0) &&
+ (properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) == NULL)) {
celixThreadMutex_lock(&admin->localPublicationsLock);
@@ -536,7 +550,8 @@ celix_status_t pubsubAdmin_addPublication(pubsub_admin_pt admin, pubsub_endpoint
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);
+ printf("PSA_ZMQ: Cannot find a serializer for publishing topic %s. Adding it to pending list.\n",
+ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
celixThreadMutex_lock(&admin->noSerializerPendingsLock);
arrayList_add(admin->noSerializerPublications,pubEP);
celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
@@ -549,7 +564,10 @@ celix_status_t pubsubAdmin_addPublication(pubsub_admin_pt admin, pubsub_endpoint
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);
+ printf("PSA_ZMQ: Cannot create a topicPublication for scope=%s, topic=%s (bundle %ld).\n",
+ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
+ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
+ pubEP->serviceID);
}
} else {
//just add the new EP to the list
@@ -597,14 +615,14 @@ celix_status_t pubsubAdmin_addPublication(pubsub_admin_pt admin, pubsub_endpoint
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);
+ if (sub != NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) != NULL) {
+ pubsub_topicSubscriptionAddConnectPublisherToPendingList(sub, (char*)properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
}
/* 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);
+ if (any_sub != NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) != NULL) {
+ pubsub_topicSubscriptionAddConnectPublisherToPendingList(any_sub, (char*)properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
}
free(scope_topic);
@@ -619,7 +637,10 @@ celix_status_t pubsubAdmin_removePublication(pubsub_admin_pt admin,pubsub_endpoi
celix_status_t status = CELIX_SUCCESS;
int count = 0;
- printf("PSA_ZMQ: 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",
+ properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
+ pubEP->serviceID,
+ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
const char* fwUUID = NULL;
@@ -628,9 +649,9 @@ celix_status_t pubsubAdmin_removePublication(pubsub_admin_pt admin,pubsub_endpoi
printf("PSA_ZMQ: Cannot retrieve fwUUID.\n");
return CELIX_INVALID_BUNDLE_CONTEXT;
}
- char *scope_topic = createScopeTopicKey(pubEP->scope, pubEP->topic);
+ char *scope_topic = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
- if(strcmp(pubEP->frameworkUUID,fwUUID)==0){
+ if(strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),fwUUID)==0){
celixThreadMutex_lock(&admin->localPublicationsLock);
service_factory_pt factory = (service_factory_pt)hashMap_get(admin->localPublications,scope_topic);
@@ -666,7 +687,7 @@ celix_status_t pubsubAdmin_removePublication(pubsub_admin_pt admin,pubsub_endpoi
// Check if there are more publishers on the same endpoint (happens when 1 celix-instance with multiple bundles publish in same topic)
for(i=0; i<arrayList_size(ext_pub_list);i++) {
pubsub_endpoint_pt p = (pubsub_endpoint_pt)arrayList_get(ext_pub_list,i);
- if (strcmp(pubEP->endpoint,p->endpoint) == 0) {
+ if (strcmp(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL),properties_get(p->endpoint_props, PUBSUB_ENDPOINT_URL)) == 0) {
count++;
}
}
@@ -688,14 +709,14 @@ 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 && count == 0){
- pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(sub,pubEP->endpoint);
+ if(sub!=NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL && count == 0){
+ pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(sub,(char*)properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
}
/* 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);
+ if(any_sub!=NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL && count == 0){
+ pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(any_sub,(char*)properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
}
free(scope_topic);
@@ -793,7 +814,7 @@ 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){
celix_status_t status = CELIX_SUCCESS;
- char* scope_topic = createScopeTopicKey(subEP->scope, subEP->topic);
+ char* scope_topic = createScopeTopicKey(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
array_list_pt pendingListPerTopic = hashMap_get(admin->pendingSubscriptions,scope_topic);
if(pendingListPerTopic==NULL){
arrayList_create(&pendingListPerTopic);
@@ -887,9 +908,8 @@ celix_status_t pubsubAdmin_serializerRemoved(void * handle, service_reference_pt
/* Remove the publication */
pubsubAdmin_removePublication(admin, pubEP);
/* Reset the endpoint field, so that will be recreated from scratch when a new serializer will be found */
- if(pubEP->endpoint!=NULL){
- free(pubEP->endpoint);
- pubEP->endpoint = NULL;
+ if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL){
+ properties_unset(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL);
}
/* Add the orphan endpoint to the noSerializer pending list */
celixThreadMutex_lock(&admin->noSerializerPendingsLock);
@@ -939,9 +959,8 @@ celix_status_t pubsubAdmin_serializerRemoved(void * handle, service_reference_pt
/* Remove the subscription */
pubsubAdmin_removeSubscription(admin, subEP);
/* Reset the endpoint field, so that will be recreated from scratch when a new serializer will be found */
- if(subEP->endpoint!=NULL){
- free(subEP->endpoint);
- subEP->endpoint = NULL;
+ if(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL){
+ properties_unset(subEP->endpoint_props, PUBSUB_ENDPOINT_URL);
}
/* Add the orphan endpoint to the noSerializer pending list */
celixThreadMutex_lock(&admin->noSerializerPendingsLock);
http://git-wip-us.apache.org/repos/asf/celix/blob/9094f554/pubsub/pubsub_admin_zmq/private/src/topic_publication.c
----------------------------------------------------------------------
diff --git a/pubsub/pubsub_admin_zmq/private/src/topic_publication.c b/pubsub/pubsub_admin_zmq/private/src/topic_publication.c
index 34c25b3..105d540 100644
--- a/pubsub/pubsub_admin_zmq/private/src/topic_publication.c
+++ b/pubsub/pubsub_admin_zmq/private/src/topic_publication.c
@@ -198,7 +198,7 @@ celix_status_t pubsub_topicPublicationCreate(bundle_context_pt bundle_context, p
memset(bindAddress, 0, EP_ADDRESS_LEN);
snprintf(ep,EP_ADDRESS_LEN,"tcp://%s:%u",bindIP,port);
- snprintf(bindAddress, EP_ADDRESS_LEN, "tcp://0.0.0.0:%u", port); //NOTE using a different bind addres than endpoint address
+ snprintf(bindAddress, EP_ADDRESS_LEN, "tcp://0.0.0.0:%u", port); //NOTE using a different bind address than endpoint address
rv = zsock_bind (socket, "%s", bindAddress);
if (rv == -1) {
perror("Error for zmq_bind");
@@ -289,15 +289,16 @@ 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_TOPIC,pubEP->topic);
- properties_set(props,PUBSUB_PUBLISHER_SCOPE,pubEP->scope);
+ properties_set(props,PUBSUB_PUBLISHER_TOPIC,properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+ properties_set(props,PUBSUB_PUBLISHER_SCOPE,properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE));
properties_set(props,"service.version", PUBSUB_PUBLISHER_SERVICE_VERSION);
status = bundleContext_registerServiceFactory(bundle_context,PUBSUB_PUBLISHER_SERVICE_NAME,factory,props,&(pub->svcFactoryReg));
if(status != CELIX_SUCCESS){
properties_destroy(props);
- printf("PSA_ZMQ_PSA_ZMQ_TP: 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",
+ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),pubEP->serviceID);
}
else{
*svcFactory = factory;
@@ -318,7 +319,7 @@ celix_status_t pubsub_topicPublicationStop(topic_publication_pt pub){
celix_status_t pubsub_topicPublicationAddPublisherEP(topic_publication_pt pub,pubsub_endpoint_pt ep){
celixThreadMutex_lock(&(pub->tp_lock));
- ep->endpoint = strdup(pub->endpoint);
+ pubsubEndpoint_setField(ep, PUBSUB_ENDPOINT_URL, pub->endpoint);
arrayList_add(pub->pub_ep_list,ep);
celixThreadMutex_unlock(&(pub->tp_lock));
@@ -587,7 +588,7 @@ static publish_bundle_bound_service_pt pubsub_createPublishBundleBoundService(to
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->topic=strdup(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
bound->service.handle = bound;
bound->service.localMsgTypeIdForMsgType = pubsub_localMsgTypeIdForUUID;
http://git-wip-us.apache.org/repos/asf/celix/blob/9094f554/pubsub/pubsub_common/public/include/pubsub_endpoint.h
----------------------------------------------------------------------
diff --git a/pubsub/pubsub_common/public/include/pubsub_endpoint.h b/pubsub/pubsub_common/public/include/pubsub_endpoint.h
index 8a979eb..0a0b727 100644
--- a/pubsub/pubsub_common/public/include/pubsub_endpoint.h
+++ b/pubsub/pubsub_common/public/include/pubsub_endpoint.h
@@ -34,13 +34,19 @@
#include "publisher.h"
#include "subscriber.h"
+#define PUBSUB_ENDPOINT_ID "pubsub.endpoint.id"
+#define PUBSUB_ENDPOINT_SERVICE_ID "service.id"
+#define PUBSUB_ENDPOINT_SERIALIZER "serializer"
+#define PUBSUB_ENDPOINT_ADMIN_TYPE "pubsub.admin.type"
+#define PUBSUB_ENDPOINT_URL "pubsub.endpoint"
+#define PUBSUB_ENDPOINT_TOPIC "pubsub.topic"
+#define PUBSUB_ENDPOINT_SCOPE "pubsub.scope"
+#define PUBSUB_ENDPOINT_TYPE "pubsub.type"
+
struct pubsub_endpoint {
- char *frameworkUUID;
- char *scope;
- char *topic;
- long serviceID;
- char* endpoint;
- bool is_secure;
+ long serviceID; //optional
+ bool is_secure; //optional
+ properties_pt endpoint_props;
properties_pt topic_props;
};
@@ -52,6 +58,7 @@ celix_status_t pubsubEndpoint_createFromListenerHookInfo(listener_hook_info_pt i
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);
+celix_status_t pubsubEndpoint_setField(pubsub_endpoint_pt ep, const char* key, const char* value);
char *createScopeTopicKey(const char* scope, const char* topic);
http://git-wip-us.apache.org/repos/asf/celix/blob/9094f554/pubsub/pubsub_common/public/src/pubsub_endpoint.c
----------------------------------------------------------------------
diff --git a/pubsub/pubsub_common/public/src/pubsub_endpoint.c b/pubsub/pubsub_common/public/src/pubsub_endpoint.c
index c3fd293..d3b746e 100644
--- a/pubsub/pubsub_common/public/src/pubsub_endpoint.c
+++ b/pubsub/pubsub_common/public/src/pubsub_endpoint.c
@@ -26,6 +26,7 @@
#include <string.h>
#include <stdlib.h>
+#include <uuid/uuid.h>
#include "celix_errno.h"
#include "celix_log.h"
@@ -42,22 +43,33 @@ static properties_pt pubsubEndpoint_getTopicProperties(bundle_pt bundle, const c
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 (psEp->endpoint_props == NULL) {
+ psEp->endpoint_props = properties_create();
+ }
+
+ char endpointUuid[37];
+
+ uuid_t endpointUid;
+ uuid_generate(endpointUid);
+ uuid_unparse(endpointUid, endpointUuid);
+ properties_set(psEp->endpoint_props, PUBSUB_ENDPOINT_ID, endpointUuid);
+
if (fwUUID != NULL) {
- psEp->frameworkUUID = strdup(fwUUID);
+ properties_set(psEp->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID, fwUUID);
}
if (scope != NULL) {
- psEp->scope = strdup(scope);
+ properties_set(psEp->endpoint_props, PUBSUB_ENDPOINT_SCOPE, scope);
}
if (topic != NULL) {
- psEp->topic = strdup(topic);
+ properties_set(psEp->endpoint_props, PUBSUB_ENDPOINT_TOPIC, topic);
}
psEp->serviceID = serviceId;
if(endpoint != NULL) {
- psEp->endpoint = strdup(endpoint);
+ properties_set(psEp->endpoint_props, PUBSUB_ENDPOINT_URL, endpoint);
}
if(topic_props != NULL){
@@ -102,6 +114,21 @@ static properties_pt pubsubEndpoint_getTopicProperties(bundle_pt bundle, const c
return topic_props;
}
+celix_status_t pubsubEndpoint_setField(pubsub_endpoint_pt ep, const char* key, const char* value) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ if (ep->endpoint_props == NULL) {
+ printf("PUBSUB_EP: No endpoint_props for endpoint available!\n");
+ return CELIX_ILLEGAL_STATE;
+ }
+
+ if (key != NULL && value != NULL) {
+ properties_set(ep->endpoint_props, key, value);
+ }
+
+ return status;
+}
+
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;
@@ -116,9 +143,22 @@ celix_status_t pubsubEndpoint_create(const char* fwUUID, const char* scope, cons
celix_status_t pubsubEndpoint_clone(pubsub_endpoint_pt in, pubsub_endpoint_pt *out){
celix_status_t status = CELIX_SUCCESS;
- *out = calloc(1,sizeof(**out));
+ pubsub_endpoint_pt ep = calloc(1,sizeof(*ep));
- pubsubEndpoint_setFields(*out, in->frameworkUUID, in->scope, in->topic, in->serviceID, in->endpoint, in->topic_props, true);
+ status = properties_copy(in->endpoint_props, &(ep->endpoint_props));
+
+ if (in->topic_props != NULL) {
+ status += properties_copy(in->topic_props, &(ep->topic_props));
+ }
+
+ ep->serviceID = in->serviceID;
+ ep->is_secure = in->is_secure;
+
+ if (status == CELIX_SUCCESS) {
+ *out = ep;
+ } else {
+ pubsubEndpoint_destroy(ep);
+ }
return status;
@@ -150,7 +190,11 @@ celix_status_t pubsubEndpoint_createFromServiceReference(service_reference_pt re
pubsubEndpoint_setFields(ep, fwUUID, scope!=NULL?scope:PUBSUB_SUBSCRIBER_SCOPE_DEFAULT, topic, strtol(serviceId,NULL,10), NULL, topic_props, false);
- if (!ep->frameworkUUID || !ep->serviceID || !ep->scope || !ep->topic) {
+ if (!properties_get(ep->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID) ||
+ !ep->serviceID ||
+ !properties_get(ep->endpoint_props, PUBSUB_ENDPOINT_SCOPE) ||
+ !properties_get(ep->endpoint_props, PUBSUB_ENDPOINT_TOPIC)) {
+
fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "PUBSUB_ENDPOINT: incomplete description!.");
status = CELIX_BUNDLE_EXCEPTION;
pubsubEndpoint_destroy(ep);
@@ -206,30 +250,14 @@ celix_status_t pubsubEndpoint_createFromListenerHookInfo(listener_hook_info_pt i
celix_status_t pubsubEndpoint_destroy(pubsub_endpoint_pt psEp){
- 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);
}
+ if (psEp->endpoint_props != NULL) {
+ properties_destroy(psEp->endpoint_props);
+ }
+
free(psEp);
return CELIX_SUCCESS;
@@ -238,9 +266,9 @@ celix_status_t pubsubEndpoint_destroy(pubsub_endpoint_pt psEp){
bool pubsubEndpoint_equals(pubsub_endpoint_pt psEp1,pubsub_endpoint_pt psEp2){
- return ((strcmp(psEp1->frameworkUUID,psEp2->frameworkUUID)==0) &&
- (strcmp(psEp1->scope,psEp2->scope)==0) &&
- (strcmp(psEp1->topic,psEp2->topic)==0) &&
+ return ((strcmp(properties_get(psEp1->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),properties_get(psEp2->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID))==0) &&
+ (strcmp(properties_get(psEp1->endpoint_props, PUBSUB_ENDPOINT_SCOPE),properties_get(psEp2->endpoint_props, PUBSUB_ENDPOINT_SCOPE))==0) &&
+ (strcmp(properties_get(psEp1->endpoint_props, PUBSUB_ENDPOINT_TOPIC),properties_get(psEp2->endpoint_props, PUBSUB_ENDPOINT_TOPIC))==0) &&
(psEp1->serviceID == psEp2->serviceID) /*&&
((psEp1->endpoint==NULL && psEp2->endpoint==NULL)||(strcmp(psEp1->endpoint,psEp2->endpoint)==0))*/
);
http://git-wip-us.apache.org/repos/asf/celix/blob/9094f554/pubsub/pubsub_discovery/private/src/etcd_watcher.c
----------------------------------------------------------------------
diff --git a/pubsub/pubsub_discovery/private/src/etcd_watcher.c b/pubsub/pubsub_discovery/private/src/etcd_watcher.c
index 3c3a5a8..726269a 100644
--- a/pubsub/pubsub_discovery/private/src/etcd_watcher.c
+++ b/pubsub/pubsub_discovery/private/src/etcd_watcher.c
@@ -21,6 +21,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
+#include <jansson.h>
#include "celix_log.h"
#include "constants.h"
@@ -143,7 +144,60 @@ celix_status_t etcdWatcher_getPublisherEndpointFromKey(pubsub_discovery_pt pubsu
status = CELIX_ILLEGAL_STATE;
}
else{
- status = pubsubEndpoint_create(fwUUID,scope,topic,strtol(serviceId,NULL,10),etcdValue,NULL,pubEP);
+
+ // etcdValue contains the json formatted string
+ json_error_t error;
+ json_t* jsonRoot = json_loads(etcdValue, JSON_DECODE_ANY, &error);
+
+ const char* endpoint_serializer = NULL;
+ const char* endpoint_admin_type = NULL;
+ const char* endpoint_url = NULL;
+ const char* endpoint_type = NULL;
+
+ if (json_is_object(jsonRoot)){
+
+ void *iter = json_object_iter(jsonRoot);
+
+ const char *key;
+ json_t *value;
+
+ while (iter) {
+ key = json_object_iter_key(iter);
+ value = json_object_iter_value(iter);
+
+ if (strcmp(key, PUBSUB_ENDPOINT_SERIALIZER) == 0) {
+ endpoint_serializer = json_string_value(value);
+ } else if (strcmp(key, PUBSUB_ENDPOINT_ADMIN_TYPE) == 0) {
+ endpoint_admin_type = json_string_value(value);
+ } else if (strcmp(key, PUBSUB_ENDPOINT_URL) == 0) {
+ endpoint_url = json_string_value(value);
+ } else if (strcmp(key, PUBSUB_ENDPOINT_TYPE) == 0) {
+ endpoint_type = json_string_value(value);
+ }
+
+ iter = json_object_iter_next(jsonRoot, iter);
+ }
+
+ if (endpoint_url == NULL) {
+ printf("EW: No endpoint found in json object!\n");
+ endpoint_url = etcdValue;
+ }
+
+ } else {
+ endpoint_url = etcdValue;
+ }
+
+ status = pubsubEndpoint_create(fwUUID,scope,topic,strtol(serviceId,NULL,10),endpoint_url,NULL,pubEP);
+
+ if (status == CELIX_SUCCESS) {
+ status += pubsubEndpoint_setField(*pubEP, PUBSUB_ENDPOINT_SERIALIZER, endpoint_serializer);
+ status += pubsubEndpoint_setField(*pubEP, PUBSUB_ENDPOINT_ADMIN_TYPE, endpoint_admin_type);
+ status += pubsubEndpoint_setField(*pubEP, PUBSUB_ENDPOINT_TYPE, endpoint_type);
+ }
+
+ if (jsonRoot != NULL) {
+ json_decref(jsonRoot);
+ }
}
}
return status;
http://git-wip-us.apache.org/repos/asf/celix/blob/9094f554/pubsub/pubsub_discovery/private/src/etcd_writer.c
----------------------------------------------------------------------
diff --git a/pubsub/pubsub_discovery/private/src/etcd_writer.c b/pubsub/pubsub_discovery/private/src/etcd_writer.c
index 1c423f3..e820e50 100644
--- a/pubsub/pubsub_discovery/private/src/etcd_writer.c
+++ b/pubsub/pubsub_discovery/private/src/etcd_writer.c
@@ -21,6 +21,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
+#include <jansson.h>
#include "celix_log.h"
#include "constants.h"
@@ -82,7 +83,12 @@ void etcdWriter_destroy(etcd_writer_pt writer) {
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);
+ snprintf(dir,MAX_ROOTNODE_LENGTH,"%s/%s/%s/%s",
+ rootPath,
+ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
+ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
+ properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID));
+
etcd_del(dir);
pubsubEndpoint_destroy(pubEP);
}
@@ -100,7 +106,7 @@ celix_status_t etcdWriter_addPublisherEndpoint(etcd_writer_pt writer, pubsub_end
if(storeEP){
const char *fwUUID = NULL;
bundleContext_getProperty(writer->pubsub_discovery->context, OSGI_FRAMEWORK_FRAMEWORK_UUID, &fwUUID);
- if(fwUUID && strcmp(pubEP->frameworkUUID, fwUUID) == 0) {
+ if(fwUUID && strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID), fwUUID) == 0) {
celixThreadMutex_lock(&writer->localPubsLock);
pubsub_endpoint_pt p = NULL;
pubsubEndpoint_clone(pubEP, &p);
@@ -128,12 +134,33 @@ celix_status_t etcdWriter_addPublisherEndpoint(etcd_writer_pt writer, pubsub_end
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);
-
- if(!etcd_set(key,pubEP->endpoint,ttl,false)){
+ asprintf(&key,"%s/%s/%s/%s/%ld",
+ rootPath,
+ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
+ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
+ properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
+ pubEP->serviceID);
+
+ char serviceID [sizeof(pubEP->serviceID)];
+ snprintf(serviceID, sizeof(pubEP->serviceID), "%ld", pubEP->serviceID);
+ json_t* jsonEndpoint = json_pack("{s:s,s:s,s:s,s:s,s:s,s:s,s:s}",
+ PUBSUB_ENDPOINT_SERVICE_ID, serviceID,
+ PUBSUB_ENDPOINT_SERIALIZER, "serializer.json", //TODO: Serializer not (yet) stored in endpoint
+ PUBSUB_ENDPOINT_ADMIN_TYPE, "zmq", //TODO: PSA type not (yet) stored in endpoint
+ PUBSUB_ENDPOINT_URL, properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL),
+ PUBSUB_ENDPOINT_TYPE, "publisher", //TODO: Check if necessary
+ PUBSUB_ENDPOINT_TOPIC, properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
+ PUBSUB_ENDPOINT_SCOPE, properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE)
+ );
+ char* jsonEndpointStr = json_dumps(jsonEndpoint, JSON_COMPACT);
+
+ if (!etcd_set(key,jsonEndpointStr,ttl,false)) {
status = CELIX_ILLEGAL_ARGUMENT;
}
FREE_MEM(key);
+ FREE_MEM(jsonEndpointStr);
+ json_decref(jsonEndpoint);
+
return status;
}
@@ -143,7 +170,12 @@ celix_status_t etcdWriter_deletePublisherEndpoint(etcd_writer_pt writer, pubsub_
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);
+ asprintf(&key, "%s/%s/%s/%s/%ld",
+ rootPath,
+ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
+ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
+ properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
+ pubEP->serviceID);
celixThreadMutex_lock(&writer->localPubsLock);
for (unsigned int i = 0; i < arrayList_size(writer->localPubs); i++) {
http://git-wip-us.apache.org/repos/asf/celix/blob/9094f554/pubsub/pubsub_discovery/private/src/pubsub_discovery_impl.c
----------------------------------------------------------------------
diff --git a/pubsub/pubsub_discovery/private/src/pubsub_discovery_impl.c b/pubsub/pubsub_discovery/private/src/pubsub_discovery_impl.c
index 94a8e11..e3e9704 100644
--- a/pubsub/pubsub_discovery/private/src/pubsub_discovery_impl.c
+++ b/pubsub/pubsub_discovery/private/src/pubsub_discovery_impl.c
@@ -143,7 +143,7 @@ celix_status_t pubsub_discovery_stop(pubsub_discovery_pt ps_discovery) {
int i;
for (i = 0; i < arrayList_size(pubEP_list); i++) {
pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt) arrayList_get(pubEP_list, i);
- if (strcmp(pubEP->frameworkUUID, fwUUID) == 0) {
+ if (strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID), fwUUID) == 0) {
etcdWriter_deletePublisherEndpoint(ps_discovery->writer, pubEP);
} else {
pubsub_discovery_informPublishersListeners(ps_discovery, pubEP, false);
@@ -177,7 +177,7 @@ celix_status_t pubsub_discovery_addNode(pubsub_discovery_pt pubsub_discovery, pu
bool inform=false;
celixThreadMutex_lock(&pubsub_discovery->discoveredPubsMutex);
- char *pubs_key = createScopeTopicKey(pubEP->scope, pubEP->topic);
+ char *pubs_key = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
array_list_pt pubEP_list = (array_list_pt)hashMap_get(pubsub_discovery->discoveredPubs,pubs_key);
if(pubEP_list==NULL){
arrayList_create(&pubEP_list);
@@ -216,11 +216,12 @@ celix_status_t pubsub_discovery_removeNode(pubsub_discovery_pt pubsub_discovery,
bool found = false;
celixThreadMutex_lock(&pubsub_discovery->discoveredPubsMutex);
- char *pubs_key = createScopeTopicKey(pubEP->scope, pubEP->topic);
+ char *pubs_key = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
array_list_pt pubEP_list = (array_list_pt) hashMap_get(pubsub_discovery->discoveredPubs, pubs_key);
free(pubs_key);
if (pubEP_list == NULL) {
- printf("PSD: Cannot find any registered publisher for topic %s. Something is not consistent.\n", pubEP->topic);
+ printf("PSD: Cannot find any registered publisher for topic %s. Something is not consistent.\n",
+ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
status = CELIX_ILLEGAL_STATE;
} else {
int i;
@@ -278,12 +279,14 @@ celix_status_t pubsub_discovery_informPublishersListeners(pubsub_discovery_pt pu
/* Service's functions implementation */
celix_status_t pubsub_discovery_announcePublisher(void *handle, pubsub_endpoint_pt pubEP) {
celix_status_t status = CELIX_SUCCESS;
- printf("pubsub_discovery_announcePublisher : %s / %s\n", pubEP->topic, pubEP->endpoint);
+ printf("pubsub_discovery_announcePublisher : %s / %s\n",
+ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
+ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
pubsub_discovery_pt pubsub_discovery = (pubsub_discovery_pt) handle;
celixThreadMutex_lock(&pubsub_discovery->discoveredPubsMutex);
- char *pub_key = createScopeTopicKey(pubEP->scope,pubEP->topic);
+ char *pub_key = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
array_list_pt pubEP_list = (array_list_pt)hashMap_get(pubsub_discovery->discoveredPubs,pub_key);
if(pubEP_list==NULL){
@@ -310,11 +313,11 @@ celix_status_t pubsub_discovery_removePublisher(void *handle, pubsub_endpoint_pt
celixThreadMutex_lock(&pubsub_discovery->discoveredPubsMutex);
- char *pub_key = createScopeTopicKey(pubEP->scope,pubEP->topic);
+ char *pub_key = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
array_list_pt pubEP_list = (array_list_pt)hashMap_get(pubsub_discovery->discoveredPubs,pub_key);
free(pub_key);
if(pubEP_list==NULL){
- printf("PSD: Cannot find any registered publisher for topic %s. Something is not consistent.\n",pubEP->topic);
+ printf("PSD: Cannot find any registered publisher for topic %s. Something is not consistent.\n",properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
status = CELIX_ILLEGAL_STATE;
}
else{
http://git-wip-us.apache.org/repos/asf/celix/blob/9094f554/pubsub/pubsub_topology_manager/private/src/pubsub_topology_manager.c
----------------------------------------------------------------------
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 987d864..4ee9951 100644
--- a/pubsub/pubsub_topology_manager/private/src/pubsub_topology_manager.c
+++ b/pubsub/pubsub_topology_manager/private/src/pubsub_topology_manager.c
@@ -216,7 +216,7 @@ celix_status_t pubsub_topologyManager_psaRemoved(void * handle, service_referenc
int i;
for(i=0;i<arrayList_size(pubEP_list);i++){
pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(pubEP_list,i);
- if(strcmp(pubEP->frameworkUUID,fwUUID)==0){
+ if(strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),fwUUID)==0){
disc->removePublisher(disc->handle,pubEP);
}
}
@@ -263,7 +263,7 @@ celix_status_t pubsub_topologyManager_subscriberAdded(void * handle, service_ref
pubsub_endpoint_pt sub = NULL;
if(pubsubEndpoint_createFromServiceReference(reference,&sub,false) == CELIX_SUCCESS){
celixThreadMutex_lock(&manager->subscriptionsLock);
- char *sub_key = createScopeTopicKey(sub->scope, sub->topic);
+ char *sub_key = createScopeTopicKey(properties_get(sub->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(sub->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
array_list_pt sub_list_by_topic = hashMap_get(manager->subscriptions,sub_key);
if(sub_list_by_topic==NULL){
@@ -300,7 +300,7 @@ celix_status_t pubsub_topologyManager_subscriberAdded(void * handle, service_ref
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);
+ disc->interestedInTopic(disc->handle, properties_get(sub->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(sub->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
bundleContext_ungetService(manager->context, disc_sr, NULL);
}
hashMapIterator_destroy(iter);
@@ -339,7 +339,7 @@ celix_status_t pubsub_topologyManager_subscriberRemoved(void * handle, service_r
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);
+ disc->uninterestedInTopic(disc->handle, properties_get(subcmp->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(subcmp->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
bundleContext_ungetService(manager->context, disc_sr, NULL);
}
hashMapIterator_destroy(iter);
@@ -348,7 +348,7 @@ celix_status_t pubsub_topologyManager_subscriberRemoved(void * handle, service_r
celixThreadMutex_lock(&manager->subscriptionsLock);
celixThreadMutex_lock(&manager->psaListLock);
- char *sub_key = createScopeTopicKey(subcmp->scope,subcmp->topic);
+ char *sub_key = createScopeTopicKey(properties_get(subcmp->endpoint_props, PUBSUB_ENDPOINT_SCOPE),properties_get(subcmp->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
array_list_pt sub_list_by_topic = hashMap_get(manager->subscriptions,sub_key);
free(sub_key);
if(sub_list_by_topic!=NULL){
@@ -368,7 +368,7 @@ celix_status_t pubsub_topologyManager_subscriberRemoved(void * handle, service_r
if(arrayList_size(sub_list_by_topic)==0){
for(k=0;k<arrayList_size(manager->psaList);k++){
pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,k);
- psa->closeAllSubscriptions(psa->admin,sub->scope, sub->topic);
+ psa->closeAllSubscriptions(psa->admin, (char*) properties_get(subcmp->endpoint_props, PUBSUB_ENDPOINT_SCOPE), (char*) properties_get(subcmp->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
}
}
@@ -415,7 +415,7 @@ celix_status_t pubsub_topologyManager_pubsubDiscoveryAdded(void* handle, service
array_list_pt pubEP_list = (array_list_pt)hashMapIterator_nextValue(iter);
for(int i = 0; i < arrayList_size(pubEP_list); i++) {
pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(pubEP_list,i);
- if( (strcmp(pubEP->frameworkUUID,fwUUID)==0) && (pubEP->endpoint!=NULL)){
+ if( (strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),fwUUID)==0) && (properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL)){
status += disc->announcePublisher(disc->handle,pubEP);
}
}
@@ -433,7 +433,7 @@ celix_status_t pubsub_topologyManager_pubsubDiscoveryAdded(void* handle, service
for(i=0;i<arrayList_size(l);i++){
pubsub_endpoint_pt subEp = (pubsub_endpoint_pt)arrayList_get(l,i);
- disc->interestedInTopic(disc->handle, subEp->scope, subEp->topic);
+ disc->interestedInTopic(disc->handle, properties_get(subEp->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(subEp->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
}
}
hashMapIterator_destroy(iter);
@@ -486,7 +486,7 @@ celix_status_t pubsub_topologyManager_publisherTrackerAdded(void *handle, array_
if(pubsubEndpoint_createFromListenerHookInfo(info, &pub, true) == CELIX_SUCCESS){
celixThreadMutex_lock(&manager->publicationsLock);
- char *pub_key = createScopeTopicKey(pub->scope, pub->topic);
+ char *pub_key = createScopeTopicKey(properties_get(pub->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pub->endpoint_props, PUBSUB_ENDPOINT_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);
@@ -558,7 +558,7 @@ celix_status_t pubsub_topologyManager_publisherTrackerRemoved(void *handle, arra
celixThreadMutex_lock(&manager->psaListLock);
celixThreadMutex_lock(&manager->publicationsLock);
- char *pub_key = createScopeTopicKey(pubcmp->scope, pubcmp->topic);
+ char *pub_key = createScopeTopicKey(properties_get(pubcmp->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubcmp->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
array_list_pt pub_list_by_topic = hashMap_get(manager->publications,pub_key);
if(pub_list_by_topic!=NULL){
for(j=0;j<arrayList_size(pub_list_by_topic);j++){
@@ -591,7 +591,7 @@ celix_status_t pubsub_topologyManager_publisherTrackerRemoved(void *handle, arra
if(arrayList_size(pub_list_by_topic)==0){
for(k=0;k<arrayList_size(manager->psaList);k++){
pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,k);
- psa->closeAllPublications(psa->admin,pub->scope, pub->topic);
+ psa->closeAllPublications(psa->admin, (char*) properties_get(pub->endpoint_props, PUBSUB_ENDPOINT_SCOPE), (char*) properties_get(pub->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
}
}
@@ -617,13 +617,16 @@ celix_status_t pubsub_topologyManager_publisherTrackerRemoved(void *handle, arra
celix_status_t pubsub_topologyManager_announcePublisher(void *handle, pubsub_endpoint_pt pubEP){
celix_status_t status = CELIX_SUCCESS;
- printf("PSTM: New publisher discovered for topic %s [fwUUID=%s, ep=%s]\n",pubEP->topic,pubEP->frameworkUUID,pubEP->endpoint);
+ printf("PSTM: New publisher discovered for topic %s [fwUUID=%s, ep=%s]\n",
+ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
+ properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
+ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
pubsub_topology_manager_pt manager = handle;
celixThreadMutex_lock(&manager->psaListLock);
celixThreadMutex_lock(&manager->publicationsLock);
- char *pub_key = createScopeTopicKey(pubEP->scope, pubEP->topic);
+ char *pub_key = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
array_list_pt pub_list_by_topic = hashMap_get(manager->publications,pub_key);
if(pub_list_by_topic==NULL){
@@ -666,17 +669,20 @@ celix_status_t pubsub_topologyManager_announcePublisher(void *handle, pubsub_end
celix_status_t pubsub_topologyManager_removePublisher(void *handle, pubsub_endpoint_pt pubEP){
celix_status_t status = CELIX_SUCCESS;
- printf("PSTM: Publisher removed for topic %s [fwUUID=%s, ep=%s]\n",pubEP->topic,pubEP->frameworkUUID,pubEP->endpoint);
+ printf("PSTM: Publisher removed for topic %s [fwUUID=%s, ep=%s]\n",
+ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
+ properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
+ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
pubsub_topology_manager_pt manager = handle;
celixThreadMutex_lock(&manager->psaListLock);
celixThreadMutex_lock(&manager->publicationsLock);
int i;
- char *pub_key = createScopeTopicKey(pubEP->scope, pubEP->topic);
+ char *pub_key = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
array_list_pt pub_list_by_topic = hashMap_get(manager->publications,pub_key);
if(pub_list_by_topic==NULL){
- printf("PSTM: ERROR: Cannot find topic for known endpoint [%s,%s,%s]. Something is inconsistent.\n",pub_key,pubEP->frameworkUUID,pubEP->endpoint);
+ printf("PSTM: ERROR: Cannot find topic for known endpoint [%s,%s,%s]. Something is inconsistent.\n",pub_key,properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
status = CELIX_ILLEGAL_STATE;
}
else{
@@ -704,7 +710,7 @@ celix_status_t pubsub_topologyManager_removePublisher(void *handle, pubsub_endpo
for(i=0;i<arrayList_size(manager->psaList);i++){
pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,i);
- psa->closeAllPublications(psa->admin,p->scope, p->topic);
+ psa->closeAllPublications(psa->admin, (char*) properties_get(p->endpoint_props, PUBSUB_ENDPOINT_SCOPE), (char*) properties_get(p->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
}
}
http://git-wip-us.apache.org/repos/asf/celix/blob/9094f554/utils/private/src/properties.c
----------------------------------------------------------------------
diff --git a/utils/private/src/properties.c b/utils/private/src/properties.c
index 1e097a0..860b9bb 100644
--- a/utils/private/src/properties.c
+++ b/utils/private/src/properties.c
@@ -212,6 +212,11 @@ void properties_set(properties_pt properties, const char* key, const char* value
free(oldValue);
}
+void properties_unset(properties_pt properties, const char* key) {
+ char* oldValue = hashMap_remove(properties, key);
+ free(oldValue);
+}
+
static void updateBuffers(char **key, char ** value, char **output, int outputPos, int *key_len, int *value_len) {
if (*output == *key) {
if (outputPos == (*key_len) - 1) {
http://git-wip-us.apache.org/repos/asf/celix/blob/9094f554/utils/public/include/properties.h
----------------------------------------------------------------------
diff --git a/utils/public/include/properties.h b/utils/public/include/properties.h
index 5c6dc4d..582a242 100644
--- a/utils/public/include/properties.h
+++ b/utils/public/include/properties.h
@@ -56,6 +56,8 @@ UTILS_EXPORT const char *properties_getWithDefault(properties_pt properties, con
UTILS_EXPORT void properties_set(properties_pt properties, const char *key, const char *value);
+UTILS_EXPORT void properties_unset(properties_pt properties, const char *key);
+
UTILS_EXPORT celix_status_t properties_copy(properties_pt properties, properties_pt *copy);
#define PROPERTIES_FOR_EACH(props, key) \
[3/4] celix git commit: Merge branch 'endpoint-format' into develop
Posted by rl...@apache.org.
http://git-wip-us.apache.org/repos/asf/celix/blob/0a5ef69a/pubsub/pubsub_admin_zmq/src/pubsub_admin_impl.c
----------------------------------------------------------------------
diff --cc pubsub/pubsub_admin_zmq/src/pubsub_admin_impl.c
index 2dcec25,0000000..9929437
mode 100644,000000..100644
--- a/pubsub/pubsub_admin_zmq/src/pubsub_admin_impl.c
+++ b/pubsub/pubsub_admin_zmq/src/pubsub_admin_impl.c
@@@ -1,1040 -1,0 +1,1059 @@@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+/*
+ * pubsub_admin_impl.c
+ *
+ * \date Sep 30, 2011
+ * \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ * \copyright Apache License, Version 2.0
+ */
+
+#include "pubsub_admin_impl.h"
+#include <zmq.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+#ifndef ANDROID
+#include <ifaddrs.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "constants.h"
+#include "utils.h"
+#include "hash_map.h"
+#include "array_list.h"
+#include "bundle_context.h"
+#include "bundle.h"
+#include "service_reference.h"
+#include "service_registration.h"
+#include "log_helper.h"
+#include "log_service.h"
+#include "celix_threads.h"
+#include "service_factory.h"
+
+#include "topic_subscription.h"
+#include "topic_publication.h"
+#include "pubsub_endpoint.h"
+#include "pubsub_utils.h"
+#include "pubsub/subscriber.h"
+
+#define MAX_KEY_FOLDER_PATH_LENGTH 512
+
+static const char *DEFAULT_IP = "127.0.0.1";
+
+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_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_ZMQ: zeromq curve unsupported\n");
+ return CELIX_SERVICE_EXCEPTION;
+ }
+#endif
+
+ *admin = calloc(1, sizeof(**admin));
+
+ if (!*admin) {
+ status = CELIX_ENOMEM;
+ }
+ else{
+
+ const char *ip = NULL;
+ char *detectedIp = NULL;
+ (*admin)->bundle_context= context;
+ (*admin)->localPublications = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
+ (*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)->externalPublicationsLock, NULL);
+ celixThreadMutex_create(&(*admin)->serializerListLock, NULL);
+ celixThreadMutex_create(&(*admin)->usedSerializersLock, NULL);
+
+ celixThreadMutexAttr_create(&(*admin)->noSerializerPendingsAttr);
+ celixThreadMutexAttr_settype(&(*admin)->noSerializerPendingsAttr, CELIX_THREAD_MUTEX_RECURSIVE);
+ celixThreadMutex_create(&(*admin)->noSerializerPendingsLock, &(*admin)->noSerializerPendingsAttr);
+
+ celixThreadMutexAttr_create(&(*admin)->pendingSubscriptionsAttr);
+ celixThreadMutexAttr_settype(&(*admin)->pendingSubscriptionsAttr, CELIX_THREAD_MUTEX_RECURSIVE);
+ celixThreadMutex_create(&(*admin)->pendingSubscriptionsLock, &(*admin)->pendingSubscriptionsAttr);
+
+ if (logHelper_create(context, &(*admin)->loghelper) == CELIX_SUCCESS) {
+ logHelper_start((*admin)->loghelper);
+ }
+
+ bundleContext_getProperty(context,PSA_IP , &ip);
+
+#ifndef ANDROID
+ if (ip == NULL) {
+ const char *interface = NULL;
+
+ bundleContext_getProperty(context, PSA_ITF, &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;
+ }
+#endif
+
+ if (ip != NULL) {
+ 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_ZMQ: No IP address for service annunciation set. Using %s", DEFAULT_IP);
+ (*admin)->ipAddress = strdup(DEFAULT_IP);
+ }
+
+ if (detectedIp != NULL) {
+ 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
+ setenv("ZSYS_SIGHANDLER", "false", true);
+
+ const char *nrZmqThreads = NULL;
+ bundleContext_getProperty(context, "PSA_NR_ZMQ_THREADS", &nrZmqThreads);
+
+ if(nrZmqThreads != NULL) {
+ char *endPtr = NULL;
+ 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_ZMQ: Using %d threads for ZMQ", nrThreads);
+ printf("PSA_ZMQ: Using %d threads for ZMQ\n", nrThreads);
+ }
+ }
+
+#ifdef BUILD_WITH_ZMQ_SECURITY
+ // Setup authenticator
+ zactor_t* auth = zactor_new (zauth, NULL);
+ zstr_sendx(auth, "VERBOSE", NULL);
+
+ // Load all public keys of subscribers into the application
+ // This step is done for authenticating subscribers
+ char curve_folder_path[MAX_KEY_FOLDER_PATH_LENGTH];
+ char* keys_bundle_dir = pubsub_getKeysBundleDir(context);
+ snprintf(curve_folder_path, MAX_KEY_FOLDER_PATH_LENGTH, "%s/META-INF/keys/subscriber/public", keys_bundle_dir);
+ zstr_sendx (auth, "CURVE", curve_folder_path, NULL);
+ free(keys_bundle_dir);
+
+ (*admin)->zmq_auth = auth;
+#endif
+
+ }
+
+ return status;
+}
+
+
+celix_status_t pubsubAdmin_destroy(pubsub_admin_pt admin)
+{
+ celix_status_t status = CELIX_SUCCESS;
+
+ free(admin->ipAddress);
+
+ celixThreadMutex_lock(&admin->pendingSubscriptionsLock);
+ hash_map_iterator_pt iter = hashMapIterator_create(admin->pendingSubscriptions);
+ while(hashMapIterator_hasNext(iter)){
+ hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
+ free((char*)hashMapEntry_getKey(entry));
+ arrayList_destroy((array_list_pt)hashMapEntry_getValue(entry));
+ }
+ hashMapIterator_destroy(iter);
+ hashMap_destroy(admin->pendingSubscriptions,false,false);
+ celixThreadMutex_unlock(&admin->pendingSubscriptionsLock);
+
+ celixThreadMutex_lock(&admin->subscriptionsLock);
+ hashMap_destroy(admin->subscriptions,false,false);
+ celixThreadMutex_unlock(&admin->subscriptionsLock);
+
+ celixThreadMutex_lock(&admin->localPublicationsLock);
+ hashMap_destroy(admin->localPublications,true,false);
+ celixThreadMutex_unlock(&admin->localPublicationsLock);
+
+ celixThreadMutex_lock(&admin->externalPublicationsLock);
+ iter = hashMapIterator_create(admin->externalPublications);
+ while(hashMapIterator_hasNext(iter)){
+ hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
+ free((char*)hashMapEntry_getKey(entry));
+ arrayList_destroy((array_list_pt)hashMapEntry_getValue(entry));
+ }
+ hashMapIterator_destroy(iter);
+ 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->serializerListLock);
+ celixThreadMutex_destroy(&admin->pendingSubscriptionsLock);
+
+ celixThreadMutexAttr_destroy(&admin->noSerializerPendingsAttr);
+ celixThreadMutex_destroy(&admin->noSerializerPendingsLock);
+
+ celixThreadMutexAttr_destroy(&admin->pendingSubscriptionsAttr);
+ celixThreadMutex_destroy(&admin->subscriptionsLock);
+
+ celixThreadMutex_destroy(&admin->localPublicationsLock);
+ celixThreadMutex_destroy(&admin->externalPublicationsLock);
+
+ logHelper_stop(admin->loghelper);
+
+ logHelper_destroy(&admin->loghelper);
+
+#ifdef BUILD_WITH_ZMQ_SECURITY
+ if (admin->zmq_auth != NULL){
+ zactor_destroy(&(admin->zmq_auth));
+ }
+#endif
+
+ free(admin);
+
+ return status;
+}
+
+static celix_status_t pubsubAdmin_addAnySubscription(pubsub_admin_pt admin,pubsub_endpoint_pt subEP){
+ celix_status_t status = CELIX_SUCCESS;
+
+ celixThreadMutex_lock(&admin->subscriptionsLock);
+
+ topic_subscription_pt any_sub = hashMap_get(admin->subscriptions,PUBSUB_ANY_SUB_TOPIC);
+
+ 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, 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);
++ printf("PSA_ZMQ: Cannot find a serializer for subscribing topic %s. Adding it to pending list.\n",
++ properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+ celixThreadMutex_lock(&admin->noSerializerPendingsLock);
+ arrayList_add(admin->noSerializerSubscriptions,subEP);
+ celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
+ }
+
+ 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;i<arrayList_size(topic_publishers);i++){
+ pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(topic_publishers,i);
- if(pubEP->endpoint !=NULL){
- status += pubsub_topicSubscriptionConnectPublisher(any_sub,pubEP->endpoint);
++ if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
++ status += pubsub_topicSubscriptionConnectPublisher(any_sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
+ }
+ }
+ 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;i<arrayList_size(ext_pub_list);i++){
+ pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(ext_pub_list,i);
- if(pubEP->endpoint !=NULL){
- status += pubsub_topicSubscriptionConnectPublisher(any_sub,pubEP->endpoint);
++ if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
++ status += pubsub_topicSubscriptionConnectPublisher(any_sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
+ }
+ }
+ }
+ }
+ hashMapIterator_destroy(extp_iter);
+ celixThreadMutex_unlock(&admin->externalPublicationsLock);
+
+
+ pubsub_topicSubscriptionAddSubscriber(any_sub,subEP);
+
+ status += pubsub_topicSubscriptionStart(any_sub);
+
+ }
+
+ if (status == CELIX_SUCCESS){
+ hashMap_put(admin->subscriptions,strdup(PUBSUB_ANY_SUB_TOPIC),any_sub);
+ connectTopicPubSubToSerializer(admin, best_serializer, any_sub, false);
+ }
+
+ }
+
+ celixThreadMutex_unlock(&admin->subscriptionsLock);
+
+ return status;
+}
+
+celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint_pt subEP){
+ celix_status_t status = CELIX_SUCCESS;
+
- printf("PSA_ZMQ: 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",
++ properties_get(subEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
++ subEP->serviceID,
++ properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
++ properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+
- if(strcmp(subEP->topic,PUBSUB_ANY_SUB_TOPIC)==0){
++ if(strcmp(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),PUBSUB_ANY_SUB_TOPIC)==0){
+ return pubsubAdmin_addAnySubscription(admin,subEP);
+ }
+
+ /* Check if we already know some publisher about this topic, otherwise let's put the subscription in the pending hashmap */
+ celixThreadMutex_lock(&admin->pendingSubscriptionsLock);
+ celixThreadMutex_lock(&admin->subscriptionsLock);
+ celixThreadMutex_lock(&admin->localPublicationsLock);
+ celixThreadMutex_lock(&admin->externalPublicationsLock);
+
- char* scope_topic = createScopeTopicKey(subEP->scope, subEP->topic);
++ char* scope_topic = createScopeTopicKey(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_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);
+
+ if(factory==NULL && ext_pub_list==NULL){ //No (local or external) publishers yet for this topic
+ pubsubAdmin_addSubscriptionToPendingList(admin,subEP);
+ }
+ 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,subEP->scope, subEP->topic, best_serializer, &subscription);
++ status += pubsub_topicSubscriptionCreate(admin->bundle_context, (char*) properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), (char*) properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC), best_serializer, &subscription);
+ }
+ else{
- printf("PSA_ZMQ: Cannot find a serializer for subscribing topic %s. Adding it to pending list.\n",subEP->topic);
++ printf("PSA_ZMQ: Cannot find a serializer for subscribing topic %s. Adding it to pending list.\n",
++ properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+ celixThreadMutex_lock(&admin->noSerializerPendingsLock);
+ arrayList_add(admin->noSerializerSubscriptions,subEP);
+ celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
+ }
+
+ 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);
+
+ if(topic_publishers!=NULL){
+ for(i=0;i<arrayList_size(topic_publishers);i++){
+ pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(topic_publishers,i);
- if(pubEP->endpoint !=NULL){
- status += pubsub_topicSubscriptionConnectPublisher(subscription,pubEP->endpoint);
++ if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
++ status += pubsub_topicSubscriptionConnectPublisher(subscription,(char*)properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
+ }
+ }
+ arrayList_destroy(topic_publishers);
+ }
+
+ }
+
+ /* Look also for external publishers */
+ if(ext_pub_list!=NULL){
+ for(i=0;i<arrayList_size(ext_pub_list);i++){
+ pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(ext_pub_list,i);
- if(pubEP->endpoint !=NULL){
- status += pubsub_topicSubscriptionConnectPublisher(subscription,pubEP->endpoint);
++ if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
++ status += pubsub_topicSubscriptionConnectPublisher(subscription,(char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
+ }
+ }
+ }
+
+ pubsub_topicSubscriptionAddSubscriber(subscription,subEP);
+
+ status += pubsub_topicSubscriptionStart(subscription);
+
+ }
+
+ if(status==CELIX_SUCCESS){
+
+ hashMap_put(admin->subscriptions,strdup(scope_topic),subscription);
+
+ connectTopicPubSubToSerializer(admin, best_serializer, subscription, false);
+ }
+ }
+
+ if (status == CELIX_SUCCESS){
+ pubsub_topicIncreaseNrSubscribers(subscription);
+ }
+ }
+
+ free(scope_topic);
+ celixThreadMutex_unlock(&admin->externalPublicationsLock);
+ celixThreadMutex_unlock(&admin->localPublicationsLock);
+ celixThreadMutex_unlock(&admin->subscriptionsLock);
+ celixThreadMutex_unlock(&admin->pendingSubscriptionsLock);
+
+ return status;
+
+}
+
+celix_status_t pubsubAdmin_removeSubscription(pubsub_admin_pt admin,pubsub_endpoint_pt subEP){
+ celix_status_t status = CELIX_SUCCESS;
+
- printf("PSA_ZMQ: 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",
++ properties_get(subEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
++ subEP->serviceID,
++ properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+
- char* scope_topic = createScopeTopicKey(subEP->scope, subEP->topic);
++ char* scope_topic = createScopeTopicKey(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+
+ celixThreadMutex_lock(&admin->subscriptionsLock);
+ topic_subscription_pt sub = (topic_subscription_pt)hashMap_get(admin->subscriptions,scope_topic);
+ if(sub!=NULL){
+ pubsub_topicDecreaseNrSubscribers(sub);
+ if(pubsub_topicGetNrSubscribers(sub) == 0) {
+ status = pubsub_topicSubscriptionRemoveSubscriber(sub,subEP);
+ }
+ }
+ celixThreadMutex_unlock(&admin->subscriptionsLock);
+
+ if(sub==NULL){
+ /* 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);
+
+
+
+ return status;
+
+}
+
+celix_status_t pubsubAdmin_addPublication(pubsub_admin_pt admin, pubsub_endpoint_pt pubEP) {
+ 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);
++ printf("PSA_ZMQ: Received publication [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",
++ properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
++ pubEP->serviceID,
++ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
++ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_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);
++ char *scope_topic = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+
- if ((strcmp(pubEP->frameworkUUID, fwUUID) == 0) && (pubEP->endpoint == NULL)) {
++ if ((strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID), fwUUID) == 0) &&
++ (properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) == 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);
++ printf("PSA_ZMQ: Cannot find a serializer for publishing topic %s. Adding it to pending list.\n",
++ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_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);
++ printf("PSA_ZMQ: Cannot create a topicPublication for scope=%s, topic=%s (bundle %ld).\n",
++ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
++ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_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);
++ if (sub != NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) != NULL) {
++ pubsub_topicSubscriptionAddConnectPublisherToPendingList(sub, (char*)properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
+ }
+
+ /* 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);
++ if (any_sub != NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) != NULL) {
++ pubsub_topicSubscriptionAddConnectPublisherToPendingList(any_sub, (char*)properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
+ }
+
+ 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_ZMQ: 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",
++ properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
++ pubEP->serviceID,
++ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_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);
++ char *scope_topic = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+
- if(strcmp(pubEP->frameworkUUID,fwUUID)==0){
++ if(strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),fwUUID)==0){
+
+ celixThreadMutex_lock(&admin->localPublicationsLock);
+ service_factory_pt factory = (service_factory_pt)hashMap_get(admin->localPublications,scope_topic);
+ if(factory!=NULL){
+ topic_publication_pt pub = (topic_publication_pt)factory->handle;
+ pubsub_topicPublicationRemovePublisherEP(pub,pubEP);
+ }
+ celixThreadMutex_unlock(&admin->localPublicationsLock);
+
+ if(factory==NULL){
+ /* Maybe the endpoint was pending */
+ celixThreadMutex_lock(&admin->noSerializerPendingsLock);
+ if(!arrayList_removeElement(admin->noSerializerPublications, pubEP)){
+ status = CELIX_ILLEGAL_STATE;
+ }
+ celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
+ }
+ }
+ 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){
+ int i;
+ bool found = false;
+ for(i=0;!found && i<arrayList_size(ext_pub_list);i++){
+ pubsub_endpoint_pt p = (pubsub_endpoint_pt)arrayList_get(ext_pub_list,i);
+ found = pubsubEndpoint_equals(pubEP,p);
+ if (found){
+ 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)
+ for(i=0; i<arrayList_size(ext_pub_list);i++) {
+ pubsub_endpoint_pt p = (pubsub_endpoint_pt)arrayList_get(ext_pub_list,i);
- if (strcmp(pubEP->endpoint,p->endpoint) == 0) {
++ if (strcmp(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL),properties_get(p->endpoint_props, PUBSUB_ENDPOINT_URL)) == 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,topic);
+ arrayList_destroy(list);
+ free(topic);
+ }
+ }
+
+ celixThreadMutex_unlock(&admin->externalPublicationsLock);
+ }
+
+ /* Check if this publisher was connected to one of our subscribers*/
+ celixThreadMutex_lock(&admin->subscriptionsLock);
+
+ topic_subscription_pt sub = (topic_subscription_pt)hashMap_get(admin->subscriptions,scope_topic);
- if(sub!=NULL && pubEP->endpoint!=NULL && count == 0){
- pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(sub,pubEP->endpoint);
++ if(sub!=NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL && count == 0){
++ pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(sub,(char*)properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
+ }
+
+ /* 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);
++ if(any_sub!=NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL && count == 0){
++ pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(any_sub,(char*)properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
+ }
+
+ free(scope_topic);
+ celixThreadMutex_unlock(&admin->subscriptionsLock);
+
+ return status;
+
+}
+
+celix_status_t pubsubAdmin_closeAllPublications(pubsub_admin_pt admin, char *scope, char* topic){
+ celix_status_t status = CELIX_SUCCESS;
+
+ 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* 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);
+ disconnectTopicPubSubFromSerializer(admin, pub, true);
+ status += pubsub_topicPublicationDestroy(pub);
+ hashMap_remove(admin->localPublications,scope_topic);
+ free(key);
+ free(factory);
+ }
+ free(scope_topic);
+ celixThreadMutex_unlock(&admin->localPublicationsLock);
+
+ return status;
+
+}
+
+celix_status_t pubsubAdmin_closeAllSubscriptions(pubsub_admin_pt admin,char* scope,char* topic){
+ celix_status_t status = CELIX_SUCCESS;
+
+ printf("PSA_ZMQ: Closing all subscriptions\n");
+
+ celixThreadMutex_lock(&admin->subscriptionsLock);
+ char *scope_topic = createScopeTopicKey(scope, topic);
+ hash_map_entry_pt sub_entry = (hash_map_entry_pt)hashMap_getEntry(admin->subscriptions,scope_topic);
+ if(sub_entry!=NULL){
+ char* topic = (char*)hashMapEntry_getKey(sub_entry);
+
+ topic_subscription_pt ts = (topic_subscription_pt)hashMapEntry_getValue(sub_entry);
+ status += pubsub_topicSubscriptionStop(ts);
+ disconnectTopicPubSubFromSerializer(admin, ts, false);
+ status += pubsub_topicSubscriptionDestroy(ts);
+ hashMap_remove(admin->subscriptions,scope_topic);
+ free(topic);
+
+ }
+ free(scope_topic);
+ celixThreadMutex_unlock(&admin->subscriptionsLock);
+
+ return status;
+
+}
+
+
+#ifndef ANDROID
+static celix_status_t pubsubAdmin_getIpAdress(const char* interface, char** ip) {
+ celix_status_t status = CELIX_BUNDLE_EXCEPTION;
+
+ struct ifaddrs *ifaddr, *ifa;
+ char host[NI_MAXHOST];
+
+ if (getifaddrs(&ifaddr) != -1)
+ {
+ for (ifa = ifaddr; ifa != NULL && status != CELIX_SUCCESS; ifa = ifa->ifa_next)
+ {
+ if (ifa->ifa_addr == NULL)
+ continue;
+
+ if ((getnameinfo(ifa->ifa_addr,sizeof(struct sockaddr_in), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST) == 0) && (ifa->ifa_addr->sa_family == AF_INET)) {
+ if (interface == NULL) {
+ *ip = strdup(host);
+ status = CELIX_SUCCESS;
+ }
+ else if (strcmp(ifa->ifa_name, interface) == 0) {
+ *ip = strdup(host);
+ status = CELIX_SUCCESS;
+ }
+ }
+ }
+
+ freeifaddrs(ifaddr);
+ }
+
+ return status;
+}
+#endif
+
+static celix_status_t pubsubAdmin_addSubscriptionToPendingList(pubsub_admin_pt admin,pubsub_endpoint_pt subEP){
+ celix_status_t status = CELIX_SUCCESS;
- char* scope_topic = createScopeTopicKey(subEP->scope, subEP->topic);
++ char* scope_topic = createScopeTopicKey(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+ array_list_pt pendingListPerTopic = hashMap_get(admin->pendingSubscriptions,scope_topic);
+ if(pendingListPerTopic==NULL){
+ arrayList_create(&pendingListPerTopic);
+ 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;i<arrayList_size(admin->noSerializerSubscriptions);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;i<arrayList_size(admin->noSerializerPublications);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);
+ /* Remove the serializer from the list */
+ arrayList_removeElement(admin->serializerList, reference);
+ celixThreadMutex_unlock(&admin->serializerListLock);
+
+
+ celixThreadMutex_lock(&admin->usedSerializersLock);
+ array_list_pt topicPubList = (array_list_pt)hashMap_remove(admin->topicPublicationsPerSerializer, service);
+ array_list_pt topicSubList = (array_list_pt)hashMap_remove(admin->topicSubscriptionsPerSerializer, service);
+ celixThreadMutex_unlock(&admin->usedSerializersLock);
+
+ /* Now destroy the topicPublications, but first put back the pubsub_endpoints back to the noSerializer pending list */
+ if(topicPubList!=NULL){
+ for(i=0;i<arrayList_size(topicPubList);i++){
+ topic_publication_pt topicPub = (topic_publication_pt)arrayList_get(topicPubList,i);
+ /* Stop the topic publication */
+ pubsub_topicPublicationStop(topicPub);
+ /* Get the endpoints that are going to be orphan */
+ array_list_pt pubList = pubsub_topicPublicationGetPublisherList(topicPub);
+ for(j=0;j<arrayList_size(pubList);j++){
+ pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(pubList,j);
+ /* Remove the publication */
+ pubsubAdmin_removePublication(admin, pubEP);
+ /* Reset the endpoint field, so that will be recreated from scratch when a new serializer will be found */
- if(pubEP->endpoint!=NULL){
- free(pubEP->endpoint);
- pubEP->endpoint = NULL;
++ if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL){
++ properties_unset(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL);
+ }
+ /* 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 */
+ if(topicSubList!=NULL){
+ for(i=0;i<arrayList_size(topicSubList);i++){
+ topic_subscription_pt topicSub = (topic_subscription_pt)arrayList_get(topicSubList,i);
+ /* Stop the topic subscription */
+ pubsub_topicSubscriptionStop(topicSub);
+ /* Get the endpoints that are going to be orphan */
+ array_list_pt subList = pubsub_topicSubscriptionGetSubscribersList(topicSub);
+ for(j=0;j<arrayList_size(subList);j++){
+ pubsub_endpoint_pt subEP = (pubsub_endpoint_pt)arrayList_get(subList,j);
+ /* Remove the subscription */
+ pubsubAdmin_removeSubscription(admin, subEP);
+ /* Reset the endpoint field, so that will be recreated from scratch when a new serializer will be found */
- if(subEP->endpoint!=NULL){
- free(subEP->endpoint);
- subEP->endpoint = NULL;
++ if(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL){
++ properties_unset(subEP->endpoint_props, PUBSUB_ENDPOINT_URL);
+ }
+ /* 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);
+ }
+
+
+
+ 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);
+
+}
http://git-wip-us.apache.org/repos/asf/celix/blob/0a5ef69a/pubsub/pubsub_admin_zmq/src/topic_publication.c
----------------------------------------------------------------------
diff --cc pubsub/pubsub_admin_zmq/src/topic_publication.c
index b612605,0000000..873cec2
mode 100644,000000..100644
--- a/pubsub/pubsub_admin_zmq/src/topic_publication.c
+++ b/pubsub/pubsub_admin_zmq/src/topic_publication.c
@@@ -1,630 -1,0 +1,631 @@@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include <czmq.h>
+/* The following undefs prevent the collision between:
+ * - sys/syslog.h (which is included within czmq)
+ * - celix/dfi/dfi_log_util.h
+ */
+#undef LOG_DEBUG
+#undef LOG_WARNING
+#undef LOG_INFO
+#undef LOG_WARNING
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "array_list.h"
+#include "celixbool.h"
+#include "service_registration.h"
+#include "utils.h"
+#include "service_factory.h"
+#include "version.h"
+
+#include "pubsub_common.h"
+#include "pubsub_utils.h"
+#include "pubsub/publisher.h"
+
+#include "topic_publication.h"
+
+#include "pubsub_serializer.h"
+
+#ifdef BUILD_WITH_ZMQ_SECURITY
+ #include "zmq_crypto.h"
+
+ #define MAX_CERT_PATH_LENGTH 512
+#endif
+
+#define EP_ADDRESS_LEN 32
+#define ZMQ_BIND_MAX_RETRY 5
+
+#define FIRST_SEND_DELAY 2
+
+struct topic_publication {
+ zsock_t* zmq_socket;
+ celix_thread_mutex_t socket_lock; //Protects zmq_socket access
+ zcert_t * zmq_cert;
+ char* endpoint;
+ service_registration_pt svcFactoryReg;
+ array_list_pt pub_ep_list; //List<pubsub_endpoint>
+ hash_map_pt boundServices; //<bundle_pt,bound_service>
+ pubsub_serializer_service_t *serializer;
+ celix_thread_mutex_t tp_lock;
+};
+
+typedef struct publish_bundle_bound_service {
+ topic_publication_pt parent;
+ pubsub_publisher_t service;
+ bundle_pt bundle;
+ char *topic;
+ 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_pt;
+
+/* Note: correct locking order is
+ * 1. tp_lock
+ * 2. mp_lock
+ * 3. socket_lock
+ *
+ * tp_lock and socket_lock are independent.
+ */
+
+typedef struct pubsub_msg{
+ pubsub_msg_header_pt header;
+ char* payload;
+ int payloadSize;
+}* 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_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 *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, 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
+ 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(pubEP->topic, top) == 0){
+ printf("PSA_ZMQ_TP: Secure topic: '%s'\n", top);
+ pubEP->is_secure = true;
+ }
+ free(top);
+ top = NULL;
+ }
+
+ arrayList_destroy(secure_topics_list);
+ }
+
+ zcert_t* pub_cert = NULL;
+ if (pubEP->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);
+
+ char cert_path[MAX_CERT_PATH_LENGTH];
+
+ //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("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("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;
+ }
+ }
+#endif
+
+ zsock_t* socket = zsock_new (ZMQ_PUB);
+ if(socket==NULL){
+ #ifdef BUILD_WITH_ZMQ_SECURITY
+ if (pubEP->is_secure){
+ zcert_destroy(&pub_cert);
+ }
+ #endif
+
+ perror("Error for zmq_socket");
+ return CELIX_SERVICE_EXCEPTION;
+ }
+#ifdef BUILD_WITH_ZMQ_SECURITY
+ if (pubEP->is_secure){
+ zcert_apply (pub_cert, socket); // apply certificate to socket
+ zsock_set_curve_server (socket, true); // setup the publisher's socket to use the curve functions
+ }
+#endif
+
+ int rv = -1, retry=0;
+ char* ep = malloc(EP_ADDRESS_LEN);
+ char bindAddress[EP_ADDRESS_LEN];
+
+ while(rv==-1 && retry<ZMQ_BIND_MAX_RETRY){
+ /* Randomized part due to same bundle publishing on different topics */
+ unsigned int port = rand_range(basePort,maxPort);
+ memset(ep,0,EP_ADDRESS_LEN);
+ memset(bindAddress, 0, EP_ADDRESS_LEN);
+
+ snprintf(ep,EP_ADDRESS_LEN,"tcp://%s:%u",bindIP,port);
- snprintf(bindAddress, EP_ADDRESS_LEN, "tcp://0.0.0.0:%u", port); //NOTE using a different bind addres than endpoint address
++ snprintf(bindAddress, EP_ADDRESS_LEN, "tcp://0.0.0.0:%u", port); //NOTE using a different bind address than endpoint address
+ rv = zsock_bind (socket, "%s", bindAddress);
+ if (rv == -1) {
+ perror("Error for zmq_bind");
+ }
+ retry++;
+ }
+
+ if(rv == -1){
+ free(ep);
+ return CELIX_SERVICE_EXCEPTION;
+ }
+
+ /* ZMQ stuffs are all fine at this point. Let's create and initialize the structure */
+
+ topic_publication_pt pub = calloc(1,sizeof(*pub));
+
+ arrayList_create(&(pub->pub_ep_list));
+ pub->boundServices = hashMap_create(NULL,NULL,NULL,NULL);
+ celixThreadMutex_create(&(pub->tp_lock),NULL);
+
+ pub->endpoint = ep;
+ pub->zmq_socket = socket;
+ pub->serializer = best_serializer;
+
+ celixThreadMutex_create(&(pub->socket_lock),NULL);
+
+#ifdef BUILD_WITH_ZMQ_SECURITY
+ if (pubEP->is_secure){
+ pub->zmq_cert = pub_cert;
+ }
+#endif
+
+ pubsub_topicPublicationAddPublisherEP(pub,pubEP);
+
+ *out = pub;
+
+ return status;
+}
+
+celix_status_t pubsub_topicPublicationDestroy(topic_publication_pt pub){
+ celix_status_t status = CELIX_SUCCESS;
+
+ celixThreadMutex_lock(&(pub->tp_lock));
+
+ free(pub->endpoint);
+ arrayList_destroy(pub->pub_ep_list);
+
+ hash_map_iterator_pt iter = hashMapIterator_create(pub->boundServices);
+ while(hashMapIterator_hasNext(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
+
+ celixThreadMutex_unlock(&(pub->tp_lock));
+
+ celixThreadMutex_destroy(&(pub->tp_lock));
+
+ celixThreadMutex_lock(&(pub->socket_lock));
+ zsock_destroy(&(pub->zmq_socket));
+ celixThreadMutex_unlock(&(pub->socket_lock));
+
+ celixThreadMutex_destroy(&(pub->socket_lock));
+
+ free(pub);
+
+ return status;
+}
+
+celix_status_t pubsub_topicPublicationStart(bundle_context_pt bundle_context,topic_publication_pt pub,service_factory_pt* svcFactory){
+ celix_status_t status = CELIX_SUCCESS;
+
+ /* Let's register the new service */
+
+ pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(pub->pub_ep_list,0);
+
+ if(pubEP!=NULL){
+ service_factory_pt factory = calloc(1, sizeof(*factory));
+ factory->handle = pub;
+ factory->getService = pubsub_topicPublicationGetService;
+ factory->ungetService = pubsub_topicPublicationUngetService;
+
+ properties_pt props = properties_create();
- properties_set(props,PUBSUB_PUBLISHER_TOPIC,pubEP->topic);
- properties_set(props,PUBSUB_PUBLISHER_SCOPE,pubEP->scope);
++ properties_set(props,PUBSUB_PUBLISHER_TOPIC,properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
++ properties_set(props,PUBSUB_PUBLISHER_SCOPE,properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE));
+ properties_set(props,"service.version", PUBSUB_PUBLISHER_SERVICE_VERSION);
+
+ status = bundleContext_registerServiceFactory(bundle_context,PUBSUB_PUBLISHER_SERVICE_NAME,factory,props,&(pub->svcFactoryReg));
+
+ if(status != CELIX_SUCCESS){
+ properties_destroy(props);
- printf("PSA_ZMQ_PSA_ZMQ_TP: 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",
++ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),pubEP->serviceID);
+ }
+ else{
+ *svcFactory = factory;
+ }
+ }
+ else{
+ printf("PSA_ZMQ_PSA_ZMQ_TP: Cannot find pubsub_endpoint after adding it...Should never happen!\n");
+ status = CELIX_SERVICE_EXCEPTION;
+ }
+
+ return status;
+}
+
+celix_status_t pubsub_topicPublicationStop(topic_publication_pt pub){
+ return serviceRegistration_unregister(pub->svcFactoryReg);
+}
+
+celix_status_t pubsub_topicPublicationAddPublisherEP(topic_publication_pt pub,pubsub_endpoint_pt ep){
+
+ celixThreadMutex_lock(&(pub->tp_lock));
- ep->endpoint = strdup(pub->endpoint);
++ pubsubEndpoint_setField(ep, PUBSUB_ENDPOINT_URL, pub->endpoint);
+ arrayList_add(pub->pub_ep_list,ep);
+ celixThreadMutex_unlock(&(pub->tp_lock));
+
+ return CELIX_SUCCESS;
+}
+
+celix_status_t pubsub_topicPublicationRemovePublisherEP(topic_publication_pt pub,pubsub_endpoint_pt ep){
+
+ celixThreadMutex_lock(&(pub->tp_lock));
+ for (int i = 0; i < arrayList_size(pub->pub_ep_list); i++) {
+ pubsub_endpoint_pt e = arrayList_get(pub->pub_ep_list, i);
+ if(pubsubEndpoint_equals(ep, e)) {
+ arrayList_removeElement(pub->pub_ep_list,ep);
+ break;
+ }
+ }
+ celixThreadMutex_unlock(&(pub->tp_lock));
+
+ return CELIX_SUCCESS;
+}
+
+array_list_pt pubsub_topicPublicationGetPublisherList(topic_publication_pt pub){
+ array_list_pt list = NULL;
+ celixThreadMutex_lock(&(pub->tp_lock));
+ list = arrayList_clone(pub->pub_ep_list);
+ celixThreadMutex_unlock(&(pub->tp_lock));
+ return list;
+}
+
+
+static celix_status_t pubsub_topicPublicationGetService(void* handle, bundle_pt bundle, service_registration_pt registration, void **service) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ topic_publication_pt publish = (topic_publication_pt)handle;
+
+ celixThreadMutex_lock(&(publish->tp_lock));
+
+ 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{
+ bound->getCount++;
+ }
+
+ *service = &bound->service;
+
+ celixThreadMutex_unlock(&(publish->tp_lock));
+
+ return status;
+}
+
+static celix_status_t pubsub_topicPublicationUngetService(void* handle, bundle_pt bundle, service_registration_pt registration, void **service) {
+
+ topic_publication_pt publish = (topic_publication_pt)handle;
+
+ celixThreadMutex_lock(&(publish->tp_lock));
+
+ 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){
+ pubsub_destroyPublishBundleBoundService(bound);
+ hashMap_remove(publish->boundServices,bundle);
+ }
+
+ }
+ else{
+ long bundleId = -1;
+ bundle_getBundleId(bundle,&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 */
+ *service = NULL;
+
+ celixThreadMutex_unlock(&(publish->tp_lock));
+
+ return CELIX_SUCCESS;
+}
+
+static bool send_pubsub_msg(zsock_t* zmq_socket, pubsub_msg_pt msg, bool last){
+
+ bool ret = true;
+
+ zframe_t* headerMsg = zframe_new(msg->header, sizeof(struct pubsub_msg_header));
+ if (headerMsg == NULL) ret=false;
+ zframe_t* payloadMsg = zframe_new(msg->payload, msg->payloadSize);
+ if (payloadMsg == NULL) ret=false;
+
+ delay_first_send_for_late_joiners();
+
+ if( zframe_send(&headerMsg,zmq_socket, ZFRAME_MORE) == -1) ret=false;
+
+ if(!last){
+ if( zframe_send(&payloadMsg,zmq_socket, ZFRAME_MORE) == -1) ret=false;
+ }
+ else{
+ if( zframe_send(&payloadMsg,zmq_socket, 0) == -1) ret=false;
+ }
+
+ if (!ret){
+ zframe_destroy(&headerMsg);
+ zframe_destroy(&payloadMsg);
+ }
+
+ free(msg->header);
+ free(msg->payload);
+ free(msg);
+
+ return ret;
+
+}
+
+static bool send_pubsub_mp_msg(zsock_t* zmq_socket, array_list_pt mp_msg_parts){
+
+ bool ret = true;
+
+ unsigned int i = 0;
+ unsigned int mp_num = arrayList_size(mp_msg_parts);
+ for(;i<mp_num;i++){
+ ret = ret && send_pubsub_msg(zmq_socket, (pubsub_msg_pt)arrayList_get(mp_msg_parts,i), (i==mp_num-1));
+ }
+ arrayList_clear(mp_msg_parts);
+
+ return ret;
+
+}
+
+static int pubsub_topicPublicationSend(void* handle, unsigned int msgTypeId, const void *msg) {
+
+ return pubsub_topicPublicationSendMultipart(handle,msgTypeId,msg, PUBSUB_PUBLISHER_FIRST_MSG | PUBSUB_PUBLISHER_LAST_MSG);
+
+}
+
+static int pubsub_topicPublicationSendMultipart(void *handle, unsigned int msgTypeId, const void *inMsg, int flags){
+
+ int status = 0;
+
+ publish_bundle_bound_service_pt bound = (publish_bundle_bound_service_pt) handle;
+
+ celixThreadMutex_lock(&(bound->parent->tp_lock));
+ 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("PSA_ZMQ_TP: Multipart send already in progress. Cannot process a new one.\n");
+ celixThreadMutex_unlock(&(bound->mp_lock));
+ celixThreadMutex_unlock(&(bound->parent->tp_lock));
+ return -3;
+ }
+
+ 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;
+
+ 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);
+ msg_hdr->major = major;
+ msg_hdr->minor = minor;
+ }
+
+ void *serializedOutput = NULL;
+ size_t serializedOutputLen = 0;
+ 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->payloadSize = serializedOutputLen;
+ bool snd = true;
+
+ 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("PSA_ZMQ_TP: ERROR: received msg part without the first part.\n");
+ status = -4;
+ }
+ else{
+ arrayList_add(bound->mp_parts,msg);
+ }
+ break;
+ case PUBSUB_PUBLISHER_LAST_MSG:
+ if(!bound->mp_send_in_progress){
+ printf("PSA_ZMQ_TP: ERROR: received end msg without the first part.\n");
+ status = -4;
+ }
+ else{
+ arrayList_add(bound->mp_parts,msg);
+ snd = send_pubsub_mp_msg(bound->parent->zmq_socket,bound->mp_parts);
+ bound->mp_send_in_progress = false;
+ }
+ break;
+ case PUBSUB_PUBLISHER_FIRST_MSG | PUBSUB_PUBLISHER_LAST_MSG: //Normal send case
+ snd = send_pubsub_msg(bound->parent->zmq_socket,msg,true);
+ break;
+ default:
+ printf("PSA_ZMQ_TP: ERROR: Invalid MP flags combination\n");
+ status = -4;
+ break;
+ }
+
+ if(status==-4){
+ free(msg);
+ }
+
+ if(!snd){
+ 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("PSA_ZMQ_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;
+
+}
+
+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)random())/((double)RAND_MAX));
+ return (max-min+1)*scaled + min;
+
+}
+
+static publish_bundle_bound_service_pt pubsub_createPublishBundleBoundService(topic_publication_pt tp,bundle_pt bundle){
+
+ //PRECOND lock on tp->lock
+
+ 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);
+
+ 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->topic=strdup(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+
+ 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_pt boundSvc){
+
+ //PRECOND lock on tp->lock
+
+ celixThreadMutex_lock(&boundSvc->mp_lock);
+
+
+ if(boundSvc->parent->serializer != NULL && boundSvc->msgTypes != NULL){
+ boundSvc->parent->serializer->destroySerializerMap(boundSvc->parent->serializer->handle, boundSvc->msgTypes);
+ }
+
+ if(boundSvc->mp_parts!=NULL){
+ arrayList_destroy(boundSvc->mp_parts);
+ }
+
+ if(boundSvc->topic!=NULL){
+ free(boundSvc->topic);
+ }
+
+ celixThreadMutex_unlock(&boundSvc->mp_lock);
+ celixThreadMutex_destroy(&boundSvc->mp_lock);
+
+ free(boundSvc);
+
+}
+
+static void delay_first_send_for_late_joiners(){
+
+ static bool firstSend = true;
+
+ if(firstSend){
+ printf("PSA_ZMQ_TP: Delaying first send for late joiners...\n");
+ sleep(FIRST_SEND_DELAY);
+ firstSend = false;
+ }
+}
http://git-wip-us.apache.org/repos/asf/celix/blob/0a5ef69a/pubsub/pubsub_discovery/src/etcd_watcher.c
----------------------------------------------------------------------
diff --cc pubsub/pubsub_discovery/src/etcd_watcher.c
index 3c3a5a8,0000000..726269a
mode 100644,000000..100644
--- a/pubsub/pubsub_discovery/src/etcd_watcher.c
+++ b/pubsub/pubsub_discovery/src/etcd_watcher.c
@@@ -1,290 -1,0 +1,344 @@@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
++#include <jansson.h>
+
+#include "celix_log.h"
+#include "constants.h"
+
+#include "etcd.h"
+#include "etcd_watcher.h"
+
+#include "pubsub_discovery.h"
+#include "pubsub_discovery_impl.h"
+
+
+
+#define MAX_ROOTNODE_LENGTH 128
+#define MAX_LOCALNODE_LENGTH 4096
+#define MAX_FIELD_LENGTH 128
+
+#define CFG_ETCD_ROOT_PATH "PUBSUB_DISCOVERY_ETCD_ROOT_PATH"
+#define DEFAULT_ETCD_ROOTPATH "pubsub/discovery"
+
+#define CFG_ETCD_SERVER_IP "PUBSUB_DISCOVERY_ETCD_SERVER_IP"
+#define DEFAULT_ETCD_SERVER_IP "127.0.0.1"
+
+#define CFG_ETCD_SERVER_PORT "PUBSUB_DISCOVERY_ETCD_SERVER_PORT"
+#define DEFAULT_ETCD_SERVER_PORT 2379
+
+// be careful - this should be higher than the curl timeout
+#define CFG_ETCD_TTL "DISCOVERY_ETCD_TTL"
+#define DEFAULT_ETCD_TTL 30
+
+
+struct etcd_watcher {
+ pubsub_discovery_pt pubsub_discovery;
+
+ celix_thread_mutex_t watcherLock;
+ celix_thread_t watcherThread;
+
+ 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;
+};
+
+
+// note that the rootNode shouldn't have a leading slash
+static celix_status_t etcdWatcher_getTopicRootPath(bundle_context_pt context, const char *scope, const char *topic, char* rootNode, int rootNodeLen) {
+ celix_status_t status = CELIX_SUCCESS;
+ 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);
+ } else {
+ 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;
+
+ 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;
+}
+
+
+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);
+ }
+}
+
+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;
+ }
+ return status;
+}
+
+// gets everything from provided key
+celix_status_t etcdWatcher_getPublisherEndpointFromKey(pubsub_discovery_pt pubsub_discovery, const char* etcdKey, const char* etcdValue, pubsub_endpoint_pt* pubEP) {
+
+ celix_status_t status = CELIX_SUCCESS;
+
+ char rootPath[MAX_ROOTNODE_LENGTH];
+ char *expr = NULL;
+ char scope[MAX_FIELD_LENGTH];
+ char topic[MAX_FIELD_LENGTH];
+ char fwUUID[MAX_FIELD_LENGTH];
+ char serviceId[MAX_FIELD_LENGTH];
+
+ memset(rootPath,0,MAX_ROOTNODE_LENGTH);
+ memset(topic,0,MAX_FIELD_LENGTH);
+ memset(fwUUID,0,MAX_FIELD_LENGTH);
+ memset(serviceId,0,MAX_FIELD_LENGTH);
+
+ etcdWatcher_getRootPath(pubsub_discovery->context, rootPath);
+
+ 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,NULL,pubEP);
++
++ // etcdValue contains the json formatted string
++ json_error_t error;
++ json_t* jsonRoot = json_loads(etcdValue, JSON_DECODE_ANY, &error);
++
++ const char* endpoint_serializer = NULL;
++ const char* endpoint_admin_type = NULL;
++ const char* endpoint_url = NULL;
++ const char* endpoint_type = NULL;
++
++ if (json_is_object(jsonRoot)){
++
++ void *iter = json_object_iter(jsonRoot);
++
++ const char *key;
++ json_t *value;
++
++ while (iter) {
++ key = json_object_iter_key(iter);
++ value = json_object_iter_value(iter);
++
++ if (strcmp(key, PUBSUB_ENDPOINT_SERIALIZER) == 0) {
++ endpoint_serializer = json_string_value(value);
++ } else if (strcmp(key, PUBSUB_ENDPOINT_ADMIN_TYPE) == 0) {
++ endpoint_admin_type = json_string_value(value);
++ } else if (strcmp(key, PUBSUB_ENDPOINT_URL) == 0) {
++ endpoint_url = json_string_value(value);
++ } else if (strcmp(key, PUBSUB_ENDPOINT_TYPE) == 0) {
++ endpoint_type = json_string_value(value);
++ }
++
++ iter = json_object_iter_next(jsonRoot, iter);
++ }
++
++ if (endpoint_url == NULL) {
++ printf("EW: No endpoint found in json object!\n");
++ endpoint_url = etcdValue;
++ }
++
++ } else {
++ endpoint_url = etcdValue;
++ }
++
++ status = pubsubEndpoint_create(fwUUID,scope,topic,strtol(serviceId,NULL,10),endpoint_url,NULL,pubEP);
++
++ if (status == CELIX_SUCCESS) {
++ status += pubsubEndpoint_setField(*pubEP, PUBSUB_ENDPOINT_SERIALIZER, endpoint_serializer);
++ status += pubsubEndpoint_setField(*pubEP, PUBSUB_ENDPOINT_ADMIN_TYPE, endpoint_admin_type);
++ status += pubsubEndpoint_setField(*pubEP, PUBSUB_ENDPOINT_TYPE, endpoint_type);
++ }
++
++ if (jsonRoot != NULL) {
++ json_decref(jsonRoot);
++ }
+ }
+ }
+ return status;
+}
+
+/*
+ * performs (blocking) etcd_watch calls to check for
+ * 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;
+}
+
+celix_status_t etcdWatcher_create(pubsub_discovery_pt pubsub_discovery, bundle_context_pt context, const char *scope, const char *topic, etcd_watcher_pt *watcher) {
+ celix_status_t status = CELIX_SUCCESS;
+
+
+ if (pubsub_discovery == NULL) {
+ return CELIX_BUNDLE_EXCEPTION;
+ }
+
+ (*watcher) = calloc(1, sizeof(struct etcd_watcher));
+
+ if(*watcher == NULL){
+ return CELIX_ENOMEM;
+ }
+
+ (*watcher)->pubsub_discovery = pubsub_discovery;
+ (*watcher)->scope = strdup(scope);
+ (*watcher)->topic = strdup(topic);
+
+
+ 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;
+ }
+
+ celixThreadMutex_unlock(&(*watcher)->watcherLock);
+
+
+ return status;
+}
+
+celix_status_t etcdWatcher_destroy(etcd_watcher_pt watcher) {
+
+ celix_status_t status = CELIX_SUCCESS;
+
+ char rootPath[MAX_ROOTNODE_LENGTH];
+ etcdWatcher_getTopicRootPath(watcher->pubsub_discovery->context, watcher->scope, watcher->topic, rootPath, MAX_ROOTNODE_LENGTH);
+ celixThreadMutex_destroy(&(watcher->watcherLock));
+
+ free(watcher->scope);
+ free(watcher->topic);
+ free(watcher);
+
+ return status;
+}
+
+celix_status_t etcdWatcher_stop(etcd_watcher_pt watcher){
+ celix_status_t status = CELIX_SUCCESS;
+
+ celixThreadMutex_lock(&(watcher->watcherLock));
+ watcher->running = false;
+ celixThreadMutex_unlock(&(watcher->watcherLock));
+
+ celixThread_join(watcher->watcherThread, NULL);
+
+ return status;
+
+}
+
+
http://git-wip-us.apache.org/repos/asf/celix/blob/0a5ef69a/pubsub/pubsub_discovery/src/etcd_writer.c
----------------------------------------------------------------------
diff --cc pubsub/pubsub_discovery/src/etcd_writer.c
index 1c423f3,0000000..e820e50
mode 100644,000000..100644
--- a/pubsub/pubsub_discovery/src/etcd_writer.c
+++ b/pubsub/pubsub_discovery/src/etcd_writer.c
@@@ -1,189 -1,0 +1,221 @@@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
++#include <jansson.h>
+
+#include "celix_log.h"
+#include "constants.h"
+
+#include "etcd.h"
+#include "etcd_writer.h"
+
+#include "pubsub_discovery.h"
+#include "pubsub_discovery_impl.h"
+
+#define MAX_ROOTNODE_LENGTH 128
+
+#define CFG_ETCD_ROOT_PATH "PUBSUB_DISCOVERY_ETCD_ROOT_PATH"
+#define DEFAULT_ETCD_ROOTPATH "pubsub/discovery"
+
+#define CFG_ETCD_SERVER_IP "PUBSUB_DISCOVERY_ETCD_SERVER_IP"
+#define DEFAULT_ETCD_SERVER_IP "127.0.0.1"
+
+#define CFG_ETCD_SERVER_PORT "PUBSUB_DISCOVERY_ETCD_SERVER_PORT"
+#define DEFAULT_ETCD_SERVER_PORT 2379
+
+// be careful - this should be higher than the curl timeout
+#define CFG_ETCD_TTL "DISCOVERY_ETCD_TTL"
+#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;
+};
+
+
+static const char* etcdWriter_getRootPath(bundle_context_pt context);
+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;
+}
+
+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);
++ snprintf(dir,MAX_ROOTNODE_LENGTH,"%s/%s/%s/%s",
++ rootPath,
++ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
++ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
++ properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID));
++
+ 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){
+ celix_status_t status = CELIX_BUNDLE_EXCEPTION;
+
+ if(storeEP){
+ const char *fwUUID = NULL;
+ bundleContext_getProperty(writer->pubsub_discovery->context, OSGI_FRAMEWORK_FRAMEWORK_UUID, &fwUUID);
- if(fwUUID && strcmp(pubEP->frameworkUUID, fwUUID) == 0) {
++ if(fwUUID && strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID), fwUUID) == 0) {
+ celixThreadMutex_lock(&writer->localPubsLock);
+ pubsub_endpoint_pt p = NULL;
+ pubsubEndpoint_clone(pubEP, &p);
+ arrayList_add(writer->localPubs,p);
+ celixThreadMutex_unlock(&writer->localPubsLock);
+ }
+ }
+
+ char *key;
+
+ const char* ttlStr = NULL;
+ int ttl = 0;
+
+ // determine ttl
+ if ((bundleContext_getProperty(writer->pubsub_discovery->context, CFG_ETCD_TTL, &ttlStr) != CELIX_SUCCESS) || !ttlStr) {
+ ttl = DEFAULT_ETCD_TTL;
+ } else {
+ char* endptr = NULL;
+ errno = 0;
+ ttl = strtol(ttlStr, &endptr, 10);
+ if (*endptr || errno != 0) {
+ ttl = DEFAULT_ETCD_TTL;
+ }
+ }
+
+ 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);
-
- if(!etcd_set(key,pubEP->endpoint,ttl,false)){
++ asprintf(&key,"%s/%s/%s/%s/%ld",
++ rootPath,
++ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
++ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
++ properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
++ pubEP->serviceID);
++
++ char serviceID [sizeof(pubEP->serviceID)];
++ snprintf(serviceID, sizeof(pubEP->serviceID), "%ld", pubEP->serviceID);
++ json_t* jsonEndpoint = json_pack("{s:s,s:s,s:s,s:s,s:s,s:s,s:s}",
++ PUBSUB_ENDPOINT_SERVICE_ID, serviceID,
++ PUBSUB_ENDPOINT_SERIALIZER, "serializer.json", //TODO: Serializer not (yet) stored in endpoint
++ PUBSUB_ENDPOINT_ADMIN_TYPE, "zmq", //TODO: PSA type not (yet) stored in endpoint
++ PUBSUB_ENDPOINT_URL, properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL),
++ PUBSUB_ENDPOINT_TYPE, "publisher", //TODO: Check if necessary
++ PUBSUB_ENDPOINT_TOPIC, properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
++ PUBSUB_ENDPOINT_SCOPE, properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE)
++ );
++ char* jsonEndpointStr = json_dumps(jsonEndpoint, JSON_COMPACT);
++
++ if (!etcd_set(key,jsonEndpointStr,ttl,false)) {
+ status = CELIX_ILLEGAL_ARGUMENT;
+ }
+ FREE_MEM(key);
++ FREE_MEM(jsonEndpointStr);
++ json_decref(jsonEndpoint);
++
+ return status;
+}
+
+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);
++ asprintf(&key, "%s/%s/%s/%s/%ld",
++ rootPath,
++ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
++ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
++ properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
++ 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;
+}
+
+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;
+}
+
[2/4] celix git commit: Merge branch 'endpoint-format' into develop
Posted by rl...@apache.org.
http://git-wip-us.apache.org/repos/asf/celix/blob/0a5ef69a/pubsub/pubsub_discovery/src/pubsub_discovery_impl.c
----------------------------------------------------------------------
diff --cc pubsub/pubsub_discovery/src/pubsub_discovery_impl.c
index 94a8e11,0000000..e3e9704
mode 100644,000000..100644
--- a/pubsub/pubsub_discovery/src/pubsub_discovery_impl.c
+++ b/pubsub/pubsub_discovery/src/pubsub_discovery_impl.c
@@@ -1,457 -1,0 +1,460 @@@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <netdb.h>
+#include <netinet/in.h>
+
+#include "constants.h"
+#include "celix_threads.h"
+#include "bundle_context.h"
+#include "array_list.h"
+#include "utils.h"
+#include "celix_errno.h"
+#include "filter.h"
+#include "service_reference.h"
+#include "service_registration.h"
+
+#include "publisher_endpoint_announce.h"
+#include "etcd_common.h"
+#include "etcd_watcher.h"
+#include "etcd_writer.h"
+#include "pubsub_endpoint.h"
+#include "pubsub_discovery_impl.h"
+
+/* Discovery activator functions */
+celix_status_t pubsub_discovery_create(bundle_context_pt context, pubsub_discovery_pt *ps_discovery) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ *ps_discovery = calloc(1, sizeof(**ps_discovery));
+
+ if (*ps_discovery == NULL) {
+ status = CELIX_ENOMEM;
+ }
+ else{
+ (*ps_discovery)->context = context;
+ (*ps_discovery)->discoveredPubs = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
+ (*ps_discovery)->listenerReferences = hashMap_create(serviceReference_hashCode, NULL, serviceReference_equals2, NULL);
+ (*ps_discovery)->watchers = hashMap_create(utils_stringHash,NULL,utils_stringEquals, NULL);
+ celixThreadMutex_create(&(*ps_discovery)->listenerReferencesMutex, NULL);
+ celixThreadMutex_create(&(*ps_discovery)->discoveredPubsMutex, NULL);
+ celixThreadMutex_create(&(*ps_discovery)->watchersMutex, NULL);
+ }
+
+ return status;
+}
+
+celix_status_t pubsub_discovery_destroy(pubsub_discovery_pt ps_discovery) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ celixThreadMutex_lock(&ps_discovery->discoveredPubsMutex);
+
+ hash_map_iterator_pt iter = hashMapIterator_create(ps_discovery->discoveredPubs);
+
+ while (hashMapIterator_hasNext(iter)) {
+ array_list_pt pubEP_list = (array_list_pt) hashMapIterator_nextValue(iter);
+
+ for(int i=0; i < arrayList_size(pubEP_list); i++) {
+ pubsubEndpoint_destroy(((pubsub_endpoint_pt)arrayList_get(pubEP_list,i)));
+ }
+ arrayList_destroy(pubEP_list);
+ }
+
+ hashMapIterator_destroy(iter);
+
+ hashMap_destroy(ps_discovery->discoveredPubs, true, false);
+ ps_discovery->discoveredPubs = NULL;
+
+ celixThreadMutex_unlock(&ps_discovery->discoveredPubsMutex);
+
+ celixThreadMutex_destroy(&ps_discovery->discoveredPubsMutex);
+
+
+ celixThreadMutex_lock(&ps_discovery->listenerReferencesMutex);
+
+ hashMap_destroy(ps_discovery->listenerReferences, false, false);
+ ps_discovery->listenerReferences = NULL;
+
+ celixThreadMutex_unlock(&ps_discovery->listenerReferencesMutex);
+
+ celixThreadMutex_destroy(&ps_discovery->listenerReferencesMutex);
+
+ free(ps_discovery);
+
+ return status;
+}
+
+celix_status_t pubsub_discovery_start(pubsub_discovery_pt ps_discovery) {
+ celix_status_t status = CELIX_SUCCESS;
+ status = etcdCommon_init(ps_discovery->context);
+ ps_discovery->writer = etcdWriter_create(ps_discovery);
+
+ return status;
+}
+
+celix_status_t pubsub_discovery_stop(pubsub_discovery_pt ps_discovery) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ const char* fwUUID = NULL;
+
+ bundleContext_getProperty(ps_discovery->context, OSGI_FRAMEWORK_FRAMEWORK_UUID, &fwUUID);
+ if (fwUUID == NULL) {
+ printf("PSD: Cannot retrieve fwUUID.\n");
+ return CELIX_INVALID_BUNDLE_CONTEXT;
+ }
+
+ celixThreadMutex_lock(&ps_discovery->watchersMutex);
+
+ hash_map_iterator_pt iter = hashMapIterator_create(ps_discovery->watchers);
+ while (hashMapIterator_hasNext(iter)) {
+ struct watcher_info * wi = hashMapIterator_nextValue(iter);
+ etcdWatcher_stop(wi->watcher);
+ }
+ hashMapIterator_destroy(iter);
+
+ celixThreadMutex_lock(&ps_discovery->discoveredPubsMutex);
+
+ /* Unexport all publishers for the local framework, and also delete from ETCD publisher belonging to the local framework */
+
+ iter = hashMapIterator_create(ps_discovery->discoveredPubs);
+ while (hashMapIterator_hasNext(iter)) {
+ array_list_pt pubEP_list = (array_list_pt) hashMapIterator_nextValue(iter);
+
+ int i;
+ for (i = 0; i < arrayList_size(pubEP_list); i++) {
+ pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt) arrayList_get(pubEP_list, i);
- if (strcmp(pubEP->frameworkUUID, fwUUID) == 0) {
++ if (strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID), fwUUID) == 0) {
+ etcdWriter_deletePublisherEndpoint(ps_discovery->writer, pubEP);
+ } else {
+ pubsub_discovery_informPublishersListeners(ps_discovery, pubEP, false);
+ arrayList_remove(pubEP_list, i);
+ pubsubEndpoint_destroy(pubEP);
+ i--;
+ }
+ }
+ }
+
+ hashMapIterator_destroy(iter);
+
+ celixThreadMutex_unlock(&ps_discovery->discoveredPubsMutex);
+ etcdWriter_destroy(ps_discovery->writer);
+
+ iter = hashMapIterator_create(ps_discovery->watchers);
+ while (hashMapIterator_hasNext(iter)) {
+ struct watcher_info * wi = hashMapIterator_nextValue(iter);
+ etcdWatcher_destroy(wi->watcher);
+ }
+ hashMapIterator_destroy(iter);
+ hashMap_destroy(ps_discovery->watchers, true, true);
+ celixThreadMutex_unlock(&ps_discovery->watchersMutex);
+ return status;
+}
+
+/* Functions called by the etcd_watcher */
+
+celix_status_t pubsub_discovery_addNode(pubsub_discovery_pt pubsub_discovery, pubsub_endpoint_pt pubEP) {
+ celix_status_t status = CELIX_SUCCESS;
+ bool inform=false;
+ celixThreadMutex_lock(&pubsub_discovery->discoveredPubsMutex);
+
- char *pubs_key = createScopeTopicKey(pubEP->scope, pubEP->topic);
++ char *pubs_key = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+ array_list_pt pubEP_list = (array_list_pt)hashMap_get(pubsub_discovery->discoveredPubs,pubs_key);
+ if(pubEP_list==NULL){
+ arrayList_create(&pubEP_list);
+ arrayList_add(pubEP_list,pubEP);
+ hashMap_put(pubsub_discovery->discoveredPubs,strdup(pubs_key),pubEP_list);
+ inform=true;
+ }
+ else{
+ int i;
+ bool found = false;
+ for(i=0;i<arrayList_size(pubEP_list) && !found;i++){
+ found = pubsubEndpoint_equals(pubEP,(pubsub_endpoint_pt)arrayList_get(pubEP_list,i));
+ }
+ if(found){
+ pubsubEndpoint_destroy(pubEP);
+ }
+ else{
+ arrayList_add(pubEP_list,pubEP);
+ inform=true;
+ }
+ }
+ free(pubs_key);
+
+ celixThreadMutex_unlock(&pubsub_discovery->discoveredPubsMutex);
+
+ if(inform){
+ status = pubsub_discovery_informPublishersListeners(pubsub_discovery,pubEP,true);
+ }
+
+ return status;
+}
+
+celix_status_t pubsub_discovery_removeNode(pubsub_discovery_pt pubsub_discovery, pubsub_endpoint_pt pubEP) {
+ celix_status_t status = CELIX_SUCCESS;
+ pubsub_endpoint_pt p = NULL;
+ bool found = false;
+
+ celixThreadMutex_lock(&pubsub_discovery->discoveredPubsMutex);
- char *pubs_key = createScopeTopicKey(pubEP->scope, pubEP->topic);
++ char *pubs_key = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+ array_list_pt pubEP_list = (array_list_pt) hashMap_get(pubsub_discovery->discoveredPubs, pubs_key);
+ free(pubs_key);
+ if (pubEP_list == NULL) {
- printf("PSD: Cannot find any registered publisher for topic %s. Something is not consistent.\n", pubEP->topic);
++ printf("PSD: Cannot find any registered publisher for topic %s. Something is not consistent.\n",
++ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+ status = CELIX_ILLEGAL_STATE;
+ } else {
+ int i;
+
+ for (i = 0; !found && i < arrayList_size(pubEP_list); i++) {
+ p = arrayList_get(pubEP_list, i);
+ found = pubsubEndpoint_equals(pubEP, p);
+ if (found) {
+ arrayList_remove(pubEP_list, i);
+ pubsubEndpoint_destroy(p);
+ }
+ }
+ }
+
+ celixThreadMutex_unlock(&pubsub_discovery->discoveredPubsMutex);
+ if (found) {
+ status = pubsub_discovery_informPublishersListeners(pubsub_discovery, pubEP, false);
+ }
+ pubsubEndpoint_destroy(pubEP);
+
+ return status;
+}
+
+/* Callback to the pubsub_topology_manager */
+celix_status_t pubsub_discovery_informPublishersListeners(pubsub_discovery_pt pubsub_discovery, pubsub_endpoint_pt pubEP, bool epAdded) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ // Inform listeners of new publisher endpoint
+ celixThreadMutex_lock(&pubsub_discovery->listenerReferencesMutex);
+
+ if (pubsub_discovery->listenerReferences != NULL) {
+ hash_map_iterator_pt iter = hashMapIterator_create(pubsub_discovery->listenerReferences);
+ while (hashMapIterator_hasNext(iter)) {
+ service_reference_pt reference = hashMapIterator_nextKey(iter);
+
+ publisher_endpoint_announce_pt listener = NULL;
+
+ bundleContext_getService(pubsub_discovery->context, reference, (void**) &listener);
+ if (epAdded) {
+ listener->announcePublisher(listener->handle, pubEP);
+ } else {
+ listener->removePublisher(listener->handle, pubEP);
+ }
+ bundleContext_ungetService(pubsub_discovery->context, reference, NULL);
+ }
+ hashMapIterator_destroy(iter);
+ }
+
+ celixThreadMutex_unlock(&pubsub_discovery->listenerReferencesMutex);
+
+ return status;
+}
+
+
+/* Service's functions implementation */
+celix_status_t pubsub_discovery_announcePublisher(void *handle, pubsub_endpoint_pt pubEP) {
+ celix_status_t status = CELIX_SUCCESS;
- printf("pubsub_discovery_announcePublisher : %s / %s\n", pubEP->topic, pubEP->endpoint);
++ printf("pubsub_discovery_announcePublisher : %s / %s\n",
++ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
++ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
+ pubsub_discovery_pt pubsub_discovery = (pubsub_discovery_pt) handle;
+
+ celixThreadMutex_lock(&pubsub_discovery->discoveredPubsMutex);
+
- char *pub_key = createScopeTopicKey(pubEP->scope,pubEP->topic);
++ char *pub_key = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+ array_list_pt pubEP_list = (array_list_pt)hashMap_get(pubsub_discovery->discoveredPubs,pub_key);
+
+ if(pubEP_list==NULL){
+ arrayList_create(&pubEP_list);
+ hashMap_put(pubsub_discovery->discoveredPubs,strdup(pub_key),pubEP_list);
+ }
+ free(pub_key);
+ pubsub_endpoint_pt p = NULL;
+ pubsubEndpoint_clone(pubEP, &p);
+
+ arrayList_add(pubEP_list,p);
+
+ status = etcdWriter_addPublisherEndpoint(pubsub_discovery->writer,p,true);
+
+ celixThreadMutex_unlock(&pubsub_discovery->discoveredPubsMutex);
+
+ return status;
+}
+
+celix_status_t pubsub_discovery_removePublisher(void *handle, pubsub_endpoint_pt pubEP) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ pubsub_discovery_pt pubsub_discovery = (pubsub_discovery_pt) handle;
+
+ celixThreadMutex_lock(&pubsub_discovery->discoveredPubsMutex);
+
- char *pub_key = createScopeTopicKey(pubEP->scope,pubEP->topic);
++ char *pub_key = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+ array_list_pt pubEP_list = (array_list_pt)hashMap_get(pubsub_discovery->discoveredPubs,pub_key);
+ free(pub_key);
+ if(pubEP_list==NULL){
- printf("PSD: Cannot find any registered publisher for topic %s. Something is not consistent.\n",pubEP->topic);
++ printf("PSD: Cannot find any registered publisher for topic %s. Something is not consistent.\n",properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+ status = CELIX_ILLEGAL_STATE;
+ }
+ else{
+
+ int i;
+ bool found = false;
+ pubsub_endpoint_pt p = NULL;
+
+ for(i=0;!found && i<arrayList_size(pubEP_list);i++){
+ p = (pubsub_endpoint_pt)arrayList_get(pubEP_list,i);
+ found = pubsubEndpoint_equals(pubEP,p);
+ }
+
+ if(!found){
+ printf("PSD: Trying to remove a not existing endpoint. Something is not consistent.\n");
+ status = CELIX_ILLEGAL_STATE;
+ }
+ else{
+
+ arrayList_removeElement(pubEP_list,p);
+
+ status = etcdWriter_deletePublisherEndpoint(pubsub_discovery->writer,p);
+
+ pubsubEndpoint_destroy(p);
+ }
+ }
+
+ celixThreadMutex_unlock(&pubsub_discovery->discoveredPubsMutex);
+
+ return status;
+}
+
+celix_status_t pubsub_discovery_interestedInTopic(void *handle, const char* scope, const char* topic) {
+ pubsub_discovery_pt pubsub_discovery = (pubsub_discovery_pt) handle;
+
+ char *scope_topic_key = createScopeTopicKey(scope, topic);
+ celixThreadMutex_lock(&pubsub_discovery->watchersMutex);
+ struct watcher_info * wi = hashMap_get(pubsub_discovery->watchers, scope_topic_key);
+ if(wi) {
+ wi->nr_references++;
+ free(scope_topic_key);
+ } else {
+ wi = calloc(1, sizeof(*wi));
+ etcdWatcher_create(pubsub_discovery, pubsub_discovery->context, scope, topic, &wi->watcher);
+ wi->nr_references = 1;
+ hashMap_put(pubsub_discovery->watchers, scope_topic_key, wi);
+ }
+
+ celixThreadMutex_unlock(&pubsub_discovery->watchersMutex);
+
+ return CELIX_SUCCESS;
+}
+
+celix_status_t pubsub_discovery_uninterestedInTopic(void *handle, const char* scope, const char* topic) {
+ pubsub_discovery_pt pubsub_discovery = (pubsub_discovery_pt) handle;
+
+ char *scope_topic_key = createScopeTopicKey(scope, topic);
+ celixThreadMutex_lock(&pubsub_discovery->watchersMutex);
+
+ hash_map_entry_pt entry = hashMap_getEntry(pubsub_discovery->watchers, scope_topic_key);
+ if(entry) {
+ struct watcher_info * wi = hashMapEntry_getValue(entry);
+ wi->nr_references--;
+ if(wi->nr_references == 0) {
+ char *key = hashMapEntry_getKey(entry);
+ hashMap_remove(pubsub_discovery->watchers, scope_topic_key);
+ free(key);
+ free(scope_topic_key);
+ etcdWatcher_stop(wi->watcher);
+ etcdWatcher_destroy(wi->watcher);
+ free(wi);
+ }
+ } else {
+ fprintf(stderr, "[DISC] Inconsistency error: Removing unknown topic %s\n", topic);
+ }
+ celixThreadMutex_unlock(&pubsub_discovery->watchersMutex);
+ return CELIX_SUCCESS;
+}
+
+/* pubsub_topology_manager tracker callbacks */
+
+celix_status_t pubsub_discovery_tmPublisherAnnounceAdded(void * handle, service_reference_pt reference, void * service) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ pubsub_discovery_pt pubsub_discovery = (pubsub_discovery_pt)handle;
+ publisher_endpoint_announce_pt listener = (publisher_endpoint_announce_pt)service;
+
+ celixThreadMutex_lock(&pubsub_discovery->discoveredPubsMutex);
+ celixThreadMutex_lock(&pubsub_discovery->listenerReferencesMutex);
+
+ /* Notify the PSTM about discovered publisher endpoints */
+ hash_map_iterator_pt iter = hashMapIterator_create(pubsub_discovery->discoveredPubs);
+ while(hashMapIterator_hasNext(iter)){
+ array_list_pt pubEP_list = (array_list_pt)hashMapIterator_nextValue(iter);
+ int i;
+ for(i=0;i<arrayList_size(pubEP_list);i++){
+ pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(pubEP_list,i);
+ status += listener->announcePublisher(listener->handle, pubEP);
+ }
+ }
+
+ hashMapIterator_destroy(iter);
+
+ hashMap_put(pubsub_discovery->listenerReferences, reference, NULL);
+
+ celixThreadMutex_unlock(&pubsub_discovery->listenerReferencesMutex);
+ celixThreadMutex_unlock(&pubsub_discovery->discoveredPubsMutex);
+
+ printf("PSD: pubsub_tm_announce_publisher added.\n");
+
+ return status;
+}
+
+celix_status_t pubsub_discovery_tmPublisherAnnounceModified(void * handle, service_reference_pt reference, void * service) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ status = pubsub_discovery_tmPublisherAnnounceRemoved(handle, reference, service);
+ if (status == CELIX_SUCCESS) {
+ status = pubsub_discovery_tmPublisherAnnounceAdded(handle, reference, service);
+ }
+
+ return status;
+}
+
+celix_status_t pubsub_discovery_tmPublisherAnnounceRemoved(void * handle, service_reference_pt reference, void * service) {
+ celix_status_t status = CELIX_SUCCESS;
+ pubsub_discovery_pt pubsub_discovery = handle;
+
+ celixThreadMutex_lock(&pubsub_discovery->listenerReferencesMutex);
+
+ if (pubsub_discovery->listenerReferences != NULL) {
+ if (hashMap_remove(pubsub_discovery->listenerReferences, reference)) {
+ printf("PSD: pubsub_tm_announce_publisher removed.\n");
+ }
+ }
+ celixThreadMutex_unlock(&pubsub_discovery->listenerReferencesMutex);
+
+ return status;
+}
+
http://git-wip-us.apache.org/repos/asf/celix/blob/0a5ef69a/pubsub/pubsub_spi/include/pubsub_endpoint.h
----------------------------------------------------------------------
diff --cc pubsub/pubsub_spi/include/pubsub_endpoint.h
index 4c39d2f,0000000..598d673
mode 100644,000000..100644
--- a/pubsub/pubsub_spi/include/pubsub_endpoint.h
+++ b/pubsub/pubsub_spi/include/pubsub_endpoint.h
@@@ -1,58 -1,0 +1,65 @@@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+/*
+ * pubsub_endpoint.h
+ *
+ * \date Sep 21, 2015
+ * \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ * \copyright Apache License, Version 2.0
+ */
+
+#ifndef PUBSUB_ENDPOINT_H_
+#define PUBSUB_ENDPOINT_H_
+
+#include "service_reference.h"
+#include "listener_hook_service.h"
+#include "properties.h"
+
+#include "pubsub/publisher.h"
+#include "pubsub/subscriber.h"
+
++#define PUBSUB_ENDPOINT_ID "pubsub.endpoint.id"
++#define PUBSUB_ENDPOINT_SERVICE_ID "service.id"
++#define PUBSUB_ENDPOINT_SERIALIZER "serializer"
++#define PUBSUB_ENDPOINT_ADMIN_TYPE "pubsub.admin.type"
++#define PUBSUB_ENDPOINT_URL "pubsub.endpoint"
++#define PUBSUB_ENDPOINT_TOPIC "pubsub.topic"
++#define PUBSUB_ENDPOINT_SCOPE "pubsub.scope"
++#define PUBSUB_ENDPOINT_TYPE "pubsub.type"
++
+struct pubsub_endpoint {
- char *frameworkUUID;
- char *scope;
- char *topic;
- long serviceID;
- char* endpoint;
- bool is_secure;
++ long serviceID; //optional
++ bool is_secure; //optional
++ properties_pt endpoint_props;
+ 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,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);
++celix_status_t pubsubEndpoint_setField(pubsub_endpoint_pt ep, const char* key, const char* value);
+
+char *createScopeTopicKey(const char* scope, const char* topic);
+
+#endif /* PUBSUB_ENDPOINT_H_ */
http://git-wip-us.apache.org/repos/asf/celix/blob/0a5ef69a/pubsub/pubsub_spi/src/pubsub_endpoint.c
----------------------------------------------------------------------
diff --cc pubsub/pubsub_spi/src/pubsub_endpoint.c
index c3fd293,0000000..d3b746e
mode 100644,000000..100644
--- a/pubsub/pubsub_spi/src/pubsub_endpoint.c
+++ b/pubsub/pubsub_spi/src/pubsub_endpoint.c
@@@ -1,254 -1,0 +1,282 @@@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+/*
+ * endpoint_description.c
+ *
+ * \date 25 Jul 2014
+ * \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ * \copyright Apache License, Version 2.0
+ */
+
+#include <string.h>
+#include <stdlib.h>
++#include <uuid/uuid.h>
+
+#include "celix_errno.h"
+#include "celix_log.h"
+
+#include "pubsub_common.h"
+#include "pubsub_endpoint.h"
+#include "constants.h"
+
+#include "pubsub_utils.h"
+
+
+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);
+
+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 (psEp->endpoint_props == NULL) {
++ psEp->endpoint_props = properties_create();
++ }
++
++ char endpointUuid[37];
++
++ uuid_t endpointUid;
++ uuid_generate(endpointUid);
++ uuid_unparse(endpointUid, endpointUuid);
++ properties_set(psEp->endpoint_props, PUBSUB_ENDPOINT_ID, endpointUuid);
++
+ if (fwUUID != NULL) {
- psEp->frameworkUUID = strdup(fwUUID);
++ properties_set(psEp->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID, fwUUID);
+ }
+
+ if (scope != NULL) {
- psEp->scope = strdup(scope);
++ properties_set(psEp->endpoint_props, PUBSUB_ENDPOINT_SCOPE, scope);
+ }
+
+ if (topic != NULL) {
- psEp->topic = strdup(topic);
++ properties_set(psEp->endpoint_props, PUBSUB_ENDPOINT_TOPIC, topic);
+ }
+
+ psEp->serviceID = serviceId;
+
+ if(endpoint != NULL) {
- psEp->endpoint = strdup(endpoint);
++ properties_set(psEp->endpoint_props, PUBSUB_ENDPOINT_URL, 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) {
+
+ char *bundleRoot = NULL;
+ char* topicPropertiesPath = NULL;
+ bundle_getEntry(bundle, ".", &bundleRoot);
+
+ if(bundleRoot != NULL){
+
+ 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);
+ }
+
+ free(topicPropertiesPath);
+ free(bundleRoot);
+ }
+ }
+
+ return topic_props;
+}
+
++celix_status_t pubsubEndpoint_setField(pubsub_endpoint_pt ep, const char* key, const char* value) {
++ celix_status_t status = CELIX_SUCCESS;
++
++ if (ep->endpoint_props == NULL) {
++ printf("PUBSUB_EP: No endpoint_props for endpoint available!\n");
++ return CELIX_ILLEGAL_STATE;
++ }
++
++ if (key != NULL && value != NULL) {
++ properties_set(ep->endpoint_props, key, value);
++ }
++
++ return status;
++}
++
+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_clone(pubsub_endpoint_pt in, pubsub_endpoint_pt *out){
+ celix_status_t status = CELIX_SUCCESS;
+
- *out = calloc(1,sizeof(**out));
++ pubsub_endpoint_pt ep = calloc(1,sizeof(*ep));
+
- pubsubEndpoint_setFields(*out, in->frameworkUUID, in->scope, in->topic, in->serviceID, in->endpoint, in->topic_props, true);
++ status = properties_copy(in->endpoint_props, &(ep->endpoint_props));
++
++ if (in->topic_props != NULL) {
++ status += properties_copy(in->topic_props, &(ep->topic_props));
++ }
++
++ ep->serviceID = in->serviceID;
++ ep->is_secure = in->is_secure;
++
++ if (status == CELIX_SUCCESS) {
++ *out = ep;
++ } else {
++ pubsubEndpoint_destroy(ep);
++ }
+
+ return status;
+
+}
+
+celix_status_t pubsubEndpoint_createFromServiceReference(service_reference_pt reference, pubsub_endpoint_pt* psEp, bool isPublisher){
+ celix_status_t status = CELIX_SUCCESS;
+
+ pubsub_endpoint_pt ep = calloc(1,sizeof(*ep));
+
+ bundle_pt bundle = NULL;
+ bundle_context_pt ctxt = NULL;
+ const char* fwUUID = NULL;
+ serviceReference_getBundle(reference,&bundle);
+ bundle_getContext(bundle,&ctxt);
+ bundleContext_getProperty(ctxt,OSGI_FRAMEWORK_FRAMEWORK_UUID,&fwUUID);
+
+ const char* scope = NULL;
+ serviceReference_getProperty(reference, PUBSUB_SUBSCRIBER_SCOPE,&scope);
+
+ const char* topic = NULL;
+ serviceReference_getProperty(reference, PUBSUB_SUBSCRIBER_TOPIC,&topic);
+
+ const char* serviceId = NULL;
+ serviceReference_getProperty(reference,(char*)OSGI_FRAMEWORK_SERVICE_ID,&serviceId);
+
+ /* TODO: is topic_props==NULL a fatal error such that EP cannot be created? */
+ properties_pt topic_props = pubsubEndpoint_getTopicProperties(bundle, topic, isPublisher);
+
+ pubsubEndpoint_setFields(ep, fwUUID, scope!=NULL?scope:PUBSUB_SUBSCRIBER_SCOPE_DEFAULT, topic, strtol(serviceId,NULL,10), NULL, topic_props, false);
+
- if (!ep->frameworkUUID || !ep->serviceID || !ep->scope || !ep->topic) {
++ if (!properties_get(ep->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID) ||
++ !ep->serviceID ||
++ !properties_get(ep->endpoint_props, PUBSUB_ENDPOINT_SCOPE) ||
++ !properties_get(ep->endpoint_props, PUBSUB_ENDPOINT_TOPIC)) {
++
+ fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "PUBSUB_ENDPOINT: incomplete description!.");
+ status = CELIX_BUNDLE_EXCEPTION;
+ pubsubEndpoint_destroy(ep);
+ *psEp = NULL;
+ }
+ else{
+ *psEp = ep;
+ }
+
+ return status;
+
+}
+
+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);
+
+ if(fwUUID==NULL){
+ return CELIX_BUNDLE_EXCEPTION;
+ }
+
+ char* topic = pubsub_getTopicFromFilter(info->filter);
+ if(topic==NULL){
+ return CELIX_BUNDLE_EXCEPTION;
+ }
+
+ *psEp = calloc(1, sizeof(**psEp));
+
+ char* scope = pubsub_getScopeFromFilter(info->filter);
+ if(scope == NULL) {
+ scope = strdup(PUBSUB_PUBLISHER_SCOPE_DEFAULT);
+ }
+
+ 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->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);
+ }
+
++ if (psEp->endpoint_props != NULL) {
++ properties_destroy(psEp->endpoint_props);
++ }
++
+ free(psEp);
+
+ return CELIX_SUCCESS;
+
+}
+
+bool pubsubEndpoint_equals(pubsub_endpoint_pt psEp1,pubsub_endpoint_pt psEp2){
+
- return ((strcmp(psEp1->frameworkUUID,psEp2->frameworkUUID)==0) &&
- (strcmp(psEp1->scope,psEp2->scope)==0) &&
- (strcmp(psEp1->topic,psEp2->topic)==0) &&
++ return ((strcmp(properties_get(psEp1->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),properties_get(psEp2->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID))==0) &&
++ (strcmp(properties_get(psEp1->endpoint_props, PUBSUB_ENDPOINT_SCOPE),properties_get(psEp2->endpoint_props, PUBSUB_ENDPOINT_SCOPE))==0) &&
++ (strcmp(properties_get(psEp1->endpoint_props, PUBSUB_ENDPOINT_TOPIC),properties_get(psEp2->endpoint_props, PUBSUB_ENDPOINT_TOPIC))==0) &&
+ (psEp1->serviceID == psEp2->serviceID) /*&&
+ ((psEp1->endpoint==NULL && psEp2->endpoint==NULL)||(strcmp(psEp1->endpoint,psEp2->endpoint)==0))*/
+ );
+}
+
+char *createScopeTopicKey(const char* scope, const char* topic) {
+ char *result = NULL;
+ asprintf(&result, "%s:%s", scope, topic);
+
+ return result;
+}
http://git-wip-us.apache.org/repos/asf/celix/blob/0a5ef69a/pubsub/pubsub_topology_manager/src/pubsub_topology_manager.c
----------------------------------------------------------------------
diff --cc pubsub/pubsub_topology_manager/src/pubsub_topology_manager.c
index 2ac75c9,0000000..a63b275
mode 100644,000000..100644
--- a/pubsub/pubsub_topology_manager/src/pubsub_topology_manager.c
+++ b/pubsub/pubsub_topology_manager/src/pubsub_topology_manager.c
@@@ -1,721 -1,0 +1,727 @@@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+/*
+ * pubsub_topology_manager.c
+ *
+ * \date Sep 29, 2011
+ * \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ * \copyright Apache License, Version 2.0
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include "hash_map.h"
+#include "array_list.h"
+#include "bundle_context.h"
+#include "constants.h"
+#include "module.h"
+#include "bundle.h"
+#include "filter.h"
+#include "listener_hook_service.h"
+#include "utils.h"
+#include "service_reference.h"
+#include "service_registration.h"
+#include "log_service.h"
+#include "log_helper.h"
+
+#include "publisher_endpoint_announce.h"
+#include "pubsub_topology_manager.h"
+#include "pubsub_endpoint.h"
+#include "pubsub_admin.h"
+#include "pubsub_utils.h"
+
+
+celix_status_t pubsub_topologyManager_create(bundle_context_pt context, log_helper_pt logHelper, pubsub_topology_manager_pt *manager) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ *manager = calloc(1, sizeof(**manager));
+ if (!*manager) {
+ return CELIX_ENOMEM;
+ }
+
+ (*manager)->context = context;
+
+ celix_thread_mutexattr_t psaAttr;
+ celixThreadMutexAttr_create(&psaAttr);
+ celixThreadMutexAttr_settype(&psaAttr, CELIX_THREAD_MUTEX_RECURSIVE);
+ status = celixThreadMutex_create(&(*manager)->psaListLock, &psaAttr);
+ celixThreadMutexAttr_destroy(&psaAttr);
+
+ status = celixThreadMutex_create(&(*manager)->publicationsLock, NULL);
+ status = celixThreadMutex_create(&(*manager)->subscriptionsLock, NULL);
+ status = celixThreadMutex_create(&(*manager)->discoveryListLock, NULL);
+
+ arrayList_create(&(*manager)->psaList);
+
+ (*manager)->discoveryList = hashMap_create(serviceReference_hashCode, NULL, serviceReference_equals2, NULL);
+ (*manager)->publications = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
+ (*manager)->subscriptions = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
+
+ (*manager)->loghelper = logHelper;
+
+ return status;
+}
+
+celix_status_t pubsub_topologyManager_destroy(pubsub_topology_manager_pt manager) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ celixThreadMutex_lock(&manager->discoveryListLock);
+ hashMap_destroy(manager->discoveryList, false, false);
+ celixThreadMutex_unlock(&manager->discoveryListLock);
+ celixThreadMutex_destroy(&manager->discoveryListLock);
+
+ celixThreadMutex_lock(&manager->psaListLock);
+ arrayList_destroy(manager->psaList);
+ celixThreadMutex_unlock(&manager->psaListLock);
+ celixThreadMutex_destroy(&manager->psaListLock);
+
+ celixThreadMutex_lock(&manager->publicationsLock);
+ hash_map_iterator_pt pubit = hashMapIterator_create(manager->publications);
+ while(hashMapIterator_hasNext(pubit)){
+ array_list_pt l = (array_list_pt)hashMapIterator_nextValue(pubit);
+ int i;
+ for(i=0;i<arrayList_size(l);i++){
+ pubsubEndpoint_destroy((pubsub_endpoint_pt)arrayList_get(l,i));
+ }
+ arrayList_destroy(l);
+ }
+ hashMapIterator_destroy(pubit);
+ hashMap_destroy(manager->publications, true, false);
+ celixThreadMutex_unlock(&manager->publicationsLock);
+ celixThreadMutex_destroy(&manager->publicationsLock);
+
+ celixThreadMutex_lock(&manager->subscriptionsLock);
+ hash_map_iterator_pt subit = hashMapIterator_create(manager->subscriptions);
+ while(hashMapIterator_hasNext(subit)){
+ array_list_pt l = (array_list_pt)hashMapIterator_nextValue(subit);
+ int i;
+ for(i=0;i<arrayList_size(l);i++){
+ pubsubEndpoint_destroy((pubsub_endpoint_pt)arrayList_get(l,i));
+ }
+ arrayList_destroy(l);
+ }
+ hashMapIterator_destroy(subit);
+ hashMap_destroy(manager->subscriptions, true, false);
+ celixThreadMutex_unlock(&manager->subscriptionsLock);
+ celixThreadMutex_destroy(&manager->subscriptionsLock);
+
+ free(manager);
+
+ 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;
+
+ 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);
+
+ while (hashMapIterator_hasNext(subscriptionsIterator)) {
+ array_list_pt sub_ep_list = hashMapIterator_nextValue(subscriptionsIterator);
+ for(i=0;i<arrayList_size(sub_ep_list);i++){
+ status += psa->addSubscription(psa->admin, (pubsub_endpoint_pt)arrayList_get(sub_ep_list,i));
+ }
+ }
+
+ hashMapIterator_destroy(subscriptionsIterator);
+
+ celixThreadMutex_unlock(&manager->subscriptionsLock);
+
+ // Add already detected publications to new PSA
+ status = celixThreadMutex_lock(&manager->publicationsLock);
+ hash_map_iterator_pt publicationsIterator = hashMapIterator_create(manager->publications);
+
+ while (hashMapIterator_hasNext(publicationsIterator)) {
+ array_list_pt pub_ep_list = hashMapIterator_nextValue(publicationsIterator);
+ for(i=0;i<arrayList_size(pub_ep_list);i++){
+ status += psa->addPublication(psa->admin, (pubsub_endpoint_pt)arrayList_get(pub_ep_list,i));
+ }
+ }
+
+ hashMapIterator_destroy(publicationsIterator);
+
+ celixThreadMutex_unlock(&manager->publicationsLock);
+
+ return status;
+}
+
+celix_status_t pubsub_topologyManager_psaModified(void * handle, service_reference_pt reference, void * service) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ // Nop...
+
+ return status;
+}
+
+celix_status_t pubsub_topologyManager_psaRemoved(void * handle, service_reference_pt reference, void * service) {
+ celix_status_t status = CELIX_SUCCESS;
+ pubsub_topology_manager_pt manager = handle;
+
+ pubsub_admin_service_pt psa = (pubsub_admin_service_pt) service;
+
+ /* Deactivate all publications */
+ celixThreadMutex_lock(&manager->publicationsLock);
+
+ hash_map_iterator_pt pubit = hashMapIterator_create(manager->publications);
+ while(hashMapIterator_hasNext(pubit)){
+ hash_map_entry_pt pub_entry = hashMapIterator_nextEntry(pubit);
+ char* scope_topic_key = (char*)hashMapEntry_getKey(pub_entry);
+ // Extract scope/topic name from key
+ char scope[MAX_SCOPE_LEN];
+ char topic[MAX_TOPIC_LEN];
+ sscanf(scope_topic_key, "%[^:]:%s", scope, topic );
+ array_list_pt pubEP_list = (array_list_pt)hashMapEntry_getValue(pub_entry);
+
+ status = psa->closeAllPublications(psa->admin,scope,topic);
+
+ 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);
+ const char* fwUUID = NULL;
+ bundleContext_getProperty(manager->context,OSGI_FRAMEWORK_FRAMEWORK_UUID,&fwUUID);
+ int i;
+ for(i=0;i<arrayList_size(pubEP_list);i++){
+ pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(pubEP_list,i);
- if(strcmp(pubEP->frameworkUUID,fwUUID)==0){
++ if(strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),fwUUID)==0){
+ disc->removePublisher(disc->handle,pubEP);
+ }
+ }
+ bundleContext_ungetService(manager->context, disc_sr, NULL);
+ }
+ hashMapIterator_destroy(iter);
+ celixThreadMutex_unlock(&manager->discoveryListLock);
+ }
+ }
+ hashMapIterator_destroy(pubit);
+
+ celixThreadMutex_unlock(&manager->publicationsLock);
+
+ /* Deactivate all subscriptions */
+ celixThreadMutex_lock(&manager->subscriptionsLock);
+ hash_map_iterator_pt subit = hashMapIterator_create(manager->subscriptions);
+ while(hashMapIterator_hasNext(subit)){
+ // TODO do some error checking
+ char* scope_topic = (char*)hashMapIterator_nextKey(subit);
+ char scope[MAX_TOPIC_LEN];
+ char topic[MAX_TOPIC_LEN];
+ memset(scope, 0 , MAX_TOPIC_LEN*sizeof(char));
+ memset(topic, 0 , MAX_TOPIC_LEN*sizeof(char));
+ sscanf(scope_topic, "%[^:]:%s", scope, topic );
+ status += psa->closeAllSubscriptions(psa->admin,scope, topic);
+ }
+ hashMapIterator_destroy(subit);
+ celixThreadMutex_unlock(&manager->subscriptionsLock);
+
+ celixThreadMutex_lock(&manager->psaListLock);
+ arrayList_removeElement(manager->psaList, psa);
+ celixThreadMutex_unlock(&manager->psaListLock);
+
+ logHelper_log(manager->loghelper, OSGI_LOGSERVICE_INFO, "PSTM: Removed PSA");
+
+ 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,false) == CELIX_SUCCESS){
+ celixThreadMutex_lock(&manager->subscriptionsLock);
- char *sub_key = createScopeTopicKey(sub->scope, sub->topic);
++ char *sub_key = createScopeTopicKey(properties_get(sub->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(sub->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+
+ array_list_pt sub_list_by_topic = hashMap_get(manager->subscriptions,sub_key);
+ if(sub_list_by_topic==NULL){
+ arrayList_create(&sub_list_by_topic);
+ hashMap_put(manager->subscriptions,strdup(sub_key),sub_list_by_topic);
+ }
+ free(sub_key);
+ arrayList_add(sub_list_by_topic,sub);
+
+ celixThreadMutex_unlock(&manager->subscriptionsLock);
+
+ int j;
+ double score = 0;
+ double best_score = 0;
+ pubsub_admin_service_pt best_psa = NULL;
+ celixThreadMutex_lock(&manager->psaListLock);
+ for(j=0;j<arrayList_size(manager->psaList);j++){
+ pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,j);
+ 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 && best_score>0){
+ best_psa->addSubscription(best_psa->admin,sub);
+ }
+
+ // Inform discoveries for interest in the topic
+ 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);
++ disc->interestedInTopic(disc->handle, properties_get(sub->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(sub->endpoint_props, PUBSUB_ENDPOINT_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;
+ }
+
+ return status;
+}
+
+celix_status_t pubsub_topologyManager_subscriberModified(void * handle, service_reference_pt reference, void * service) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ // Nop...
+
+ return status;
+}
+
+celix_status_t pubsub_topologyManager_subscriberRemoved(void * handle, service_reference_pt reference, void * service) {
+ celix_status_t status = CELIX_SUCCESS;
+ pubsub_topology_manager_pt manager = handle;
+
+ pubsub_endpoint_pt subcmp = NULL;
+ 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);
++ disc->uninterestedInTopic(disc->handle, properties_get(subcmp->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(subcmp->endpoint_props, PUBSUB_ENDPOINT_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);
++ char *sub_key = createScopeTopicKey(properties_get(subcmp->endpoint_props, PUBSUB_ENDPOINT_SCOPE),properties_get(subcmp->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+ array_list_pt sub_list_by_topic = hashMap_get(manager->subscriptions,sub_key);
+ free(sub_key);
+ if(sub_list_by_topic!=NULL){
+ for(j=0;j<arrayList_size(sub_list_by_topic);j++){
+ pubsub_endpoint_pt sub = arrayList_get(sub_list_by_topic,j);
+ if(pubsubEndpoint_equals(sub,subcmp)){
+ for(k=0;k<arrayList_size(manager->psaList);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);
+ psa->removeSubscription(psa->admin,sub);
+ }
+
+ }
+ arrayList_remove(sub_list_by_topic,j);
+
+ /* If it was the last subscriber for this topic, tell PSA to close the ZMQ socket */
+ if(arrayList_size(sub_list_by_topic)==0){
+ for(k=0;k<arrayList_size(manager->psaList);k++){
+ pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,k);
- psa->closeAllSubscriptions(psa->admin,sub->scope, sub->topic);
++ psa->closeAllSubscriptions(psa->admin, (char*) properties_get(subcmp->endpoint_props, PUBSUB_ENDPOINT_SCOPE), (char*) properties_get(subcmp->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+ }
+ }
+
+ pubsubEndpoint_destroy(sub);
+
+ }
+ }
+
+ celixThreadMutex_unlock(&manager->psaListLock);
+ celixThreadMutex_unlock(&manager->subscriptionsLock);
+
+ pubsubEndpoint_destroy(subcmp);
+
+ }
+ else{
+ status=CELIX_INVALID_BUNDLE_CONTEXT;
+ }
+
+ 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;
+ publisher_endpoint_announce_pt disc = (publisher_endpoint_announce_pt)service;
+
+ const char* fwUUID = NULL;
+
+ bundleContext_getProperty(manager->context,OSGI_FRAMEWORK_FRAMEWORK_UUID,&fwUUID);
+ if(fwUUID==NULL){
+ printf("PSD: ERRROR: Cannot retrieve fwUUID.\n");
+ return CELIX_INVALID_BUNDLE_CONTEXT;
+ }
+
+ celixThreadMutex_lock(&manager->publicationsLock);
+
+ celixThreadMutex_lock(&manager->discoveryListLock);
+ hashMap_put(manager->discoveryList, reference, NULL);
+ celixThreadMutex_unlock(&manager->discoveryListLock);
+
+ hash_map_iterator_pt iter = hashMapIterator_create(manager->publications);
+ while(hashMapIterator_hasNext(iter)){
+ array_list_pt pubEP_list = (array_list_pt)hashMapIterator_nextValue(iter);
+ for(int i = 0; i < arrayList_size(pubEP_list); i++) {
+ pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(pubEP_list,i);
- if( (strcmp(pubEP->frameworkUUID,fwUUID)==0) && (pubEP->endpoint!=NULL)){
++ if( (strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),fwUUID)==0) && (properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL)){
+ status += disc->announcePublisher(disc->handle,pubEP);
+ }
+ }
+ }
+ hashMapIterator_destroy(iter);
+
+ celixThreadMutex_unlock(&manager->publicationsLock);
+
+ celixThreadMutex_lock(&manager->subscriptionsLock);
+ iter = hashMapIterator_create(manager->subscriptions);
+
+ while(hashMapIterator_hasNext(iter)) {
+ array_list_pt l = (array_list_pt)hashMapIterator_nextValue(iter);
+ int i;
+ for(i=0;i<arrayList_size(l);i++){
+ pubsub_endpoint_pt subEp = (pubsub_endpoint_pt)arrayList_get(l,i);
+
- disc->interestedInTopic(disc->handle, subEp->scope, subEp->topic);
++ disc->interestedInTopic(disc->handle, properties_get(subEp->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(subEp->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+ }
+ }
+ hashMapIterator_destroy(iter);
+ celixThreadMutex_unlock(&manager->subscriptionsLock);
+
+ return status;
+}
+
+celix_status_t pubsub_topologyManager_pubsubDiscoveryModified(void * handle, service_reference_pt reference, void * service) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ status = pubsub_topologyManager_pubsubDiscoveryRemoved(handle, reference, service);
+ if (status == CELIX_SUCCESS) {
+ status = pubsub_topologyManager_pubsubDiscoveryAdded(handle, reference, service);
+ }
+
+ return status;
+}
+
+celix_status_t pubsub_topologyManager_pubsubDiscoveryRemoved(void * handle, service_reference_pt reference, void * service) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ pubsub_topology_manager_pt manager = handle;
+
+ celixThreadMutex_lock(&manager->discoveryListLock);
+
+
+ if (hashMap_remove(manager->discoveryList, reference)) {
+ logHelper_log(manager->loghelper, OSGI_LOGSERVICE_INFO, "EndpointListener Removed");
+ }
+
+ celixThreadMutex_unlock(&manager->discoveryListLock);
+
+ return status;
+}
+
+
+celix_status_t pubsub_topologyManager_publisherTrackerAdded(void *handle, array_list_pt listeners) {
+
+ celix_status_t status = CELIX_SUCCESS;
+ pubsub_topology_manager_pt manager = handle;
+
+ int l_index;
+
+ for (l_index = 0; l_index < arrayList_size(listeners); l_index++) {
+
+ listener_hook_info_pt info = arrayList_get(listeners, l_index);
+
+ pubsub_endpoint_pt pub = NULL;
+ if(pubsubEndpoint_createFromListenerHookInfo(info, &pub, true) == CELIX_SUCCESS){
+
+ celixThreadMutex_lock(&manager->publicationsLock);
- char *pub_key = createScopeTopicKey(pub->scope, pub->topic);
++ char *pub_key = createScopeTopicKey(properties_get(pub->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pub->endpoint_props, PUBSUB_ENDPOINT_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);
+
+ celixThreadMutex_unlock(&manager->publicationsLock);
+
+ int j;
+ double score = 0;
+ double best_score = 0;
+ pubsub_admin_service_pt best_psa = NULL;
+ celixThreadMutex_lock(&manager->psaListLock);
+
+ for(j=0;j<arrayList_size(manager->psaList);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;
+ }
+ }
+
+ 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);
+ }
+ }
+
+ celixThreadMutex_unlock(&manager->psaListLock);
+
+ }
+
+ }
+
+ return status;
+
+}
+
+
+celix_status_t pubsub_topologyManager_publisherTrackerRemoved(void *handle, array_list_pt listeners) {
+ celix_status_t status = CELIX_SUCCESS;
+ pubsub_topology_manager_pt manager = handle;
+
+ int l_index;
+
+ for (l_index = 0; l_index < arrayList_size(listeners); l_index++) {
+
+ listener_hook_info_pt info = arrayList_get(listeners, l_index);
+
+ 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);
++ char *pub_key = createScopeTopicKey(properties_get(pubcmp->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubcmp->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+ array_list_pt pub_list_by_topic = hashMap_get(manager->publications,pub_key);
+ if(pub_list_by_topic!=NULL){
+ for(j=0;j<arrayList_size(pub_list_by_topic);j++){
+ pubsub_endpoint_pt pub = arrayList_get(pub_list_by_topic,j);
+ if(pubsubEndpoint_equals(pub,pubcmp)){
+ for(k=0;k<arrayList_size(manager->psaList);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);
+ }
+ 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 */
+ if(arrayList_size(pub_list_by_topic)==0){
+ for(k=0;k<arrayList_size(manager->psaList);k++){
+ pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,k);
- psa->closeAllPublications(psa->admin,pub->scope, pub->topic);
++ psa->closeAllPublications(psa->admin, (char*) properties_get(pub->endpoint_props, PUBSUB_ENDPOINT_SCOPE), (char*) properties_get(pub->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+ }
+ }
+
+ pubsubEndpoint_destroy(pub);
+ }
+
+ }
+ }
+
+ celixThreadMutex_unlock(&manager->publicationsLock);
+ celixThreadMutex_unlock(&manager->psaListLock);
+
+ free(pub_key);
+
+ pubsubEndpoint_destroy(pubcmp);
+
+ }
+
+ }
+
+ return status;
+}
+
+celix_status_t pubsub_topologyManager_announcePublisher(void *handle, pubsub_endpoint_pt pubEP){
+ celix_status_t status = CELIX_SUCCESS;
- printf("PSTM: New publisher discovered for topic %s [fwUUID=%s, ep=%s]\n",pubEP->topic,pubEP->frameworkUUID,pubEP->endpoint);
++ printf("PSTM: New publisher discovered for topic %s [fwUUID=%s, ep=%s]\n",
++ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
++ properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
++ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
+
+ pubsub_topology_manager_pt manager = handle;
+ celixThreadMutex_lock(&manager->psaListLock);
+ celixThreadMutex_lock(&manager->publicationsLock);
+
- char *pub_key = createScopeTopicKey(pubEP->scope, pubEP->topic);
++ char *pub_key = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_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);
+
+ /* Shouldn't be any other duplicate, since it's filtered out by the discovery */
+ pubsub_endpoint_pt p = NULL;
+ pubsubEndpoint_clone(pubEP, &p);
+ arrayList_add(pub_list_by_topic,p);
+
+ int j;
+ double score = 0;
+ double best_score = 0;
+ pubsub_admin_service_pt best_psa = NULL;
+
+ for(j=0;j<arrayList_size(manager->psaList);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 && best_score>0){
+ best_psa->addPublication(best_psa->admin,p);
+ }
+ else{
+ status = CELIX_ILLEGAL_STATE;
+ }
+
+ celixThreadMutex_unlock(&manager->publicationsLock);
+ celixThreadMutex_unlock(&manager->psaListLock);
+
+ return status;
+}
+
+celix_status_t pubsub_topologyManager_removePublisher(void *handle, pubsub_endpoint_pt pubEP){
+ celix_status_t status = CELIX_SUCCESS;
- printf("PSTM: Publisher removed for topic %s [fwUUID=%s, ep=%s]\n",pubEP->topic,pubEP->frameworkUUID,pubEP->endpoint);
++ printf("PSTM: Publisher removed for topic %s [fwUUID=%s, ep=%s]\n",
++ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
++ properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
++ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
+
+ pubsub_topology_manager_pt manager = handle;
+ celixThreadMutex_lock(&manager->psaListLock);
+ celixThreadMutex_lock(&manager->publicationsLock);
+ int i;
+
- char *pub_key = createScopeTopicKey(pubEP->scope, pubEP->topic);
++ char *pub_key = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+ array_list_pt pub_list_by_topic = hashMap_get(manager->publications,pub_key);
+ if(pub_list_by_topic==NULL){
- printf("PSTM: ERROR: Cannot find topic for known endpoint [%s,%s,%s]. Something is inconsistent.\n",pub_key,pubEP->frameworkUUID,pubEP->endpoint);
++ printf("PSTM: ERROR: Cannot find topic for known endpoint [%s,%s,%s]. Something is inconsistent.\n",pub_key,properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
+ status = CELIX_ILLEGAL_STATE;
+ }
+ else{
+
+ pubsub_endpoint_pt p = NULL;
+ bool found = false;
+
+ for(i=0;!found && i<arrayList_size(pub_list_by_topic);i++){
+ p = (pubsub_endpoint_pt)arrayList_get(pub_list_by_topic,i);
+ found = pubsubEndpoint_equals(p,pubEP);
+ }
+
+ if(found && p !=NULL){
+
+ for(i=0;i<arrayList_size(manager->psaList);i++){
+ pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,i);
+ /* 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);
+
+ /* If it was the last publisher for this topic, tell PSA to close the ZMQ socket */
+ if(arrayList_size(pub_list_by_topic)==0){
+
+ for(i=0;i<arrayList_size(manager->psaList);i++){
+ pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,i);
- psa->closeAllPublications(psa->admin,p->scope, p->topic);
++ psa->closeAllPublications(psa->admin, (char*) properties_get(p->endpoint_props, PUBSUB_ENDPOINT_SCOPE), (char*) properties_get(p->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+ }
+ }
+
+ pubsubEndpoint_destroy(p);
+ }
+
+
+ }
+ free(pub_key);
+ celixThreadMutex_unlock(&manager->publicationsLock);
+ celixThreadMutex_unlock(&manager->psaListLock);
+
+
+ return status;
+}
+
http://git-wip-us.apache.org/repos/asf/celix/blob/0a5ef69a/utils/include/properties.h
----------------------------------------------------------------------
diff --cc utils/include/properties.h
index 5c6dc4d,0000000..582a242
mode 100644,000000..100644
--- a/utils/include/properties.h
+++ b/utils/include/properties.h
@@@ -1,68 -1,0 +1,70 @@@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+/*
+ * properties.h
+ *
+ * \date Apr 27, 2010
+ * \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ * \copyright Apache License, Version 2.0
+ */
+
+#ifndef PROPERTIES_H_
+#define PROPERTIES_H_
+
+#include <stdio.h>
+
+#include "hash_map.h"
+#include "exports.h"
+#include "celix_errno.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+typedef hash_map_pt properties_pt;
+typedef hash_map_t properties_t;
+
+UTILS_EXPORT properties_pt properties_create(void);
+
+UTILS_EXPORT void properties_destroy(properties_pt properties);
+
+UTILS_EXPORT properties_pt properties_load(const char *filename);
+
+UTILS_EXPORT properties_pt properties_loadWithStream(FILE *stream);
+
+UTILS_EXPORT properties_pt properties_loadFromString(const char *input);
+
+UTILS_EXPORT void properties_store(properties_pt properties, const char *file, const char *header);
+
+UTILS_EXPORT const char *properties_get(properties_pt properties, const char *key);
+
+UTILS_EXPORT const char *properties_getWithDefault(properties_pt properties, const char *key, const char *defaultValue);
+
+UTILS_EXPORT void properties_set(properties_pt properties, const char *key, const char *value);
+
++UTILS_EXPORT void properties_unset(properties_pt properties, const char *key);
++
+UTILS_EXPORT celix_status_t properties_copy(properties_pt properties, properties_pt *copy);
+
+#define PROPERTIES_FOR_EACH(props, key) \
+ for(hash_map_iterator_t iter = hashMapIterator_construct(props); \
+ hashMapIterator_hasNext(&iter), (key) = (const char*)hashMapIterator_nextKey(&iter);)
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PROPERTIES_H_ */
http://git-wip-us.apache.org/repos/asf/celix/blob/0a5ef69a/utils/src/properties.c
----------------------------------------------------------------------
diff --cc utils/src/properties.c
index 1e097a0,0000000..860b9bb
mode 100644,000000..100644
--- a/utils/src/properties.c
+++ b/utils/src/properties.c
@@@ -1,330 -1,0 +1,335 @@@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+/*
+ * properties.c
+ *
+ * \date Apr 27, 2010
+ * \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ * \copyright Apache License, Version 2.0
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "celixbool.h"
+#include "properties.h"
+#include "utils.h"
+
+#define MALLOC_BLOCK_SIZE 5
+
+static void parseLine(const char* line, properties_pt props);
+
+properties_pt properties_create(void) {
+ return hashMap_create(utils_stringHash, utils_stringHash, utils_stringEquals, utils_stringEquals);
+}
+
+void properties_destroy(properties_pt properties) {
+ hash_map_iterator_pt iter = hashMapIterator_create(properties);
+ while (hashMapIterator_hasNext(iter)) {
+ hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
+ free(hashMapEntry_getKey(entry));
+ free(hashMapEntry_getValue(entry));
+ }
+ hashMapIterator_destroy(iter);
+ hashMap_destroy(properties, false, false);
+}
+
+properties_pt properties_load(const char* filename) {
+ FILE *file = fopen(filename, "r");
+ if(file==NULL){
+ return NULL;
+ }
+ properties_pt props = properties_loadWithStream(file);
+ fclose(file);
+ return props;
+}
+
+properties_pt properties_loadWithStream(FILE *file) {
+ properties_pt props = NULL;
+
+
+ if (file != NULL ) {
+ char *saveptr;
+ char *filebuffer = NULL;
+ char *line = NULL;
+ size_t file_size = 0;
+
+ props = properties_create();
+ fseek(file, 0, SEEK_END);
+ file_size = ftell(file);
+ fseek(file, 0, SEEK_SET);
+
+ if(file_size > 0){
+ filebuffer = calloc(file_size + 1, sizeof(char));
+ if(filebuffer) {
+ size_t rs = fread(filebuffer, sizeof(char), file_size, file);
+ if(rs != file_size){
+ fprintf(stderr,"fread read only %lu bytes out of %lu\n",rs,file_size);
+ }
+ filebuffer[file_size]='\0';
+ line = strtok_r(filebuffer, "\n", &saveptr);
+ while ( line != NULL ) {
+ parseLine(line, props);
+ line = strtok_r(NULL, "\n", &saveptr);
+ }
+ free(filebuffer);
+ }
+ }
+ }
+
+ return props;
+}
+
+properties_pt properties_loadFromString(const char *input){
+ properties_pt props = properties_create();
+
+ char *in = strdup(input);
+ char *line = NULL;
+ char *saveLinePointer = NULL;
+
+ bool firstTime = true;
+ do {
+ if (firstTime){
+ line = strtok_r(in, "\n", &saveLinePointer);
+ firstTime = false;
+ }else {
+ line = strtok_r(NULL, "\n", &saveLinePointer);
+ }
+
+ if (line == NULL){
+ break;
+ }
+
+ parseLine(line, props);
+ } while(line != NULL);
+
+ free(in);
+
+ return props;
+}
+
+
+/**
+ * Header is ignored for now, cannot handle comments yet
+ */
+void properties_store(properties_pt properties, const char* filename, const char* header) {
+ FILE *file = fopen ( filename, "w+" );
+ char *str;
+
+ if (file != NULL) {
+ if (hashMap_size(properties) > 0) {
+ hash_map_iterator_pt iterator = hashMapIterator_create(properties);
+ while (hashMapIterator_hasNext(iterator)) {
+ hash_map_entry_pt entry = hashMapIterator_nextEntry(iterator);
+ str = hashMapEntry_getKey(entry);
+ for (int i = 0; i < strlen(str); i += 1) {
+ if (str[i] == '#' || str[i] == '!' || str[i] == '=' || str[i] == ':') {
+ fputc('\\', file);
+ }
+ fputc(str[i], file);
+ }
+
+ fputc('=', file);
+
+ str = hashMapEntry_getValue(entry);
+ for (int i = 0; i < strlen(str); i += 1) {
+ if (str[i] == '#' || str[i] == '!' || str[i] == '=' || str[i] == ':') {
+ fputc('\\', file);
+ }
+ fputc(str[i], file);
+ }
+
+ fputc('\n', file);
+
+ }
+ hashMapIterator_destroy(iterator);
+ }
+ fclose(file);
+ } else {
+ perror("File is null");
+ }
+}
+
+celix_status_t properties_copy(properties_pt properties, properties_pt *out) {
+ celix_status_t status = CELIX_SUCCESS;
+ properties_pt copy = properties_create();
+
+ if (copy != NULL) {
+ hash_map_iterator_pt iter = hashMapIterator_create(properties);
+ while (hashMapIterator_hasNext(iter)) {
+ hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
+ char *key = hashMapEntry_getKey(entry);
+ char *value = hashMapEntry_getValue(entry);
+ properties_set(copy, key, value);
+ }
+ hashMapIterator_destroy(iter);
+ } else {
+ status = CELIX_ENOMEM;
+ }
+
+ if (status == CELIX_SUCCESS) {
+ *out = copy;
+ }
+
+ return status;
+}
+
+const char* properties_get(properties_pt properties, const char* key) {
+ return hashMap_get(properties, (void*)key);
+}
+
+const char* properties_getWithDefault(properties_pt properties, const char* key, const char* defaultValue) {
+ const char* value = properties_get(properties, key);
+ return value == NULL ? defaultValue : value;
+}
+
+void properties_set(properties_pt properties, const char* key, const char* value) {
+ hash_map_entry_pt entry = hashMap_getEntry(properties, key);
+ char* oldValue = NULL;
+ if (entry != NULL) {
+ char* oldKey = hashMapEntry_getKey(entry);
+ oldValue = hashMapEntry_getValue(entry);
+ hashMap_put(properties, oldKey, strndup(value, 1024*10));
+ } else {
+ hashMap_put(properties, strndup(key, 1024*10), strndup(value, 1024*10));
+ }
+ free(oldValue);
+}
+
++void properties_unset(properties_pt properties, const char* key) {
++ char* oldValue = hashMap_remove(properties, key);
++ free(oldValue);
++}
++
+static void updateBuffers(char **key, char ** value, char **output, int outputPos, int *key_len, int *value_len) {
+ if (*output == *key) {
+ if (outputPos == (*key_len) - 1) {
+ (*key_len) += MALLOC_BLOCK_SIZE;
+ *key = realloc(*key, *key_len);
+ *output = *key;
+ }
+ }
+ else {
+ if (outputPos == (*value_len) - 1) {
+ (*value_len) += MALLOC_BLOCK_SIZE;
+ *value = realloc(*value, *value_len);
+ *output = *value;
+ }
+ }
+}
+
+static void parseLine(const char* line, properties_pt props) {
+ int linePos = 0;
+ bool precedingCharIsBackslash = false;
+ bool isComment = false;
+ int outputPos = 0;
+ char *output = NULL;
+ int key_len = MALLOC_BLOCK_SIZE;
+ int value_len = MALLOC_BLOCK_SIZE;
+ linePos = 0;
+ precedingCharIsBackslash = false;
+ isComment = false;
+ output = NULL;
+ outputPos = 0;
+
+ //Ignore empty lines
+ if (line[0] == '\n' && line[1] == '\0') {
+ return;
+ }
+
+ char *key = calloc(1, key_len);
+ char *value = calloc(1, value_len);
+ key[0] = '\0';
+ value[0] = '\0';
+
+ while (line[linePos] != '\0') {
+ if (line[linePos] == ' ' || line[linePos] == '\t') {
+ if (output == NULL) {
+ //ignore
+ linePos += 1;
+ continue;
+ }
+ }
+ else {
+ if (output == NULL) {
+ output = key;
+ }
+ }
+ if (line[linePos] == '=' || line[linePos] == ':' || line[linePos] == '#' || line[linePos] == '!') {
+ if (precedingCharIsBackslash) {
+ //escaped special character
+ output[outputPos++] = line[linePos];
+ updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len);
+ precedingCharIsBackslash = false;
+ }
+ else {
+ if (line[linePos] == '#' || line[linePos] == '!') {
+ if (outputPos == 0) {
+ isComment = true;
+ break;
+ }
+ else {
+ output[outputPos++] = line[linePos];
+ updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len);
+ }
+ }
+ else { // = or :
+ if (output == value) { //already have a seperator
+ output[outputPos++] = line[linePos];
+ updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len);
+ }
+ else {
+ output[outputPos++] = '\0';
+ updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len);
+ output = value;
+ outputPos = 0;
+ }
+ }
+ }
+ }
+ else if (line[linePos] == '\\') {
+ if (precedingCharIsBackslash) { //double backslash -> backslash
+ output[outputPos++] = '\\';
+ updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len);
+ }
+ precedingCharIsBackslash = true;
+ }
+ else { //normal character
+ precedingCharIsBackslash = false;
+ output[outputPos++] = line[linePos];
+ updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len);
+ }
+ linePos += 1;
+ }
+ if (output != NULL) {
+ output[outputPos] = '\0';
+ }
+
+ if (!isComment) {
+ //printf("putting 'key'/'value' '%s'/'%s' in properties\n", utils_stringTrim(key), utils_stringTrim(value));
+ properties_set(props, utils_stringTrim(key), utils_stringTrim(value));
+ }
+ if(key) {
+ free(key);
+ }
+ if(value) {
+ free(value);
+ }
+
+}
[4/4] celix git commit: Merge branch 'endpoint-format' into develop
Posted by rl...@apache.org.
Merge branch 'endpoint-format' into develop
Project: http://git-wip-us.apache.org/repos/asf/celix/repo
Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/0a5ef69a
Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/0a5ef69a
Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/0a5ef69a
Branch: refs/heads/develop
Commit: 0a5ef69a6a6a2167953c4ad4fa807142d46ad768
Parents: a8b8410 9094f55
Author: Roy Lenferink <rl...@apache.org>
Authored: Fri Feb 2 14:01:36 2018 +0100
Committer: Roy Lenferink <rl...@apache.org>
Committed: Fri Feb 2 14:01:36 2018 +0100
----------------------------------------------------------------------
.../pubsub_admin_udp_mc/src/pubsub_admin_impl.c | 103 ++++++++++++-------
.../pubsub_admin_udp_mc/src/topic_publication.c | 15 +--
pubsub/pubsub_admin_zmq/src/pubsub_admin_impl.c | 99 +++++++++++-------
pubsub/pubsub_admin_zmq/src/topic_publication.c | 13 +--
pubsub/pubsub_discovery/src/etcd_watcher.c | 56 +++++++++-
pubsub/pubsub_discovery/src/etcd_writer.c | 44 ++++++--
.../src/pubsub_discovery_impl.c | 19 ++--
pubsub/pubsub_spi/include/pubsub_endpoint.h | 19 ++--
pubsub/pubsub_spi/src/pubsub_endpoint.c | 88 ++++++++++------
.../src/pubsub_topology_manager.c | 40 ++++---
utils/include/properties.h | 2 +
utils/src/properties.c | 5 +
12 files changed, 343 insertions(+), 160 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/celix/blob/0a5ef69a/pubsub/pubsub_admin_udp_mc/src/pubsub_admin_impl.c
----------------------------------------------------------------------
diff --cc pubsub/pubsub_admin_udp_mc/src/pubsub_admin_impl.c
index 674f817,0000000..a71344a
mode 100644,000000..100644
--- a/pubsub/pubsub_admin_udp_mc/src/pubsub_admin_impl.c
+++ b/pubsub/pubsub_admin_udp_mc/src/pubsub_admin_impl.c
@@@ -1,1039 -1,0 +1,1062 @@@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+/*
+ * pubsub_admin_impl.c
+ *
+ * \date Sep 30, 2011
+ * \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ * \copyright Apache License, Version 2.0
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef ANDROID
+#include <ifaddrs.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include "constants.h"
+#include "utils.h"
+#include "hash_map.h"
+#include "array_list.h"
+#include "bundle_context.h"
+#include "bundle.h"
+#include "service_reference.h"
+#include "service_registration.h"
+#include "log_helper.h"
+#include "log_service.h"
+#include "celix_threads.h"
+#include "service_factory.h"
+
+#include "pubsub_admin_impl.h"
+#include "topic_subscription.h"
+#include "topic_publication.h"
+#include "pubsub_endpoint.h"
+#include "pubsub/subscriber.h"
+#include "pubsub_admin_match.h"
+
+static const char *DEFAULT_MC_IP = "224.100.1.1";
+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_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;
+
+ *admin = calloc(1, sizeof(**admin));
+
+ if (!*admin) {
+ return CELIX_ENOMEM;
+ }
+
+ char *mc_ip = NULL;
+ char *if_ip = NULL;
+ int sendSocket = -1;
+
+ if (logHelper_create(context, &(*admin)->loghelper) == CELIX_SUCCESS) {
+ logHelper_start((*admin)->loghelper);
+ }
+ const char *mc_ip_prop = NULL;
+ bundleContext_getProperty(context,PSA_IP , &mc_ip_prop);
+ if(mc_ip_prop) {
+ mc_ip = strdup(mc_ip_prop);
+ }
+
+#ifndef ANDROID
+ if (mc_ip == NULL) {
+ const char *mc_prefix = NULL;
+ const char *interface = NULL;
+ 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;
+ }
+
+ bundleContext_getProperty(context, PSA_ITF, &interface);
+ if (pubsubAdmin_getIpAddress(interface, &if_ip) != CELIX_SUCCESS) {
+ 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_UDP_MC: Could not parse IP address %s", if_ip);
+ b2 = 1;
+ b3 = 1;
+ }
+
+ asprintf(&mc_ip, "%s.%d.%d",mc_prefix, b2, b3);
+
+ sendSocket = socket(AF_INET, SOCK_DGRAM, 0);
+ if(sendSocket == -1) {
+ perror("pubsubAdmin_create:socket");
+ status = CELIX_SERVICE_EXCEPTION;
+ }
+
+ if(status == CELIX_SUCCESS){
+ 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;
+ }
+ }
+
+ }
+
+
+ if(status != CELIX_SUCCESS){
+ logHelper_stop((*admin)->loghelper);
+ logHelper_destroy(&((*admin)->loghelper));
+ if(sendSocket >=0){
+ close(sendSocket);
+ }
+ if(if_ip != NULL){
+ free(if_ip);
+ }
+ if(mc_ip != NULL){
+ free(mc_ip);
+ }
+ return status;
+ }
+ else{
+ (*admin)->sendSocket = sendSocket;
+ }
+
+#endif
+
+ (*admin)->bundle_context= context;
+ (*admin)->localPublications = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
+ (*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)->externalPublicationsLock, NULL);
+ celixThreadMutex_create(&(*admin)->serializerListLock, NULL);
+ celixThreadMutex_create(&(*admin)->usedSerializersLock, NULL);
+
+ celixThreadMutexAttr_create(&(*admin)->noSerializerPendingsAttr);
+ celixThreadMutexAttr_settype(&(*admin)->noSerializerPendingsAttr, CELIX_THREAD_MUTEX_RECURSIVE);
+ celixThreadMutex_create(&(*admin)->noSerializerPendingsLock, &(*admin)->noSerializerPendingsAttr);
+
+ celixThreadMutexAttr_create(&(*admin)->pendingSubscriptionsAttr);
+ celixThreadMutexAttr_settype(&(*admin)->pendingSubscriptionsAttr, CELIX_THREAD_MUTEX_RECURSIVE);
+ celixThreadMutex_create(&(*admin)->pendingSubscriptionsLock, &(*admin)->pendingSubscriptionsAttr);
+
+ if (if_ip != NULL) {
+ 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_UDP_MC: Using %s for service annunciation", mc_ip);
+ (*admin)->mcIpAddress = mc_ip;
+ }
+ else {
+ 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);
+ }
+
+ return status;
+}
+
+
+celix_status_t pubsubAdmin_destroy(pubsub_admin_pt admin)
+{
+ celix_status_t status = CELIX_SUCCESS;
+
+ free(admin->mcIpAddress);
+ free(admin->ifIpAddress);
+
+ celixThreadMutex_lock(&admin->pendingSubscriptionsLock);
+ hash_map_iterator_pt iter = hashMapIterator_create(admin->pendingSubscriptions);
+ while(hashMapIterator_hasNext(iter)){
+ hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
+ free((char*)hashMapEntry_getKey(entry));
+ arrayList_destroy((array_list_pt)hashMapEntry_getValue(entry));
+ }
+ hashMapIterator_destroy(iter);
+ hashMap_destroy(admin->pendingSubscriptions,false,false);
+ celixThreadMutex_unlock(&admin->pendingSubscriptionsLock);
+
+ celixThreadMutex_lock(&admin->subscriptionsLock);
+ hashMap_destroy(admin->subscriptions,false,false);
+ celixThreadMutex_unlock(&admin->subscriptionsLock);
+
+ celixThreadMutex_lock(&admin->localPublicationsLock);
+ hashMap_destroy(admin->localPublications,true,false);
+ celixThreadMutex_unlock(&admin->localPublicationsLock);
+
+ celixThreadMutex_lock(&admin->externalPublicationsLock);
+ iter = hashMapIterator_create(admin->externalPublications);
+ while(hashMapIterator_hasNext(iter)){
+ hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
+ free((char*)hashMapEntry_getKey(entry));
+ arrayList_destroy((array_list_pt)hashMapEntry_getValue(entry));
+ }
+ hashMapIterator_destroy(iter);
+ 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->serializerListLock);
+
+ celixThreadMutexAttr_destroy(&admin->noSerializerPendingsAttr);
+ celixThreadMutex_destroy(&admin->noSerializerPendingsLock);
+
+ celixThreadMutex_destroy(&admin->pendingSubscriptionsLock);
+ celixThreadMutexAttr_destroy(&admin->pendingSubscriptionsAttr);
+
+ celixThreadMutex_destroy(&admin->subscriptionsLock);
+ celixThreadMutex_destroy(&admin->localPublicationsLock);
+ celixThreadMutex_destroy(&admin->externalPublicationsLock);
+
+ logHelper_stop(admin->loghelper);
+
+ logHelper_destroy(&admin->loghelper);
+
+ free(admin);
+
+ return status;
+}
+
+static celix_status_t pubsubAdmin_addAnySubscription(pubsub_admin_pt admin,pubsub_endpoint_pt subEP){
+ celix_status_t status = CELIX_SUCCESS;
+
+ celixThreadMutex_lock(&admin->subscriptionsLock);
+
+ topic_subscription_pt any_sub = hashMap_get(admin->subscriptions,PUBSUB_ANY_SUB_TOPIC);
+
+ 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);
++ printf("PSA_UDP_MC: Cannot find a serializer for subscribing topic %s. Adding it to pending list.\n",
++ properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
++
+ celixThreadMutex_lock(&admin->noSerializerPendingsLock);
+ arrayList_add(admin->noSerializerSubscriptions,subEP);
+ celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
+ }
+
+ 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;i<arrayList_size(topic_publishers);i++){
+ pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(topic_publishers,i);
- if(pubEP->endpoint !=NULL){
- status += pubsub_topicSubscriptionConnectPublisher(any_sub,pubEP->endpoint);
++ if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
++ status += pubsub_topicSubscriptionConnectPublisher(any_sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
+ }
+ }
+ 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;i<arrayList_size(ext_pub_list);i++){
+ pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(ext_pub_list,i);
- if(pubEP->endpoint !=NULL){
- status += pubsub_topicSubscriptionConnectPublisher(any_sub,pubEP->endpoint);
++ if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
++ status += pubsub_topicSubscriptionConnectPublisher(any_sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
+ }
+ }
+ }
+ }
+ hashMapIterator_destroy(extp_iter);
+ celixThreadMutex_unlock(&admin->externalPublicationsLock);
+
+
+ pubsub_topicSubscriptionAddSubscriber(any_sub,subEP);
+
+ status += pubsub_topicSubscriptionStart(any_sub);
+
+ }
+
+ if (status == CELIX_SUCCESS){
+ hashMap_put(admin->subscriptions,strdup(PUBSUB_ANY_SUB_TOPIC),any_sub);
+ connectTopicPubSubToSerializer(admin, best_serializer, any_sub, false);
+ }
+
+ }
+
+ celixThreadMutex_unlock(&admin->subscriptionsLock);
+
+ return status;
+}
+
+celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint_pt subEP){
+ celix_status_t status = CELIX_SUCCESS;
+
- printf("PSA_UDP_MC: 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",
++ properties_get(subEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
++ subEP->serviceID,
++ properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
++ properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+
- if(strcmp(subEP->topic,PUBSUB_ANY_SUB_TOPIC)==0){
++ if(strcmp(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),PUBSUB_ANY_SUB_TOPIC)==0){
+ return pubsubAdmin_addAnySubscription(admin,subEP);
+ }
+
+ /* Check if we already know some publisher about this topic, otherwise let's put the subscription in the pending hashmap */
+ celixThreadMutex_lock(&admin->pendingSubscriptionsLock);
+ celixThreadMutex_lock(&admin->subscriptionsLock);
+ celixThreadMutex_lock(&admin->localPublicationsLock);
+ celixThreadMutex_lock(&admin->externalPublicationsLock);
+
- char* scope_topic = createScopeTopicKey(subEP->scope,subEP->topic);
++ char* scope_topic = createScopeTopicKey(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_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);
+
+ if(factory==NULL && ext_pub_list==NULL){ //No (local or external) publishers yet for this topic
+ pubsubAdmin_addSubscriptionToPendingList(admin,subEP);
+ }
+ 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);
++ status += pubsub_topicSubscriptionCreate(admin->bundle_context,admin->ifIpAddress, (char*) properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), (char*) properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_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);
++ printf("PSA_UDP_MC: Cannot find a serializer for subscribing topic %s. Adding it to pending list.\n",
++ properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
++
+ celixThreadMutex_lock(&admin->noSerializerPendingsLock);
+ arrayList_add(admin->noSerializerSubscriptions,subEP);
+ celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
+ }
+
+ 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);
+
+ if(topic_publishers!=NULL){
+ for(i=0;i<arrayList_size(topic_publishers);i++){
+ pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(topic_publishers,i);
- if(pubEP->endpoint !=NULL){
- status += pubsub_topicSubscriptionConnectPublisher(subscription,pubEP->endpoint);
++ if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
++ status += pubsub_topicSubscriptionConnectPublisher(subscription, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
+ }
+ }
+ arrayList_destroy(topic_publishers);
+ }
+
+ }
+
+ /* Look also for external publishers */
+ if(ext_pub_list!=NULL){
+ for(i=0;i<arrayList_size(ext_pub_list);i++){
+ pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(ext_pub_list,i);
- if(pubEP->endpoint !=NULL){
- status += pubsub_topicSubscriptionConnectPublisher(subscription,pubEP->endpoint);
++ if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
++ status += pubsub_topicSubscriptionConnectPublisher(subscription, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
+ }
+ }
+ }
+
+ pubsub_topicSubscriptionAddSubscriber(subscription,subEP);
+
+ status += pubsub_topicSubscriptionStart(subscription);
+
+ }
+
+ if(status==CELIX_SUCCESS){
+
+ hashMap_put(admin->subscriptions,strdup(scope_topic),subscription);
+
+ connectTopicPubSubToSerializer(admin, best_serializer, subscription, false);
+ }
+ }
+
+ if (status == CELIX_SUCCESS){
+ pubsub_topicIncreaseNrSubscribers(subscription);
+ }
+ }
+
+ free(scope_topic);
+ celixThreadMutex_unlock(&admin->externalPublicationsLock);
+ celixThreadMutex_unlock(&admin->localPublicationsLock);
+ celixThreadMutex_unlock(&admin->subscriptionsLock);
+ celixThreadMutex_unlock(&admin->pendingSubscriptionsLock);
+
+ return status;
+
+}
+
+celix_status_t pubsubAdmin_removeSubscription(pubsub_admin_pt admin,pubsub_endpoint_pt subEP){
+ celix_status_t status = CELIX_SUCCESS;
+
- printf("PSA_UDP_MC: 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",
++ properties_get(subEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
++ subEP->serviceID,
++ properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
++ properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+
- char* scope_topic = createScopeTopicKey(subEP->scope, subEP->topic);
++ char* scope_topic = createScopeTopicKey(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+
+ celixThreadMutex_lock(&admin->subscriptionsLock);
+ topic_subscription_pt sub = (topic_subscription_pt)hashMap_get(admin->subscriptions,scope_topic);
+ if(sub!=NULL){
+ pubsub_topicDecreaseNrSubscribers(sub);
+ if(pubsub_topicGetNrSubscribers(sub) == 0) {
+ status = pubsub_topicSubscriptionRemoveSubscriber(sub,subEP);
+ }
+ }
+ celixThreadMutex_unlock(&admin->subscriptionsLock);
+
+ if(sub==NULL){
+ /* 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);
+
+
+
+ return status;
+
+}
+
+celix_status_t pubsubAdmin_addPublication(pubsub_admin_pt admin,pubsub_endpoint_pt pubEP){
+ celix_status_t status = CELIX_SUCCESS;
+
- printf("PSA_UDP_MC: 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",
++ properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
++ pubEP->serviceID,
++ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
++ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+
+ const char* fwUUID = NULL;
+
+ bundleContext_getProperty(admin->bundle_context,OSGI_FRAMEWORK_FRAMEWORK_UUID,&fwUUID);
+ if(fwUUID==NULL){
+ printf("PSA_UDP_MC: Cannot retrieve fwUUID.\n");
+ return CELIX_INVALID_BUNDLE_CONTEXT;
+ }
- char* scope_topic = createScopeTopicKey(pubEP->scope, pubEP->topic);
++ char* scope_topic = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+
- if ((strcmp(pubEP->frameworkUUID, fwUUID) == 0) && (pubEP->endpoint == NULL)) {
++ if ((strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID), fwUUID) == 0) && (properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) == 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->sendSocket, pubEP, best_serializer, admin->mcIpAddress, &pub);
+ }
+ else{
- printf("PSA_UDP_MC: Cannot find a serializer for publishing topic %s. Adding it to pending list.\n", pubEP->topic);
++ printf("PSA_UDP_MC: Cannot find a serializer for publishing topic %s. Adding it to pending list.\n",
++ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_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_UDP_MC: Cannot create a topicPublication for scope=%s, topic=%s (bundle %ld).\n", pubEP->scope, pubEP->topic, pubEP->serviceID);
++ printf("PSA_UDP_MC: Cannot create a topicPublication for scope=%s, topic=%s (bundle %ld).\n",
++ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
++ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_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);
++ if (sub != NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) != NULL) {
++ pubsub_topicSubscriptionAddConnectPublisherToPendingList(sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
+ }
+
+ /* 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);
++ if (any_sub != NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) != NULL) {
++ pubsub_topicSubscriptionAddConnectPublisherToPendingList(any_sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
+ }
+
+ 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_UDP_MC: 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",
++ properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
++ pubEP->serviceID,
++ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
++ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+
+ const char* fwUUID = NULL;
+
+ bundleContext_getProperty(admin->bundle_context,OSGI_FRAMEWORK_FRAMEWORK_UUID,&fwUUID);
+ if(fwUUID==NULL){
+ printf("PSA_UDP_MC: Cannot retrieve fwUUID.\n");
+ return CELIX_INVALID_BUNDLE_CONTEXT;
+ }
- char *scope_topic = createScopeTopicKey(pubEP->scope, pubEP->topic);
++ char *scope_topic = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+
- if(strcmp(pubEP->frameworkUUID,fwUUID)==0){
++ if(strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),fwUUID)==0){
+
+ celixThreadMutex_lock(&admin->localPublicationsLock);
+ service_factory_pt factory = (service_factory_pt)hashMap_get(admin->localPublications,scope_topic);
+ if(factory!=NULL){
+ topic_publication_pt pub = (topic_publication_pt)factory->handle;
+ pubsub_topicPublicationRemovePublisherEP(pub,pubEP);
+ }
+ celixThreadMutex_unlock(&admin->localPublicationsLock);
+
+ if(factory==NULL){
+ /* Maybe the endpoint was pending */
+ celixThreadMutex_lock(&admin->noSerializerPendingsLock);
+ if(!arrayList_removeElement(admin->noSerializerPublications, pubEP)){
+ status = CELIX_ILLEGAL_STATE;
+ }
+ celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
+ }
+
+ }
+ 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){
+ int i;
+ bool found = false;
+ for(i=0;!found && i<arrayList_size(ext_pub_list);i++){
+ pubsub_endpoint_pt p = (pubsub_endpoint_pt)arrayList_get(ext_pub_list,i);
+ found = pubsubEndpoint_equals(pubEP,p);
+ if (found){
+ 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)
+ for(i=0; i<arrayList_size(ext_pub_list);i++) {
+ pubsub_endpoint_pt p = (pubsub_endpoint_pt)arrayList_get(ext_pub_list,i);
- if (strcmp(pubEP->endpoint,p->endpoint) == 0) {
++ if (strcmp(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL),properties_get(p->endpoint_props, PUBSUB_ENDPOINT_URL)) == 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,topic);
+ arrayList_destroy(list);
+ free(topic);
+ }
+ }
+
+ celixThreadMutex_unlock(&admin->externalPublicationsLock);
+ }
+
+ /* Check if this publisher was connected to one of our subscribers*/
+ celixThreadMutex_lock(&admin->subscriptionsLock);
+
+ topic_subscription_pt sub = (topic_subscription_pt)hashMap_get(admin->subscriptions,scope_topic);
- if(sub!=NULL && pubEP->endpoint!=NULL && count == 0){
- pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(sub,pubEP->endpoint);
++ if(sub!=NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL && count == 0){
++ pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
+ }
+
+ /* 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);
++ if(any_sub!=NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL && count == 0){
++ pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(any_sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
+ }
+
+ free(scope_topic);
+ celixThreadMutex_unlock(&admin->subscriptionsLock);
+
+ return status;
+
+}
+
+celix_status_t pubsubAdmin_closeAllPublications(pubsub_admin_pt admin,char *scope, char* topic){
+ celix_status_t status = CELIX_SUCCESS;
+
+ 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);
+ hash_map_entry_pt pubsvc_entry = (hash_map_entry_pt)hashMap_getEntry(admin->localPublications,scope_topic);
+ if(pubsvc_entry!=NULL){
+ 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);
+ disconnectTopicPubSubFromSerializer(admin, pub, true);
+ status += pubsub_topicPublicationDestroy(pub);
+ hashMap_remove(admin->localPublications,scope_topic);
+ free(key);
+ free(factory);
+ }
+ free(scope_topic);
+ celixThreadMutex_unlock(&admin->localPublicationsLock);
+
+ return status;
+
+}
+
+celix_status_t pubsubAdmin_closeAllSubscriptions(pubsub_admin_pt admin,char *scope, char* topic){
+ celix_status_t status = CELIX_SUCCESS;
+
+ printf("PSA_UDP_MC: Closing all subscriptions\n");
+
+ celixThreadMutex_lock(&admin->subscriptionsLock);
+ char* scope_topic =createScopeTopicKey(scope, topic);
+ hash_map_entry_pt sub_entry = (hash_map_entry_pt)hashMap_getEntry(admin->subscriptions,scope_topic);
+ if(sub_entry!=NULL){
+ char* topic = (char*)hashMapEntry_getKey(sub_entry);
+
+ topic_subscription_pt ts = (topic_subscription_pt)hashMapEntry_getValue(sub_entry);
+ status += pubsub_topicSubscriptionStop(ts);
+ disconnectTopicPubSubFromSerializer(admin, ts, false);
+ status += pubsub_topicSubscriptionDestroy(ts);
+ hashMap_remove(admin->subscriptions,topic);
+ free(topic);
+
+ }
+ free(scope_topic);
+ celixThreadMutex_unlock(&admin->subscriptionsLock);
+
+ return status;
+
+}
+
+
+#ifndef ANDROID
+static celix_status_t pubsubAdmin_getIpAddress(const char* interface, char** ip) {
+ celix_status_t status = CELIX_BUNDLE_EXCEPTION;
+
+ struct ifaddrs *ifaddr, *ifa;
+ char host[NI_MAXHOST];
+
+ if (getifaddrs(&ifaddr) != -1)
+ {
+ for (ifa = ifaddr; ifa != NULL && status != CELIX_SUCCESS; ifa = ifa->ifa_next)
+ {
+ if (ifa->ifa_addr == NULL)
+ continue;
+
+ if ((getnameinfo(ifa->ifa_addr,sizeof(struct sockaddr_in), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST) == 0) && (ifa->ifa_addr->sa_family == AF_INET)) {
+ if (interface == NULL) {
+ *ip = strdup(host);
+ status = CELIX_SUCCESS;
+ }
+ else if (strcmp(ifa->ifa_name, interface) == 0) {
+ *ip = strdup(host);
+ status = CELIX_SUCCESS;
+ }
+ }
+ }
+
+ freeifaddrs(ifaddr);
+ }
+
+ return status;
+}
+#endif
+
+static celix_status_t pubsubAdmin_addSubscriptionToPendingList(pubsub_admin_pt admin,pubsub_endpoint_pt subEP){
+ celix_status_t status = CELIX_SUCCESS;
+
- char* scope_topic =createScopeTopicKey(subEP->scope, subEP->topic);
++ char* scope_topic =createScopeTopicKey(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+ array_list_pt pendingListPerTopic = hashMap_get(admin->pendingSubscriptions,scope_topic);
+ if(pendingListPerTopic==NULL){
+ arrayList_create(&pendingListPerTopic);
+ 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;i<arrayList_size(admin->noSerializerSubscriptions);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;i<arrayList_size(admin->noSerializerPublications);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);
+ /* Remove the serializer from the list */
+ arrayList_removeElement(admin->serializerList, reference);
+ celixThreadMutex_unlock(&admin->serializerListLock);
+
+ celixThreadMutex_lock(&admin->usedSerializersLock);
+ array_list_pt topicPubList = (array_list_pt)hashMap_remove(admin->topicPublicationsPerSerializer, service);
+ array_list_pt topicSubList = (array_list_pt)hashMap_remove(admin->topicSubscriptionsPerSerializer, service);
+ celixThreadMutex_unlock(&admin->usedSerializersLock);
+
+ /* Now destroy the topicPublications, but first put back the pubsub_endpoints back to the noSerializer pending list */
+ if(topicPubList!=NULL){
+ for(i=0;i<arrayList_size(topicPubList);i++){
+ topic_publication_pt topicPub = (topic_publication_pt)arrayList_get(topicPubList,i);
+ /* Stop the topic publication */
+ pubsub_topicPublicationStop(topicPub);
+ /* Get the endpoints that are going to be orphan */
+ array_list_pt pubList = pubsub_topicPublicationGetPublisherList(topicPub);
+ for(j=0;j<arrayList_size(pubList);j++){
+ pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(pubList,j);
+ /* Remove the publication */
+ pubsubAdmin_removePublication(admin, pubEP);
+ /* Reset the endpoint field, so that will be recreated from scratch when a new serializer will be found */
- if(pubEP->endpoint!=NULL){
- free(pubEP->endpoint);
- pubEP->endpoint = NULL;
++ if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL){
++ properties_unset(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL);
+ }
+ /* 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 */
+ if(topicSubList!=NULL){
+ for(i=0;i<arrayList_size(topicSubList);i++){
+ topic_subscription_pt topicSub = (topic_subscription_pt)arrayList_get(topicSubList,i);
+ /* Stop the topic subscription */
+ pubsub_topicSubscriptionStop(topicSub);
+ /* Get the endpoints that are going to be orphan */
+ array_list_pt subList = pubsub_topicSubscriptionGetSubscribersList(topicSub);
+ for(j=0;j<arrayList_size(subList);j++){
+ pubsub_endpoint_pt subEP = (pubsub_endpoint_pt)arrayList_get(subList,j);
+ /* Remove the subscription */
+ pubsubAdmin_removeSubscription(admin, subEP);
+ /* Reset the endpoint field, so that will be recreated from scratch when a new serializer will be found */
- if(subEP->endpoint!=NULL){
- free(subEP->endpoint);
- subEP->endpoint = NULL;
++ if(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL){
++ properties_unset(subEP->endpoint_props, PUBSUB_ENDPOINT_URL);
+ }
+ /* 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);
+ }
+
+ 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);
+
+}
http://git-wip-us.apache.org/repos/asf/celix/blob/0a5ef69a/pubsub/pubsub_admin_udp_mc/src/topic_publication.c
----------------------------------------------------------------------
diff --cc pubsub/pubsub_admin_udp_mc/src/topic_publication.c
index 15af108,0000000..79a2698
mode 100644,000000..100644
--- a/pubsub/pubsub_admin_udp_mc/src/topic_publication.c
+++ b/pubsub/pubsub_admin_udp_mc/src/topic_publication.c
@@@ -1,437 -1,0 +1,440 @@@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "array_list.h"
+#include "celixbool.h"
+#include "service_registration.h"
+#include "utils.h"
+#include "service_factory.h"
+#include "version.h"
+
+#include "topic_publication.h"
+#include "pubsub_common.h"
+#include "pubsub/publisher.h"
+#include "large_udp.h"
+
+#include "pubsub_serializer.h"
+
+#define EP_ADDRESS_LEN 32
+
+#define FIRST_SEND_DELAY 2
+
+struct topic_publication {
+ int sendSocket;
+ char* endpoint;
+ service_registration_pt svcFactoryReg;
+ array_list_pt pub_ep_list; //List<pubsub_endpoint>
+ hash_map_pt boundServices; //<bundle_pt,bound_service>
+ celix_thread_mutex_t tp_lock;
+ pubsub_serializer_service_t *serializer;
+ struct sockaddr_in destAddr;
+};
+
+typedef struct publish_bundle_bound_service {
+ topic_publication_pt parent;
+ pubsub_publisher_t service;
+ bundle_pt bundle;
+ char *scope;
+ char *topic;
+ hash_map_pt msgTypes;
+ unsigned short getCount;
+ celix_thread_mutex_t mp_lock;
+ largeUdp_pt largeUdpHandle;
+}* publish_bundle_bound_service_pt;
+
+
+typedef struct pubsub_msg{
+ pubsub_msg_header_pt header;
+ char* payload;
+ 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);
+static celix_status_t pubsub_topicPublicationUngetService(void* handle, bundle_pt bundle, service_registration_pt registration, void **service);
+
+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_localMsgTypeIdForUUID(void* handle, const char* msgType, unsigned int* msgTypeId);
+
+
+static void delay_first_send_for_late_joiners(void);
+
+
+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);
+
+
+ topic_publication_pt pub = calloc(1,sizeof(*pub));
+
+ arrayList_create(&(pub->pub_ep_list));
+ pub->boundServices = hashMap_create(NULL,NULL,NULL,NULL);
+ celixThreadMutex_create(&(pub->tp_lock),NULL);
+
+ pub->endpoint = ep;
+ pub->sendSocket = sendSocket;
+ pub->destAddr.sin_family = AF_INET;
+ pub->destAddr.sin_addr.s_addr = inet_addr(bindIP);
+ pub->destAddr.sin_port = htons(port);
+
+ pub->serializer = best_serializer;
+
+ pubsub_topicPublicationAddPublisherEP(pub,pubEP);
+
+ *out = pub;
+
+ return CELIX_SUCCESS;
+}
+
+celix_status_t pubsub_topicPublicationDestroy(topic_publication_pt pub){
+ celix_status_t status = CELIX_SUCCESS;
+
+ celixThreadMutex_lock(&(pub->tp_lock));
+
+ free(pub->endpoint);
+ arrayList_destroy(pub->pub_ep_list);
+
+ hash_map_iterator_pt iter = hashMapIterator_create(pub->boundServices);
+ while(hashMapIterator_hasNext(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;
+
+ if(close(pub->sendSocket) != 0){
+ status = CELIX_FILE_IO_EXCEPTION;
+ }
+
+ celixThreadMutex_unlock(&(pub->tp_lock));
+
+ celixThreadMutex_destroy(&(pub->tp_lock));
+
+ free(pub);
+
+ return status;
+}
+
+celix_status_t pubsub_topicPublicationStart(bundle_context_pt bundle_context,topic_publication_pt pub,service_factory_pt* svcFactory){
+ celix_status_t status = CELIX_SUCCESS;
+
+ /* Let's register the new service */
+
+ pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(pub->pub_ep_list,0);
+
+ if(pubEP!=NULL){
+ service_factory_pt factory = calloc(1, sizeof(*factory));
+ factory->handle = pub;
+ factory->getService = pubsub_topicPublicationGetService;
+ factory->ungetService = pubsub_topicPublicationUngetService;
+
+ properties_pt props = properties_create();
- properties_set(props,PUBSUB_PUBLISHER_SCOPE,pubEP->scope);
- properties_set(props,PUBSUB_PUBLISHER_TOPIC,pubEP->topic);
++ properties_set(props,PUBSUB_PUBLISHER_SCOPE,properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE));
++ properties_set(props,PUBSUB_PUBLISHER_TOPIC,properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+
+ status = bundleContext_registerServiceFactory(bundle_context,PUBSUB_PUBLISHER_SERVICE_NAME,factory,props,&(pub->svcFactoryReg));
+
+ if(status != CELIX_SUCCESS){
+ properties_destroy(props);
- 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);
++ printf("PSA_UDP_MC_PSA_UDP_MC_TP: Cannot register ServiceFactory for topic %s, topic %s (bundle %ld).\n",
++ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
++ properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
++ pubEP->serviceID);
+ }
+ else{
+ *svcFactory = factory;
+ }
+ }
+ else{
+ printf("PSA_UDP_MC_PSA_UDP_MC_TP: Cannot find pubsub_endpoint after adding it...Should never happen!\n");
+ status = CELIX_SERVICE_EXCEPTION;
+ }
+
+ return status;
+}
+
+celix_status_t pubsub_topicPublicationStop(topic_publication_pt pub){
+ return serviceRegistration_unregister(pub->svcFactoryReg);
+}
+
+celix_status_t pubsub_topicPublicationAddPublisherEP(topic_publication_pt pub,pubsub_endpoint_pt ep){
+
+ celixThreadMutex_lock(&(pub->tp_lock));
- ep->endpoint = strdup(pub->endpoint);
++ pubsubEndpoint_setField(ep, PUBSUB_ENDPOINT_URL, pub->endpoint);
+ arrayList_add(pub->pub_ep_list,ep);
+ celixThreadMutex_unlock(&(pub->tp_lock));
+
+ return CELIX_SUCCESS;
+}
+
+celix_status_t pubsub_topicPublicationRemovePublisherEP(topic_publication_pt pub,pubsub_endpoint_pt ep){
+
+ celixThreadMutex_lock(&(pub->tp_lock));
+ arrayList_removeElement(pub->pub_ep_list,ep);
+ celixThreadMutex_unlock(&(pub->tp_lock));
+
+ return CELIX_SUCCESS;
+}
+
+array_list_pt pubsub_topicPublicationGetPublisherList(topic_publication_pt pub){
+ array_list_pt list = NULL;
+ celixThreadMutex_lock(&(pub->tp_lock));
+ list = arrayList_clone(pub->pub_ep_list);
+ celixThreadMutex_unlock(&(pub->tp_lock));
+ return list;
+}
+
+
+static celix_status_t pubsub_topicPublicationGetService(void* handle, bundle_pt bundle, service_registration_pt registration, void **service) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ topic_publication_pt publish = (topic_publication_pt)handle;
+
+ celixThreadMutex_lock(&(publish->tp_lock));
+
+ 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{
+ bound->getCount++;
+ }
+
+ if (bound != NULL) {
+ *service = &bound->service;
+ }
+
+ celixThreadMutex_unlock(&(publish->tp_lock));
+
+ return status;
+}
+
+static celix_status_t pubsub_topicPublicationUngetService(void* handle, bundle_pt bundle, service_registration_pt registration, void **service) {
+
+ topic_publication_pt publish = (topic_publication_pt)handle;
+
+ celixThreadMutex_lock(&(publish->tp_lock));
+
+ 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){
+ pubsub_destroyPublishBundleBoundService(bound);
+ hashMap_remove(publish->boundServices,bundle);
+ }
+
+ }
+ else{
+ long bundleId = -1;
+ bundle_getBundleId(bundle,&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 */
+ *service = NULL;
+
+ celixThreadMutex_unlock(&(publish->tp_lock));
+
+ return CELIX_SUCCESS;
+}
+
+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;
+
+ struct iovec msg_iovec[iovec_len];
+ msg_iovec[0].iov_base = msg->header;
+ msg_iovec[0].iov_len = sizeof(*msg->header);
+ msg_iovec[1].iov_base = &msg->payloadSize;
+ msg_iovec[1].iov_len = sizeof(msg->payloadSize);
+ msg_iovec[2].iov_base = msg->payload;
+ msg_iovec[2].iov_len = msg->payloadSize;
+
+ 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) {
+ perror("send_pubsub_msg:sendSocket");
+ ret = false;
+ }
+
+ if(releaseCallback) {
+ releaseCallback->release(msg->payload, bound);
+ }
+ return ret;
+
+}
+
+
+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;
+
+ celixThreadMutex_lock(&(bound->parent->tp_lock));
+ celixThreadMutex_lock(&(bound->mp_lock));
+
+ pubsub_msg_serializer_t* msgSer = (pubsub_msg_serializer_t*)hashMap_get(bound->msgTypes, (void*)(intptr_t)msgTypeId);
+
+ if (msgSer != NULL) {
+ int major=0, minor=0;
+
+ 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);
+ msg_hdr->major = major;
+ msg_hdr->minor = minor;
+ }
+
+ void* serializedOutput = NULL;
+ size_t serializedOutputLen = 0;
+ msgSer->serialize(msgSer,inMsg,&serializedOutput, &serializedOutputLen);
+
+ pubsub_msg_t *msg = calloc(1,sizeof(pubsub_msg_t));
+ msg->header = msg_hdr;
+ msg->payload = (char*)serializedOutput;
+ msg->payloadSize = serializedOutputLen;
+
+
+ if(send_pubsub_msg(bound, msg,true, NULL) == false) {
+ status = -1;
+ }
+ free(msg_hdr);
+ free(msg);
+ free(serializedOutput);
+
+
+ } 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;
+}
+
+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)random())/((double)RAND_MAX));
+ return (max-min+1)*scaled + min;
+
+}
+
+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;
+ celixThreadMutex_create(&bound->mp_lock,NULL);
+
+ 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->scope=strdup(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE));
++ bound->topic=strdup(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+ bound->largeUdpHandle = largeUdp_create(1);
+
+ 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_pt boundSvc){
+
+ celixThreadMutex_lock(&boundSvc->mp_lock);
+
+ 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->topic!=NULL){
+ free(boundSvc->topic);
+ }
+
+ largeUdp_destroy(boundSvc->largeUdpHandle);
+
+ celixThreadMutex_unlock(&boundSvc->mp_lock);
+ celixThreadMutex_destroy(&boundSvc->mp_lock);
+
+ free(boundSvc);
+
+}
+
+static void delay_first_send_for_late_joiners(){
+
+ static bool firstSend = true;
+
+ if(firstSend){
+ printf("PSA_UDP_MC_TP: Delaying first send for late joiners...\n");
+ sleep(FIRST_SEND_DELAY);
+ firstSend = false;
+ }
+}