You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pn...@apache.org on 2018/05/27 18:37:12 UTC
[29/51] [partial] celix git commit: CELIX-424: Cleans up the
directory structure. Moves all libraries to the libs subdir and all bundles
to the bundles subdir
http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/remote_service_admin_shm/private/src/remote_service_admin_impl.c
----------------------------------------------------------------------
diff --git a/bundles/remote_services/remote_service_admin_shm/private/src/remote_service_admin_impl.c b/bundles/remote_services/remote_service_admin_shm/private/src/remote_service_admin_impl.c
new file mode 100644
index 0000000..f090223
--- /dev/null
+++ b/bundles/remote_services/remote_service_admin_shm/private/src/remote_service_admin_impl.c
@@ -0,0 +1,924 @@
+/**
+ *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.
+ */
+/*
+ * remote_service_admin_impl.c
+ *
+ * \date Sep 14, 2013
+ * \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 <dirent.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/sem.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <unistd.h>
+#include <uuid/uuid.h>
+
+#include "remote_service_admin_shm.h"
+#include "remote_service_admin_shm_impl.h"
+
+#include "export_registration_impl.h"
+#include "import_registration_impl.h"
+#include "remote_constants.h"
+#include "constants.h"
+#include "utils.h"
+#include "bundle_context.h"
+#include "bundle.h"
+#include "service_reference.h"
+#include "service_registration.h"
+
+static celix_status_t remoteServiceAdmin_lock(int semId, int semNr);
+static celix_status_t remoteServiceAdmin_unlock(int semId, int semNr);
+static int remoteServiceAdmin_getCount(int semId, int semNr);
+
+celix_status_t remoteServiceAdmin_installEndpoint(remote_service_admin_pt admin, export_registration_pt registration, service_reference_pt reference, char *interface);
+celix_status_t remoteServiceAdmin_createEndpointDescription(remote_service_admin_pt admin, service_reference_pt reference, properties_pt endpointProperties, char *interface, endpoint_description_pt *description);
+
+celix_status_t remoteServiceAdmin_createOrAttachShm(hash_map_pt ipcSegment, remote_service_admin_pt admin, endpoint_description_pt endpointDescription, bool createIfNotFound);
+celix_status_t remoteServiceAdmin_getIpcSegment(remote_service_admin_pt admin, endpoint_description_pt endpointDescription, ipc_segment_pt* ipc);
+celix_status_t remoteServiceAdmin_detachIpcSegment(ipc_segment_pt ipc);
+celix_status_t remoteServiceAdmin_deleteIpcSegment(ipc_segment_pt ipc);
+
+celix_status_t remoteServiceAdmin_getSharedIdentifierFile(remote_service_admin_pt admin, char *fwUuid, char* servicename, char* outFile);
+celix_status_t remoteServiceAdmin_removeSharedIdentityFile(remote_service_admin_pt admin, char *fwUuid, char* servicename);
+celix_status_t remoteServiceAdmin_removeSharedIdentityFiles(remote_service_admin_pt admin);
+
+celix_status_t remoteServiceAdmin_create(bundle_context_pt context, remote_service_admin_pt *admin) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ *admin = calloc(1, sizeof(**admin));
+
+ if (!*admin) {
+ status = CELIX_ENOMEM;
+ } else {
+ (*admin)->context = context;
+ (*admin)->exportedServices = hashMap_create(NULL, NULL, NULL, NULL);
+ (*admin)->importedServices = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
+ (*admin)->exportedIpcSegment = hashMap_create(NULL, NULL, NULL, NULL);
+ (*admin)->importedIpcSegment = hashMap_create(NULL, NULL, NULL, NULL);
+ (*admin)->pollThread = hashMap_create(NULL, NULL, NULL, NULL);
+ (*admin)->pollThreadRunning = hashMap_create(NULL, NULL, NULL, NULL);
+
+ if (logHelper_create(context, &(*admin)->loghelper) == CELIX_SUCCESS) {
+ logHelper_start((*admin)->loghelper);
+ }
+ }
+
+ return status;
+}
+
+celix_status_t remoteServiceAdmin_destroy(remote_service_admin_pt* admin) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ hashMap_destroy((*admin)->exportedServices, false, false);
+ hashMap_destroy((*admin)->importedServices, false, false);
+ hashMap_destroy((*admin)->exportedIpcSegment, false, false);
+ hashMap_destroy((*admin)->importedIpcSegment, false, false);
+ hashMap_destroy((*admin)->pollThread, false, false);
+ hashMap_destroy((*admin)->pollThreadRunning, false, false);
+
+ free(*admin);
+
+ *admin = NULL;
+
+ return status;
+}
+
+celix_status_t remoteServiceAdmin_stop(remote_service_admin_pt admin) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ celixThreadMutex_lock(&admin->exportedServicesLock);
+
+ hash_map_iterator_pt iter = hashMapIterator_create(admin->exportedServices);
+ while (hashMapIterator_hasNext(iter)) {
+ array_list_pt exports = hashMapIterator_nextValue(iter);
+ int i;
+ for (i = 0; i < arrayList_size(exports); i++) {
+ export_registration_pt export = arrayList_get(exports, i);
+ exportRegistration_stopTracking(export);
+ }
+ }
+ hashMapIterator_destroy(iter);
+ celixThreadMutex_unlock(&admin->exportedServicesLock);
+
+ celixThreadMutex_lock(&admin->importedServicesLock);
+
+ iter = hashMapIterator_create(admin->importedServices);
+ while (hashMapIterator_hasNext(iter)) {
+ hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
+
+ char* service = hashMapEntry_getKey(entry);
+ import_registration_factory_pt importFactory = hashMapEntry_getValue(entry);
+
+ if (importFactory != NULL) {
+
+ int i;
+ for (i = 0; i < arrayList_size(importFactory->registrations); i++) {
+ import_registration_pt importRegistration = arrayList_get(importFactory->registrations, i);
+
+ if (importFactory->trackedFactory != NULL) {
+ importFactory->trackedFactory->unregisterProxyService(importFactory->trackedFactory->factory, importRegistration->endpointDescription);
+ }
+ }
+ serviceTracker_close(importFactory->proxyFactoryTracker);
+ importRegistrationFactory_close(importFactory);
+
+ hashMap_remove(admin->importedServices, service);
+ importRegistrationFactory_destroy(&importFactory);
+ }
+ }
+ hashMapIterator_destroy(iter);
+ celixThreadMutex_unlock(&admin->importedServicesLock);
+
+ // set stop-thread-variable
+ iter = hashMapIterator_create(admin->pollThreadRunning);
+ while (hashMapIterator_hasNext(iter)) {
+ bool *pollThreadRunning = hashMapIterator_nextValue(iter);
+ *pollThreadRunning = false;
+ }
+ hashMapIterator_destroy(iter);
+
+ // release lock
+ iter = hashMapIterator_create(admin->exportedIpcSegment);
+ while (hashMapIterator_hasNext(iter)) {
+ ipc_segment_pt ipc = hashMapIterator_nextValue(iter);
+ remoteServiceAdmin_unlock(ipc->semId, 1);
+ }
+ hashMapIterator_destroy(iter);
+
+ // wait till threads has stopped
+ iter = hashMapIterator_create(admin->pollThread);
+ while (hashMapIterator_hasNext(iter)) {
+ celix_thread_t *pollThread = hashMapIterator_nextValue(iter);
+
+ if (pollThread != NULL) {
+ status = celixThread_join(*pollThread, NULL);
+ }
+ }
+ hashMapIterator_destroy(iter);
+
+ iter = hashMapIterator_create(admin->importedIpcSegment);
+ while (hashMapIterator_hasNext(iter)) {
+ ipc_segment_pt ipc = hashMapIterator_nextValue(iter);
+ remoteServiceAdmin_detachIpcSegment(ipc);
+ free(ipc);
+ }
+ hashMapIterator_destroy(iter);
+
+ iter = hashMapIterator_create(admin->exportedIpcSegment);
+ while (hashMapIterator_hasNext(iter)) {
+ ipc_segment_pt ipc = hashMapIterator_nextValue(iter);
+ remoteServiceAdmin_deleteIpcSegment(ipc);
+ free(ipc);
+ }
+ hashMapIterator_destroy(iter);
+
+ remoteServiceAdmin_removeSharedIdentityFiles(admin);
+
+ logHelper_stop(admin->loghelper);
+ logHelper_destroy(&admin->loghelper);
+ return status;
+}
+
+static int remoteServiceAdmin_getCount(int semId, int semNr) {
+ int token = -1;
+ unsigned short semVals[3];
+ union semun semArg;
+
+ semArg.array = semVals;
+
+ if (semctl(semId, 0, GETALL, semArg) == 0) {
+ token = semArg.array[semNr];
+ }
+
+ return token;
+}
+
+static celix_status_t remoteServiceAdmin_lock(int semId, int semNr) {
+ celix_status_t status = CELIX_SUCCESS;
+ int semOpStatus = 0;
+ struct sembuf semOperation;
+
+ semOperation.sem_num = semNr;
+ semOperation.sem_op = -1;
+ semOperation.sem_flg = 0;
+
+ do {
+ status = CELIX_SUCCESS;
+
+ if ((semOpStatus = semop(semId, &semOperation, 1)) != 0) {
+ status = CELIX_BUNDLE_EXCEPTION;
+ }
+ } while (semOpStatus == -1 && errno == EINTR);
+
+ return status;
+}
+
+static celix_status_t remoteServiceAdmin_unlock(int semId, int semNr) {
+ celix_status_t status = CELIX_SUCCESS;
+ int semOpStatus = 0;
+ struct sembuf semOperation;
+
+ semOperation.sem_num = semNr;
+ semOperation.sem_op = 1;
+ semOperation.sem_flg = 0;
+
+ do {
+ status = CELIX_SUCCESS;
+
+ if ((semOpStatus = semop(semId, &semOperation, 1)) != 0) {
+ status = CELIX_BUNDLE_EXCEPTION;
+ }
+ } while (semOpStatus == -1 && errno == EINTR);
+
+ return status;
+}
+
+celix_status_t remoteServiceAdmin_send(remote_service_admin_pt admin, endpoint_description_pt recpEndpoint, char *request, char **reply, int *replyStatus) {
+ celix_status_t status = CELIX_SUCCESS;
+ ipc_segment_pt ipc = NULL;
+
+ if ((ipc = hashMap_get(admin->importedIpcSegment, recpEndpoint->service)) != NULL) {
+ int semid = ipc->semId;
+
+ /* lock critical area */
+ remoteServiceAdmin_lock(semid, 0);
+
+ /* write method and data */
+ strcpy(ipc->shmBaseAdress, request);
+
+ /* Check the status of the send-receive semaphore and reset them if not correct */
+ if (remoteServiceAdmin_getCount(ipc->semId, 1) > 0) {
+ semctl(semid, 1, SETVAL, (int) 0);
+ }
+ if (remoteServiceAdmin_getCount(ipc->semId, 2) > 0) {
+ semctl(semid, 2, SETVAL, (int) 0);
+ }
+
+ /* Inform receiver we are invoking the remote service */
+ remoteServiceAdmin_unlock(semid, 1);
+
+ /* Wait until the receiver finished his operations */
+ remoteServiceAdmin_lock(semid, 2);
+
+ /* read reply */
+ *reply = strdup(ipc->shmBaseAdress);
+
+ /* TODO: fix replyStatus */
+ *replyStatus = 0;
+
+ /* release critical area */
+ remoteServiceAdmin_unlock(semid, 0);
+
+ } else {
+ status = CELIX_ILLEGAL_STATE; /* could not find ipc segment */
+ }
+
+ return status;
+}
+
+static void * remoteServiceAdmin_receiveFromSharedMemory(void *data) {
+ recv_shm_thread_pt thread_data = data;
+
+ remote_service_admin_pt admin = thread_data->admin;
+ endpoint_description_pt exportedEndpointDesc = thread_data->endpointDescription;
+
+ ipc_segment_pt ipc;
+
+ if ((ipc = hashMap_get(admin->exportedIpcSegment, exportedEndpointDesc->service)) != NULL) {
+ bool *pollThreadRunning = hashMap_get(admin->pollThreadRunning, exportedEndpointDesc);
+
+ while (*pollThreadRunning == true) {
+ if ((remoteServiceAdmin_lock(ipc->semId, 1) == CELIX_SUCCESS) && (*pollThreadRunning == true)) {
+
+ // TODO: align data size
+ char *data = calloc(1024, sizeof(*data));
+ strcpy(data, ipc->shmBaseAdress);
+
+ hash_map_iterator_pt iter = hashMapIterator_create(admin->exportedServices);
+
+ while (hashMapIterator_hasNext(iter)) {
+ hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
+ array_list_pt exports = hashMapEntry_getValue(entry);
+ int expIt = 0;
+
+ for (expIt = 0; expIt < arrayList_size(exports); expIt++) {
+ export_registration_pt export = arrayList_get(exports, expIt);
+
+ if ((strcmp(exportedEndpointDesc->service, export->endpointDescription->service) == 0) && (export->endpoint != NULL)) {
+ char *reply = NULL;
+
+ /* TODO: fix handling of handleRequest return value*/
+ export->endpoint->handleRequest(export->endpoint->endpoint, data, &reply);
+
+ if (reply != NULL) {
+ if ((strlen(reply) * sizeof(char)) >= RSA_SHM_MEMSIZE) {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "receiveFromSharedMemory : size of message bigger than shared memory message. NOT SENDING.");
+ } else {
+ strcpy(ipc->shmBaseAdress, reply);
+ }
+ free(reply);
+ }
+ } else {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "receiveFromSharedMemory : No endpoint set for %s.", export->endpointDescription->service);
+ }
+ }
+ }
+ hashMapIterator_destroy(iter);
+ free(data);
+
+ remoteServiceAdmin_unlock(ipc->semId, 2);
+
+ }
+ }
+ }
+
+ free(data);
+
+ return NULL;
+}
+
+celix_status_t remoteServiceAdmin_getSharedIdentifierFile(remote_service_admin_pt admin, char *fwUuid, char* servicename, char* outFile) {
+ celix_status_t status = CELIX_SUCCESS;
+ snprintf(outFile, RSA_FILEPATH_LENGTH, "%s/%s/%s", P_tmpdir, fwUuid, servicename);
+
+ if (access(outFile, F_OK) != 0) {
+ char tmpDir[RSA_FILEPATH_LENGTH];
+
+ snprintf(tmpDir, RSA_FILEPATH_LENGTH, "%s/%s", P_tmpdir, fwUuid);
+
+ if(mkdir(tmpDir, 0755) == -1 ){
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "error while creating directory %s (%s)", tmpDir, strerror(errno));
+ }
+ FILE *shid_file = fopen(outFile, "wb");
+ if (shid_file == NULL) {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "error while creating shared identifier file %s (%s)", outFile, strerror(errno));
+ status = CELIX_FILE_IO_EXCEPTION;
+ } else {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_DEBUG, "create shared identifier file %s", outFile);
+ fclose(shid_file);
+ }
+ } else {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_DEBUG, "shared identifier file %s already exists", outFile);
+ }
+
+ return status;
+}
+
+celix_status_t remoteServiceAdmin_removeSharedIdentityFile(remote_service_admin_pt admin, char *fwUuid, char* servicename) {
+ celix_status_t status = CELIX_SUCCESS;
+ char tmpPath[RSA_FILEPATH_LENGTH];
+ int retVal = 0;
+
+ snprintf(tmpPath, RSA_FILEPATH_LENGTH, "%s/%s/%s", P_tmpdir, fwUuid, servicename);
+
+ retVal = unlink(tmpPath);
+
+ if (retVal == 0) {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_DEBUG, "Removed shared identifier file %s", tmpPath);
+ } else {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "Cannot remove shared identifier file %s", tmpPath);
+ status = CELIX_FILE_IO_EXCEPTION;
+ }
+
+ return status;
+}
+
+celix_status_t remoteServiceAdmin_removeSharedIdentityFiles(remote_service_admin_pt admin) {
+ char tmpDir[RSA_FILEPATH_LENGTH];
+ const char* fwUuid = NULL;
+ bundleContext_getProperty(admin->context, OSGI_FRAMEWORK_FRAMEWORK_UUID, &fwUuid);
+
+ snprintf(tmpDir, RSA_FILEPATH_LENGTH, "%s/%s", P_tmpdir, fwUuid);
+
+ DIR *d = opendir(tmpDir);
+ size_t path_len = strlen(tmpDir);
+ int retVal = 0;
+
+ if (d) {
+ struct dirent *p;
+
+ while (!retVal && (p = readdir(d))) {
+ char* f_name;
+ size_t len;
+
+ if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, "..")) {
+ continue;
+ }
+
+ len = path_len + strlen(p->d_name) + 2;
+ f_name = (char*) calloc(len, 1);
+
+ if (f_name) {
+ snprintf(f_name, len, "%s/%s", tmpDir, p->d_name);
+
+ retVal = unlink(f_name);
+
+ if(retVal==0){
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_WARNING, "Removed shared identifier file %s (unproper clean-up?)", f_name);
+ }
+ else{
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_WARNING, "Unable to remove shared identifier file %s ", f_name);
+ }
+
+ }
+ free(f_name);
+ }
+ }
+
+ closedir(d);
+
+ if (!retVal) {
+ rmdir(tmpDir);
+ }
+
+ return retVal;
+}
+
+celix_status_t remoteServiceAdmin_exportService(remote_service_admin_pt admin, char *serviceId, properties_pt properties, array_list_pt *registrations) {
+ celix_status_t status = CELIX_SUCCESS;
+ arrayList_create(registrations);
+
+ array_list_pt references = NULL;
+ service_reference_pt reference = NULL;
+ char filter[256];
+ const char *exportsProp = NULL;
+ const char *providedProp = NULL;
+
+ snprintf(filter, 256, "(%s=%s)", (char *) OSGI_FRAMEWORK_SERVICE_ID, serviceId);
+
+ bundleContext_getServiceReferences(admin->context, NULL, filter, &references);
+
+ if (arrayList_size(references) >= 1) {
+ reference = arrayList_get(references, 0);
+ }
+
+ arrayList_destroy(references);
+
+ serviceReference_getProperty(reference, (char *) OSGI_RSA_SERVICE_EXPORTED_INTERFACES, &exportsProp);
+ serviceReference_getProperty(reference, (char *) OSGI_FRAMEWORK_OBJECTCLASS, &providedProp);
+
+ char* exports = strndup(exportsProp, 1024*10);
+ char* provided = strndup(providedProp, 1024*10);
+
+ if (reference == NULL) {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "expected a reference for service id %s.", serviceId);
+ status = CELIX_ILLEGAL_STATE;
+ }
+ else if (exports == NULL || provided == NULL) {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_WARNING, "No Services to export.");
+ } else {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "Export services (%s)", exports);
+ array_list_pt interfaces = NULL;
+ arrayList_create(&interfaces);
+ if (strcmp(utils_stringTrim(exports), "*") == 0) {
+ char *provided_save_ptr = NULL;
+ char *interface = strtok_r(provided, ",", &provided_save_ptr);
+ while (interface != NULL) {
+ arrayList_add(interfaces, utils_stringTrim(interface));
+ interface = strtok_r(NULL, ",", &provided_save_ptr);
+ }
+ } else {
+ char *provided_save_ptr = NULL;
+ char *pinterface = strtok_r(provided, ",", &provided_save_ptr);
+ while (pinterface != NULL) {
+ char *exports_save_ptr = NULL;
+ char *einterface = strtok_r(exports, ",", &exports_save_ptr);
+ while (einterface != NULL) {
+ if (strcmp(einterface, pinterface) == 0) {
+ arrayList_add(interfaces, einterface);
+ }
+ einterface = strtok_r(NULL, ",", &exports_save_ptr);
+ }
+ pinterface = strtok_r(NULL, ",", &provided_save_ptr);
+ }
+ }
+
+ if (arrayList_size(interfaces) != 0) {
+ int iter = 0;
+ for (iter = 0; iter < arrayList_size(interfaces); iter++) {
+ char *interface = arrayList_get(interfaces, iter);
+ export_registration_pt registration = NULL;
+
+ exportRegistration_create(admin->loghelper, reference, NULL, admin, admin->context, ®istration);
+ arrayList_add(*registrations, registration);
+
+ remoteServiceAdmin_installEndpoint(admin, registration, reference, interface);
+ exportRegistration_open(registration);
+ exportRegistration_startTracking(registration);
+
+ if (remoteServiceAdmin_createOrAttachShm(admin->exportedIpcSegment, admin, registration->endpointDescription, true) == CELIX_SUCCESS) {
+ recv_shm_thread_pt recvThreadData = NULL;
+
+ if ((recvThreadData = calloc(1, sizeof(*recvThreadData))) == NULL) {
+ status = CELIX_ENOMEM;
+ } else {
+ recvThreadData->admin = admin;
+ recvThreadData->endpointDescription = registration->endpointDescription;
+
+ celix_thread_t* pollThread = calloc(1, sizeof(*pollThread));
+ bool *pollThreadRunningPtr = calloc(1, sizeof(*pollThreadRunningPtr));
+ *pollThreadRunningPtr = true;
+
+ hashMap_put(admin->pollThreadRunning, registration->endpointDescription, pollThreadRunningPtr);
+
+ // start receiving thread
+ status = celixThread_create(pollThread, NULL, remoteServiceAdmin_receiveFromSharedMemory, recvThreadData);
+
+ hashMap_put(admin->pollThread, registration->endpointDescription, pollThread);
+ }
+ }
+ }
+
+ celixThreadMutex_lock(&admin->exportedServicesLock);
+ hashMap_put(admin->exportedServices, reference, *registrations);
+ celixThreadMutex_unlock(&admin->exportedServicesLock);
+
+ }
+ arrayList_destroy(interfaces);
+ }
+
+ free(exports);
+ free(provided);
+
+ return status;
+}
+
+celix_status_t remoteServiceAdmin_removeExportedService(remote_service_admin_pt admin, export_registration_pt registration) {
+ celix_status_t status;
+ ipc_segment_pt ipc = NULL;
+
+ export_reference_pt ref = NULL;
+ status = exportRegistration_getExportReference(registration, &ref);
+
+ if (status == CELIX_SUCCESS) {
+ bool *pollThreadRunning = NULL;
+
+ service_reference_pt servRef;
+ celixThreadMutex_lock(&admin->exportedServicesLock);
+ exportReference_getExportedService(ref, &servRef);
+
+ array_list_pt exports = (array_list_pt)hashMap_remove(admin->exportedServices, servRef);
+ if(exports!=NULL){
+ arrayList_destroy(exports);
+ }
+
+ exportRegistration_close(registration);
+
+ if ((pollThreadRunning = hashMap_get(admin->pollThreadRunning, registration->endpointDescription)) != NULL) {
+ *pollThreadRunning = false;
+
+ if ((ipc = hashMap_get(admin->exportedIpcSegment, registration->endpointDescription->service)) != NULL) {
+ celix_thread_t* pollThread;
+
+ remoteServiceAdmin_unlock(ipc->semId, 1);
+
+ if ((pollThread = hashMap_get(admin->pollThread, registration->endpointDescription)) != NULL) {
+ status = celixThread_join(*pollThread, NULL);
+
+ if (status == CELIX_SUCCESS) {
+ semctl(ipc->semId, 1 , IPC_RMID);
+ shmctl(ipc->shmId, IPC_RMID, 0);
+
+ remoteServiceAdmin_removeSharedIdentityFile(admin, registration->endpointDescription->frameworkUUID, registration->endpointDescription->service);
+
+ hashMap_remove(admin->pollThreadRunning, registration->endpointDescription);
+ hashMap_remove(admin->exportedIpcSegment, registration->endpointDescription->service);
+ hashMap_remove(admin->pollThread, registration->endpointDescription);
+
+ free(pollThreadRunning);
+ free(pollThread);
+ free(ipc);
+ }
+ }
+ }
+ }
+ exportRegistration_destroy(®istration);
+ }
+
+ if(ref!=NULL){
+ free(ref);
+ }
+
+ celixThreadMutex_unlock(&admin->exportedServicesLock);
+
+ return status;
+}
+
+celix_status_t remoteServiceAdmin_getIpcSegment(remote_service_admin_pt admin, endpoint_description_pt endpointDescription, ipc_segment_pt* ipc) {
+ (*ipc) = (hashMap_containsKey(admin->importedIpcSegment, endpointDescription) == true) ? hashMap_get(admin->importedIpcSegment, endpointDescription) : NULL;
+
+ return (*ipc != NULL) ? CELIX_SUCCESS : CELIX_ILLEGAL_ARGUMENT;
+}
+
+celix_status_t remoteServiceAdmin_detachIpcSegment(ipc_segment_pt ipc) {
+ return (shmdt(ipc->shmBaseAdress) != -1) ? CELIX_SUCCESS : CELIX_BUNDLE_EXCEPTION;
+}
+
+celix_status_t remoteServiceAdmin_deleteIpcSegment(ipc_segment_pt ipc) {
+ return ((semctl(ipc->semId, 1 /*ignored*/, IPC_RMID) != -1) && (shmctl(ipc->shmId, IPC_RMID, 0) != -1)) ? CELIX_SUCCESS : CELIX_BUNDLE_EXCEPTION;
+}
+
+celix_status_t remoteServiceAdmin_createOrAttachShm(hash_map_pt ipcSegment, remote_service_admin_pt admin, endpoint_description_pt endpointDescription, bool createIfNotFound) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ /* setup ipc sehment */
+ ipc_segment_pt ipc = NULL;
+
+ properties_pt endpointProperties = endpointDescription->properties;
+
+ char *shmPath = NULL;
+ char *shmFtokId = NULL;
+
+ char *semPath = NULL;
+ char *semFtokId = NULL;
+
+ if ((shmPath = (char*)properties_get(endpointProperties, (char *) RSA_SHM_PATH_PROPERTYNAME)) == NULL) {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_DEBUG, "No value found for key %s in endpointProperties.", RSA_SHM_PATH_PROPERTYNAME);
+ status = CELIX_BUNDLE_EXCEPTION;
+ } else if ((shmFtokId = (char*)properties_get(endpointProperties, (char *) RSA_SHM_FTOK_ID_PROPERTYNAME)) == NULL) {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_DEBUG, "No value found for key %s in endpointProperties.", RSA_SHM_FTOK_ID_PROPERTYNAME);
+ status = CELIX_BUNDLE_EXCEPTION;
+ } else if ((semPath = (char*)properties_get(endpointProperties, (char *) RSA_SEM_PATH_PROPERTYNAME)) == NULL) {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_DEBUG, "No value found for key %s in endpointProperties.", RSA_SEM_PATH_PROPERTYNAME);
+ status = CELIX_BUNDLE_EXCEPTION;
+ } else if ((semFtokId = (char*)properties_get(endpointProperties, (char *) RSA_SEM_FTOK_ID_PROPERTYNAME)) == NULL) {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_DEBUG, "No value found for key %s in endpointProperties.", RSA_SEM_FTOK_ID_PROPERTYNAME);
+ status = CELIX_BUNDLE_EXCEPTION;
+ } else {
+ key_t shmKey = ftok(shmPath, atoi(shmFtokId));
+ ipc = calloc(1, sizeof(*ipc));
+ if(ipc == NULL){
+ return CELIX_ENOMEM;
+ }
+
+ if ((ipc->shmId = shmget(shmKey, RSA_SHM_MEMSIZE, 0666)) < 0) {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_WARNING, "Could not attach to shared memory");
+
+ if (createIfNotFound == true) {
+ if ((ipc->shmId = shmget(shmKey, RSA_SHM_MEMSIZE, IPC_CREAT | 0666)) < 0) {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "Creation of shared memory segment failed.");
+ status = CELIX_BUNDLE_EXCEPTION;
+ } else if ((ipc->shmBaseAdress = shmat(ipc->shmId, 0, 0)) == (char *) -1) {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "Attaching of shared memory segment failed.");
+ status = CELIX_BUNDLE_EXCEPTION;
+ } else {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "shared memory segment sucessfully created at %p.", ipc->shmBaseAdress);
+ }
+ }
+ } else if ((ipc->shmBaseAdress = shmat(ipc->shmId, 0, 0)) == (char *) -1) {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "Attaching to shared memory segment failed.");
+ status = CELIX_BUNDLE_EXCEPTION;
+ } else {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "sucessfully attached to shared memory at %p.", ipc->shmBaseAdress);
+ }
+ }
+
+ if(ipc != NULL && status == CELIX_SUCCESS){
+
+ key_t semkey = ftok(semPath, atoi(semFtokId));
+ int semflg = (createIfNotFound == true) ? (0666 | IPC_CREAT) : (0666);
+ int semid = semget(semkey, 3, semflg);
+
+ if (semid != -1) {
+ // only reset semaphores if a create was supposed
+ if ((createIfNotFound == true) && ((semctl(semid, 0, SETVAL, (int) 1) == -1) || (semctl(semid, 1, SETVAL, (int) 0) == -1) || (semctl(semid, 2, SETVAL, (int) 0) == -1))) {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "error while initialize semaphores.");
+ }
+
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_DEBUG, "semaphores w/ key %s and id %i added.", endpointDescription->service, semid);
+ ipc->semId = semid;
+
+ hashMap_put(ipcSegment, endpointDescription->service, ipc);
+ } else {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "error getting semaphores.");
+ status = CELIX_BUNDLE_EXCEPTION;
+ }
+ }
+
+ if(ipc != NULL && status != CELIX_SUCCESS){
+ free(ipc);
+ }
+
+ return status;
+}
+
+celix_status_t remoteServiceAdmin_installEndpoint(remote_service_admin_pt admin, export_registration_pt registration, service_reference_pt reference, char *interface) {
+ celix_status_t status = CELIX_SUCCESS;
+ properties_pt endpointProperties = properties_create();
+
+ unsigned int size = 0;
+ char **keys;
+
+ serviceReference_getPropertyKeys(reference, &keys, &size);
+ for (int i = 0; i < size; i++) {
+ char *key = keys[i];
+ const char *value = NULL;
+
+ if (serviceReference_getProperty(reference, key, &value) == CELIX_SUCCESS && strcmp(key, (char*) OSGI_RSA_SERVICE_EXPORTED_INTERFACES) != 0 && strcmp(key, (char*) OSGI_FRAMEWORK_OBJECTCLASS) != 0) {
+ properties_set(endpointProperties, key, value);
+ }
+ }
+
+ hash_map_entry_pt entry = hashMap_getEntry(endpointProperties, (void *) OSGI_FRAMEWORK_SERVICE_ID);
+
+ char* key = hashMapEntry_getKey(entry);
+ char *serviceId = (char *) hashMap_remove(endpointProperties, (void *) OSGI_FRAMEWORK_SERVICE_ID);
+ const char *uuid = NULL;
+
+ uuid_t endpoint_uid;
+ uuid_generate(endpoint_uid);
+ char endpoint_uuid[37];
+ uuid_unparse_lower(endpoint_uid, endpoint_uuid);
+
+ bundleContext_getProperty(admin->context, OSGI_FRAMEWORK_FRAMEWORK_UUID, &uuid);
+ properties_set(endpointProperties, (char*) OSGI_RSA_ENDPOINT_FRAMEWORK_UUID, uuid);
+ properties_set(endpointProperties, (char*) OSGI_FRAMEWORK_OBJECTCLASS, interface);
+ properties_set(endpointProperties, (char*) OSGI_RSA_ENDPOINT_SERVICE_ID, serviceId);
+ properties_set(endpointProperties, (char*) OSGI_RSA_ENDPOINT_ID, endpoint_uuid);
+ properties_set(endpointProperties, (char*) OSGI_RSA_SERVICE_IMPORTED, "true");
+ // properties_set(endpointProperties, (char*) OSGI_RSA_SERVICE_IMPORTED_CONFIGS, (char*) CONFIGURATION_TYPE);
+
+ if (properties_get(endpointProperties, (char *) RSA_SHM_PATH_PROPERTYNAME) == NULL) {
+ char sharedIdentifierFile[RSA_FILEPATH_LENGTH];
+
+ if (remoteServiceAdmin_getSharedIdentifierFile(admin, (char*)uuid, interface, sharedIdentifierFile) == CELIX_SUCCESS) {
+ properties_set(endpointProperties, RSA_SHM_PATH_PROPERTYNAME, sharedIdentifierFile);
+ } else {
+ properties_set(endpointProperties, (char *) RSA_SHM_PATH_PROPERTYNAME, (char *) RSA_SHM_DEFAULTPATH);
+ }
+ }
+ if (properties_get(endpointProperties, (char *) RSA_SHM_FTOK_ID_PROPERTYNAME) == NULL) {
+ properties_set(endpointProperties, (char *) RSA_SHM_FTOK_ID_PROPERTYNAME, (char *) RSA_SHM_DEFAULT_FTOK_ID);
+ }
+ if (properties_get(endpointProperties, (char *) RSA_SEM_PATH_PROPERTYNAME) == NULL) {
+ char sharedIdentifierFile[RSA_FILEPATH_LENGTH];
+
+ if (remoteServiceAdmin_getSharedIdentifierFile(admin, (char*)uuid, interface, sharedIdentifierFile) == CELIX_SUCCESS) {
+ properties_set(endpointProperties, (char *) RSA_SEM_PATH_PROPERTYNAME, sharedIdentifierFile);
+ } else {
+ properties_set(endpointProperties, (char *) RSA_SEM_PATH_PROPERTYNAME, (char *) RSA_SEM_DEFAULTPATH);
+ }
+ }
+ if (properties_get(endpointProperties, (char *) RSA_SEM_FTOK_ID_PROPERTYNAME) == NULL) {
+ properties_set(endpointProperties, (char *) RSA_SEM_FTOK_ID_PROPERTYNAME, (char *) RSA_SEM_DEFAULT_FTOK_ID);
+ }
+
+ endpoint_description_pt endpointDescription = NULL;
+ remoteServiceAdmin_createEndpointDescription(admin, reference, endpointProperties, interface, &endpointDescription);
+ exportRegistration_setEndpointDescription(registration, endpointDescription);
+
+ free(key);
+ free(serviceId);
+ free(keys);
+
+ return status;
+}
+
+celix_status_t remoteServiceAdmin_createEndpointDescription(remote_service_admin_pt admin, service_reference_pt reference, properties_pt endpointProperties, char *interface, endpoint_description_pt *description) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ *description = calloc(1, sizeof(**description));
+ if (!*description) {
+ status = CELIX_ENOMEM;
+ } else {
+ if (status == CELIX_SUCCESS) {
+ (*description)->properties = endpointProperties;
+ (*description)->frameworkUUID = (char*)properties_get(endpointProperties, (char*) OSGI_RSA_ENDPOINT_FRAMEWORK_UUID);
+ const char *serviceId = NULL;
+ serviceReference_getProperty(reference, (char*)OSGI_FRAMEWORK_SERVICE_ID, &serviceId);
+ (*description)->serviceId = strtoull(serviceId, NULL, 0);
+ (*description)->id = (char*)properties_get(endpointProperties, (char*) OSGI_RSA_ENDPOINT_ID);
+ (*description)->service = strndup(interface, 1024*10);
+ }
+ }
+
+ return status;
+}
+
+celix_status_t remoteServiceAdmin_destroyEndpointDescription(endpoint_description_pt *description) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ properties_destroy((*description)->properties);
+ free((*description)->service);
+ free(*description);
+
+ return status;
+}
+
+celix_status_t remoteServiceAdmin_getExportedServices(remote_service_admin_pt admin, array_list_pt *services) {
+ celix_status_t status = CELIX_SUCCESS;
+ return status;
+}
+
+celix_status_t remoteServiceAdmin_getImportedEndpoints(remote_service_admin_pt admin, array_list_pt *services) {
+ celix_status_t status = CELIX_SUCCESS;
+ return status;
+}
+
+celix_status_t remoteServiceAdmin_importService(remote_service_admin_pt admin, endpoint_description_pt endpointDescription, import_registration_pt *registration) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "RSA: Import service %s", endpointDescription->service);
+
+ celixThreadMutex_lock(&admin->importedServicesLock);
+
+ import_registration_factory_pt registration_factory = (import_registration_factory_pt) hashMap_get(admin->importedServices, endpointDescription->service);
+
+ // check whether we already have a registration_factory registered in the hashmap
+ if (registration_factory == NULL) {
+ status = importRegistrationFactory_install(admin->loghelper, endpointDescription->service, admin->context, ®istration_factory);
+ if (status == CELIX_SUCCESS) {
+ hashMap_put(admin->importedServices, endpointDescription->service, registration_factory);
+ }
+ }
+
+ // factory available
+ if (status != CELIX_SUCCESS || (registration_factory->trackedFactory == NULL)) {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_WARNING, "RSA: no proxyFactory available.");
+ if (status == CELIX_SUCCESS) {
+ status = CELIX_SERVICE_EXCEPTION;
+ }
+ } else {
+ // we create an importRegistration per imported service
+ importRegistration_create(endpointDescription, admin, (sendToHandle) &remoteServiceAdmin_send, admin->context, registration);
+ registration_factory->trackedFactory->registerProxyService(registration_factory->trackedFactory->factory, endpointDescription, admin, (sendToHandle) &remoteServiceAdmin_send);
+
+ arrayList_add(registration_factory->registrations, *registration);
+ remoteServiceAdmin_createOrAttachShm(admin->importedIpcSegment, admin, endpointDescription, false);
+ }
+
+ celixThreadMutex_unlock(&admin->importedServicesLock);
+
+ return status;
+}
+
+celix_status_t remoteServiceAdmin_removeImportedService(remote_service_admin_pt admin, import_registration_pt registration) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ if (registration != NULL) {
+
+ celixThreadMutex_lock(&admin->importedServicesLock);
+
+ ipc_segment_pt ipc = NULL;
+ endpoint_description_pt endpointDescription = (endpoint_description_pt) registration->endpointDescription;
+ import_registration_factory_pt registration_factory = (import_registration_factory_pt) hashMap_get(admin->importedServices, endpointDescription->service);
+
+ // detach from IPC
+ if (remoteServiceAdmin_getIpcSegment(admin, endpointDescription, &ipc) != CELIX_SUCCESS) {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "Error while retrieving IPC segment for imported service %s.", endpointDescription->service);
+ } else if (remoteServiceAdmin_detachIpcSegment(ipc) != CELIX_SUCCESS) {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "Error while detaching IPC segment for imported service %s.", endpointDescription->service);
+ }
+
+ ipc = hashMap_remove(admin->importedIpcSegment,endpointDescription);
+ if(ipc!=NULL){
+ free(ipc);
+ }
+
+ // factory available
+ if ((registration_factory == NULL) || (registration_factory->trackedFactory == NULL)) {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "Error while retrieving registration factory for imported service %s.", endpointDescription->service);
+ } else {
+ registration_factory->trackedFactory->unregisterProxyService(registration_factory->trackedFactory->factory, endpointDescription);
+ arrayList_removeElement(registration_factory->registrations, registration);
+ importRegistration_destroy(registration);
+
+ if (arrayList_isEmpty(registration_factory->registrations) == true) {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "closing proxy");
+
+ serviceTracker_close(registration_factory->proxyFactoryTracker);
+ importRegistrationFactory_close(registration_factory);
+
+ hashMap_remove(admin->importedServices, endpointDescription->service);
+
+ importRegistrationFactory_destroy(®istration_factory);
+ }
+ }
+
+ celixThreadMutex_unlock(&admin->importedServicesLock);
+ }
+
+ return status;
+}
http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/remote_service_admin_shm/private/test/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/bundles/remote_services/remote_service_admin_shm/private/test/CMakeLists.txt b/bundles/remote_services/remote_service_admin_shm/private/test/CMakeLists.txt
new file mode 100644
index 0000000..5e32643
--- /dev/null
+++ b/bundles/remote_services/remote_service_admin_shm/private/test/CMakeLists.txt
@@ -0,0 +1,58 @@
+# 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_directories(
+ ${PROJECT_SOURCE_DIR}/framework/public/include
+ ${PROJECT_SOURCE_DIR}/utils/public/include
+ ${PROJECT_SOURCE_DIR}/utils/public/include
+ ${PROJECT_SOURCE_DIR}/remote_services/remote_service_admin/public/include
+ ${PROJECT_SOURCE_DIR}/remote_services/examples/calculator_service/public/include
+ bundle
+)
+
+
+SET(CMAKE_SKIP_BUILD_RPATH FALSE) #TODO needed?
+SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) #TODO needed?
+SET(CMAKE_INSTALL_RPATH "${PROJECT_BINARY_DIR}/framework" "${PROJECT_BINARY_DIR}/utils")
+
+add_executable(test_rsa_shm
+ run_tests.cpp
+ rsa_client_server_tests.cpp
+
+ ${PROJECT_SOURCE_DIR}/remote_services/remote_service_admin/private/src/endpoint_description.c
+)
+target_link_libraries(test_rsa_shm celix_framework celix_utils ${CURL_LIBRARIES} ${CPPUTEST_LIBRARY})
+
+get_property(rsa_bundle_file TARGET remote_service_admin_shm PROPERTY BUNDLE_FILE)
+get_property(calc_bundle_file TARGET calculator PROPERTY BUNDLE_FILE)
+get_property(calculator_shell_bundle_file TARGET calculator_shell PROPERTY BUNDLE_FILE)
+get_property(discovery_shm_bundle_file TARGET discovery_shm PROPERTY BUNDLE_FILE)
+get_property(topology_manager_bundle_file TARGET topology_manager PROPERTY BUNDLE_FILE)
+get_property(calc_proxy_bundle_file TARGET org.apache.celix.calc.api.Calculator_proxy PROPERTY BUNDLE_FILE)
+get_property(calc_endpoint_bundle_file TARGET org.apache.celix.calc.api.Calculator_endpoint PROPERTY BUNDLE_FILE)
+
+get_filename_component(client_endpoints ${calc_proxy_bundle_file} PATH)
+get_filename_component(server_endpoints ${calc_endpoint_bundle_file} PATH)
+
+configure_file(client.properties.in client.properties)
+configure_file(server.properties.in server.properties)
+
+add_dependencies(test_rsa_shm remote_service_admin_shm calculator org.apache.celix.calc.api.Calculator_proxy org.apache.celix.calc.api.Calculator_endpoint)
+
+#add_test(NAME run_test_rsa_shm COMMAND test_rsa_shm)
+#SETUP_TARGET_FOR_COVERAGE(test_rsa_shm_cov test_rsa_shm ${CMAKE_BINARY_DIR}/coverage/test_rsa_shm/test_rsa_shm)
+
http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/remote_service_admin_shm/private/test/client.properties.in
----------------------------------------------------------------------
diff --git a/bundles/remote_services/remote_service_admin_shm/private/test/client.properties.in b/bundles/remote_services/remote_service_admin_shm/private/test/client.properties.in
new file mode 100644
index 0000000..d4eb239
--- /dev/null
+++ b/bundles/remote_services/remote_service_admin_shm/private/test/client.properties.in
@@ -0,0 +1,25 @@
+# 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.
+
+cosgi.auto.start.1=${rsa_bundle_file} ${calculator_shell_bundle_file} ${discovery_shm_bundle_file} ${topology_manager_bundle_file} ${tst_bundle_file}
+LOGHELPER_ENABLE_STDOUT_FALLBACK=true
+ENDPOINTS=@client_endpoints@
+RSA_PORT=50881
+DISCOVERY_CFG_SERVER_PORT=50993
+org.osgi.framework.storage.clean=onFirstInit
+org.osgi.framework.storage=.cacheClient
+DISCOVERY_CFG_POLL_INTERVAL=1
http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/remote_service_admin_shm/private/test/rsa_client_server_tests.cpp
----------------------------------------------------------------------
diff --git a/bundles/remote_services/remote_service_admin_shm/private/test/rsa_client_server_tests.cpp b/bundles/remote_services/remote_service_admin_shm/private/test/rsa_client_server_tests.cpp
new file mode 100644
index 0000000..13c6941
--- /dev/null
+++ b/bundles/remote_services/remote_service_admin_shm/private/test/rsa_client_server_tests.cpp
@@ -0,0 +1,496 @@
+/**
+ *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 <CppUTest/TestHarness.h>
+#include <remote_constants.h>
+#include <constants.h>
+#include "CppUTest/CommandLineTestRunner.h"
+#include "../../../examples/calculator_service/public/include/calculator_service.h"
+
+extern "C" {
+
+ #include <stdio.h>
+ #include <stdint.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <ctype.h>
+ #include <unistd.h>
+
+ #include "celix_launcher.h"
+ #include "framework.h"
+ #include "remote_service_admin.h"
+ #include "calculator_service.h"
+ #include "bundle.h"
+
+ #define DISCOVERY_CFG_NAME "apache_celix_rsa_discovery_shm"
+ #define RSA_HTTP_NAME "apache_celix_remote_service_admin_shm"
+ #define TOPOLOGY_MANAGER_NAME "apache_celix_rs_topology_manager"
+ #define CALCULATOR_PROXY "apache_celix_remoting_calculator_proxy"
+ #define CALCULATOR_ENDPOINT "apache_celix_remoting_calculator_endpoint"
+
+ static framework_pt serverFramework = NULL;
+ static bundle_context_pt serverContext = NULL;
+
+ static framework_pt clientFramework = NULL;
+ static bundle_context_pt clientContext = NULL;
+
+ static void setupFm(void) {
+ int rc = 0;
+ bundle_pt bundle = NULL;
+
+ //server
+ rc = celixLauncher_launch("server.properties", &serverFramework);
+ CHECK_EQUAL(CELIX_SUCCESS, rc);
+
+ bundle = NULL;
+ rc = framework_getFrameworkBundle(serverFramework, &bundle);
+ CHECK_EQUAL(CELIX_SUCCESS, rc);
+
+ rc = bundle_getContext(bundle, &serverContext);
+ CHECK_EQUAL(CELIX_SUCCESS, rc);
+
+ //client
+ rc = celixLauncher_launch("client.properties", &clientFramework);
+ CHECK_EQUAL(CELIX_SUCCESS, rc);
+
+ bundle = NULL;
+ rc = framework_getFrameworkBundle(clientFramework, &bundle);
+ CHECK_EQUAL(CELIX_SUCCESS, rc);
+
+ rc = bundle_getContext(bundle, &clientContext);
+ CHECK_EQUAL(CELIX_SUCCESS, rc);
+ }
+
+ static void teardownFm(void) {
+ celixLauncher_stop(serverFramework);
+ celixLauncher_waitForShutdown(serverFramework);
+ celixLauncher_destroy(serverFramework);
+
+ celixLauncher_stop(clientFramework);
+ celixLauncher_waitForShutdown(clientFramework);
+ celixLauncher_destroy(clientFramework);
+
+ serverContext = NULL;
+ serverFramework = NULL;
+ clientContext = NULL;
+ clientFramework = NULL;
+ }
+
+ static void test1(void) {
+ celix_status_t status;
+ service_reference_pt ref = NULL;
+ calculator_service_pt calcService = NULL;
+ int retries = 6;
+
+ while (ref == NULL && retries > 0) {
+ printf("Waiting for service .. %d\n", retries);
+ status = bundleContext_getServiceReference(clientContext, (char *) CALCULATOR_SERVICE, &ref);
+ usleep(1000000);
+ --retries;
+ }
+
+
+ CHECK_EQUAL(CELIX_SUCCESS, status);
+ CHECK(ref != NULL);
+
+ status = bundleContext_getService(clientContext, ref, (void **) &calcService);
+ CHECK_EQUAL(CELIX_SUCCESS, status);
+ CHECK(calcService != NULL);
+
+ double result = 0;
+ status = calcService->add(calcService->calculator, 2.0, 5.0, &result);
+ CHECK_EQUAL(CELIX_SUCCESS, status);
+ CHECK_EQUAL(7.0, result);
+
+ bundleContext_ungetService(clientContext, ref, NULL);
+ bundleContext_ungetServiceReference(clientContext, ref);
+ }
+
+
+ static celix_status_t getPermutations(array_list_pt bundleIds, int from, int to, array_list_pt permutations) {
+ celix_status_t status = CELIX_SUCCESS;
+ int i = 0;
+
+ if (from == to) {
+ long* permutation = (long*) calloc(to + 1, sizeof(*permutation));
+
+ if (!permutation) {
+ status = CELIX_ENOMEM;
+ } else {
+ for (; i <= to; i++) {
+ permutation[i] = (long) arrayList_get(bundleIds, i);
+ }
+
+ arrayList_add(permutations, permutation);
+ }
+ } else {
+ for (i = from; i <= to; i++) {
+ long fromOrg = (long) arrayList_get(bundleIds, from);
+ long iOrg = (long) arrayList_get(bundleIds, i);
+
+ arrayList_set(bundleIds, from, (void*) iOrg);
+ arrayList_set(bundleIds, i, (void*) fromOrg);
+
+ status = getPermutations(bundleIds, from + 1, to, permutations);
+
+ arrayList_set(bundleIds, from, (void*) fromOrg);
+ arrayList_set(bundleIds, i, (void*) iOrg);
+ }
+ }
+
+ return status;
+ }
+
+ static celix_status_t getSpecifiedBundles(bundle_context_pt context, array_list_pt bundleNames, array_list_pt retrievedBundles) {
+ celix_status_t status;
+ array_list_pt bundles = NULL;
+
+ status = bundleContext_getBundles(context, &bundles);
+
+ if (status == CELIX_SUCCESS) {
+ unsigned int size = arrayList_size(bundles);
+ unsigned int i;
+
+ for (i = 0; i < size; i++) {
+ module_pt module = NULL;
+ const char *name = NULL;
+
+ bundle_pt bundle = (bundle_pt) arrayList_get(bundles, i);
+
+ status = bundle_getCurrentModule(bundle, &module);
+
+ if (status == CELIX_SUCCESS) {
+ status = module_getSymbolicName(module, &name);
+ }
+
+ if (status == CELIX_SUCCESS) {
+ array_list_iterator_pt iter = arrayListIterator_create(bundleNames);
+
+ while(arrayListIterator_hasNext(iter)) {
+ char* bundleName = (char*) arrayListIterator_next(iter);
+
+ if ((strcmp(name, bundleName) == 0)) {
+
+ bundle_archive_pt bundleArchive = NULL;
+ long bundleId = -1;
+
+ status = bundle_getArchive(bundle, &bundleArchive);
+
+ if (status == CELIX_SUCCESS) {
+ status = bundleArchive_getId(bundleArchive, &bundleId);
+ }
+
+ if (status == CELIX_SUCCESS) {
+ arrayList_add(retrievedBundles, (void*) bundleId);
+ break;
+ }
+ }
+ }
+
+ arrayListIterator_destroy(iter);
+
+ }
+ }
+
+ arrayList_destroy(bundles);
+ }
+
+ return status;
+ }
+
+ static celix_status_t stopStartPermutation(bundle_context_pt context, long* permutation, int size) {
+ celix_status_t status = CELIX_SUCCESS;
+ int y = 0;
+
+ printf("Test stop/start permutation: ");
+
+ for (y = 0; (y < size) && (status == CELIX_SUCCESS); y++) {
+ bundle_pt bundle = NULL;
+
+ status = bundleContext_getBundleById(context, permutation[y], &bundle);
+
+ if (status == CELIX_SUCCESS) {
+ module_pt module = NULL;
+ const char *name = NULL;
+
+ status = bundle_getCurrentModule(bundle, &module);
+
+ if (status == CELIX_SUCCESS) {
+ status = module_getSymbolicName(module, &name);
+ printf("%s (%ld) ", name, permutation[y]);
+ }
+ }
+ }
+ printf("\n");
+
+ // stop all bundles
+ if (status == CELIX_SUCCESS) {
+ for (y = 0; (y < size) && (status == CELIX_SUCCESS); y++) {
+ bundle_pt bundle = NULL;
+
+ status = bundleContext_getBundleById(context, permutation[y], &bundle);
+
+ if (status == CELIX_SUCCESS) {
+ printf("stop bundle: %ld\n", permutation[y]);
+ status = bundle_stop(bundle);
+ }
+ }
+ }
+
+ // verify stop state
+ if (status == CELIX_SUCCESS) {
+ for (y = 0; (y < size) && (status == CELIX_SUCCESS); y++) {
+ bundle_pt bundle = NULL;
+
+ status = bundleContext_getBundleById(context, permutation[y], &bundle);
+
+ if (status == CELIX_SUCCESS) {
+ bundle_state_e state;
+ status = bundle_getState(bundle, &state);
+
+ if (state != OSGI_FRAMEWORK_BUNDLE_RESOLVED) {
+ printf("bundle %ld has state %d (should be %d) \n", permutation[y], state, OSGI_FRAMEWORK_BUNDLE_RESOLVED);
+ status = CELIX_ILLEGAL_STATE;
+ }
+ }
+ }
+ }
+
+ // start all bundles
+ if (status == CELIX_SUCCESS) {
+
+ for (y = 0; (y < size) && (status == CELIX_SUCCESS); y++) {
+ bundle_pt bundle = NULL;
+
+ status = bundleContext_getBundleById(context, permutation[y], &bundle);
+
+ if (status == CELIX_SUCCESS) {
+ printf("start bundle: %ld\n", permutation[y]);
+ status = bundle_start(bundle);
+ }
+ }
+ }
+
+ // verify started state
+ if (status == CELIX_SUCCESS) {
+ for (y = 0; (y < size) && (status == CELIX_SUCCESS); y++) {
+ bundle_pt bundle = NULL;
+
+ status = bundleContext_getBundleById(context, permutation[y], &bundle);
+
+ if (status == CELIX_SUCCESS) {
+ bundle_state_e state;
+ status = bundle_getState(bundle, &state);
+
+ if (state != OSGI_FRAMEWORK_BUNDLE_ACTIVE) {
+ printf("bundle %ld has state %d (should be %d) \n", permutation[y], state, OSGI_FRAMEWORK_BUNDLE_ACTIVE);
+ status = CELIX_ILLEGAL_STATE;
+ }
+ }
+ }
+ }
+
+ return status;
+ }
+
+ static void testImport(void) {
+ celix_status_t status;
+ array_list_pt bundleNames = NULL;
+ array_list_pt bundlePermutations = NULL;
+ array_list_pt rsaBundles = NULL;
+ unsigned int i, size;
+
+ arrayList_create(&bundleNames);
+ arrayList_create(&bundlePermutations);
+ arrayList_create(&rsaBundles);
+
+ arrayList_add(bundleNames, (void*) DISCOVERY_CFG_NAME);
+ arrayList_add(bundleNames, (void*) RSA_HTTP_NAME);
+ arrayList_add(bundleNames, (void*) TOPOLOGY_MANAGER_NAME);
+
+ status = getSpecifiedBundles(clientContext, bundleNames, rsaBundles);
+ CHECK_EQUAL(CELIX_SUCCESS, status);
+ CHECK_EQUAL(arrayList_size(rsaBundles), arrayList_size(bundleNames));
+
+ status = getPermutations(rsaBundles, 0, arrayList_size(rsaBundles) - 1, bundlePermutations);
+ CHECK_EQUAL(CELIX_SUCCESS, status);
+
+ size = arrayList_size(bundlePermutations);
+
+ for (i = 0; i < size; ++i) {
+ long* singlePermutation = (long*) arrayList_get(bundlePermutations, i);
+
+ status = stopStartPermutation(clientContext, singlePermutation, arrayList_size(rsaBundles));
+ CHECK_EQUAL(CELIX_SUCCESS, status);
+
+ // check whether calc service is available
+ test1();
+
+ free(singlePermutation);
+ }
+
+ arrayList_destroy(bundlePermutations);
+ arrayList_destroy(bundleNames);
+ arrayList_destroy(rsaBundles);
+ }
+
+ static void testExport(void) {
+ celix_status_t status;
+ array_list_pt bundleNames = NULL;
+ array_list_pt bundlePermutations = NULL;
+ array_list_pt rsaBundles = NULL;
+
+ unsigned int i, size;
+
+ arrayList_create(&bundleNames);
+ arrayList_create(&bundlePermutations);
+ arrayList_create(&rsaBundles);
+
+ arrayList_add(bundleNames, (void*) DISCOVERY_CFG_NAME);
+ arrayList_add(bundleNames, (void*) RSA_HTTP_NAME);
+ arrayList_add(bundleNames, (void*) TOPOLOGY_MANAGER_NAME);
+
+ status = getSpecifiedBundles(serverContext, bundleNames, rsaBundles);
+ CHECK_EQUAL(CELIX_SUCCESS, status);
+ CHECK_EQUAL(arrayList_size(rsaBundles), arrayList_size(bundleNames));
+
+ status = getPermutations(rsaBundles, 0, arrayList_size(rsaBundles) - 1, bundlePermutations);
+ CHECK_EQUAL(CELIX_SUCCESS, status);
+
+ size = arrayList_size(bundlePermutations);
+
+ for (i = 0; i < size; ++i) {
+ long* singlePermutation = (long*) arrayList_get(bundlePermutations, i);
+
+ status = stopStartPermutation(serverContext, singlePermutation, arrayList_size(rsaBundles));
+ CHECK_EQUAL(CELIX_SUCCESS, status);
+
+ /* we need to sleep here for a bit to ensure
+ * that the client has flushed the old discovery
+ * values
+ */
+ sleep(2);
+
+ // check whether calc service is available
+ test1();
+
+ free(singlePermutation);
+ }
+
+ arrayList_destroy(bundlePermutations);
+ arrayList_destroy(bundleNames);
+ arrayList_destroy(rsaBundles);
+ }
+
+ /*
+ static void testProxyRemoval(void) {
+ celix_status_t status;
+ bundle_pt bundle = NULL;
+ array_list_pt bundleNames = NULL;
+ array_list_pt proxyBundle = NULL;
+ service_reference_pt ref = NULL;
+
+ arrayList_create(&bundleNames);
+ arrayList_create(&proxyBundle);
+
+ arrayList_add(bundleNames, (void*) CALCULATOR_PROXY);
+ status = getSpecifiedBundles(clientContext, bundleNames, proxyBundle);
+ CHECK_EQUAL(CELIX_SUCCESS, status);
+ CHECK_EQUAL(arrayList_size(proxyBundle), arrayList_size(bundleNames));
+
+ status = bundleContext_getBundleById(clientContext, (long) arrayList_get(proxyBundle, 0), &bundle);
+ CHECK_EQUAL(CELIX_SUCCESS, status);
+
+ status = bundle_stop(bundle);
+ CHECK_EQUAL(CELIX_SUCCESS, status);
+
+ status = bundleContext_getServiceReference(clientContext, (char *) CALCULATOR_SERVICE, &ref);
+ CHECK_EQUAL(CELIX_SUCCESS, status);
+ CHECK(ref == NULL);
+
+ arrayList_destroy(bundleNames);
+ arrayList_destroy(proxyBundle);
+ }
+ */
+
+ /*
+ static void testEndpointRemoval(void) {
+ celix_status_t status;
+ bundle_pt bundle = NULL;
+ array_list_pt bundleNames = NULL;
+ array_list_pt endpointBundle = NULL;
+ service_reference_pt ref = NULL;
+
+ arrayList_create(&bundleNames);
+ arrayList_create(&endpointBundle);
+
+ arrayList_add(bundleNames, (void*) CALCULATOR_ENDPOINT);
+ status = getSpecifiedBundles(serverContext, bundleNames, endpointBundle);
+ CHECK_EQUAL(CELIX_SUCCESS, status);
+ CHECK_EQUAL(arrayList_size(endpointBundle), arrayList_size(bundleNames));
+
+ status = bundleContext_getBundleById(serverContext, (long) arrayList_get(endpointBundle, 0), &bundle);
+ CHECK_EQUAL(CELIX_SUCCESS, status);
+
+ status = bundle_stop(bundle);
+ CHECK_EQUAL(CELIX_SUCCESS, status);
+
+ status = bundleContext_getServiceReference(serverContext, (char *) CALCULATOR_SERVICE, &ref);
+ CHECK_EQUAL(CELIX_SUCCESS, status);
+ CHECK(ref == NULL);
+
+ arrayList_destroy(bundleNames);
+ arrayList_destroy(endpointBundle);
+ }
+ */
+}
+
+ TEST_GROUP(RsaShmClientServerTests) {
+ void setup() {
+ setupFm();
+ }
+
+ void teardown() {
+ teardownFm();
+ }
+};
+
+
+TEST(RsaShmClientServerTests, Test1) {
+ test1();
+}
+
+TEST(RsaShmClientServerTests, TestImport) {
+ testImport();
+}
+
+TEST(RsaShmClientServerTests, TestExport) {
+ testExport();
+}
+
+/*
+TEST(RsaShmClientServerTests, TestProxyRemoval) {
+ // test is currenlty failing
+ // testProxyRemoval();
+}
+
+TEST(RsaShmClientServerTests, TestEndpointRemoval) {
+ // test is currenlty failing
+ //testEndpointRemoval();
+}
+*/
http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/remote_service_admin_shm/private/test/run_tests.cpp
----------------------------------------------------------------------
diff --git a/bundles/remote_services/remote_service_admin_shm/private/test/run_tests.cpp b/bundles/remote_services/remote_service_admin_shm/private/test/run_tests.cpp
new file mode 100644
index 0000000..fb6ca3a
--- /dev/null
+++ b/bundles/remote_services/remote_service_admin_shm/private/test/run_tests.cpp
@@ -0,0 +1,24 @@
+/**
+ *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 <CppUTest/TestHarness.h>
+#include "CppUTest/CommandLineTestRunner.h"
+
+int main(int argc, char** argv) {
+ return RUN_ALL_TESTS(argc, argv);
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/remote_service_admin_shm/private/test/server.properties.in
----------------------------------------------------------------------
diff --git a/bundles/remote_services/remote_service_admin_shm/private/test/server.properties.in b/bundles/remote_services/remote_service_admin_shm/private/test/server.properties.in
new file mode 100644
index 0000000..0b40556
--- /dev/null
+++ b/bundles/remote_services/remote_service_admin_shm/private/test/server.properties.in
@@ -0,0 +1,25 @@
+# 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.
+
+cosgi.auto.start.1=@rsa_bundle_file@ @calc_bundle_file@ @discovery_shm_bundle_file@ @topology_manager_bundle_file@
+LOGHELPER_ENABLE_STDOUT_FALLBACK=true
+ENDPOINTS=@server_endpoints@
+RSA_PORT=50882
+DISCOVERY_CFG_SERVER_PORT=50994
+org.osgi.framework.storage.clean=onFirstInit
+org.osgi.framework.storage=.cacheServer
+DISCOVERY_CFG_POLL_INTERVAL=1
http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/remote_service_admin_shm/public/include/remote_service_admin_shm.h
----------------------------------------------------------------------
diff --git a/bundles/remote_services/remote_service_admin_shm/public/include/remote_service_admin_shm.h b/bundles/remote_services/remote_service_admin_shm/public/include/remote_service_admin_shm.h
new file mode 100644
index 0000000..676a049
--- /dev/null
+++ b/bundles/remote_services/remote_service_admin_shm/public/include/remote_service_admin_shm.h
@@ -0,0 +1,35 @@
+/**
+ *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.
+ */
+/*
+ * remote_service_admin_shm.h
+ *
+ * \date Sep 30, 2011
+ * \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ * \copyright Apache License, Version 2.0
+ */
+
+#ifndef REMOTE_SERVICE_ADMIN_SHM_H_
+#define REMOTE_SERVICE_ADMIN_SHM_H_
+
+#define RSA_FUNCTIONCALL_DATA_PROPERTYNAME "data"
+#define RSA_FUNCTIONCALL_RETURN_PROPERTYNAME "reply"
+#define RSA_FUNCTIONCALL_RETURNSTATUS_PROPERTYNAME "replyStatus"
+
+
+#endif /* REMOTE_SERVICE_ADMIN_SHM_H_ */
http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/remote_services_api/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/bundles/remote_services/remote_services_api/CMakeLists.txt b/bundles/remote_services/remote_services_api/CMakeLists.txt
new file mode 100644
index 0000000..a092f59
--- /dev/null
+++ b/bundles/remote_services/remote_services_api/CMakeLists.txt
@@ -0,0 +1,28 @@
+# 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.
+
+add_library(remote_services_api INTERFACE)
+target_include_directories(remote_services_api INTERFACE
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>
+ $<INSTALL_INTERFACE:include/celix/remote_service_admin>
+)
+
+install(TARGETS remote_services_api EXPORT celix DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT rsa)
+install(DIRECTORY include/ DESTINATION include/celix/remote_service_admin COMPONENT rsa)
+
+#Setup target aliases to match external usage
+add_library(Celix::remote_services_api ALIAS remote_services_api)
http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/remote_services_api/README.md
----------------------------------------------------------------------
diff --git a/bundles/remote_services/remote_services_api/README.md b/bundles/remote_services/remote_services_api/README.md
new file mode 100644
index 0000000..2e3d268
--- /dev/null
+++ b/bundles/remote_services/remote_services_api/README.md
@@ -0,0 +1,11 @@
+# Remote Service Admin
+
+The Remote Service Admin (RSA) provides the mechanisms to import and export services when instructed to do so by the Topology Manager.
+
+To delegate method calls to the actual service implementation, the RSA_SHM and the RSA_HTTP are using "endpoint/proxy" bundles, which has all the knowledge about the marshalling and unmarshalling of data for the service. The RSA_DFI implementation combines a [foreign function interface](https://en.wikipedia.org/wiki/Foreign_function_interface) technique together with manualy created descriptors.
+
+Note that this folder contains code commonly used by the RSA implementations and therefore does not include any CMAKE configuration.
+
+## Properties
+ ENDPOINTS defines the relative directory where endpoints and proxys can be found (default: endpoints)
+ CELIX_FRAMEWORK_EXTENDER_PATH Used in RSA_DFI only. Can be used to define a path to use as an extender path point for the framework bundle. For normal bundles the bundle cache is used.
http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/remote_services_api/include/remote_constants.h
----------------------------------------------------------------------
diff --git a/bundles/remote_services/remote_services_api/include/remote_constants.h b/bundles/remote_services/remote_services_api/include/remote_constants.h
new file mode 100644
index 0000000..277f837
--- /dev/null
+++ b/bundles/remote_services/remote_services_api/include/remote_constants.h
@@ -0,0 +1,31 @@
+/**
+ *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.
+ */
+
+#ifndef REMOTE_CONSTANTS_H_
+#define REMOTE_CONSTANTS_H_
+
+static const char * const OSGI_RSA_SERVICE_EXPORTED_INTERFACES = "service.exported.interfaces";
+static const char * const OSGI_RSA_ENDPOINT_FRAMEWORK_UUID = "endpoint.framework.uuid";
+static const char * const OSGI_RSA_ENDPOINT_SERVICE_ID = "endpoint.service.id";
+static const char * const OSGI_RSA_ENDPOINT_ID = "endpoint.id";
+static const char * const OSGI_RSA_SERVICE_IMPORTED = "service.imported";
+static const char * const OSGI_RSA_SERVICE_IMPORTED_CONFIGS = "service.imported.configs";
+static const char * const OSGI_RSA_SERVICE_LOCATION = "service.location";
+
+#endif /* REMOTE_CONSTANTS_H_ */
http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/rsa_common/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/bundles/remote_services/rsa_common/CMakeLists.txt b/bundles/remote_services/rsa_common/CMakeLists.txt
new file mode 100644
index 0000000..397fa8c
--- /dev/null
+++ b/bundles/remote_services/rsa_common/CMakeLists.txt
@@ -0,0 +1,30 @@
+# 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.
+
+add_library(rsa_common STATIC
+ src/endpoint_description.c
+ src/export_registration_impl.c
+ src/import_registration_impl.c
+)
+set_target_properties(rsa_common PROPERTIES OUTPUT_NAME "celix_rsa_common")
+target_include_directories(rsa_common PRIVATE src)
+target_link_libraries(rsa_common PUBLIC Celix::framework Celix::rsa_spi Celix::log_helper)
+
+#install(TARGETS rsa_common EXPORT celix COMPONENT rsa DESTINATION ${CMAKE_INSTALL_LIBDIR})
+
+#Setup target aliases to match external usage
+add_library(Celix::rsa_common ALIAS rsa_common)
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/rsa_common/src/endpoint_description.c
----------------------------------------------------------------------
diff --git a/bundles/remote_services/rsa_common/src/endpoint_description.c b/bundles/remote_services/rsa_common/src/endpoint_description.c
new file mode 100644
index 0000000..0d8b684
--- /dev/null
+++ b/bundles/remote_services/rsa_common/src/endpoint_description.c
@@ -0,0 +1,89 @@
+/**
+ *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 <stdlib.h>
+#include <string.h>
+
+#include "celix_errno.h"
+#include "celix_log.h"
+
+#include "endpoint_description.h"
+#include "remote_constants.h"
+#include "constants.h"
+
+static celix_status_t endpointDescription_verifyLongProperty(properties_pt properties, char *propertyName, unsigned long *longProperty);
+
+celix_status_t endpointDescription_create(properties_pt properties, endpoint_description_pt *endpointDescription) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ unsigned long serviceId = 0UL;
+ status = endpointDescription_verifyLongProperty(properties, (char *) OSGI_RSA_ENDPOINT_SERVICE_ID, &serviceId);
+ if (status != CELIX_SUCCESS) {
+ return status;
+ }
+
+ endpoint_description_pt ep = calloc(1,sizeof(*ep));
+
+ ep->properties = properties;
+ ep->frameworkUUID = (char*)properties_get(properties, OSGI_RSA_ENDPOINT_FRAMEWORK_UUID);
+ ep->id = (char*)properties_get(properties, OSGI_RSA_ENDPOINT_ID);
+ ep->service = strndup(properties_get(properties, OSGI_FRAMEWORK_OBJECTCLASS), 1024*10);
+ ep->serviceId = serviceId;
+
+ if (!(ep->frameworkUUID) || !(ep->id) || !(ep->service) ) {
+ fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "ENDPOINT_DESCRIPTION: incomplete description!.");
+ status = CELIX_BUNDLE_EXCEPTION;
+ }
+
+ if(status == CELIX_SUCCESS){
+ *endpointDescription = ep;
+ }
+ else{
+ *endpointDescription = NULL;
+ free(ep);
+ }
+
+ return status;
+}
+
+celix_status_t endpointDescription_destroy(endpoint_description_pt description) {
+ properties_destroy(description->properties);
+ free(description->service);
+ free(description);
+ return CELIX_SUCCESS;
+}
+
+static celix_status_t endpointDescription_verifyLongProperty(properties_pt properties, char *propertyName, unsigned long *longProperty) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ const char *value = properties_get(properties, propertyName);
+ if (value == NULL) {
+ *longProperty = 0UL;
+ } else {
+ *longProperty = strtoul(value,NULL,10);
+ }
+
+ return status;
+}
http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/rsa_common/src/export_registration_impl.c
----------------------------------------------------------------------
diff --git a/bundles/remote_services/rsa_common/src/export_registration_impl.c b/bundles/remote_services/rsa_common/src/export_registration_impl.c
new file mode 100644
index 0000000..1c684e7
--- /dev/null
+++ b/bundles/remote_services/rsa_common/src/export_registration_impl.c
@@ -0,0 +1,257 @@
+/**
+ *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.
+ */
+/*
+ * export_registration_impl.c
+ *
+ * \date Oct 6, 2011
+ * \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ * \copyright Apache License, Version 2.0
+ */
+#include <stdlib.h>
+
+#include "constants.h"
+
+#include "celix_errno.h"
+
+#include "export_registration_impl.h"
+#include "remote_service_admin_impl.h"
+
+
+struct export_reference {
+ endpoint_description_pt endpoint;
+ service_reference_pt reference;
+};
+
+celix_status_t exportRegistration_endpointAdding(void * handle, service_reference_pt reference, void **service);
+celix_status_t exportRegistration_endpointAdded(void * handle, service_reference_pt reference, void *service);
+celix_status_t exportRegistration_endpointModified(void * handle, service_reference_pt reference, void *service);
+celix_status_t exportRegistration_endpointRemoved(void * handle, service_reference_pt reference, void *service);
+
+celix_status_t exportRegistration_createEndpointTracker(export_registration_pt registration, service_tracker_pt *tracker);
+
+celix_status_t exportRegistration_create(log_helper_pt helper, service_reference_pt reference, endpoint_description_pt endpoint, remote_service_admin_pt rsa, bundle_context_pt context, export_registration_pt *registration) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ *registration = calloc(1, sizeof(**registration));
+ if (!*registration) {
+ status = CELIX_ENOMEM;
+ } else {
+ (*registration)->context = context;
+ (*registration)->closed = false;
+ (*registration)->endpointDescription = endpoint;
+ (*registration)->reference = reference;
+ (*registration)->rsa = rsa;
+ (*registration)->tracker = NULL;
+ (*registration)->endpoint = NULL;
+ (*registration)->endpointTracker = NULL;
+ (*registration)->exportReference = NULL;
+ (*registration)->bundle = NULL;
+ (*registration)->loghelper = helper;
+ }
+
+ return status;
+}
+
+celix_status_t exportRegistration_destroy(export_registration_pt *registration) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ remoteServiceAdmin_destroyEndpointDescription(&(*registration)->endpointDescription);
+ free(*registration);
+
+ return status;
+}
+
+celix_status_t exportRegistration_startTracking(export_registration_pt registration) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ if (registration->endpointTracker == NULL) {
+ status = exportRegistration_createEndpointTracker(registration, ®istration->endpointTracker);
+ if (status == CELIX_SUCCESS) {
+ status = serviceTracker_open(registration->endpointTracker);
+ }
+ }
+
+ return status;
+}
+
+celix_status_t exportRegistration_stopTracking(export_registration_pt registration) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ if (registration->endpointTracker != NULL) {
+ status = serviceTracker_close(registration->endpointTracker);
+ if (status != CELIX_SUCCESS) {
+ logHelper_log(registration->loghelper, OSGI_LOGSERVICE_ERROR, "EXPORT_REGISTRATION: Could not close endpoint tracker");
+ }
+ else {
+ status = serviceTracker_destroy(registration->endpointTracker);
+ }
+ }
+ if (registration->tracker != NULL) {
+ status = serviceTracker_close(registration->tracker);
+ if (status != CELIX_SUCCESS) {
+ logHelper_log(registration->loghelper, OSGI_LOGSERVICE_ERROR, "EXPORT_REGISTRATION: Could not close service tracker");
+ }
+ else {
+ status = serviceTracker_destroy(registration->tracker);
+ }
+ }
+
+ return status;
+}
+
+celix_status_t exportRegistration_createEndpointTracker(export_registration_pt registration, service_tracker_pt *tracker) {
+ celix_status_t status;
+
+ service_tracker_customizer_pt customizer = NULL;
+
+ status = serviceTrackerCustomizer_create(registration, exportRegistration_endpointAdding,
+ exportRegistration_endpointAdded, exportRegistration_endpointModified, exportRegistration_endpointRemoved, &customizer);
+
+ if (status == CELIX_SUCCESS) {
+ char filter[512];
+
+ snprintf(filter, 512, "(&(%s=%s)(remote.interface=%s))", (char*) OSGI_FRAMEWORK_OBJECTCLASS, (char*) OSGI_RSA_REMOTE_ENDPOINT, registration->endpointDescription->service);
+ status = serviceTracker_createWithFilter(registration->context, filter, customizer, tracker);
+ }
+
+ return status;
+}
+
+celix_status_t exportRegistration_endpointAdding(void * handle, service_reference_pt reference, void **service) {
+ celix_status_t status;
+ export_registration_pt registration = handle;
+
+ status = bundleContext_getService(registration->context, reference, service);
+
+ return status;
+}
+
+celix_status_t exportRegistration_endpointAdded(void * handle, service_reference_pt reference, void *endpoint_service) {
+ celix_status_t status = CELIX_SUCCESS;
+ export_registration_pt registration = handle;
+
+ remote_endpoint_service_pt endpoint = endpoint_service;
+ if (registration->endpoint == NULL) {
+ registration->endpoint = endpoint;
+ void *service = NULL;
+ status = bundleContext_getService(registration->context, registration->reference, &service);
+ if (status == CELIX_SUCCESS) {
+ endpoint->setService(endpoint->endpoint, service);
+ }
+ }
+
+ return status;
+}
+
+celix_status_t exportRegistration_endpointModified(void * handle, service_reference_pt reference, void *service) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ return status;
+}
+
+celix_status_t exportRegistration_endpointRemoved(void * handle, service_reference_pt reference, void *service) {
+ celix_status_t status = CELIX_SUCCESS;
+ export_registration_pt registration = handle;
+
+ remote_endpoint_service_pt endpoint = service;
+ if (registration->endpoint != NULL) {
+ endpoint->setService(endpoint->endpoint, NULL);
+ }
+
+ return status;
+}
+
+celix_status_t exportRegistration_open(export_registration_pt registration) {
+ celix_status_t status = CELIX_SUCCESS;
+ const char *bundleStore = NULL;
+
+ bundleContext_getProperty(registration->context, BUNDLE_STORE_PROPERTY_NAME, &bundleStore);
+
+ if (bundleStore == NULL) {
+ bundleStore = DEFAULT_BUNDLE_STORE;
+ }
+ char name[256];
+
+ snprintf(name, 256, "%s/%s_endpoint.zip", bundleStore, registration->endpointDescription->service);
+
+ status = bundleContext_installBundle(registration->context, name, ®istration->bundle);
+ if (status == CELIX_SUCCESS) {
+ status = bundle_start(registration->bundle);
+ if (status == CELIX_SUCCESS) {
+ }
+ }
+
+ return status;
+}
+
+celix_status_t exportRegistration_close(export_registration_pt registration) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ exportRegistration_stopTracking(registration);
+
+ bundle_uninstall(registration->bundle);
+
+
+ return status;
+}
+
+celix_status_t exportRegistration_getException(export_registration_pt registration) {
+ celix_status_t status = CELIX_SUCCESS;
+ return status;
+}
+
+celix_status_t exportRegistration_getExportReference(export_registration_pt registration, export_reference_pt *reference) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ registration->exportReference = calloc(1, sizeof(*registration->exportReference));
+
+ if (registration->exportReference == NULL) {
+ status = CELIX_ENOMEM;
+ } else {
+ registration->exportReference->endpoint = registration->endpointDescription;
+ registration->exportReference->reference = registration->reference;
+ }
+
+ *reference = registration->exportReference;
+
+ return status;
+}
+
+celix_status_t exportRegistration_setEndpointDescription(export_registration_pt registration, endpoint_description_pt endpointDescription) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ registration->endpointDescription = endpointDescription;
+
+ return status;
+}
+
+celix_status_t exportReference_getExportedEndpoint(export_reference_pt reference, endpoint_description_pt *endpoint) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ *endpoint = reference->endpoint;
+
+ return status;
+}
+
+celix_status_t exportReference_getExportedService(export_reference_pt reference, service_reference_pt *service) {
+ celix_status_t status = CELIX_SUCCESS;
+ *service = reference->reference;
+ return status;
+}
+
http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/rsa_common/src/export_registration_impl.h
----------------------------------------------------------------------
diff --git a/bundles/remote_services/rsa_common/src/export_registration_impl.h b/bundles/remote_services/rsa_common/src/export_registration_impl.h
new file mode 100644
index 0000000..bb276f9
--- /dev/null
+++ b/bundles/remote_services/rsa_common/src/export_registration_impl.h
@@ -0,0 +1,61 @@
+/**
+ *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.
+ */
+/*
+ * export_registration_impl.h
+ *
+ * \date Oct 6, 2011
+ * \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ * \copyright Apache License, Version 2.0
+ */
+
+#ifndef EXPORT_REGISTRATION_IMPL_H_
+#define EXPORT_REGISTRATION_IMPL_H_
+
+#include "remote_service_admin.h"
+#include "remote_endpoint.h"
+#include "service_tracker.h"
+#include "log_helper.h"
+
+struct export_registration {
+ bundle_context_pt context;
+ remote_service_admin_pt rsa;
+ endpoint_description_pt endpointDescription;
+ service_reference_pt reference;
+ log_helper_pt loghelper;
+
+ service_tracker_pt tracker;
+ service_tracker_pt endpointTracker;
+
+ remote_endpoint_service_pt endpoint;
+
+ export_reference_pt exportReference;
+ bundle_pt bundle;
+
+ bool closed;
+};
+
+celix_status_t exportRegistration_create(log_helper_pt helper, service_reference_pt reference, endpoint_description_pt endpoint, remote_service_admin_pt rsa, bundle_context_pt context, export_registration_pt *registration);
+celix_status_t exportRegistration_destroy(export_registration_pt *registration);
+celix_status_t exportRegistration_open(export_registration_pt registration);
+
+celix_status_t exportRegistration_setEndpointDescription(export_registration_pt registration, endpoint_description_pt endpointDescription);
+celix_status_t exportRegistration_startTracking(export_registration_pt registration);
+celix_status_t exportRegistration_stopTracking(export_registration_pt registration);
+
+#endif /* EXPORT_REGISTRATION_IMPL_H_ */