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 2020/12/17 19:04:55 UTC
[celix] 01/02: Refactors dep man component / service dependency to
use celix_bundleContext_trackServices instead directly using service
references.
This is an automated email from the ASF dual-hosted git repository.
pnoltes pushed a commit to branch feature/refactor_c_dep_man_service_trackers
in repository https://gitbox.apache.org/repos/asf/celix.git
commit 5740833d08ec5917495a463930d0fee92af49618
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Thu Dec 17 19:53:42 2020 +0100
Refactors dep man component / service dependency to use celix_bundleContext_trackServices instead directly using service references.
---
bundles/shell/shell/src/dm_shell_list_command.c | 35 +-
libs/framework/CMakeLists.txt | 2 +-
libs/framework/include/celix_dm_component.h | 8 +-
libs/framework/include/celix_dm_info.h | 2 +
.../include/celix_dm_service_dependency.h | 7 +-
libs/framework/include/dm_service_dependency.h | 15 -
libs/framework/include/requirement.h | 10 +-
.../src/celix_dm_event.h} | 42 +-
libs/framework/src/dm_component_impl.c | 1313 ++++----------------
libs/framework/src/dm_component_impl.h | 4 +-
libs/framework/src/dm_event.c | 103 --
libs/framework/src/dm_event.h | 72 --
libs/framework/src/dm_service_dependency.c | 815 +++---------
libs/framework/src/dm_service_dependency_impl.h | 91 +-
libs/framework/src/requirement.c | 2 +-
libs/utils/CMakeLists.txt | 4 -
libs/utils/gtest/CMakeLists.txt | 2 +
libs/utils/gtest/src/VersionRangeTestSuite.cc | 423 +++++++
libs/utils/include/array_list.h | 7 -
libs/utils/include/celix_utils.h | 5 +
libs/utils/include/celix_version_range.h | 144 +++
libs/utils/include/version_range.h | 25 +-
libs/utils/private/test/utils_test.cpp | 11 +
libs/utils/private/test/version_range_test.cpp | 475 -------
libs/utils/private/test/version_test.cpp | 11 +
libs/utils/src/utils.c | 4 +
libs/utils/src/version.c | 8 +-
libs/utils/src/version_range.c | 276 ++--
libs/utils/src/version_range_private.h | 15 +-
29 files changed, 1297 insertions(+), 2634 deletions(-)
diff --git a/bundles/shell/shell/src/dm_shell_list_command.c b/bundles/shell/shell/src/dm_shell_list_command.c
index e656c90..34b0fcc 100644
--- a/bundles/shell/shell/src/dm_shell_list_command.c
+++ b/bundles/shell/shell/src/dm_shell_list_command.c
@@ -61,38 +61,41 @@ static void printFullInfo(FILE *out, bool colors, long bundleId, dm_component_in
startColors = compInfo->active ? OK_COLOR : NOK_COLOR;
endColors = END_COLOR;
}
- fprintf(out, "Component: Name=%s\n|- ID=%s, %sActive=%s%s, State=%s, Bundle=%li\n", compInfo->name, compInfo->id,
- startColors, compInfo->active ? "true " : "false", endColors, compInfo->state, bundleId);
- fprintf(out, "|- Interfaces (%d):\n", arrayList_size(compInfo->interfaces));
- for (unsigned int interfCnt = 0; interfCnt < arrayList_size(compInfo->interfaces); interfCnt++) {
- dm_interface_info_pt intfInfo = arrayList_get(compInfo->interfaces, interfCnt);
- fprintf(out, " |- Interface: %s\n", intfInfo->name);
+ fprintf(out, "%sComponent: Name=%s%s\n", startColors, compInfo->name, endColors);
+ fprintf(out, "|- UUID = %s\n", compInfo->id);
+ fprintf(out, "|- Active = %s\n", compInfo->active ? "true" : "false");
+ fprintf(out, "|- State = %s\n", compInfo->state);
+ fprintf(out, "|- Bundle = %li\n", bundleId);
+
+ fprintf(out, "|- Interfaces (%d):\n", celix_arrayList_size(compInfo->interfaces));
+ for (int interfCnt = 0; interfCnt < celix_arrayList_size(compInfo->interfaces); interfCnt++) {
+ dm_interface_info_pt intfInfo = celix_arrayList_get(compInfo->interfaces, interfCnt);
+ fprintf(out, " |- %sInterface %i: %s%s\n", startColors, (interfCnt+1), intfInfo->name, endColors);
hash_map_iterator_t iter = hashMapIterator_construct((hash_map_pt) intfInfo->properties);
char *key = NULL;
while ((key = hashMapIterator_nextKey(&iter)) != NULL) {
- fprintf(out, " | %15s = %s\n", key, properties_get(intfInfo->properties, key));
+ fprintf(out, " | %15s = %s\n", key, celix_properties_get(intfInfo->properties, key, "!ERROR!"));
}
}
- fprintf(out, "|- Dependencies (%d):\n", arrayList_size(compInfo->dependency_list));
- for (unsigned int depCnt = 0; depCnt < arrayList_size(compInfo->dependency_list); depCnt++) {
+ fprintf(out, "|- Dependencies (%d):\n", celix_arrayList_size(compInfo->dependency_list));
+ for (int depCnt = 0; depCnt < celix_arrayList_size(compInfo->dependency_list); ++depCnt) {
dm_service_dependency_info_pt dependency;
- dependency = arrayList_get(compInfo->dependency_list, depCnt);
+ dependency = celix_arrayList_get(compInfo->dependency_list, depCnt);
const char *depStartColors = "";
- const char *depEndColors = "";
if (colors) {
if (dependency->required) {
depStartColors = dependency->available ? OK_COLOR : NOK_COLOR;
} else {
depStartColors = dependency->available ? OK_COLOR : WARNING_COLOR;
}
-
- depEndColors = END_COLOR;
}
- fprintf(out, " |- Dependency: %sAvailable = %s%s, Required = %s, Filter = %s\n", depStartColors,
- dependency->available ? "true " : "false", depEndColors,
- dependency->required ? "true " : "false", dependency->filter);
+ fprintf(out, " |- %sDependency %i: %s%s\n", depStartColors, (depCnt+1), dependency->serviceName == NULL ? "(any)" : dependency->serviceName, endColors);
+ fprintf(out, " | %15s = %s\n", "Available", dependency->available ? "true " : "false");
+ fprintf(out, " | %15s = %s\n", "Required", dependency->required ? "true " : "false");
+ fprintf(out, " | %15s = %s\n", "Version Range", dependency->versionRange == NULL ? "N/A" : dependency->versionRange);
+ fprintf(out, " | %15s = %s\n", "Filter", dependency->filter == NULL ? "N/A" : dependency->filter);
}
fprintf(out, "\n");
diff --git a/libs/framework/CMakeLists.txt b/libs/framework/CMakeLists.txt
index 950de4e..5ac13e0 100644
--- a/libs/framework/CMakeLists.txt
+++ b/libs/framework/CMakeLists.txt
@@ -30,7 +30,7 @@ set(SOURCES
src/celix_log.c src/celix_launcher.c
src/celix_framework_factory.c
src/dm_dependency_manager_impl.c src/dm_component_impl.c
- src/dm_service_dependency.c src/dm_event.c src/celix_library_loader.c
+ src/dm_service_dependency.c src/celix_library_loader.c
)
add_library(framework SHARED ${SOURCES})
set_target_properties(framework PROPERTIES OUTPUT_NAME "celix_framework")
diff --git a/libs/framework/include/celix_dm_component.h b/libs/framework/include/celix_dm_component.h
index 38bb88b..9e6b7db 100644
--- a/libs/framework/include/celix_dm_component.h
+++ b/libs/framework/include/celix_dm_component.h
@@ -47,12 +47,18 @@ typedef enum celix_dm_component_state_enum {
typedef int (*celix_dm_cmp_lifecycle_fpt)(void *userData);
/**
- * Creates a DM Component
+ * Creates a DM Component with a random generated UUID.
* Caller has ownership.
*/
celix_dm_component_t* celix_dmComponent_create(celix_bundle_context_t *context, const char* name);
/**
+ * Creates a DM Component with a provided UUID.
+ * Caller has ownership.
+ */
+celix_dm_component_t* celix_dmComponent_createWithUUID(celix_bundle_context_t *context, const char* name, const char* UUID);
+
+/**
* Destroys a DM Component
*/
void celix_dmComponent_destroy(celix_dm_component_t *cmp);
diff --git a/libs/framework/include/celix_dm_info.h b/libs/framework/include/celix_dm_info.h
index d6b8ea4..b7cfda9 100644
--- a/libs/framework/include/celix_dm_info.h
+++ b/libs/framework/include/celix_dm_info.h
@@ -40,7 +40,9 @@ typedef struct celix_dm_interface_info_struct dm_interface_info_t; //deprecated
typedef struct celix_dm_interface_info_struct celix_dm_interface_info_t;
struct celix_dm_service_dependency_info_struct {
+ char *serviceName;
char *filter;
+ char *versionRange;
bool available;
bool required;
size_t count;
diff --git a/libs/framework/include/celix_dm_service_dependency.h b/libs/framework/include/celix_dm_service_dependency.h
index 2d80fed..9ef51a8 100644
--- a/libs/framework/include/celix_dm_service_dependency.h
+++ b/libs/framework/include/celix_dm_service_dependency.h
@@ -46,12 +46,12 @@ typedef struct celix_dm_service_dependency_callback_options {
celix_dm_service_update_fp set;
celix_dm_service_update_fp add;
celix_dm_service_update_fp remove;
- celix_dm_service_swap_fp swap;
+ celix_dm_service_swap_fp swap; //not used, deprecated
celix_dm_service_update_with_props_fp setWithProps;
celix_dm_service_update_with_props_fp addWithProps;
celix_dm_service_update_with_props_fp removeWithProps;
- celix_dm_service_swap_with_props_fp swapWithProps;
+ celix_dm_service_swap_with_props_fp swapWithProps; //not used, deprecated
} celix_dm_service_dependency_callback_options_t;
#define CELIX_EMPTY_DM_SERVICE_DEPENDENCY_CALLBACK_OPTIONS { .set = NULL, \
@@ -66,6 +66,9 @@ typedef struct celix_dm_service_dependency_callback_options {
/**
* Create a service dependency.
* Caller has ownership.
+ *
+ * \warning The dmServiceDependency is not thread safe when constructing or modifying.
+ * The handling of service updates is thread safe.
*/
celix_dm_service_dependency_t* celix_dmServiceDependency_create(void);
diff --git a/libs/framework/include/dm_service_dependency.h b/libs/framework/include/dm_service_dependency.h
index c846688..7d5fc2e 100644
--- a/libs/framework/include/dm_service_dependency.h
+++ b/libs/framework/include/dm_service_dependency.h
@@ -120,21 +120,6 @@ celix_status_t serviceDependency_getFilter(celix_dm_service_dependency_t *depend
*/
celix_status_t serviceDependency_setCallbacks(celix_dm_service_dependency_t *dependency, service_set_fpt set, service_add_fpt add, service_change_fpt change, service_remove_fpt remove, service_swap_fpt swap) CELIX_DEPRECATED_ATTR;
-/**
- * Set the set, add, change, remove and swap function callbacks when services specified by the service dependency
- * are (respectively) set, added, changed, removed or swapped.
- * The first argument of the callbacks will be the component implement (@see component_getImplementation)
- * The second argument of th callbacks will be a pointer to an instance of a service struct of the specified service dependency.
- * The third argument of th callbacks will be a pointer to a service reference of the a service instance of the specified service dependency.
- */
-celix_status_t serviceDependency_setCallbacksWithServiceReference(celix_dm_service_dependency_t *dependency, service_set_with_ref_fpt set, service_add_with_ref_fpt add, service_change_with_ref_fpt change, service_remove_with_ref_fpt remove, service_swap_with_ref_fpt swap) CELIX_DEPRECATED_ATTR;
-
-/**
- * Specifies which field member (pointer to) to update when a service dependencies is set.
- * If provided the provided service_lock will be used for locking when updating the service instance.
- */
-celix_status_t serviceDependency_setAutoConfigure(celix_dm_service_dependency_t *dependency, celix_thread_mutex_t *service_lock, const void** field) CELIX_DEPRECATED_ATTR;
-
#define serviceDependency_setCallbacksSafe(dep, cmpType, servType, set, add, change, remove, swap) \
do { \
int (*tmpSet)(cmpType, servType) = set; \
diff --git a/libs/framework/include/requirement.h b/libs/framework/include/requirement.h
index e726754..2b14c69 100644
--- a/libs/framework/include/requirement.h
+++ b/libs/framework/include/requirement.h
@@ -16,13 +16,6 @@
* specific language governing permissions and limitations
* under the License.
*/
-/**
- * requirement.h
- *
- * \date Jul 12, 2010
- * \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- * \copyright Apache License, Version 2.0
- */
#ifndef REQUIREMENT_H_
#define REQUIREMENT_H_
@@ -31,6 +24,7 @@ typedef struct requirement *requirement_pt;
#include "capability.h"
#include "hash_map.h"
+#include "celix_version_range.h"
#include "version_range.h"
#ifdef __cplusplus
extern "C" {
@@ -40,7 +34,7 @@ celix_status_t requirement_create(hash_map_pt directives, hash_map_pt attributes
celix_status_t requirement_destroy(requirement_pt requirement);
-celix_status_t requirement_getVersionRange(requirement_pt requirement, version_range_pt *range);
+celix_status_t requirement_getVersionRange(requirement_pt requirement, celix_version_range_t **range);
celix_status_t requirement_getTargetName(requirement_pt requirement, const char **targetName);
diff --git a/libs/utils/src/version_range_private.h b/libs/framework/src/celix_dm_event.h
similarity index 60%
copy from libs/utils/src/version_range_private.h
copy to libs/framework/src/celix_dm_event.h
index bcd8296..7a8f162 100644
--- a/libs/utils/src/version_range_private.h
+++ b/libs/framework/src/celix_dm_event.h
@@ -16,24 +16,32 @@
* specific language governing permissions and limitations
* under the License.
*/
-/**
- * version_range_private.h
- *
- * \date Dec 18, 2012
- * \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- * \copyright Apache License, Version 2.0
- */
-#ifndef VERSION_RANGE_PRIVATE_H_
-#define VERSION_RANGE_PRIVATE_H_
+#ifndef CELIX_DM_EVENT_H_
+#define CELIX_DM_EVENT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "celix_types.h"
+#include "celix_properties.h"
+
+typedef enum celix_dm_event_type {
+ CELIX_DM_EVENT_SVC_ADD,
+ CELIX_DM_EVENT_SVC_REM,
+ CELIX_DM_EVENT_SVC_SET
+} celix_dm_event_type_e;
-#include "version_range.h"
+typedef struct celix_dm_event {
+ celix_dm_service_dependency_t* dep;
+ celix_dm_event_type_e eventType;
+ void* svc;
+ const celix_properties_t* props;
+} celix_dm_event_t;
-struct versionRange {
- version_pt low;
- bool isLowInclusive;
- version_pt high;
- bool isHighInclusive;
-};
+#ifdef __cplusplus
+}
+#endif
-#endif /* VERSION_RANGE_PRIVATE_H_ */
+#endif /* CELIX_DM_EVENT_H_ */
diff --git a/libs/framework/src/dm_component_impl.c b/libs/framework/src/dm_component_impl.c
index b76f8e9..39484f9 100644
--- a/libs/framework/src/dm_component_impl.c
+++ b/libs/framework/src/dm_component_impl.c
@@ -17,25 +17,24 @@
* under the License.
*/
-
-#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <uuid/uuid.h>
+#include <celix_utils.h>
+#include <assert.h>
#include "celix_constants.h"
-#include "filter.h"
+#include "celix_filter.h"
#include "dm_component_impl.h"
-
-
-typedef struct dm_executor_struct * dm_executor_pt;
+#include "bundle_context_private.h"
+#include "framework_private.h"
struct celix_dm_component_struct {
- char id[DM_COMPONENT_MAX_ID_LENGTH];
+ char uuid[DM_COMPONENT_MAX_ID_LENGTH];
char name[DM_COMPONENT_MAX_NAME_LENGTH];
- bundle_context_pt context;
- array_list_pt dm_interfaces; //protected by mutex
+ celix_bundle_context_t* context;
+ bool setCLanguageProperty;
void* implementation;
celix_dm_cmp_lifecycle_fpt callbackInit;
@@ -43,18 +42,12 @@ struct celix_dm_component_struct {
celix_dm_cmp_lifecycle_fpt callbackStop;
celix_dm_cmp_lifecycle_fpt callbackDeinit;
- array_list_pt dependencies; //protected by mutex
- pthread_mutex_t mutex;
+ celix_thread_mutex_t mutex; //protects below
+ celix_array_list_t* providedInterfaces;
+ celix_array_list_t* dependencies;
celix_dm_component_state_t state;
bool isStarted;
- bool active;
-
- bool setCLanguageProperty;
-
- hash_map_pt dependencyEvents; //protected by mutex
-
- dm_executor_pt executor;
};
typedef struct dm_interface_struct {
@@ -64,100 +57,53 @@ typedef struct dm_interface_struct {
long svcId;
} dm_interface_t;
-struct dm_executor_struct {
- pthread_t runningThread;
- bool runningThreadSet;
- celix_array_list_t *workQueue;
- pthread_mutex_t mutex;
-};
-
-typedef struct dm_executor_task_struct {
- celix_dm_component_t *component;
- void (*command)(void *command_ptr, void *data);
- void *data;
-} dm_executor_task_t;
-
-typedef struct dm_handle_event_type_struct {
- celix_dm_service_dependency_t *dependency;
- dm_event_pt event;
- dm_event_pt newEvent;
-} *dm_handle_event_type_pt;
-
-static celix_status_t executor_runTasks(dm_executor_pt executor, pthread_t currentThread __attribute__((unused)));
-static celix_status_t executor_execute(dm_executor_pt executor);
-static celix_status_t executor_executeTask(dm_executor_pt executor, celix_dm_component_t *component, void (*command), void *data);
-static celix_status_t executor_schedule(dm_executor_pt executor, celix_dm_component_t *component, void (*command), void *data);
-static celix_status_t executor_create(celix_dm_component_t *component __attribute__((unused)), dm_executor_pt *executor);
-static void executor_destroy(dm_executor_pt executor);
-
-static celix_status_t component_invokeRemoveRequiredDependencies(celix_dm_component_t *component);
-static celix_status_t component_invokeRemoveInstanceBoundDependencies(celix_dm_component_t *component);
-static celix_status_t component_invokeRemoveOptionalDependencies(celix_dm_component_t *component);
static celix_status_t component_registerServices(celix_dm_component_t *component);
static celix_status_t component_unregisterServices(celix_dm_component_t *component);
-static celix_status_t component_invokeAddOptionalDependencies(celix_dm_component_t *component);
-static celix_status_t component_invokeAddRequiredInstanceBoundDependencies(celix_dm_component_t *component);
-static celix_status_t component_invokeAddRequiredDependencies(celix_dm_component_t *component);
-static celix_status_t component_invokeAutoConfigInstanceBoundDependencies(celix_dm_component_t *component);
-static celix_status_t component_invokeAutoConfigDependencies(celix_dm_component_t *component);
-static celix_status_t component_configureImplementation(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency);
-static celix_status_t component_allInstanceBoundAvailable(celix_dm_component_t *component, bool *available);
-static celix_status_t component_allRequiredAvailable(celix_dm_component_t *component, bool *available);
+static bool component_areAllRequiredServiceDependenciesResolved(celix_dm_component_t *component);
static celix_status_t component_performTransition(celix_dm_component_t *component, celix_dm_component_state_t oldState, celix_dm_component_state_t newState, bool *transition);
static celix_status_t component_calculateNewState(celix_dm_component_t *component, celix_dm_component_state_t currentState, celix_dm_component_state_t *newState);
static celix_status_t component_handleChange(celix_dm_component_t *component);
-static celix_status_t component_startDependencies(celix_dm_component_t *component __attribute__((unused)), array_list_pt dependencies);
-static celix_status_t component_getDependencyEvent(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency, dm_event_pt *event_pptr);
-static celix_status_t component_updateInstance(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency, dm_event_pt event, bool update, bool add);
-
-static celix_status_t component_addTask(celix_dm_component_t *component, celix_dm_service_dependency_t *dep);
-static celix_status_t component_startTask(celix_dm_component_t *component, void * data __attribute__((unused)));
-static celix_status_t component_stopTask(celix_dm_component_t *component, void * data __attribute__((unused)));
-static celix_status_t component_removeTask(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency);
-static celix_status_t component_handleEventTask(celix_dm_component_t *component, dm_handle_event_type_pt data);
-
-static celix_status_t component_handleAdded(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency, dm_event_pt event);
-static celix_status_t component_handleChanged(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency, dm_event_pt event);
-static celix_status_t component_handleRemoved(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency, dm_event_pt event);
-static celix_status_t component_handleSwapped(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency, dm_event_pt event, dm_event_pt newEvent);
-
+static celix_status_t component_handleAdd(celix_dm_component_t *component, const celix_dm_event_t* event);
+static celix_status_t component_handleRemove(celix_dm_component_t *component, const celix_dm_event_t* event);
+static celix_status_t component_handleSet(celix_dm_component_t *component, const celix_dm_event_t* event);
+static celix_status_t component_startDependencies(celix_dm_component_t *component);
static celix_status_t component_suspend(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency);
static celix_status_t component_resume(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency);
+
celix_dm_component_t* celix_dmComponent_create(bundle_context_t *context, const char* name) {
+ return celix_dmComponent_createWithUUID(context, name, NULL);
+}
+
+celix_dm_component_t* celix_dmComponent_createWithUUID(bundle_context_t *context, const char* name, const char *uuid) {
celix_dm_component_t *component = calloc(1, sizeof(*component));
- //gen uuid
- uuid_t uid;
- uuid_generate(uid);
- uuid_unparse(uid, component->id);
- //snprintf(component->id, DM_COMPONENT_MAX_ID_LENGTH, "%p", component);
+ char randomUUID[DM_COMPONENT_MAX_ID_LENGTH];
+ if (uuid == NULL) {
+ //gen uuid
+ uuid_t uid;
+ uuid_generate(uid);
+ uuid_unparse(uid, randomUUID);
+ uuid = randomUUID;
+ }
+ snprintf(component->uuid, DM_COMPONENT_MAX_ID_LENGTH, "%s", uuid);
+
snprintf(component->name, DM_COMPONENT_MAX_NAME_LENGTH, "%s", name == NULL ? "n/a" : name);
component->context = context;
-
- arrayList_create(&component->dm_interfaces);
- arrayList_create(&(component)->dependencies);
- pthread_mutex_init(&(component)->mutex, NULL);
-
component->implementation = NULL;
-
component->callbackInit = NULL;
component->callbackStart = NULL;
component->callbackStop = NULL;
component->callbackDeinit = NULL;
-
component->state = DM_CMP_STATE_INACTIVE;
- component->isStarted = false;
- component->active = false;
-
component->setCLanguageProperty = false;
- component->dependencyEvents = hashMap_create(NULL, NULL, NULL, NULL);
-
- component->executor = NULL;
- executor_create(component, &component->executor);
+ component->providedInterfaces = celix_arrayList_create();
+ component->dependencies = celix_arrayList_create();
+ celixThreadMutex_create(&component->mutex, NULL);
+ component->isStarted = false;
return component;
}
@@ -178,35 +124,26 @@ void component_destroy(celix_dm_component_t *component) {
void celix_dmComponent_destroy(celix_dm_component_t *component) {
if (component) {
- unsigned int i;
+ celix_private_dmComponent_stop(component); //all service deregistered // all svc tracker stopped
+ //TODO for async wait till events are cleared (maintain a async count + condition?)
- for (i = 0; i < arrayList_size(component->dm_interfaces); i++) {
- dm_interface_t *interface = arrayList_get(component->dm_interfaces, i);
+ for (int i = 0; i < celix_arrayList_size(component->providedInterfaces); ++i) {
+ dm_interface_t *interface = celix_arrayList_get(component->providedInterfaces, i);
- if(interface->properties!=NULL){
- properties_destroy(interface->properties);
+ if (interface->properties != NULL) {
+ celix_properties_destroy(interface->properties);
}
- free (interface->serviceName);
- free (interface);
+ free(interface->serviceName);
+ free(interface);
}
- arrayList_destroy(component->dm_interfaces);
+ celix_arrayList_destroy(component->providedInterfaces);
- executor_destroy(component->executor);
-
- hash_map_iterator_pt iter = hashMapIterator_create(component->dependencyEvents);
- while(hashMapIterator_hasNext(iter)){
- hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
- celix_dm_service_dependency_t *sdep = (celix_dm_service_dependency_t*)hashMapEntry_getKey(entry);
- array_list_pt eventList = (array_list_pt)hashMapEntry_getValue(entry);
- serviceDependency_destroy(&sdep);
- arrayList_destroy(eventList);
+ for (int i = 0; i < celix_arrayList_size(component->dependencies); ++i) {
+ celix_dm_service_dependency_t* dep = celix_arrayList_get(component->dependencies, i);
+ celix_dmServiceDependency_destroy(dep);
}
- hashMapIterator_destroy(iter);
-
- hashMap_destroy(component->dependencyEvents, false, false);
-
- arrayList_destroy(component->dependencies);
- pthread_mutex_destroy(&component->mutex);
+ celix_arrayList_destroy(component->dependencies);
+ celixThreadMutex_destroy(&component->mutex);
free(component);
}
@@ -217,41 +154,42 @@ celix_status_t component_addServiceDependency(celix_dm_component_t *component, c
}
celix_status_t celix_dmComponent_addServiceDependency(celix_dm_component_t *component, celix_dm_service_dependency_t *dep) {
-
celix_status_t status = CELIX_SUCCESS;
+ celix_serviceDependency_setComponent(dep, component);
- executor_executeTask(component->executor, component, component_addTask, dep);
-
- return status;
-}
+ celixThreadMutex_lock(&component->mutex);
+ arrayList_add(component->dependencies, dep);
+ bool startDep = component->state != DM_CMP_STATE_INACTIVE;
-static celix_status_t component_addTask(celix_dm_component_t *component, celix_dm_service_dependency_t *dep) {
- celix_status_t status = CELIX_SUCCESS;
+ celixThreadMutex_unlock(&component->mutex);
+ if (startDep) { //TODO race condition, fix with asyn branch -> async track services
+ celix_serviceDependency_start(dep);
+ }
+ celixThreadMutex_lock(&component->mutex);
- array_list_pt bounds = NULL;
- arrayList_create(&bounds);
+ component_handleChange(component);
+ celixThreadMutex_unlock(&component->mutex);
- array_list_pt events = NULL;
- arrayList_createWithEquals(event_equals, &events);
+ return status;
+}
- pthread_mutex_lock(&component->mutex);
- hashMap_put(component->dependencyEvents, dep, events);
- arrayList_add(component->dependencies, dep);
- pthread_mutex_unlock(&component->mutex);
+celix_status_t celix_dmComponent_removeServiceDependency(celix_dm_component_t *component, celix_dm_service_dependency_t *dep) {
- serviceDependency_setComponent(dep, component);
+ celixThreadMutex_lock(&component->mutex);
+ arrayList_removeElement(component->dependencies, dep);
+ bool stopDependency = component->state != DM_CMP_STATE_INACTIVE;
- if (component->state != DM_CMP_STATE_INACTIVE) {
- serviceDependency_setInstanceBound(dep, true);
- arrayList_add(bounds, dep);
+ celixThreadMutex_unlock(&component->mutex);
+ if (stopDependency) { //TODO race condition, fix with asyn branch -> async stop track services
+ celix_serviceDependency_stop(dep);
}
- component_startDependencies(component, bounds);
- component_handleChange(component);
-
- arrayList_destroy(bounds);
+ celix_dmServiceDependency_destroy(dep);
+ celixThreadMutex_lock(&component->mutex);
- return status;
+ component_handleChange(component);
+ celixThreadMutex_unlock(&component->mutex);
+ return CELIX_SUCCESS;
}
celix_dm_component_state_t component_currentState(celix_dm_component_t *cmp) {
@@ -282,78 +220,26 @@ celix_status_t component_removeServiceDependency(celix_dm_component_t *component
return celix_dmComponent_removeServiceDependency(component, dependency);
}
-celix_status_t celix_dmComponent_removeServiceDependency(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency) {
- celix_status_t status = CELIX_SUCCESS;
-
- executor_executeTask(component->executor, component, component_removeTask, dependency);
-
- return status;
-}
-
-static celix_status_t component_removeTask(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency) {
- celix_status_t status = CELIX_SUCCESS;
-
- pthread_mutex_lock(&component->mutex);
- arrayList_removeElement(component->dependencies, dependency);
- pthread_mutex_unlock(&component->mutex);
-
- if (component->state != DM_CMP_STATE_INACTIVE) {
- serviceDependency_stop(dependency);
- }
-
- pthread_mutex_lock(&component->mutex);
- array_list_pt events = hashMap_remove(component->dependencyEvents, dependency);
- pthread_mutex_unlock(&component->mutex);
-
- serviceDependency_destroy(&dependency);
-
- while (!arrayList_isEmpty(events)) {
- dm_event_pt event = arrayList_remove(events, 0);
- event_destroy(&event);
- }
- arrayList_destroy(events);
-
- component_handleChange(component);
-
- return status;
-}
-
celix_status_t celix_private_dmComponent_start(celix_dm_component_t *component) {
- celix_status_t status = CELIX_SUCCESS;
-
- component->active = true;
- executor_executeTask(component->executor, component, component_startTask, NULL);
-
- return status;
-}
-
-celix_status_t component_startTask(celix_dm_component_t *component, void *data __attribute__((unused))) {
- celix_status_t status = CELIX_SUCCESS;
-
- component->isStarted = true;
- component_handleChange(component);
-
- return status;
+ celixThreadMutex_lock(&component->mutex);
+ if (!component->isStarted) {
+ component->isStarted = true;
+ component_handleChange(component);
+ }
+ celixThreadMutex_unlock(&component->mutex);
+ return CELIX_SUCCESS;
}
celix_status_t celix_private_dmComponent_stop(celix_dm_component_t *component) {
- celix_status_t status = CELIX_SUCCESS;
-
- component->active = false;
- executor_executeTask(component->executor, component, component_stopTask, NULL);
-
- return status;
+ celixThreadMutex_lock(&component->mutex);
+ if (component->isStarted) {
+ component->isStarted = false;
+ component_handleChange(component);
+ }
+ celixThreadMutex_unlock(&component->mutex);
+ return CELIX_SUCCESS;
}
-static celix_status_t component_stopTask(celix_dm_component_t *component, void *data __attribute__((unused))) {
- celix_status_t status = CELIX_SUCCESS;
-
- component->isStarted = false;
- component_handleChange(component);
- component->active = false;
-
- return status;
-}
celix_status_t component_setCLanguageProperty(celix_dm_component_t *component, bool setCLangProp) {
return celix_dmComponent_setCLanguageProperty(component, setCLangProp);
@@ -368,7 +254,7 @@ celix_status_t component_addInterface(celix_dm_component_t *component, const cha
return celix_dmComponent_addInterface(component, serviceName, serviceVersion, service, properties);
}
-celix_status_t celix_dmComponent_addInterface(celix_dm_component_t *component, const char* serviceName, const char* serviceVersion, const void* service, properties_pt properties) {
+celix_status_t celix_dmComponent_addInterface(celix_dm_component_t *component, const char* serviceName, const char* serviceVersion, const void* service, celix_properties_t* properties) {
celix_status_t status = CELIX_SUCCESS;
dm_interface_t *interface = (dm_interface_t *) calloc(1, sizeof(*interface));
@@ -386,19 +272,19 @@ celix_status_t celix_dmComponent_addInterface(celix_dm_component_t *component, c
celix_properties_set(properties, CELIX_FRAMEWORK_SERVICE_LANGUAGE, CELIX_FRAMEWORK_SERVICE_C_LANGUAGE);
}
- celix_properties_set(properties, CELIX_DM_COMPONENT_UUID, (char*)component->id);
+ celix_properties_set(properties, CELIX_DM_COMPONENT_UUID, (char*)component->uuid);
if (interface && name) {
+ celixThreadMutex_lock(&component->mutex);
interface->serviceName = name;
interface->service = service;
interface->properties = properties;
interface->svcId= -1L;
- celixThreadMutex_lock(&component->mutex);
- arrayList_add(component->dm_interfaces, interface);
- celixThreadMutex_unlock(&component->mutex);
+ celix_arrayList_add(component->providedInterfaces, interface);
if (component->state == DM_CMP_STATE_TRACKING_OPTIONAL) {
component_registerServices(component);
}
+ celixThreadMutex_unlock(&component->mutex);
} else {
free(interface);
free(name);
@@ -416,393 +302,182 @@ celix_status_t celix_dmComponent_removeInterface(celix_dm_component_t *component
celix_status_t status = CELIX_ILLEGAL_ARGUMENT;
celixThreadMutex_lock(&component->mutex);
- int nof_interfaces = arrayList_size(component->dm_interfaces);
- for (unsigned int i = 0; i < nof_interfaces; ++i) {
- dm_interface_t *interface = (dm_interface_t *) arrayList_get(component->dm_interfaces, i);
+ int nof_interfaces = celix_arrayList_size(component->providedInterfaces);
+ dm_interface_t* removedInterface = NULL;
+ for (int i = 0; i < nof_interfaces; ++i) {
+ dm_interface_t *interface = celix_arrayList_get(component->providedInterfaces, i);
if (interface->service == service) {
- arrayList_remove(component->dm_interfaces, i);
- if (component->state == DM_CMP_STATE_TRACKING_OPTIONAL) {
- celixThreadMutex_unlock(&component->mutex);
- component_unregisterServices(component);
- component_registerServices(component);
- celixThreadMutex_lock(&component->mutex);
- }
- status = CELIX_SUCCESS;
+ celix_arrayList_removeAt(component->providedInterfaces, i);
+ removedInterface = interface;
break;
}
}
celixThreadMutex_unlock(&component->mutex);
+ if (removedInterface != NULL) {
+ celix_bundleContext_unregisterService(component->context, removedInterface->svcId);
+ free(removedInterface->serviceName);
+ free(removedInterface);
+ }
+
return status;
}
-celix_status_t component_getInterfaces(celix_dm_component_t *component, array_list_pt *out) {
+celix_status_t component_getInterfaces(celix_dm_component_t *component, celix_array_list_t **out) {
return celix_dmComponent_getInterfaces(component, out);
}
-celix_status_t celix_dmComponent_getInterfaces(celix_dm_component_t *component, array_list_pt *out) {
- celix_status_t status = CELIX_SUCCESS;
- array_list_pt names = NULL;
- arrayList_create(&names);
+celix_status_t celix_dmComponent_getInterfaces(celix_dm_component_t *component, celix_array_list_t **out) {
+ celix_array_list_t* names = celix_arrayList_create();
+
celixThreadMutex_lock(&component->mutex);
- int size = arrayList_size(component->dm_interfaces);
- int i;
- for (i = 0; i < size; i += 1) {
- dm_interface_info_pt info = calloc(1, sizeof(*info));
- dm_interface_t *interface = arrayList_get(component->dm_interfaces, i);
- info->name = strdup(interface->serviceName);
- properties_copy(interface->properties, &info->properties);
- arrayList_add(names, info);
+ int size = celix_arrayList_size(component->providedInterfaces);
+ for (int i = 0; i < size; i += 1) {
+ dm_interface_info_t* info = calloc(1, sizeof(*info));
+ dm_interface_t *interface = celix_arrayList_get(component->providedInterfaces, i);
+ info->name = celix_utils_strdup(interface->serviceName);
+ info->properties = celix_properties_copy(interface->properties);
+ celix_arrayList_add(names, info);
}
celixThreadMutex_unlock(&component->mutex);
+ *out = names;
- if (status == CELIX_SUCCESS) {
- *out = names;
- }
-
- return status;
-}
-
-celix_status_t celix_private_dmComponent_handleEvent(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency, dm_event_pt event) {
- celix_status_t status = CELIX_SUCCESS;
-
- dm_handle_event_type_pt data = calloc(1, sizeof(*data));
- data->dependency = dependency;
- data->event = event;
- data->newEvent = NULL;
-
- status = executor_executeTask(component->executor, component, component_handleEventTask, data);
-// component_handleEventTask(component, data);
-
- return status;
+ return CELIX_SUCCESS;
}
-static celix_status_t component_handleEventTask(celix_dm_component_t *component, dm_handle_event_type_pt data) {
- celix_status_t status = CELIX_SUCCESS;
-
- switch (data->event->event_type) {
- case DM_EVENT_ADDED:
- component_handleAdded(component,data->dependency, data->event);
- break;
- case DM_EVENT_CHANGED:
- component_handleChanged(component,data->dependency, data->event);
- break;
- case DM_EVENT_REMOVED:
- component_handleRemoved(component,data->dependency, data->event);
- break;
- case DM_EVENT_SWAPPED:
- component_handleSwapped(component,data->dependency, data->event, data->newEvent);
- break;
- default:
- break;
- }
-
- free(data);
-
- return status;
+celix_status_t celix_private_dmComponent_handleEvent(celix_dm_component_t *component, const celix_dm_event_t* event) {
+ celix_status_t status = CELIX_SUCCESS;
+ switch (event->eventType) {
+ case CELIX_DM_EVENT_SVC_ADD:
+ component_handleAdd(component, event);
+ break;
+ case CELIX_DM_EVENT_SVC_REM:
+ component_handleRemove(component, event);
+ break;
+ case CELIX_DM_EVENT_SVC_SET:
+ component_handleSet(component, event);
+ break;
+ default:
+ break;
+ }
+ return status;
}
static celix_status_t component_suspend(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency) {
celix_status_t status = CELIX_SUCCESS;
-
- dm_service_dependency_strategy_t strategy;
- serviceDependency_getStrategy(dependency, &strategy);
+ dm_service_dependency_strategy_t strategy = celix_dmServiceDependency_getStrategy(dependency);
if (strategy == DM_SERVICE_DEPENDENCY_STRATEGY_SUSPEND && component->callbackStop != NULL) {
status = component->callbackStop(component->implementation);
}
-
return status;
}
static celix_status_t component_resume(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency) {
celix_status_t status = CELIX_SUCCESS;
-
- dm_service_dependency_strategy_t strategy;
- serviceDependency_getStrategy(dependency, &strategy);
+ dm_service_dependency_strategy_t strategy = celix_dmServiceDependency_getStrategy(dependency);
if (strategy == DM_SERVICE_DEPENDENCY_STRATEGY_SUSPEND && component->callbackStop != NULL) {
status = component->callbackStart(component->implementation);
}
-
return status;
}
-static celix_status_t component_handleAdded(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency, dm_event_pt event) {
- celix_status_t status = CELIX_SUCCESS;
-
- pthread_mutex_lock(&component->mutex);
- array_list_pt events = hashMap_get(component->dependencyEvents, dependency);
- arrayList_add(events, event);
- pthread_mutex_unlock(&component->mutex);
-
- serviceDependency_setAvailable(dependency, true);
-
+static celix_status_t component_handleAdd(celix_dm_component_t *component, const celix_dm_event_t* event) {
+ celixThreadMutex_lock(&component->mutex);
switch (component->state) {
- case DM_CMP_STATE_WAITING_FOR_REQUIRED: {
- serviceDependency_invokeSet(dependency, event);
- bool required = false;
- serviceDependency_isRequired(dependency, &required);
- if (required) {
- component_handleChange(component);
- }
- break;
- }
- case DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED: {
- bool instanceBound = false;
- serviceDependency_isInstanceBound(dependency, &instanceBound);
- bool required = false;
- serviceDependency_isRequired(dependency, &required);
- if (!instanceBound) {
- if (required) {
- serviceDependency_invokeSet(dependency, event);
- serviceDependency_invokeAdd(dependency, event);
- }
- dm_event_pt event = NULL;
- component_getDependencyEvent(component, dependency, &event);
- component_updateInstance(component, dependency, event, false, true);
- }
-
- if (required) {
- component_handleChange(component);
- }
- break;
- }
case DM_CMP_STATE_TRACKING_OPTIONAL:
- component_suspend(component,dependency);
- serviceDependency_invokeSet(dependency, event);
- serviceDependency_invokeAdd(dependency, event);
- component_resume(component,dependency);
- dm_event_pt event = NULL;
- component_getDependencyEvent(component, dependency, &event);
- component_updateInstance(component, dependency, event, false, true);
+ if (celix_serviceDependency_hasAddCallback(event->dep)) { //if to prevent unneeded suspends
+ component_suspend(component, event->dep);
+ celix_serviceDependency_invokeAdd(event->dep, event->svc, event->props);
+ component_resume(component, event->dep);
+ }
break;
- default:
+ default: //DM_CMP_STATE_INACTIVE
+ celix_serviceDependency_invokeAdd(event->dep, event->svc, event->props);
break;
}
-
- return status;
-}
-
-static celix_status_t component_handleChanged(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency, dm_event_pt event) {
- celix_status_t status = CELIX_SUCCESS;
-
- pthread_mutex_lock(&component->mutex);
- array_list_pt events = hashMap_get(component->dependencyEvents, dependency);
- int index = arrayList_indexOf(events, event);
- if (index < 0) {
- pthread_mutex_unlock(&component->mutex);
- status = CELIX_BUNDLE_EXCEPTION;
- } else {
- dm_event_pt old = arrayList_remove(events, (unsigned int) index);
- arrayList_add(events, event);
- pthread_mutex_unlock(&component->mutex);
-
- serviceDependency_invokeSet(dependency, event);
- switch (component->state) {
- case DM_CMP_STATE_TRACKING_OPTIONAL:
- component_suspend(component,dependency);
- serviceDependency_invokeChange(dependency, event);
- component_resume(component,dependency);
- dm_event_pt hevent = NULL;
- component_getDependencyEvent(component, dependency, &hevent);
- component_updateInstance(component, dependency, hevent, true, false);
- break;
- case DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED: {
- bool instanceBound = false;
- serviceDependency_isInstanceBound(dependency, &instanceBound);
- if (!instanceBound) {
- serviceDependency_invokeChange(dependency, event);
- dm_event_pt hevent = NULL;
- component_getDependencyEvent(component, dependency, &hevent);
- component_updateInstance(component, dependency, hevent, true, false);
- }
- break;
- }
- default:
- break;
- }
-
- event_destroy(&old);
- }
-
- return status;
+ component_handleChange(component);
+ celixThreadMutex_unlock(&component->mutex);
+ return CELIX_SUCCESS;
}
-static celix_status_t component_handleRemoved(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency, dm_event_pt event) {
- celix_status_t status = CELIX_SUCCESS;
-
- pthread_mutex_lock(&component->mutex);
- array_list_pt events = hashMap_get(component->dependencyEvents, dependency);
- int size = arrayList_size(events);
- if (arrayList_contains(events, event)) {
- size--;
- }
- pthread_mutex_unlock(&component->mutex);
- serviceDependency_setAvailable(dependency, size > 0);
+static celix_status_t component_handleRemove(celix_dm_component_t *component, const celix_dm_event_t* event) {
+ celixThreadMutex_lock(&component->mutex);
component_handleChange(component);
-
- pthread_mutex_lock(&component->mutex);
- int index = arrayList_indexOf(events, event);
- if (index < 0) {
- pthread_mutex_unlock(&component->mutex);
- status = CELIX_BUNDLE_EXCEPTION;
- } else {
- dm_event_pt old = arrayList_remove(events, (unsigned int) index);
- pthread_mutex_unlock(&component->mutex);
-
-
- switch (component->state) {
- case DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED: {
- serviceDependency_invokeSet(dependency, event);
- bool instanceBound = false;
- serviceDependency_isInstanceBound(dependency, &instanceBound);
- if (!instanceBound) {
- bool required = false;
- serviceDependency_isRequired(dependency, &required);
- if (required) {
- serviceDependency_invokeRemove(dependency, event);
- }
- dm_event_pt hevent = NULL;
- component_getDependencyEvent(component, dependency, &hevent);
- component_updateInstance(component, dependency, hevent, false, false);
- }
- break;
+ switch (component->state) {
+ case DM_CMP_STATE_TRACKING_OPTIONAL:
+ if (celix_serviceDependency_hasRemoveCallback(event->dep)) { //if to prevent unneeded suspends
+ component_suspend(component, event->dep);
+ celix_serviceDependency_invokeRemove(event->dep, event->svc, event->props);
+ component_resume(component, event->dep);
}
- case DM_CMP_STATE_TRACKING_OPTIONAL:
- component_suspend(component,dependency);
- serviceDependency_invokeSet(dependency, event);
- serviceDependency_invokeRemove(dependency, event);
- component_resume(component,dependency);
- dm_event_pt hevent = NULL;
- component_getDependencyEvent(component, dependency, &hevent);
- component_updateInstance(component, dependency, hevent, false, false);
- break;
- default:
- break;
- }
-
- event_destroy(&event);
- if (old) {
- event_destroy(&old);
- }
+ break;
+ default: //DM_CMP_STATE_INACTIVE
+ celix_serviceDependency_invokeRemove(event->dep, event->svc, event->props);
+ break;
}
-
- return status;
+ celixThreadMutex_unlock(&component->mutex);
+ return CELIX_SUCCESS;
}
-static celix_status_t component_handleSwapped(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency, dm_event_pt event, dm_event_pt newEvent) {
- celix_status_t status = CELIX_SUCCESS;
- pthread_mutex_lock(&component->mutex);
- array_list_pt events = hashMap_get(component->dependencyEvents, dependency);
- int index = arrayList_indexOf(events, event);
- if (index < 0) {
- pthread_mutex_unlock(&component->mutex);
- status = CELIX_BUNDLE_EXCEPTION;
- } else {
- dm_event_pt old = arrayList_remove(events, (unsigned int) index);
- arrayList_add(events, newEvent);
- pthread_mutex_unlock(&component->mutex);
-
- serviceDependency_invokeSet(dependency, event);
-
- switch (component->state) {
- case DM_CMP_STATE_WAITING_FOR_REQUIRED:
- break;
- case DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED: {
- bool instanceBound = false;
- serviceDependency_isInstanceBound(dependency, &instanceBound);
- if (!instanceBound) {
- bool required = false;
- serviceDependency_isRequired(dependency, &required);
- if (required) {
- serviceDependency_invokeSwap(dependency, event, newEvent);
- }
- }
- break;
+static celix_status_t component_handleSet(celix_dm_component_t *component, const celix_dm_event_t* event) {
+ celixThreadMutex_lock(&component->mutex);
+ if (event->svc == NULL) {
+ //note set with removes a service -> update state first
+ component_handleChange(component);
+ }
+ switch (component->state) {
+ case DM_CMP_STATE_TRACKING_OPTIONAL:
+ if (celix_serviceDependency_hasSetCallback(event->dep)) { //if to prevent unneeded suspends
+ component_suspend(component, event->dep);
+ celix_serviceDependency_invokeSet(event->dep, event->svc, event->props);
+ component_resume(component, event->dep);
}
- case DM_CMP_STATE_TRACKING_OPTIONAL:
- component_suspend(component,dependency);
- serviceDependency_invokeSwap(dependency, event, newEvent);
- component_resume(component,dependency);
- break;
- default:
- break;
- }
-
- event_destroy(&event);
- if (old) {
- event_destroy(&old);
- }
+ break;
+ default: //DM_CMP_STATE_INACTIVE
+ celix_serviceDependency_invokeSet(event->dep, event->svc, event->props);
+ break;
}
-
- return status;
-}
-
-static celix_status_t component_updateInstance(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency, dm_event_pt event, bool update, bool add) {
- celix_status_t status = CELIX_SUCCESS;
-
- bool autoConfig = false;
-
- serviceDependency_isAutoConfig(dependency, &autoConfig);
-
- if (autoConfig) {
- const void *service = NULL;
- const void **field = NULL;
-
- if (event != NULL) {
- event_getService(event, &service);
- }
- serviceDependency_getAutoConfig(dependency, &field);
- serviceDependency_lock(dependency);
- *field = service;
- serviceDependency_unlock(dependency);
+ if (event->svc != NULL) {
+ component_handleChange(component);
}
-
- return status;
+ celixThreadMutex_unlock(&component->mutex);
+ return CELIX_SUCCESS;
}
-static celix_status_t component_startDependencies(celix_dm_component_t *component __attribute__((unused)), array_list_pt dependencies) {
- celix_status_t status = CELIX_SUCCESS;
- array_list_pt required_dependencies = NULL;
- arrayList_create(&required_dependencies);
-
- for (unsigned int i = 0; i < arrayList_size(dependencies); i++) {
- celix_dm_service_dependency_t *dependency = arrayList_get(dependencies, i);
- bool required = false;
- serviceDependency_isRequired(dependency, &required);
- if (required) {
- arrayList_add(required_dependencies, dependency);
- continue;
+/**
+ * perform state transition. This call should be called with the component->mutex locked.
+ */
+static celix_status_t component_startDependencies(celix_dm_component_t *component) {
+ for (int i = 0; i < celix_arrayList_size(component->dependencies); i++) {
+ celix_dm_service_dependency_t *dependency = arrayList_get(component->dependencies, i);
+ if (!celix_dmServiceDependency_isStarted(dependency)) {
+ celixThreadMutex_unlock(&component->mutex);
+ celix_serviceDependency_start(dependency); //TODO race condition. unlock/lock can be removed with async branch -> async startServiceTracker
+ celixThreadMutex_lock(&component->mutex);
}
-
- serviceDependency_start(dependency);
- }
-
- for (unsigned int i = 0; i < arrayList_size(required_dependencies); i++) {
- celix_dm_service_dependency_t *dependency = arrayList_get(required_dependencies, i);
- serviceDependency_start(dependency);
}
-
- arrayList_destroy(required_dependencies);
-
- return status;
+ return CELIX_SUCCESS;
}
+/**
+ * perform state transition. This call should be called with the component->mutex locked.
+ */
static celix_status_t component_stopDependencies(celix_dm_component_t *component) {
- celix_status_t status = CELIX_SUCCESS;
-
- pthread_mutex_lock(&component->mutex);
- for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) {
+ for (int i = 0; i < celix_arrayList_size(component->dependencies); i++) {
celix_dm_service_dependency_t *dependency = arrayList_get(component->dependencies, i);
- pthread_mutex_unlock(&component->mutex);
- serviceDependency_stop(dependency);
- pthread_mutex_lock(&component->mutex);
+ if (celix_dmServiceDependency_isStarted(dependency)) {
+ celixThreadMutex_unlock(&component->mutex);
+ celix_serviceDependency_stop(dependency); //TODO race condition. unlock/lock can be removed with async branch -> async stopServiceTracker
+ celixThreadMutex_lock(&component->mutex);
+ }
}
- pthread_mutex_unlock(&component->mutex);
-
- return status;
+ return CELIX_SUCCESS;
}
+/**
+ * Calculate and handle state change. This call should be called with the component->mutex locked.
+ */
static celix_status_t component_handleChange(celix_dm_component_t *component) {
celix_status_t status = CELIX_SUCCESS;
@@ -814,8 +489,8 @@ static celix_status_t component_handleChange(celix_dm_component_t *component) {
oldState = component->state;
status = component_calculateNewState(component, oldState, &newState);
if (status == CELIX_SUCCESS) {
- component->state = newState;
status = component_performTransition(component, oldState, newState, &transition);
+ component->state = newState;
}
if (status != CELIX_SUCCESS) {
@@ -826,9 +501,13 @@ static celix_status_t component_handleChange(celix_dm_component_t *component) {
return status;
}
+/**
+ * Calculate possible state change. This call should be called with the component->mutex locked.
+ */
static celix_status_t component_calculateNewState(celix_dm_component_t *component, celix_dm_component_state_t currentState, celix_dm_component_state_t *newState) {
celix_status_t status = CELIX_SUCCESS;
+ bool allResolved = component_areAllRequiredServiceDependenciesResolved(component);
if (currentState == DM_CMP_STATE_INACTIVE) {
if (component->isStarted) {
*newState = DM_CMP_STATE_WAITING_FOR_REQUIRED;
@@ -839,10 +518,7 @@ static celix_status_t component_calculateNewState(celix_dm_component_t *componen
if (!component->isStarted) {
*newState = DM_CMP_STATE_INACTIVE;
} else {
- bool available = false;
- component_allRequiredAvailable(component, &available);
-
- if (available) {
+ if (allResolved) {
*newState = DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED;
} else {
*newState = currentState;
@@ -852,30 +528,14 @@ static celix_status_t component_calculateNewState(celix_dm_component_t *componen
if (!component->isStarted) {
*newState = DM_CMP_STATE_WAITING_FOR_REQUIRED;
} else {
- bool available = false;
- component_allRequiredAvailable(component, &available);
-
- if (available) {
- bool instanceBoundAvailable = false;
- component_allInstanceBoundAvailable(component, &instanceBoundAvailable);
-
- if (instanceBoundAvailable) {
- *newState = DM_CMP_STATE_TRACKING_OPTIONAL;
- } else {
- *newState = currentState;
- }
+ if (allResolved) {
+ *newState = DM_CMP_STATE_TRACKING_OPTIONAL;
} else {
*newState = currentState;
}
}
} else if (currentState == DM_CMP_STATE_TRACKING_OPTIONAL) {
- bool instanceBoundAvailable = false;
- bool available = false;
-
- component_allInstanceBoundAvailable(component, &instanceBoundAvailable);
- component_allRequiredAvailable(component, &available);
-
- if (component->isStarted && available && instanceBoundAvailable) {
+ if (component->isStarted && allResolved) {
*newState = currentState;
} else {
*newState = DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED;
@@ -889,26 +549,25 @@ static celix_status_t component_calculateNewState(celix_dm_component_t *componen
return status;
}
+/**
+ * perform state transition. This call should be called with the component->mutex locked.
+ */
static celix_status_t component_performTransition(celix_dm_component_t *component, celix_dm_component_state_t oldState, celix_dm_component_state_t newState, bool *transition) {
celix_status_t status = CELIX_SUCCESS;
- //printf("performing transition for %s in thread %i from %i to %i\n", component->name, (int) pthread_self(), oldState, newState);
+ //TODO improve log (via bundle context?)
+ fw_log(component->context->framework->logger, CELIX_LOG_LEVEL_TRACE, "performing transition for component %s from state %i to state %i\n", component->name, oldState, newState);
if (oldState == newState) {
*transition = false;
} else if (oldState == DM_CMP_STATE_INACTIVE && newState == DM_CMP_STATE_WAITING_FOR_REQUIRED) {
- component_startDependencies(component, component->dependencies);
+ component_startDependencies(component);
*transition = true;
} else if (oldState == DM_CMP_STATE_WAITING_FOR_REQUIRED && newState == DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED) {
- component_invokeAddRequiredDependencies(component);
- component_invokeAutoConfigDependencies(component);
if (component->callbackInit) {
status = component->callbackInit(component->implementation);
}
*transition = true;
} else if (oldState == DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED && newState == DM_CMP_STATE_TRACKING_OPTIONAL) {
- component_invokeAddRequiredInstanceBoundDependencies(component);
- component_invokeAutoConfigInstanceBoundDependencies(component);
- component_invokeAddOptionalDependencies(component);
if (component->callbackStart) {
status = component->callbackStart(component->implementation);
}
@@ -919,14 +578,11 @@ static celix_status_t component_performTransition(celix_dm_component_t *componen
if (component->callbackStop) {
status = component->callbackStop(component->implementation);
}
- component_invokeRemoveOptionalDependencies(component);
- component_invokeRemoveInstanceBoundDependencies(component);
*transition = true;
} else if (oldState == DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED && newState == DM_CMP_STATE_WAITING_FOR_REQUIRED) {
if (component->callbackDeinit) {
status = component->callbackDeinit(component->implementation);
}
- component_invokeRemoveRequiredDependencies(component);
*transition = true;
} else if (oldState == DM_CMP_STATE_WAITING_FOR_REQUIRED && newState == DM_CMP_STATE_INACTIVE) {
component_stopDependencies(component);
@@ -936,355 +592,61 @@ static celix_status_t component_performTransition(celix_dm_component_t *componen
return status;
}
-static celix_status_t component_allRequiredAvailable(celix_dm_component_t *component, bool *available) {
- celix_status_t status = CELIX_SUCCESS;
-
- pthread_mutex_lock(&component->mutex);
- *available = true;
- for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) {
- celix_dm_service_dependency_t *dependency = arrayList_get(component->dependencies, i);
- bool required = false;
- bool instanceBound = false;
-
- serviceDependency_isRequired(dependency, &required);
- serviceDependency_isInstanceBound(dependency, &instanceBound);
-
- if (required && !instanceBound) {
- bool isAvailable = false;
- serviceDependency_isAvailable(dependency, &isAvailable);
- if (!isAvailable) {
- *available = false;
- break;
- }
- }
- }
- pthread_mutex_unlock(&component->mutex);
-
- return status;
-}
-
-static celix_status_t component_allInstanceBoundAvailable(celix_dm_component_t *component, bool *available) {
- celix_status_t status = CELIX_SUCCESS;
-
- pthread_mutex_lock(&component->mutex);
- *available = true;
- for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) {
- celix_dm_service_dependency_t *dependency = arrayList_get(component->dependencies, i);
- bool required = false;
- bool instanceBound = false;
-
- serviceDependency_isRequired(dependency, &required);
- serviceDependency_isInstanceBound(dependency, &instanceBound);
-
- if (required && instanceBound) {
- bool isAvailable = false;
- serviceDependency_isAvailable(dependency, &isAvailable);
- if (!isAvailable) {
- *available = false;
- break;
- }
- }
- }
- pthread_mutex_unlock(&component->mutex);
-
- return status;
-}
-
-static celix_status_t component_invokeAddRequiredDependencies(celix_dm_component_t *component) {
- celix_status_t status = CELIX_SUCCESS;
-
- pthread_mutex_lock(&component->mutex);
- for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) {
- celix_dm_service_dependency_t *dependency = arrayList_get(component->dependencies, i);
-
- bool required = false;
- bool instanceBound = false;
-
- serviceDependency_isRequired(dependency, &required);
- serviceDependency_isInstanceBound(dependency, &instanceBound);
-
- if (required && !instanceBound) {
- array_list_pt events = hashMap_get(component->dependencyEvents, dependency);
- if (events) {
- for (unsigned int j = 0; j < arrayList_size(events); j++) {
- dm_event_pt event = arrayList_get(events, j);
- serviceDependency_invokeAdd(dependency, event);
- }
- }
- }
- }
- pthread_mutex_unlock(&component->mutex);
-
- return status;
-}
-
-static celix_status_t component_invokeAutoConfigDependencies(celix_dm_component_t *component) {
- celix_status_t status = CELIX_SUCCESS;
-
- pthread_mutex_lock(&component->mutex);
- for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) {
- celix_dm_service_dependency_t *dependency = arrayList_get(component->dependencies, i);
-
- bool autoConfig = false;
- bool instanceBound = false;
-
- serviceDependency_isAutoConfig(dependency, &autoConfig);
- serviceDependency_isInstanceBound(dependency, &instanceBound);
-
- if (autoConfig && !instanceBound) {
- component_configureImplementation(component, dependency);
- }
- }
- pthread_mutex_unlock(&component->mutex);
-
- return status;
-}
-
-static celix_status_t component_invokeAutoConfigInstanceBoundDependencies(celix_dm_component_t *component) {
- celix_status_t status = CELIX_SUCCESS;
-
- pthread_mutex_lock(&component->mutex);
- for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) {
- celix_dm_service_dependency_t *dependency = arrayList_get(component->dependencies, i);
-
- bool autoConfig = false;
- bool instanceBound = false;
-
- serviceDependency_isAutoConfig(dependency, &autoConfig);
- serviceDependency_isInstanceBound(dependency, &instanceBound);
-
- if (autoConfig && instanceBound) {
- component_configureImplementation(component, dependency);
- }
- }
- pthread_mutex_unlock(&component->mutex);
-
- return status;
-}
-
-static celix_status_t component_invokeAddRequiredInstanceBoundDependencies(celix_dm_component_t *component) {
- celix_status_t status = CELIX_SUCCESS;
-
- pthread_mutex_lock(&component->mutex);
- for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) {
- celix_dm_service_dependency_t *dependency = arrayList_get(component->dependencies, i);
-
- bool required = false;
- bool instanceBound = false;
-
- serviceDependency_isRequired(dependency, &required);
- serviceDependency_isInstanceBound(dependency, &instanceBound);
-
- if (instanceBound && required) {
- array_list_pt events = hashMap_get(component->dependencyEvents, dependency);
- if (events) {
- for (unsigned int j = 0; j < arrayList_size(events); j++) {
- dm_event_pt event = arrayList_get(events, j);
- serviceDependency_invokeAdd(dependency, event);
- }
- }
- }
- }
- pthread_mutex_unlock(&component->mutex);
-
- return status;
-}
-
-static celix_status_t component_invokeAddOptionalDependencies(celix_dm_component_t *component) {
- celix_status_t status = CELIX_SUCCESS;
-
- pthread_mutex_lock(&component->mutex);
- for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) {
- celix_dm_service_dependency_t *dependency = arrayList_get(component->dependencies, i);
-
- bool required = false;
-
- serviceDependency_isRequired(dependency, &required);
-
- if (!required) {
- array_list_pt events = hashMap_get(component->dependencyEvents, dependency);
- if (events) {
- for (unsigned int j = 0; j < arrayList_size(events); j++) {
- dm_event_pt event = arrayList_get(events, j);
- serviceDependency_invokeAdd(dependency, event);
- }
- }
- }
- }
- pthread_mutex_unlock(&component->mutex);
-
- return status;
-}
-
-static celix_status_t component_invokeRemoveOptionalDependencies(celix_dm_component_t *component) {
- celix_status_t status = CELIX_SUCCESS;
-
- pthread_mutex_lock(&component->mutex);
- for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) {
- celix_dm_service_dependency_t *dependency = arrayList_get(component->dependencies, i);
-
- bool required = false;
-
- serviceDependency_isRequired(dependency, &required);
-
- if (!required) {
- array_list_pt events = hashMap_get(component->dependencyEvents, dependency);
- if (events) {
- for (unsigned int j = 0; j < arrayList_size(events); j++) {
- dm_event_pt event = arrayList_get(events, j);
- serviceDependency_invokeRemove(dependency, event);
- }
- }
- }
- }
- pthread_mutex_unlock(&component->mutex);
-
- return status;
-}
-
-static celix_status_t component_invokeRemoveInstanceBoundDependencies(celix_dm_component_t *component) {
- celix_status_t status = CELIX_SUCCESS;
-
- pthread_mutex_lock(&component->mutex);
- for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) {
- celix_dm_service_dependency_t *dependency = arrayList_get(component->dependencies, i);
-
- bool instanceBound = false;
-
- serviceDependency_isInstanceBound(dependency, &instanceBound);
-
- if (instanceBound) {
- array_list_pt events = hashMap_get(component->dependencyEvents, dependency);
- if (events) {
- for (unsigned int j = 0; j < arrayList_size(events); j++) {
- dm_event_pt event = arrayList_get(events, j);
- serviceDependency_invokeRemove(dependency, event);
- }
- }
- }
- }
- pthread_mutex_unlock(&component->mutex);
-
- return status;
-}
-
-static celix_status_t component_invokeRemoveRequiredDependencies(celix_dm_component_t *component) {
- celix_status_t status = CELIX_SUCCESS;
-
- pthread_mutex_lock(&component->mutex);
- for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) {
- celix_dm_service_dependency_t *dependency = arrayList_get(component->dependencies, i);
-
- bool required = false;
- bool instanceBound = false;
-
- serviceDependency_isRequired(dependency, &required);
- serviceDependency_isInstanceBound(dependency, &instanceBound);
-
- if (!instanceBound && required) {
- array_list_pt events = hashMap_get(component->dependencyEvents, dependency);
- if (events) {
- for (unsigned int j = 0; j < arrayList_size(events); j++) {
- dm_event_pt event = arrayList_get(events, j);
- serviceDependency_invokeRemove(dependency, event);
- }
- }
- }
- }
- pthread_mutex_unlock(&component->mutex);
-
- return status;
-}
-
-static celix_status_t component_getDependencyEvent(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency, dm_event_pt *event_pptr) {
- celix_status_t status = CELIX_SUCCESS;
-
- array_list_pt events = hashMap_get(component->dependencyEvents, dependency);
- *event_pptr = NULL;
-
- if (events) {
- for (unsigned int j = 0; j < arrayList_size(events); j++) {
- dm_event_pt event_ptr = arrayList_get(events, j);
- if (*event_pptr != NULL) {
- int compare = 0;
- event_compareTo(event_ptr, *event_pptr, &compare);
- if (compare > 0) {
- *event_pptr = event_ptr;
- }
- } else {
- *event_pptr = event_ptr;
- }
- }
- }
-
- return status;
-}
-
-static celix_status_t component_configureImplementation(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency) {
- celix_status_t status = CELIX_SUCCESS;
-
- const void **field = NULL;
-
- array_list_pt events = hashMap_get(component->dependencyEvents, dependency);
- if (events) {
- const void *service = NULL;
- dm_event_pt event = NULL;
- component_getDependencyEvent(component, dependency, &event);
- if (event != NULL) {
- event_getService(event, &service);
- serviceDependency_getAutoConfig(dependency, &field);
- serviceDependency_lock(dependency);
- *field = service;
- serviceDependency_unlock(dependency);
+/**
+ * Check if all required dependencies are resolved. This call should be called with the component->mutex locked.
+ */
+static bool component_areAllRequiredServiceDependenciesResolved(celix_dm_component_t *component) {
+ bool allResolved = true;
+ for (int i = 0; i < celix_arrayList_size(component->dependencies); i++) {
+ celix_dm_service_dependency_t *dependency = celix_arrayList_get(component->dependencies, i);
+ bool started = celix_dmServiceDependency_isStarted(dependency);
+ bool required = celix_dmServiceDependency_isRequired(dependency);
+ bool available = celix_serviceDependency_isAvailable(dependency);
+ if (started && required && !available) {
+ allResolved = false;
+ break;
}
}
-
- return status;
+ return allResolved;
}
+/**
+ * Register component services (if not already registered). This call should be called with the component->mutex locked.
+ */
static celix_status_t component_registerServices(celix_dm_component_t *component) {
- celix_status_t status = CELIX_SUCCESS;
-
- if (component->context != NULL) {
- unsigned int i;
- celixThreadMutex_lock(&component->mutex);
- for (i = 0; i < arrayList_size(component->dm_interfaces); i++) {
- dm_interface_t *interface = arrayList_get(component->dm_interfaces, i);
- if (interface->svcId == -1L) {
- celix_properties_t *regProps = celix_properties_copy(interface->properties);
- celix_service_registration_options_t opts = CELIX_EMPTY_SERVICE_REGISTRATION_OPTIONS;
- opts.properties = regProps;
- opts.svc = (void*)interface->service;
- opts.serviceName = interface->serviceName;
- opts.serviceLanguage = celix_properties_get(regProps, CELIX_FRAMEWORK_SERVICE_LANGUAGE, NULL);
- interface->svcId = celix_bundleContext_registerServiceWithOptions(component->context, &opts);
- }
+ for (int i = 0; i < celix_arrayList_size(component->providedInterfaces); i++) {
+ dm_interface_t *interface = arrayList_get(component->providedInterfaces, i);
+ if (interface->svcId == -1L) {
+ celix_properties_t *regProps = celix_properties_copy(interface->properties);
+ celix_service_registration_options_t opts = CELIX_EMPTY_SERVICE_REGISTRATION_OPTIONS;
+ opts.properties = regProps;
+ opts.svc = (void*)interface->service;
+ opts.serviceName = interface->serviceName;
+ opts.serviceLanguage = celix_properties_get(regProps, CELIX_FRAMEWORK_SERVICE_LANGUAGE, NULL);
+ celixThreadMutex_unlock(&component->mutex);
+ long svcId = celix_bundleContext_registerServiceWithOptions(component->context, &opts); //TODO fix race condition with async branch -> registerAsync
+ celixThreadMutex_lock(&component->mutex);
+ interface->svcId = svcId;
}
- celixThreadMutex_unlock(&component->mutex);
}
-
- return status;
+ return CELIX_SUCCESS;
}
+/**
+ * Unregister component services. This call should be called with the component->mutex locked.
+ */
static celix_status_t component_unregisterServices(celix_dm_component_t *component) {
celix_status_t status = CELIX_SUCCESS;
- celix_array_list_t *ids = celix_arrayList_create();
-
- celixThreadMutex_lock(&component->mutex);
- for (int i = 0; i < celix_arrayList_size(component->dm_interfaces); ++i) {
- dm_interface_t *interface = arrayList_get(component->dm_interfaces, i);
- celix_arrayList_addLong(ids, interface->svcId);
+ for (int i = 0; i < celix_arrayList_size(component->providedInterfaces); ++i) {
+ dm_interface_t *interface = arrayList_get(component->providedInterfaces, i);
+ long svcId = interface->svcId;
interface->svcId = -1L;
- }
- celixThreadMutex_unlock(&component->mutex);
-
- for (int i = 0; i < celix_arrayList_size(ids); ++i) {
- long svcId = celix_arrayList_getLong(ids, i);
- celix_bundleContext_unregisterService(component->context, svcId);
+ celixThreadMutex_unlock(&component->mutex);
+ celix_bundleContext_unregisterService(component->context, svcId); //TODO fix race condition with async branch -> unregister async
+ celixThreadMutex_lock(&component->mutex);
}
- celix_arrayList_destroy(ids);
return status;
}
@@ -1294,9 +656,6 @@ celix_status_t component_setCallbacks(celix_dm_component_t *component, celix_dm_
}
celix_status_t celix_dmComponent_setCallbacks(celix_dm_component_t *component, celix_dm_cmp_lifecycle_fpt init, celix_dm_cmp_lifecycle_fpt start, celix_dm_cmp_lifecycle_fpt stop, celix_dm_cmp_lifecycle_fpt deinit) {
- if (component->active) {
- return CELIX_ILLEGAL_STATE;
- }
component->callbackInit = init;
component->callbackStart = start;
component->callbackStop = stop;
@@ -1304,13 +663,6 @@ celix_status_t celix_dmComponent_setCallbacks(celix_dm_component_t *component, c
return CELIX_SUCCESS;
}
-
-/*
-celix_status_t component_isAvailable(celix_dm_component_t *component, bool *available) {
- *available = component->state == DM_CMP_STATE_TRACKING_OPTIONAL;
- return CELIX_SUCCESS;
-}*/
-
celix_status_t component_setImplementation(celix_dm_component_t *component, void *implementation) {
return celix_dmComponent_setImplementation(component, implementation);
}
@@ -1333,125 +685,6 @@ celix_bundle_context_t* celix_dmComponent_getBundleContext(celix_dm_component_t
return result;
}
-
-static celix_status_t executor_create(celix_dm_component_t *component __attribute__((unused)), dm_executor_pt *executor) {
- celix_status_t status = CELIX_SUCCESS;
-
- *executor = malloc(sizeof(**executor));
- if (!*executor) {
- status = CELIX_ENOMEM;
- } else {
- (*executor)->workQueue = celix_arrayList_create();
- pthread_mutex_init(&(*executor)->mutex, NULL);
- (*executor)->runningThreadSet = false;
- }
-
- return status;
-}
-
-static void executor_destroy(dm_executor_pt executor) {
-
- if (executor) {
- pthread_mutex_destroy(&executor->mutex);
- celix_arrayList_destroy(executor->workQueue);
-
- free(executor);
- }
-}
-
-static celix_status_t executor_schedule(dm_executor_pt executor, celix_dm_component_t *component, void (*command), void *data) {
- celix_status_t status = CELIX_SUCCESS;
-
- dm_executor_task_t *task = NULL;
- task = malloc(sizeof(*task));
- if (!task) {
- status = CELIX_ENOMEM;
- } else {
- task->component = component;
- task->command = command;
- task->data = data;
-
- pthread_mutex_lock(&executor->mutex);
- celix_arrayList_add(executor->workQueue, task);
- pthread_mutex_unlock(&executor->mutex);
- }
-
- return status;
-}
-
-static celix_status_t executor_executeTask(dm_executor_pt executor, celix_dm_component_t *component, void (*command), void *data) {
- celix_status_t status = CELIX_SUCCESS;
-
- // Check thread and executor thread, if the same, execute immediately.
-// bool execute = false;
-// pthread_mutex_lock(&executor->mutex);
-// pthread_t currentThread = pthread_self();
-// if (pthread_equal(executor->runningThread, currentThread)) {
-// execute = true;
-// }
-// pthread_mutex_unlock(&executor->mutex);
-
- // For now, just schedule.
- executor_schedule(executor, component, command, data);
- executor_execute(executor);
-
- return status;
-}
-
-static celix_status_t executor_execute(dm_executor_pt executor) {
- celix_status_t status = CELIX_SUCCESS;
- pthread_t currentThread = pthread_self();
-
- pthread_mutex_lock(&executor->mutex);
- bool execute = false;
- if (!executor->runningThreadSet) {
- executor->runningThread = currentThread;
- executor->runningThreadSet = true;
- execute = true;
- }
- pthread_mutex_unlock(&executor->mutex);
- if (execute) {
- executor_runTasks(executor, currentThread);
- }
-
- return status;
-}
-
-static celix_status_t executor_runTasks(dm_executor_pt executor, pthread_t currentThread __attribute__((unused))) {
- celix_status_t status = CELIX_SUCCESS;
-// bool execute = false;
-
- dm_executor_task_t *entry = NULL;
-
- pthread_mutex_lock(&executor->mutex);
- if (celix_arrayList_size(executor->workQueue) > 0) {
- entry = celix_arrayList_get(executor->workQueue, 0);
- celix_arrayList_removeAt(executor->workQueue, 0);
- }
- pthread_mutex_unlock(&executor->mutex);
-
- while (entry != NULL) {
- entry->command(entry->component, entry->data);
- free(entry);
-
- pthread_mutex_lock(&executor->mutex);
- if (celix_arrayList_size(executor->workQueue) > 0) {
- entry = celix_arrayList_get(executor->workQueue, 0);
- celix_arrayList_removeAt(executor->workQueue, 0);
- } else {
- entry = NULL;
- }
- pthread_mutex_unlock(&executor->mutex);
- }
-
-
- pthread_mutex_lock(&executor->mutex);
- executor->runningThreadSet = false;
- pthread_mutex_unlock(&executor->mutex);
-
- return status;
-}
-
celix_status_t component_getComponentInfo(celix_dm_component_t *component, dm_component_info_pt *out) {
return celix_dmComponent_getComponentInfo(component, out);
}
@@ -1470,7 +703,7 @@ celix_status_t celix_dmComponent_getComponentInfo(celix_dm_component_t *componen
arrayList_create(&info->dependency_list);
component_getInterfaces(component, &info->interfaces);
info->active = false;
- memcpy(info->id, component->id, DM_COMPONENT_MAX_ID_LENGTH);
+ memcpy(info->id, component->uuid, DM_COMPONENT_MAX_ID_LENGTH);
memcpy(info->name, component->name, DM_COMPONENT_MAX_NAME_LENGTH);
switch (component->state) {
@@ -1493,13 +726,13 @@ celix_status_t celix_dmComponent_getComponentInfo(celix_dm_component_t *componen
}
celixThreadMutex_lock(&component->mutex);
- size = arrayList_size(component->dependencies);
+ size = celix_arrayList_size(component->dependencies);
for (i = 0; i < size; i += 1) {
- celix_dm_service_dependency_t *dep = arrayList_get(component->dependencies, i);
+ celix_dm_service_dependency_t *dep = celix_arrayList_get(component->dependencies, i);
dm_service_dependency_info_pt depInfo = NULL;
status = serviceDependency_getServiceDependencyInfo(dep, &depInfo);
if (status == CELIX_SUCCESS) {
- arrayList_add(info->dependency_list, depInfo);
+ celix_arrayList_add(info->dependency_list, depInfo);
} else {
break;
}
@@ -1525,30 +758,30 @@ void celix_dmComponent_destroyComponentInfo(dm_component_info_pt info) {
free(info->state);
if (info->interfaces != NULL) {
- size = arrayList_size(info->interfaces);
+ size = celix_arrayList_size(info->interfaces);
for (i = 0; i < size; i += 1) {
- dm_interface_info_pt intfInfo = arrayList_get(info->interfaces, i);
+ dm_interface_info_pt intfInfo = celix_arrayList_get(info->interfaces, i);
free(intfInfo->name);
properties_destroy(intfInfo->properties);
free(intfInfo);
}
- arrayList_destroy(info->interfaces);
+ celix_arrayList_destroy(info->interfaces);
}
if (info->dependency_list != NULL) {
- size = arrayList_size(info->dependency_list);
+ size = celix_arrayList_size(info->dependency_list);
for (i = 0; i < size; i += 1) {
- dm_service_dependency_info_pt depInfo = arrayList_get(info->dependency_list, i);
+ dm_service_dependency_info_pt depInfo = celix_arrayList_get(info->dependency_list, i);
dependency_destroyDependencyInfo(depInfo);
}
- arrayList_destroy(info->dependency_list);
+ celix_arrayList_destroy(info->dependency_list);
}
}
free(info);
}
bool celix_dmComponent_isActive(celix_dm_component_t *component) {
- pthread_mutex_lock(&component->mutex);
+ celixThreadMutex_lock(&component->mutex);
bool active = component->state == DM_CMP_STATE_TRACKING_OPTIONAL;
- pthread_mutex_unlock(&component->mutex);
+ celixThreadMutex_unlock(&component->mutex);
return active;
}
diff --git a/libs/framework/src/dm_component_impl.h b/libs/framework/src/dm_component_impl.h
index db92d2b..897b0bc 100644
--- a/libs/framework/src/dm_component_impl.h
+++ b/libs/framework/src/dm_component_impl.h
@@ -33,13 +33,13 @@ extern "C" {
#include "dm_component.h"
#include "dm_service_dependency_impl.h"
-#include "dm_event.h"
+#include "celix_dm_event.h"
celix_status_t celix_private_dmComponent_start(celix_dm_component_t *component);
celix_status_t celix_private_dmComponent_stop(celix_dm_component_t *component);
-celix_status_t celix_private_dmComponent_handleEvent(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency, dm_event_pt event);
+celix_status_t celix_private_dmComponent_handleEvent(celix_dm_component_t *component, const celix_dm_event_t* event);
#ifdef __cplusplus
}
diff --git a/libs/framework/src/dm_event.c b/libs/framework/src/dm_event.c
deleted file mode 100644
index de03f50..0000000
--- a/libs/framework/src/dm_event.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * 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.
- */
-/**
- * dm_event.c
- *
- * \date 18 Dec 2014
- * \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- * \copyright Apache License, Version 2.0
- */
-
-#include <stdlib.h>
-#include "celix_constants.h"
-#include <utils.h>
-
-#include "dm_event.h"
-
-celix_status_t event_create(dm_event_type_e event_type, bundle_pt bundle, bundle_context_pt context, service_reference_pt reference, const void *service, dm_event_pt *event) {
- celix_status_t status = CELIX_SUCCESS;
-
- *event = calloc(1, sizeof(**event));
- if (!*event) {
- status = CELIX_ENOMEM;
- }
-
- const char* serviceIdStr = NULL;
- serviceReference_getProperty(reference, OSGI_FRAMEWORK_SERVICE_ID, &serviceIdStr);
- unsigned long servId = strtoul(serviceIdStr,NULL,10);
-
- const char* rankingStr = NULL;
- serviceReference_getProperty(reference, OSGI_FRAMEWORK_SERVICE_RANKING, &rankingStr);
- long ranking = rankingStr == NULL ? 0 : atol(rankingStr);
-
- if (status == CELIX_SUCCESS) {
- (*event)->bundle = bundle;
- (*event)->event_type = event_type;
- (*event)->context = context;
- (*event)->reference = reference;
- (*event)->service = service;
- (*event)->serviceId = servId;
- (*event)->ranking = ranking;
- }
-
- return status;
-}
-
-celix_status_t event_destroy(dm_event_pt *event) {
- celix_status_t status = CELIX_SUCCESS;
-
- if (!*event) {
- status = CELIX_ILLEGAL_ARGUMENT;
- }
-
- if (status == CELIX_SUCCESS) {
- free(*event);
- *event = NULL;
- }
-
- return status;
-}
-
-celix_status_t event_equals(const void *a, const void *b, bool *equals) {
- celix_status_t status = CELIX_SUCCESS;
-
- if (!a || !b) {
- *equals = false;
- } else {
- dm_event_pt a_ptr = (dm_event_pt)a;
- dm_event_pt b_ptr = (dm_event_pt)b;
-
- *equals = a_ptr->serviceId == b_ptr->serviceId;
- }
-
- return status;
-}
-
-celix_status_t event_compareTo(dm_event_pt event, dm_event_pt compareTo, int *compare) {
- celix_status_t status = CELIX_SUCCESS;
-
- *compare = utils_compareServiceIdsAndRanking(event->serviceId, event->ranking, compareTo->serviceId, compareTo->ranking);
-
- return status;
-}
-
-celix_status_t event_getService(dm_event_pt event, const void **service) {
- *service = event->service;
- return CELIX_SUCCESS;
-}
diff --git a/libs/framework/src/dm_event.h b/libs/framework/src/dm_event.h
deleted file mode 100644
index c2acf8d..0000000
--- a/libs/framework/src/dm_event.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.
- */
-/**
- * dm_event.h
- *
- * \date 17 Oct 2014
- * \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- * \copyright Apache License, Version 2.0
- */
-
-#ifndef DM_EVENT_H_
-#define DM_EVENT_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "service_reference.h"
-#include "bundle_context.h"
-#include "bundle.h"
-
-enum dm_event_type {
- DM_EVENT_ADDED,
- DM_EVENT_CHANGED,
- DM_EVENT_REMOVED,
- DM_EVENT_SWAPPED,
-};
-
-typedef enum dm_event_type dm_event_type_e;
-
-struct dm_event {
- const void* service;
- unsigned long serviceId;
- long ranking;
- service_reference_pt reference;
- bundle_context_pt context;
- bundle_pt bundle;
- dm_event_type_e event_type;
-};
-
-typedef struct dm_event *dm_event_pt;
-
-
-celix_status_t event_create(dm_event_type_e event_type, bundle_pt bundle, bundle_context_pt context, service_reference_pt reference, const void* service, dm_event_pt *event);
-celix_status_t event_destroy(dm_event_pt* event);
-
-celix_status_t event_equals(const void* a, const void* b, bool* equals);
-
-celix_status_t event_getService(dm_event_pt event, const void** service);
-celix_status_t event_compareTo(dm_event_pt event, dm_event_pt compareTo, int* compare);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* DM_EVENT_H_ */
diff --git a/libs/framework/src/dm_service_dependency.c b/libs/framework/src/dm_service_dependency.c
index 52118d2..2a242c1 100644
--- a/libs/framework/src/dm_service_dependency.c
+++ b/libs/framework/src/dm_service_dependency.c
@@ -16,31 +16,23 @@
* specific language governing permissions and limitations
* under the License.
*/
-/**
- * dm_service_dependency.c
- *
- * \date 17 Oct 2014
- * \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 <limits.h>
-#include <assert.h>
#include "celix_constants.h"
+#include "celix_utils.h"
#include "dm_service_dependency_impl.h"
#include "dm_component_impl.h"
+#include "bundle_context_private.h"
+#include "framework_private.h"
-#define DEFAULT_RANKING 0
#define DM_SERVICE_DEPENDENCY_DEFAULT_STRATEGY DM_SERVICE_DEPENDENCY_STRATEGY_SUSPEND
-static celix_status_t serviceDependency_addedService(void *_ptr, service_reference_pt reference, void *service);
-static celix_status_t serviceDependency_modifiedService(void *_ptr, service_reference_pt reference, void *service);
-static celix_status_t serviceDependency_removedService(void *_ptr, service_reference_pt reference, void *service);
+static void serviceDependency_addServiceTrackerCallback(void *handle, void *svc, const celix_properties_t *props);
+static void serviceDependency_removeServiceTrackerCallback(void *handle, void *svc, const celix_properties_t *props);
+static void serviceDependency_setServiceTrackerCallback(void *handle, void *svc, const celix_properties_t *props);
static void* serviceDependency_getCallbackHandle(celix_dm_service_dependency_t *dep);
celix_status_t serviceDependency_create(celix_dm_service_dependency_t **dependency_ptr) {
@@ -68,23 +60,13 @@ celix_status_t serviceDependency_destroy(celix_dm_service_dependency_t **depende
void celix_dmServiceDependency_destroy(celix_dm_service_dependency_t *dep) {
if (dep != NULL) {
- free(dep->tracked_service);
- free(dep->tracked_filter);
- free(dep->tracked_filter_unmodified);
+ free(dep->serviceName);
+ free(dep->versionRange);
+ free(dep->filter);
free(dep);
}
}
-celix_status_t serviceDependency_lock(celix_dm_service_dependency_t *dependency) {
- celixThreadMutex_lock(&dependency->lock);
- return CELIX_SUCCESS;
-}
-
-celix_status_t serviceDependency_unlock(celix_dm_service_dependency_t *dependency) {
- celixThreadMutex_unlock(&dependency->lock);
- return CELIX_SUCCESS;
-}
-
celix_status_t serviceDependency_setRequired(celix_dm_service_dependency_t *dependency, bool required) {
return celix_dmServiceDependency_setRequired(dependency, required);
}
@@ -117,15 +99,8 @@ celix_status_t serviceDependency_setStrategy(celix_dm_service_dependency_t *depe
}
celix_status_t celix_dmServiceDependency_setStrategy(celix_dm_service_dependency_t *dependency, dm_service_dependency_strategy_t strategy) {
- celix_status_t status = CELIX_SUCCESS;
-
- if (!dependency) {
- status = CELIX_ILLEGAL_ARGUMENT;
- } else {
- dependency->strategy = strategy;
- }
-
- return status;
+ dependency->strategy = strategy;
+ return CELIX_SUCCESS;
}
celix_status_t serviceDependency_getStrategy(celix_dm_service_dependency_t *dependency, dm_service_dependency_strategy_t* strategy) {
@@ -145,131 +120,21 @@ celix_status_t serviceDependency_setService(celix_dm_service_dependency_t *depen
}
celix_status_t celix_dmServiceDependency_setService(celix_dm_service_dependency_t *dependency, const char* serviceName, const char* serviceVersionRange, const char* filter) {
- celix_status_t status = CELIX_SUCCESS;
- if (!dependency || !serviceName) {
- status = CELIX_ILLEGAL_ARGUMENT;
- }
-
- if (status == CELIX_SUCCESS) {
- array_list_pt filterElements = NULL;
- arrayList_create(&filterElements);
-
- free(dependency->tracked_service);
- dependency->tracked_service = strdup(serviceName);
-
- if (serviceVersionRange != NULL) {
- version_range_pt versionRange = NULL;
-
- if (versionRange_parse(serviceVersionRange, &versionRange) == CELIX_SUCCESS) {
- version_pt lowVersion = NULL;
- version_pt highVersion = NULL;
-
- if ((versionRange_getHighVersion(versionRange, &highVersion) == CELIX_SUCCESS) && (highVersion != NULL)) {
- bool isHighInclusive;
- char* highOperator;
- char* highVersionStr = NULL;
-
- versionRange_isHighInclusive(versionRange, &isHighInclusive);
- version_toString(highVersion, &highVersionStr);
-
- highOperator = isHighInclusive ? "<=" : "<";
-
- if(highVersionStr != NULL){
- size_t len = strlen(CELIX_FRAMEWORK_SERVICE_VERSION) + strlen(highVersionStr) + strlen(highOperator) + 3;
- char serviceVersionFilter[len];
- snprintf(serviceVersionFilter, len, "(%s%s%s)", CELIX_FRAMEWORK_SERVICE_VERSION, highOperator, highVersionStr);
- arrayList_add(filterElements, strdup(serviceVersionFilter));
- free(highVersionStr);
- }
- }
-
- if ((versionRange_getLowVersion(versionRange, &lowVersion) == CELIX_SUCCESS) && (lowVersion != NULL)) {
- bool isLowInclusive;
- char* lowOperator;
- char* lowVersionStr = NULL;
-
- versionRange_isLowInclusive(versionRange, &isLowInclusive);
- version_toString(lowVersion, &lowVersionStr);
-
- lowOperator = isLowInclusive ? ">=" : ">";
-
- if(lowVersionStr != NULL){
- size_t len = strlen(CELIX_FRAMEWORK_SERVICE_VERSION) + strlen(lowVersionStr) + strlen(lowOperator) + 3;
- char serviceVersionFilter[len];
- snprintf(serviceVersionFilter, len, "(%s%s%s)", CELIX_FRAMEWORK_SERVICE_VERSION, lowOperator, lowVersionStr);
- arrayList_add(filterElements, strdup(serviceVersionFilter));
- free(lowVersionStr);
- }
- }
- }
-
- if(versionRange!=NULL){
- versionRange_destroy(versionRange);
- }
- }
-
- if (filter != NULL) {
- free(dependency->tracked_filter_unmodified);
- dependency->tracked_filter_unmodified = strdup(filter);
- arrayList_add(filterElements, strdup(filter));
- }
-
-
-
- bool needLangFilter = true;
- if (filter != NULL) {
- char needle[128];
- snprintf(needle, sizeof(needle), "(%s=", CELIX_FRAMEWORK_SERVICE_LANGUAGE);
- if (strstr(filter, needle) != NULL) {
- needLangFilter = false;
- }
- }
-
- if (needLangFilter && dependency->addCLanguageFilter) {
- char langFilter[128];
- snprintf(langFilter, sizeof(langFilter), "(%s=%s)", CELIX_FRAMEWORK_SERVICE_LANGUAGE, CELIX_FRAMEWORK_SERVICE_C_LANGUAGE);
- arrayList_add(filterElements, strdup(langFilter));
- }
-
- if (arrayList_size(filterElements) > 0) {
- array_list_iterator_pt filterElementsIter = arrayListIterator_create(filterElements);
-
- size_t len = strlen(serviceName) + strlen(OSGI_FRAMEWORK_OBJECTCLASS) + 4;
- free(dependency->tracked_filter);
- dependency->tracked_filter = calloc(len, sizeof(*dependency->tracked_filter));
- snprintf(dependency->tracked_filter, len, "(%s=%s)", OSGI_FRAMEWORK_OBJECTCLASS, serviceName);
-
- while (arrayListIterator_hasNext(filterElementsIter) == true) {
- char* filterElement = (char*) arrayListIterator_next(filterElementsIter);
- size_t len = strnlen(dependency->tracked_filter, 1024*1024) + strnlen(filterElement, 1024*1024) + 4;
- char* newFilter = calloc(len, sizeof(*newFilter));
-
- if (dependency->tracked_filter[0] == '(' && dependency->tracked_filter[1] == '&') {
- //already have an & (AND) can combine with additional filter -> easier to read
- size_t orgLen = strnlen(dependency->tracked_filter, 1024*1024);
- snprintf(newFilter, len, "%.*s%s)", (int)orgLen -1, dependency->tracked_filter, filterElement);
- } else {
- snprintf(newFilter, len, "(&%s%s)", dependency->tracked_filter, filterElement);
- }
-
- free(dependency->tracked_filter);
- free(filterElement);
-
- dependency->tracked_filter = newFilter;
- }
-
- arrayListIterator_destroy(filterElementsIter);
- }
- else {
- free(dependency->tracked_filter);
- dependency->tracked_filter = NULL;
- }
-
- arrayList_destroy(filterElements);
- }
-
- return status;
+ if (dependency->serviceName != NULL) {
+ free(dependency->serviceName);
+ }
+ if (dependency->versionRange != NULL) {
+ free(dependency->versionRange);
+ }
+ if (dependency->filter != NULL) {
+ free(dependency->filter);
+ }
+ dependency->serviceName = celix_utils_strdup(serviceName);
+ dependency->versionRange = celix_utils_strdup(serviceVersionRange);
+ dependency->filter = celix_utils_strdup(filter);
+ return CELIX_SUCCESS;
}
+
celix_status_t serviceDependency_getFilter(celix_dm_service_dependency_t *dependency, const char** filter) {
const char *f = celix_dmServiceDependency_getFilter(dependency);
if (filter != NULL) {
@@ -279,46 +144,14 @@ celix_status_t serviceDependency_getFilter(celix_dm_service_dependency_t *depend
}
const char* celix_dmServiceDependency_getFilter(celix_dm_service_dependency_t *dependency) {
- return (const char*)dependency->tracked_filter;
+ return (const char*)dependency->filter;
}
-celix_status_t serviceDependency_setCallbacks(celix_dm_service_dependency_t *dependency, service_set_fpt set, service_add_fpt add, service_change_fpt change, service_remove_fpt remove, service_swap_fpt swap) {
- celix_status_t status = CELIX_SUCCESS;
-
- //printf("Setting callbacks set %p, add %p, change %p, remove %p and swap %p\n", set, add, change, remove, swap);
-
- if (!dependency) {
- status = CELIX_ILLEGAL_ARGUMENT;
- }
-
- if (status == CELIX_SUCCESS) {
- dependency->set = (celix_dm_service_update_fp)set;
- dependency->add = (celix_dm_service_update_fp)add;
- dependency->change = (celix_dm_service_update_fp)change;
- dependency->remove = (celix_dm_service_update_fp)remove;
- dependency->swap = (celix_dm_service_swap_fp)swap;
- }
-
- return status;
-}
-
-celix_status_t serviceDependency_setCallbacksWithServiceReference(celix_dm_service_dependency_t *dependency, service_set_with_ref_fpt set, service_add_with_ref_fpt add, service_change_with_ref_fpt change, service_remove_with_ref_fpt remove,
- service_swap_with_ref_fpt swap) {
- celix_status_t status = CELIX_SUCCESS;
-
- if (!dependency) {
- status = CELIX_ILLEGAL_ARGUMENT;
- }
-
- if (status == CELIX_SUCCESS) {
- dependency->set_with_ref = set;
- dependency->add_with_ref = add;
- dependency->change_with_ref = change;
- dependency->remove_with_ref = remove;
- dependency->swap_with_ref = swap;
- }
-
- return status;
+celix_status_t serviceDependency_setCallbacks(celix_dm_service_dependency_t *dependency, service_set_fpt set, service_add_fpt add, service_change_fpt change __attribute__((unused)), service_remove_fpt remove, service_swap_fpt swap __attribute__((unused))) {
+ dependency->set = (celix_dm_service_update_fp)set;
+ dependency->add = (celix_dm_service_update_fp)add;
+ dependency->remove = (celix_dm_service_update_fp)remove;
+ return CELIX_SUCCESS;
}
celix_status_t celix_dmServiceDependency_setCallback(celix_dm_service_dependency_t *dependency, celix_dm_service_update_fp set) {
@@ -328,7 +161,7 @@ celix_status_t celix_dmServiceDependency_setCallback(celix_dm_service_dependency
celix_status_t celix_dmServiceDependency_setCallbackWithProperties(celix_dm_service_dependency_t *dependency, celix_dm_service_update_with_props_fp set) {
- dependency->set_with_props = set;
+ dependency->setWithProperties = set;
return CELIX_SUCCESS;
}
@@ -337,486 +170,176 @@ celix_status_t celix_dmServiceDependency_setCallbacksWithOptions(celix_dm_servic
dependency->set = opts->set;
dependency->add = opts->add;
dependency->remove = opts->remove;
- dependency->swap = opts->swap;
- dependency->set_with_props = opts->setWithProps;
- dependency->add_with_props = opts->addWithProps;
- dependency->rem_with_props = opts->removeWithProps;
- dependency->swap_with_props = opts->swapWithProps;
+ dependency->setWithProperties = opts->setWithProps;
+ dependency->addWithProperties = opts->addWithProps;
+ dependency->remWithProperties = opts->removeWithProps;
return CELIX_SUCCESS;
}
-celix_status_t serviceDependency_setAutoConfigure(celix_dm_service_dependency_t *dependency, celix_thread_mutex_t *service_lock, const void **field) {
- celix_status_t status = CELIX_SUCCESS;
-
- celix_thread_mutex_t lock;
-
- if (!dependency) {
- status = CELIX_ILLEGAL_ARGUMENT;
- }
-
- if (status == CELIX_SUCCESS) {
- dependency->autoConfigure = field;
- celixThreadMutex_create(&lock, NULL);
- *service_lock = lock;
- dependency->lock = lock;
- }
-
- return status;
-}
-
-celix_status_t serviceDependency_setComponent(celix_dm_service_dependency_t *dependency, celix_dm_component_t *component) {
- celix_status_t status = CELIX_SUCCESS;
-
- if (!dependency) {
- status = CELIX_ILLEGAL_ARGUMENT;
- }
-
- if (status == CELIX_SUCCESS) {
- dependency->component = component;
- }
-
- return status;
-}
-
-celix_status_t serviceDependency_start(celix_dm_service_dependency_t *dependency) {
- celix_status_t status = CELIX_SUCCESS;
- bundle_context_pt context = NULL;
-
- if (!dependency || !dependency->component || (!dependency->tracked_service && !dependency->tracked_filter)) {
- status = CELIX_ILLEGAL_ARGUMENT;
- }
- if (status == CELIX_SUCCESS) {
- status = component_getBundleContext(dependency->component, &context);
- if (!context) {
- status = CELIX_BUNDLE_EXCEPTION;
- }
- }
- if (status == CELIX_SUCCESS) {
- dependency->tracker_customizer = NULL;
- status = serviceTrackerCustomizer_create(dependency, NULL, serviceDependency_addedService, serviceDependency_modifiedService, serviceDependency_removedService, &dependency->tracker_customizer);
- }
- if (status == CELIX_SUCCESS) {
- if (dependency->tracked_filter) {
- status = serviceTracker_createWithFilter(context, dependency->tracked_filter, dependency->tracker_customizer, &dependency->tracker);
- } else if (dependency->tracked_service) {
- status = serviceTracker_create(context, dependency->tracked_service, dependency->tracker_customizer, &dependency->tracker);
- }
- }
-
- if (status == CELIX_SUCCESS) {
- status = serviceTracker_open(dependency->tracker);
- }
-
- if (status == CELIX_SUCCESS) {
- dependency->isStarted = true;
- }
-
- return status;
-}
-
-celix_status_t serviceDependency_stop(celix_dm_service_dependency_t *dependency) {
- celix_status_t status = CELIX_SUCCESS;
-
- if (!dependency) {
- status = CELIX_ILLEGAL_ARGUMENT;
- }
-
- if (status == CELIX_SUCCESS) {
- dependency->isStarted = false;
- }
-
- if (status == CELIX_SUCCESS && dependency->tracker) {
- status = serviceTracker_close(dependency->tracker);
- if (status == CELIX_SUCCESS) {
- serviceTracker_destroy(dependency->tracker);
- dependency->tracker = NULL;
- }
- }
-
- return status;
+celix_status_t celix_serviceDependency_setComponent(celix_dm_service_dependency_t *dependency, celix_dm_component_t *component) {
+ dependency->component = component;
+ return CELIX_SUCCESS;
}
-celix_status_t serviceDependency_setInstanceBound(celix_dm_service_dependency_t *dependency, bool instanceBound) {
- celix_status_t status = CELIX_SUCCESS;
-
- if (!dependency) {
- status = CELIX_ILLEGAL_ARGUMENT;
- }
-
- if (status == CELIX_SUCCESS) {
- dependency->instanceBound = instanceBound;
- }
-
- return status;
-}
+celix_status_t celix_serviceDependency_start(celix_dm_service_dependency_t *dependency) {
+ celix_bundle_context_t* ctx = celix_dmComponent_getBundleContext(dependency->component);
-celix_status_t serviceDependency_setAvailable(celix_dm_service_dependency_t *dependency, bool available) {
- celix_status_t status = CELIX_SUCCESS;
+ if (dependency->serviceName == NULL && dependency->filter == NULL) {
+ //TODO improve log (via bundle context?)
+ fw_log(ctx->framework->logger, CELIX_LOG_LEVEL_ERROR,
+ "Cannot start a service dependency without a service name and filter");
+ return CELIX_ILLEGAL_ARGUMENT;
+ }
- if (!dependency) {
- status = CELIX_ILLEGAL_ARGUMENT;
- }
+ celixThreadMutex_lock(&dependency->mutex);
+ bool open = dependency->isTrackerOpen;
+ dependency->isTrackerOpen = true;
+ celixThreadMutex_unlock(&dependency->mutex);
+
+ if (!open) {
+ celix_service_tracking_options_t opts = CELIX_EMPTY_SERVICE_TRACKING_OPTIONS;
+ opts.filter.filter = dependency->filter;
+ opts.filter.serviceName = dependency->serviceName;
+ opts.filter.versionRange = dependency->versionRange;
+ opts.callbackHandle = dependency;
+ opts.addWithProperties = serviceDependency_addServiceTrackerCallback;
+ opts.removeWithProperties = serviceDependency_removeServiceTrackerCallback;
+ opts.setWithProperties = serviceDependency_setServiceTrackerCallback;
+ if (dependency->addCLanguageFilter) {
+ opts.filter.ignoreServiceLanguage = false;
+ opts.filter.serviceLanguage = CELIX_FRAMEWORK_SERVICE_C_LANGUAGE;
+ } else {
+ opts.filter.ignoreServiceLanguage = true;
+ }
+ long newTrackerId = celix_bundleContext_trackServicesWithOptions(ctx, &opts);
- if (status == CELIX_SUCCESS) {
- dependency->available = available;
+ celixThreadMutex_lock(&dependency->mutex);
+ dependency->svcTrackerId = newTrackerId;
+ celixThreadMutex_unlock(&dependency->mutex);
}
- return status;
+ return CELIX_SUCCESS;
}
-celix_status_t serviceDependency_invokeSet(celix_dm_service_dependency_t *dependency, dm_event_pt event) {
- celix_status_t status = CELIX_SUCCESS;
- assert(dependency->isStarted == true);
- array_list_pt serviceReferences = NULL;
- int i;
- int curRanking = INT_MIN;
- service_reference_pt curServRef = NULL;
- void *service = NULL;
-
- serviceReferences = serviceTracker_getServiceReferences(dependency->tracker);
-
- /* Find the service with the highest ranking */
- for (i = 0; i < arrayList_size(serviceReferences); i++) {
- service_reference_pt serviceReference = arrayList_get(serviceReferences, i);
- const char* ranking_value;
- int ranking = 0;
-
- status = serviceReference_getProperty(serviceReference, ((char *) OSGI_FRAMEWORK_SERVICE_RANKING), &ranking_value);
-
- if (status == CELIX_SUCCESS) {
- if (ranking_value == NULL) {
- ranking = DEFAULT_RANKING;
- } else {
- char *end;
- ranking = strtol(ranking_value, &end, 10);
- if (end == ranking_value) {
- ranking = DEFAULT_RANKING;
- }
- }
-
- if (ranking > curRanking) {
- curRanking = ranking;
- curServRef = serviceReference;
- }
- } else {
- break;
- }
-
- }
+celix_status_t celix_serviceDependency_stop(celix_dm_service_dependency_t *dependency) {
+ celix_bundle_context_t* ctx = celix_dmComponent_getBundleContext(dependency->component);
- arrayList_destroy(serviceReferences);
+ celixThreadMutex_lock(&dependency->mutex);
+ long stopTrackerId = dependency->svcTrackerId;
+ dependency->svcTrackerId = -1l;
+ bool open = dependency->isTrackerOpen;
+ dependency->isTrackerOpen = false;
+ celixThreadMutex_unlock(&dependency->mutex);
- if (status == CELIX_SUCCESS) {
- if (curServRef) {
- status = bundleContext_getService(event->context, curServRef, &service);
- } else {
- service = NULL;
- }
-
- if (dependency->set) {
- dependency->set(serviceDependency_getCallbackHandle(dependency), service);
- }
- if (dependency->set_with_ref) {
- dependency->set_with_ref(serviceDependency_getCallbackHandle(dependency), curServRef, service);
- }
- if (dependency->set_with_props) {
- service_registration_pt reg = NULL;
- celix_properties_t *props = NULL;
- serviceReference_getServiceRegistration(curServRef, ®);
- if (reg != NULL) {
- serviceRegistration_getProperties(reg, &props);
- }
- dependency->set_with_props(serviceDependency_getCallbackHandle(dependency), service, props);
- }
-
- if (curServRef) {
- bundleContext_ungetService(event->context, curServRef, NULL);
- }
- }
+ //TODO if async branch is available this can be done with the lock using a async stop service tracker call
+ if (open && stopTrackerId >= 0) {
+ celix_bundleContext_stopTracker(ctx, stopTrackerId);
+ }
- return status;
+ return CELIX_SUCCESS;
}
-celix_status_t serviceDependency_invokeAdd(celix_dm_service_dependency_t *dependency, dm_event_pt event) {
- celix_status_t status = CELIX_SUCCESS;
-
- if (!dependency) {
- status = CELIX_ILLEGAL_ARGUMENT;
- }
-
- if (status == CELIX_SUCCESS) {
- if (dependency->add) {
- dependency->add(serviceDependency_getCallbackHandle(dependency), (void*)event->service);
- }
- if (dependency->add_with_ref) {
- dependency->add_with_ref(serviceDependency_getCallbackHandle(dependency), event->reference, (void*)event->service);
- }
- if (dependency->add_with_props) {
- service_registration_pt reg = NULL;
- celix_properties_t *props = NULL;
- serviceReference_getServiceRegistration(event->reference, ®);
- if (reg != NULL) {
- serviceRegistration_getProperties(reg, &props);
- }
- dependency->add_with_props(serviceDependency_getCallbackHandle(dependency), (void*)event->service, props);
- }
- }
+static void serviceDependency_setServiceTrackerCallback(void *handle, void *svc, const celix_properties_t *props) {
+ celix_dm_service_dependency_t* dependency = handle;
- return status;
+ celix_dm_event_t event;
+ event.dep = dependency;
+ event.eventType = CELIX_DM_EVENT_SVC_SET;
+ event.svc = svc;
+ event.props = props;
+ celix_private_dmComponent_handleEvent(dependency->component, &event);
}
-celix_status_t serviceDependency_invokeChange(celix_dm_service_dependency_t *dependency, dm_event_pt event) {
- celix_status_t status = CELIX_SUCCESS;
-
- if (!dependency) {
- status = CELIX_ILLEGAL_ARGUMENT;
- }
-
- if (status == CELIX_SUCCESS) {
- if (dependency->change) {
- dependency->change(serviceDependency_getCallbackHandle(dependency), (void*)event->service);
- }
- if (dependency->change_with_ref) {
- dependency->change_with_ref(serviceDependency_getCallbackHandle(dependency), event->reference, event->service);
- }
- }
-
- return status;
+celix_status_t celix_serviceDependency_invokeSet(celix_dm_service_dependency_t *dependency, void* svc, const celix_properties_t* props) {
+ if (dependency->set) {
+ dependency->set(serviceDependency_getCallbackHandle(dependency), svc);
+ }
+ if (dependency->setWithProperties) {
+ dependency->setWithProperties(serviceDependency_getCallbackHandle(dependency), svc, props);
+ }
+ return CELIX_SUCCESS;
}
-celix_status_t serviceDependency_invokeRemove(celix_dm_service_dependency_t *dependency, dm_event_pt event) {
- celix_status_t status = CELIX_SUCCESS;
+static void serviceDependency_addServiceTrackerCallback(void *handle, void *svc, const celix_properties_t *props) {
+ celix_dm_service_dependency_t* dependency = handle;
- if (!dependency) {
- status = CELIX_ILLEGAL_ARGUMENT;
- }
-
- if (status == CELIX_SUCCESS) {
- if (dependency->remove) {
- dependency->remove(serviceDependency_getCallbackHandle(dependency), (void*)event->service);
- }
- if (dependency->remove_with_ref) {
- dependency->remove_with_ref(serviceDependency_getCallbackHandle(dependency), event->reference, event->service);
- }
- if (dependency->rem_with_props) {
- service_registration_pt reg = NULL;
- celix_properties_t *props = NULL;
- serviceReference_getServiceRegistration(event->reference, ®);
- if (reg != NULL) {
- serviceRegistration_getProperties(reg, &props);
- }
- dependency->rem_with_props(serviceDependency_getCallbackHandle(dependency), (void*)event->service, props);
- }
- }
+ celixThreadMutex_lock(&dependency->mutex);
+ dependency->trackedSvcCount += 1;
+ celixThreadMutex_unlock(&dependency->mutex);
- return status;
+ celix_dm_event_t event;
+ event.dep = dependency;
+ event.eventType = CELIX_DM_EVENT_SVC_ADD;
+ event.svc = svc;
+ event.props = props;
+ celix_private_dmComponent_handleEvent(dependency->component, &event);
}
-celix_status_t serviceDependency_invokeSwap(celix_dm_service_dependency_t *dependency, dm_event_pt event, dm_event_pt newEvent) {
- celix_status_t status = CELIX_SUCCESS;
-
- if (!dependency) {
- status = CELIX_ILLEGAL_ARGUMENT;
- }
-
- if (status == CELIX_SUCCESS) {
- if (dependency->swap) {
- dependency->swap(serviceDependency_getCallbackHandle(dependency), (void*)event->service, (void*)newEvent->service);
- }
- if (dependency->swap_with_ref) {
- dependency->swap_with_ref(serviceDependency_getCallbackHandle(dependency), event->reference, event->service, newEvent->reference, newEvent->service);
- }
- if (dependency->swap_with_props) {
- service_registration_pt reg = NULL;
- celix_properties_t *props = NULL;
- serviceReference_getServiceRegistration(newEvent->reference, ®);
- if (reg != NULL) {
- serviceRegistration_getProperties(reg, &props);
- }
- dependency->swap_with_props(serviceDependency_getCallbackHandle(dependency),(void*) event->service, (void*)newEvent->service, props);
- }
- }
-
- return status;
+celix_status_t celix_serviceDependency_invokeAdd(celix_dm_service_dependency_t *dependency, void* svc, const celix_properties_t* props) {
+ if (dependency->add) {
+ dependency->add(serviceDependency_getCallbackHandle(dependency), svc);
+ }
+ if (dependency->addWithProperties) {
+ dependency->addWithProperties(serviceDependency_getCallbackHandle(dependency), svc, props);
+ }
+ return CELIX_SUCCESS;
}
-celix_status_t serviceDependency_isAvailable(celix_dm_service_dependency_t *dependency, bool *available) {
- celix_status_t status = CELIX_SUCCESS;
+static void serviceDependency_removeServiceTrackerCallback(void *handle, void *svc, const celix_properties_t *props) {
+ celix_dm_service_dependency_t* dependency = handle;
- if (!dependency) {
- status = CELIX_ILLEGAL_ARGUMENT;
- }
+ celixThreadMutex_lock(&dependency->mutex);
+ dependency->trackedSvcCount -= 1;
+ celixThreadMutex_unlock(&dependency->mutex);
- if (status == CELIX_SUCCESS) {
- *available = dependency->available;
- }
-
- return status;
+ celix_dm_event_t event;
+ event.dep = dependency;
+ event.eventType = CELIX_DM_EVENT_SVC_REM;
+ event.svc = svc;
+ event.props = props;
+ celix_private_dmComponent_handleEvent(dependency->component, &event);
}
-celix_status_t serviceDependency_isRequired(celix_dm_service_dependency_t *dependency, bool *required) {
- celix_status_t status = CELIX_SUCCESS;
-
- if (!dependency) {
- status = CELIX_ILLEGAL_ARGUMENT;
- }
-
- if (status == CELIX_SUCCESS) {
- *required = dependency->required;
- }
-
- return status;
+celix_status_t celix_serviceDependency_invokeRemove(celix_dm_service_dependency_t *dependency, void* svc, const celix_properties_t* props) {
+ if (dependency->remove) {
+ dependency->remove(serviceDependency_getCallbackHandle(dependency), svc);
+ }
+ if (dependency->remWithProperties) {
+ dependency->addWithProperties(serviceDependency_getCallbackHandle(dependency), svc, props);
+ }
+ return CELIX_SUCCESS;
}
-celix_status_t serviceDependency_isInstanceBound(celix_dm_service_dependency_t *dependency, bool *instanceBound) {
- celix_status_t status = CELIX_SUCCESS;
-
- if (!dependency) {
- status = CELIX_ILLEGAL_ARGUMENT;
- }
-
- if (status == CELIX_SUCCESS) {
- *instanceBound = dependency->instanceBound;
- }
-
- return status;
+bool celix_serviceDependency_hasSetCallback(const celix_dm_service_dependency_t *dependency) {
+ return dependency->set != NULL || dependency->setWithProperties != NULL;
}
-celix_status_t serviceDependency_isAutoConfig(celix_dm_service_dependency_t *dependency, bool *autoConfig) {
- celix_status_t status = CELIX_SUCCESS;
-
- if (!dependency) {
- status = CELIX_ILLEGAL_ARGUMENT;
- }
-
- if (status == CELIX_SUCCESS) {
- *autoConfig = dependency->autoConfigure != NULL;
- }
-
- return status;
+bool celix_serviceDependency_hasAddCallback(const celix_dm_service_dependency_t *dependency) {
+ return dependency->add != NULL || dependency->addWithProperties != NULL;
}
-celix_status_t serviceDependency_getAutoConfig(celix_dm_service_dependency_t *dependency, const void*** autoConfigure) {
- celix_status_t status = CELIX_SUCCESS;
-
- if (!dependency) {
- status = CELIX_ILLEGAL_ARGUMENT;
- }
-
- if (status == CELIX_SUCCESS) {
- *autoConfigure = dependency->autoConfigure;
- }
-
- return status;
+bool celix_serviceDependency_hasRemoveCallback(const celix_dm_service_dependency_t *dependency) {
+ return dependency->remove != NULL || dependency->remWithProperties != NULL;
}
-static celix_status_t serviceDependency_addedService(void *_ptr, service_reference_pt reference, void *service) {
- celix_status_t status = CELIX_SUCCESS;
- bundle_context_pt context = NULL;
- bundle_pt bundle = NULL;
- dm_event_pt event = NULL;
- celix_dm_service_dependency_t *dependency = _ptr;
-
- if (!dependency || !reference || !service) {
- status = CELIX_ILLEGAL_ARGUMENT;
- }
-
- if (status == CELIX_SUCCESS) {
- status = component_getBundleContext(dependency->component, &context);
- if (!context) {
- status = CELIX_BUNDLE_EXCEPTION;
- }
- }
-
- if (status == CELIX_SUCCESS) {
- status = bundleContext_getBundle(context, &bundle);
- if (!bundle) {
- status = CELIX_BUNDLE_EXCEPTION;
- }
- }
-
- if (status == CELIX_SUCCESS) {
- status = event_create(DM_EVENT_ADDED, bundle, context, reference, service, &event);
- }
-
- if (status == CELIX_SUCCESS) {
- celix_private_dmComponent_handleEvent(dependency->component, dependency, event);
- }
-
- return status;
+bool celix_serviceDependency_isAvailable(celix_dm_service_dependency_t *dependency) {
+ bool avail;
+ celixThreadMutex_lock(&dependency->mutex);
+ avail = dependency->trackedSvcCount > 0;
+ celixThreadMutex_unlock(&dependency->mutex);
+ return avail;
}
-static celix_status_t serviceDependency_modifiedService(void *_ptr, service_reference_pt reference, void *service) {
- celix_status_t status = CELIX_SUCCESS;
- bundle_context_pt context = NULL;
- bundle_pt bundle = NULL;
- dm_event_pt event = NULL;
- celix_dm_service_dependency_t *dependency = _ptr;
-
- if (!dependency || !reference || !service) {
- status = CELIX_ILLEGAL_ARGUMENT;
- }
-
- if (status == CELIX_SUCCESS) {
- status = component_getBundleContext(dependency->component, &context);
- if (!context) {
- status = CELIX_BUNDLE_EXCEPTION;
- }
- }
-
- if (status == CELIX_SUCCESS) {
- status = bundleContext_getBundle(context, &bundle);
- if (!bundle) {
- status = CELIX_BUNDLE_EXCEPTION;
- }
- }
-
- if (status == CELIX_SUCCESS) {
- status = event_create(DM_EVENT_CHANGED, bundle, context, reference, service, &event);
- }
-
- if (status == CELIX_SUCCESS) {
- celix_private_dmComponent_handleEvent(dependency->component, dependency, event);
- }
-
- return status;
+bool celix_dmServiceDependency_isRequired(const celix_dm_service_dependency_t* dep) {
+ return dep->required;
}
-static celix_status_t serviceDependency_removedService(void *_ptr, service_reference_pt reference, void *service) {
- celix_status_t status = CELIX_SUCCESS;
- bundle_context_pt context = NULL;
- bundle_pt bundle = NULL;
- dm_event_pt event = NULL;
- celix_dm_service_dependency_t *dependency = _ptr;
-
- if (!dependency || !reference || !service) {
- status = CELIX_ILLEGAL_ARGUMENT;
- }
-
- if (status == CELIX_SUCCESS) {
- status = component_getBundleContext(dependency->component, &context);
- if (!context) {
- status = CELIX_BUNDLE_EXCEPTION;
- }
- }
-
- if (status == CELIX_SUCCESS) {
- status = bundleContext_getBundle(context, &bundle);
- if (!bundle) {
- status = CELIX_BUNDLE_EXCEPTION;
- }
- }
-
- if (status == CELIX_SUCCESS) {
- status = event_create(DM_EVENT_REMOVED, bundle, context, reference, service, &event);
- }
-
- if (status == CELIX_SUCCESS) {
- celix_private_dmComponent_handleEvent(dependency->component, dependency, event);
- }
-
- return status;
+bool celix_dmServiceDependency_isStarted(celix_dm_service_dependency_t* dependency) {
+ celixThreadMutex_lock(&dependency->mutex);
+ bool started = dependency->isTrackerOpen;
+ celixThreadMutex_unlock(&dependency->mutex);
+ return started;
}
celix_status_t serviceDependency_getServiceDependencyInfo(celix_dm_service_dependency_t *dep, dm_service_dependency_info_t **out) {
@@ -829,21 +352,14 @@ celix_status_t serviceDependency_getServiceDependencyInfo(celix_dm_service_depen
dm_service_dependency_info_t* celix_dmServiceDependency_createInfo(celix_dm_service_dependency_t* dep) {
celix_dm_service_dependency_info_t *info = calloc(1, sizeof(*info));
if (info != NULL) {
- celixThreadMutex_lock(&dep->lock);
- info->available = dep->available;
- info->filter = dep->tracked_filter != NULL ? strdup(dep->tracked_filter) : NULL;
- if (info->filter == NULL) {
- info->filter = dep->tracked_service != NULL ? strdup(dep->tracked_service) : NULL;
- }
+ celixThreadMutex_lock(&dep->mutex);
+ info->available = dep->trackedSvcCount > 0;
+ info->serviceName = celix_utils_strdup(dep->serviceName);
+ info->filter = celix_utils_strdup(dep->filter);
+ info->versionRange = celix_utils_strdup(dep->versionRange);
info->required = dep->required;
-
- array_list_pt refs = serviceTracker_getServiceReferences(dep->tracker);
- if (refs != NULL) {
- info->count = arrayList_size(refs);
- }
- arrayList_destroy(refs);
-
- celixThreadMutex_unlock(&dep->lock);
+ info->count = dep->trackedSvcCount;
+ celixThreadMutex_unlock(&dep->mutex);
}
return info;
}
@@ -855,7 +371,9 @@ void dependency_destroyDependencyInfo(dm_service_dependency_info_pt info) {
void celix_dmServiceDependency_destroyInfo(celix_dm_service_dependency_t *dep __attribute__((unused)), dm_service_dependency_info_t *info) {
if (info != NULL) {
+ free(info->serviceName);
free(info->filter);
+ free(info->versionRange);
}
free(info);
}
@@ -869,6 +387,7 @@ celix_status_t celix_dmServiceDependency_setCallbackHandle(celix_dm_service_depe
return CELIX_SUCCESS;
}
+
static void* serviceDependency_getCallbackHandle(celix_dm_service_dependency_t *dependency) {
return dependency->callbackHandle == NULL ? component_getImplementation(dependency->component) : dependency->callbackHandle;
}
diff --git a/libs/framework/src/dm_service_dependency_impl.h b/libs/framework/src/dm_service_dependency_impl.h
index a3aa6e1..bab5d7c 100644
--- a/libs/framework/src/dm_service_dependency_impl.h
+++ b/libs/framework/src/dm_service_dependency_impl.h
@@ -16,13 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-/**
- * dm_service_dependency_impl.h
- *
- * \date 16 Oct 2015
- * \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- * \copyright Apache License, Version 2.0
- */
+
#ifndef DM_SERVICE_DEPENDENCY_IMPL_H_
#define DM_SERVICE_DEPENDENCY_IMPL_H_
@@ -33,74 +27,59 @@ extern "C" {
#include <stdbool.h>
-#include "dm_event.h"
+#include "celix_dm_event.h"
#include "service_tracker.h"
#include "service_tracker_customizer.h"
#include "dm_service_dependency.h"
#include "dm_component.h"
+struct celix_dm_service_dependency_svc_entry {
+ void *svc;
+ const celix_properties_t* props;
+};
+
struct celix_dm_service_dependency {
celix_dm_component_t *component;
- bool available;
- bool instanceBound;
- bool required;
- dm_service_dependency_strategy_t strategy;
void* callbackHandle; //This handle can be set to be used instead of the component implementation
celix_dm_service_update_fp set;
celix_dm_service_update_fp add;
- celix_dm_service_update_fp change;
celix_dm_service_update_fp remove;
- celix_dm_service_swap_fp swap;
-
- service_set_with_ref_fpt set_with_ref;
- service_add_with_ref_fpt add_with_ref;
- service_change_with_ref_fpt change_with_ref;
- service_remove_with_ref_fpt remove_with_ref;
- service_swap_with_ref_fpt swap_with_ref;
- celix_dm_service_update_with_props_fp set_with_props;
- celix_dm_service_update_with_props_fp add_with_props;
- celix_dm_service_update_with_props_fp rem_with_props;
- celix_dm_service_swap_with_props_fp swap_with_props;
+ celix_dm_service_update_with_props_fp setWithProperties;
+ celix_dm_service_update_with_props_fp addWithProperties;
+ celix_dm_service_update_with_props_fp remWithProperties;
+
+ char *serviceName;
+ char *filter;
+ char *versionRange;
+ bool required;
+ dm_service_dependency_strategy_t strategy;
+ bool addCLanguageFilter;
+
+ celix_thread_mutex_t mutex; //protects below
+ long svcTrackerId;
+ bool isTrackerOpen;
+ size_t trackedSvcCount;
+};
- const void **autoConfigure;
- celix_thread_mutex_t lock;
+celix_status_t celix_serviceDependency_start(celix_dm_service_dependency_t *dependency);
+celix_status_t celix_serviceDependency_stop(celix_dm_service_dependency_t *dependency);
- bool isStarted;
+celix_status_t celix_serviceDependency_setComponent(celix_dm_service_dependency_t *dependency, celix_dm_component_t *component);
- bool addCLanguageFilter;
- char *tracked_service;
- char *tracked_filter_unmodified;
- char *tracked_filter;
+celix_status_t celix_serviceDependency_invokeSet(celix_dm_service_dependency_t *dependency, void* svc, const celix_properties_t* props);
+celix_status_t celix_serviceDependency_invokeAdd(celix_dm_service_dependency_t *dependency, void* svc, const celix_properties_t* props);
+celix_status_t celix_serviceDependency_invokeRemove(celix_dm_service_dependency_t *dependency, void* svc, const celix_properties_t* props);
- service_tracker_pt tracker;
- service_tracker_customizer_pt tracker_customizer;
-};
+bool celix_serviceDependency_hasSetCallback(const celix_dm_service_dependency_t *dependency);
+bool celix_serviceDependency_hasAddCallback(const celix_dm_service_dependency_t *dependency);
+bool celix_serviceDependency_hasRemoveCallback(const celix_dm_service_dependency_t *dependency);
-celix_status_t serviceDependency_start(celix_dm_service_dependency_t *dependency);
-celix_status_t serviceDependency_stop(celix_dm_service_dependency_t *dependency);
-celix_status_t serviceDependency_setInstanceBound(celix_dm_service_dependency_t *dependency, bool instanceBound);
-celix_status_t serviceDependency_setAutoConfig(celix_dm_service_dependency_t *dependency, void **autoConfigure);
-celix_status_t serviceDependency_setAvailable(celix_dm_service_dependency_t *dependency, bool available);
-
-celix_status_t serviceDependency_setComponent(celix_dm_service_dependency_t *dependency, celix_dm_component_t *component);
-//celix_status_t serviceDependency_removeComponent(celix_dm_service_dependency_t *dependency, celix_dm_component_t *component);
-
-celix_status_t serviceDependency_invokeSet(celix_dm_service_dependency_t *dependency, dm_event_pt event);
-celix_status_t serviceDependency_invokeAdd(celix_dm_service_dependency_t *dependency, dm_event_pt event);
-celix_status_t serviceDependency_invokeChange(celix_dm_service_dependency_t *dependency, dm_event_pt event);
-celix_status_t serviceDependency_invokeRemove(celix_dm_service_dependency_t *dependency, dm_event_pt event);
-celix_status_t serviceDependency_invokeSwap(celix_dm_service_dependency_t *dependency, dm_event_pt event, dm_event_pt newEvent);
-celix_status_t serviceDependency_isAvailable(celix_dm_service_dependency_t *dependency, bool *available);
-celix_status_t serviceDependency_isRequired(celix_dm_service_dependency_t *dependency, bool *required);
-celix_status_t serviceDependency_isInstanceBound(celix_dm_service_dependency_t *dependency, bool *instanceBound);
-celix_status_t serviceDependency_isAutoConfig(celix_dm_service_dependency_t *dependency, bool *autoConfig);
-
-celix_status_t serviceDependency_getAutoConfig(celix_dm_service_dependency_t *dependency, const void*** autoConfigure);
-celix_status_t serviceDependency_unlock(celix_dm_service_dependency_t *dependency);
-celix_status_t serviceDependency_lock(celix_dm_service_dependency_t *dependency);
+bool celix_serviceDependency_isAvailable(celix_dm_service_dependency_t *dependency);
+bool celix_dmServiceDependency_isRequired(const celix_dm_service_dependency_t* dependency);
+bool celix_dmServiceDependency_isStarted(celix_dm_service_dependency_t* dependency);
#ifdef __cplusplus
}
diff --git a/libs/framework/src/requirement.c b/libs/framework/src/requirement.c
index fc032ce..84efcaa 100644
--- a/libs/framework/src/requirement.c
+++ b/libs/framework/src/requirement.c
@@ -86,7 +86,7 @@ celix_status_t requirement_destroy(requirement_pt requirement) {
return CELIX_SUCCESS;
}
-celix_status_t requirement_getVersionRange(requirement_pt requirement, version_range_pt *range) {
+celix_status_t requirement_getVersionRange(requirement_pt requirement, celix_version_range_t **range) {
*range = requirement->versionRange;
return CELIX_SUCCESS;
}
diff --git a/libs/utils/CMakeLists.txt b/libs/utils/CMakeLists.txt
index 02b1e0a..6cc5825 100644
--- a/libs/utils/CMakeLists.txt
+++ b/libs/utils/CMakeLists.txt
@@ -110,9 +110,6 @@ if (ENABLE_TESTING)
add_executable(filter_test private/test/filter_test.cpp)
target_link_libraries(filter_test ${CppUTest_LIBRARY} Celix::utils pthread)
- add_executable(version_range_test private/test/version_range_test.cpp)
- target_link_libraries(version_range_test ${CppUTest_LIBRARY} ${CppUTest_EXT_LIBRARIES} Celix::utils pthread)
-
add_executable(version_test private/test/version_test.cpp)
target_link_libraries(version_test ${CppUTest_LIBRARY} Celix::utils pthread)
@@ -126,7 +123,6 @@ if (ENABLE_TESTING)
add_test(NAME run_utils_test COMMAND utils_test)
add_test(NAME run_ip_utils_test COMMAND ip_utils_test)
add_test(NAME filter_test COMMAND filter_test)
- add_test(NAME version_range_test COMMAND version_range_test)
add_test(NAME version_test COMMAND version_test)
setup_target_for_coverage(array_list_test)
diff --git a/libs/utils/gtest/CMakeLists.txt b/libs/utils/gtest/CMakeLists.txt
index 697a3b0..b791c42 100644
--- a/libs/utils/gtest/CMakeLists.txt
+++ b/libs/utils/gtest/CMakeLists.txt
@@ -18,9 +18,11 @@
add_executable(test_utils
src/LogUtilsTestSuite.cc
+ src/VersionRangeTestSuite.cc
)
target_link_libraries(test_utils PRIVATE Celix::utils GTest::gtest GTest::gtest_main)
+target_include_directories(test_utils PRIVATE ../src) #for version_private (needs refactoring of test)
add_test(NAME test_utils COMMAND test_utils)
setup_target_for_coverage(test_utils SCAN_DIR ..)
diff --git a/libs/utils/gtest/src/VersionRangeTestSuite.cc b/libs/utils/gtest/src/VersionRangeTestSuite.cc
new file mode 100644
index 0000000..3659b39
--- /dev/null
+++ b/libs/utils/gtest/src/VersionRangeTestSuite.cc
@@ -0,0 +1,423 @@
+/*
+ * 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 <gtest/gtest.h>
+
+#include "version.h"
+#include "version_range.h" //NOTE testing celix_version_range through the deprecated version_range api.
+#include "celix_version_range.h"
+#include "version_private.h"
+
+class VersionRangeTestSuite : public ::testing::Test {};
+
+TEST_F(VersionRangeTestSuite, create) {
+ celix_status_t status = CELIX_SUCCESS;
+ version_range_pt range = nullptr;
+ version_pt low = celix_version_createEmptyVersion();
+ version_pt high = celix_version_createEmptyVersion();
+
+ status = versionRange_createVersionRange(low, false, high, true, &range);
+ EXPECT_EQ(CELIX_SUCCESS, status);
+ EXPECT_TRUE((range != nullptr));
+ EXPECT_EQ(true, celix_versionRange_isHighInclusive(range));
+ EXPECT_EQ(false, celix_versionRange_isLowInclusive(range));
+ EXPECT_EQ(low, celix_versionRange_getLowVersion(range));
+ EXPECT_EQ(high, celix_versionRange_getHighVersion(range));
+
+ versionRange_destroy(range);
+}
+
+TEST_F(VersionRangeTestSuite, createInfinite) {
+ celix_status_t status = CELIX_SUCCESS;
+ version_range_pt range = nullptr;
+ version_pt version = celix_version_createVersion(1,2, 3, nullptr);
+
+ status = versionRange_createInfiniteVersionRange(&range);
+ EXPECT_EQ(CELIX_SUCCESS, status);
+ EXPECT_TRUE(range != nullptr);
+ EXPECT_EQ(true, celix_versionRange_isHighInclusive(range));
+ EXPECT_EQ(true, celix_versionRange_isLowInclusive(range));
+ EXPECT_EQ(celix_version_getMajor(celix_versionRange_getLowVersion(range)), 0);
+ EXPECT_EQ(celix_version_getMinor(celix_versionRange_getLowVersion(range)), 0);
+ EXPECT_EQ(celix_version_getMicro(celix_versionRange_getLowVersion(range)), 0);
+ EXPECT_EQ(std::string{celix_version_getQualifier(celix_versionRange_getLowVersion(range))}, std::string{""});
+ EXPECT_EQ(nullptr, celix_versionRange_getHighVersion(range));
+
+ versionRange_destroy(range);
+ celix_version_destroy(version);
+}
+
+TEST_F(VersionRangeTestSuite, isInRange) {
+ bool result;
+ version_pt version = celix_version_createVersion(1, 2, 3, nullptr);
+
+ {
+ version_range_pt range = nullptr;
+
+ version_pt low = (version_pt) calloc(1, sizeof(*low));
+ low->major = 1;
+ low->minor = 2;
+ low->micro = 3;
+ low->qualifier = nullptr;
+
+ version_pt high = (version_pt) calloc(1, sizeof(*high));
+ high->major = 1;
+ high->minor = 2;
+ high->micro = 3;
+ high->qualifier = nullptr;
+
+ EXPECT_EQ(CELIX_SUCCESS, versionRange_createVersionRange(low, true, high, true, &range));
+ EXPECT_EQ(CELIX_SUCCESS, versionRange_isInRange(range, version, &result));
+ EXPECT_EQ(true, result);
+
+ versionRange_destroy(range);
+ }
+
+ {
+ version_range_pt range = nullptr;
+
+ version_pt low = (version_pt) calloc(1, sizeof(*low));
+ low->major = 1;
+ low->minor = 2;
+ low->micro = 3;
+
+ EXPECT_EQ(CELIX_SUCCESS, versionRange_createVersionRange(low, true, nullptr, true, &range));
+ EXPECT_EQ(CELIX_SUCCESS, versionRange_isInRange(range, version, &result));
+ EXPECT_EQ(true, result);
+
+ versionRange_destroy(range);
+ }
+
+ {
+ version_range_pt range = nullptr;
+
+ version_pt low = (version_pt) calloc(1, sizeof(*low));
+ low->major = 1;
+ low->minor = 2;
+ low->micro = 3;
+
+ version_pt high = (version_pt) calloc(1, sizeof(*high));
+ high->major = 1;
+ high->minor = 2;
+ high->micro = 3;
+
+ EXPECT_EQ(CELIX_SUCCESS, versionRange_createVersionRange(low, false, high, true, &range));
+ EXPECT_EQ(CELIX_SUCCESS, versionRange_isInRange(range, version, &result));
+ EXPECT_EQ(false, result);
+
+ versionRange_destroy(range);
+ }
+
+ {
+ version_range_pt range = nullptr;
+
+ version_pt low = (version_pt) calloc(1, sizeof(*low));
+ low->major = 1;
+ low->minor = 2;
+ low->micro = 3;
+
+ version_pt high = (version_pt) calloc(1, sizeof(*high));
+ high->major = 1;
+ high->minor = 2;
+ high->micro = 3;
+
+ EXPECT_EQ(CELIX_SUCCESS, versionRange_createVersionRange(low, true, high, false, &range));
+ EXPECT_EQ(CELIX_SUCCESS, versionRange_isInRange(range, version, &result));
+ EXPECT_EQ(false, result);
+
+ versionRange_destroy(range);
+ }
+
+ {
+ version_range_pt range = nullptr;
+
+ version_pt low = (version_pt) calloc(1, sizeof(*low));
+ low->major = 1;
+ low->minor = 2;
+ low->micro = 3;
+
+ version_pt high = (version_pt) calloc(1, sizeof(*high));
+ high->major = 1;
+ high->minor = 2;
+ high->micro = 3;
+
+ EXPECT_EQ(CELIX_SUCCESS, versionRange_createVersionRange(low, false, high, false, &range));
+ EXPECT_EQ(CELIX_SUCCESS, versionRange_isInRange(range, version, &result));
+ EXPECT_EQ(false, result);
+
+ versionRange_destroy(range);
+ }
+
+ celix_version_destroy(version);
+}
+
+TEST_F(VersionRangeTestSuite, parse) {
+ version_range_pt range = nullptr;
+ version_pt low = (version_pt) calloc(1, sizeof(*low));
+ version_pt high = (version_pt) calloc(1, sizeof(*high));
+ char * version = strdup("[1.2.3,7.8.9]");
+ low->major = 1;
+ low->minor = 2;
+ low->micro = 3;
+
+ high->major = 7;
+ high->minor = 8;
+ high->micro = 9;
+
+ EXPECT_EQ(CELIX_SUCCESS, versionRange_parse(version, &range));
+
+ versionRange_destroy(range);
+ free(version);
+ version = strdup("[1.2.3");
+
+ EXPECT_EQ(CELIX_ILLEGAL_ARGUMENT, versionRange_parse(version, &range));
+
+ free(version);
+
+ free(high);
+ free(low);
+}
+
+TEST_F(VersionRangeTestSuite, createLdapFilterInclusiveBoth) {
+ version_pt low = (version_pt) calloc(1, sizeof(*low));
+ low->major = 1;
+ low->minor = 2;
+ low->micro = 3;
+ low->qualifier = nullptr;
+
+ version_pt high = (version_pt) calloc(1, sizeof(*high));
+ high->major = 1;
+ high->minor = 2;
+ high->micro = 3;
+ high->qualifier = nullptr;
+
+ version_range_pt range = nullptr;
+ EXPECT_EQ(CELIX_SUCCESS, versionRange_createVersionRange(low, true, high, true, &range));
+
+ auto filter = versionRange_createLDAPFilter(range, "service.version");
+ EXPECT_EQ(std::string{filter}, std::string{"(&(service.version>=1.2.3)(service.version<=1.2.3))"});
+
+ versionRange_destroy(range);
+ free(filter);
+}
+
+TEST_F(VersionRangeTestSuite, createLdapFilterInclusiveLow) {
+ version_pt low = (version_pt) calloc(1, sizeof(*low));
+ low->major = 1;
+ low->minor = 2;
+ low->micro = 3;
+ low->qualifier = nullptr;
+
+ version_pt high = (version_pt) calloc(1, sizeof(*high));
+ high->major = 1;
+ high->minor = 2;
+ high->micro = 3;
+ high->qualifier = nullptr;
+
+ version_range_pt range = nullptr;
+ EXPECT_EQ(CELIX_SUCCESS, versionRange_createVersionRange(low, false, high, true, &range));
+
+ auto filter = versionRange_createLDAPFilter(range, "service.version");
+ EXPECT_STREQ(filter, "(&(service.version>1.2.3)(service.version<=1.2.3))");
+
+ versionRange_destroy(range);
+ free(filter);
+}
+
+TEST_F(VersionRangeTestSuite, createLdapFilterInclusiveHigh) {
+ version_pt low = (version_pt) calloc(1, sizeof(*low));
+ low->major = 1;
+ low->minor = 2;
+ low->micro = 3;
+ low->qualifier = nullptr;
+
+ version_pt high = (version_pt) calloc(1, sizeof(*high));
+ high->major = 1;
+ high->minor = 2;
+ high->micro = 3;
+ high->qualifier = nullptr;
+
+ version_range_pt range = nullptr;
+ EXPECT_EQ(CELIX_SUCCESS, versionRange_createVersionRange(low, true, high, false, &range));
+
+ auto filter = versionRange_createLDAPFilter(range, "service.version");
+ EXPECT_STREQ(filter, "(&(service.version>=1.2.3)(service.version<1.2.3))");
+
+ versionRange_destroy(range);
+ free(filter);
+}
+
+TEST_F(VersionRangeTestSuite, createLdapFilterExclusiveBoth) {
+ version_pt low = (version_pt) calloc(1, sizeof(*low));
+ low->major = 1;
+ low->minor = 2;
+ low->micro = 3;
+ low->qualifier = nullptr;
+
+ version_pt high = (version_pt) calloc(1, sizeof(*high));
+ high->major = 1;
+ high->minor = 2;
+ high->micro = 3;
+ high->qualifier = nullptr;
+
+ version_range_pt range = nullptr;
+ EXPECT_EQ(CELIX_SUCCESS, versionRange_createVersionRange(low, false, high, false, &range));
+
+ auto filter = versionRange_createLDAPFilter(range, "service.version");
+ EXPECT_STREQ(filter, "(&(service.version>1.2.3)(service.version<1.2.3))");
+
+ versionRange_destroy(range);
+ free(filter);
+}
+
+TEST_F(VersionRangeTestSuite, createLdapFilterInfinite) {
+ version_pt low = (version_pt) calloc(1, sizeof(*low));
+ low->major = 1;
+ low->minor = 2;
+ low->micro = 3;
+ low->qualifier = nullptr;
+
+ version_range_pt range = nullptr;
+ EXPECT_EQ(CELIX_SUCCESS, versionRange_createVersionRange(low, true, nullptr, true, &range));
+
+ auto filter = versionRange_createLDAPFilter(range, "service.version");
+ EXPECT_STREQ(filter, "(&(service.version>=1.2.3))");
+
+ versionRange_destroy(range);
+ free(filter);
+}
+
+TEST_F(VersionRangeTestSuite, createLdapFilterInPlaceInclusiveBoth) {
+ version_pt low = (version_pt) calloc(1, sizeof(*low));
+ low->major = 1;
+ low->minor = 2;
+ low->micro = 3;
+ low->qualifier = nullptr;
+
+ version_pt high = (version_pt) calloc(1, sizeof(*high));
+ high->major = 1;
+ high->minor = 2;
+ high->micro = 3;
+ high->qualifier = nullptr;
+
+ version_range_pt range = nullptr;
+ EXPECT_EQ(CELIX_SUCCESS, versionRange_createVersionRange(low, true, high, true, &range));
+ char buffer[100];
+ int bufferLen = sizeof(buffer) / sizeof(buffer[0]);
+
+ EXPECT_EQ(1, versionRange_createLDAPFilterInPlace(range, "service.version", buffer, bufferLen));
+
+ EXPECT_STREQ(buffer, "(&(service.version>=1.2.3)(service.version<=1.2.3))");
+
+ versionRange_destroy(range);
+}
+
+TEST_F(VersionRangeTestSuite, createLdapFilterInPlaceInclusiveLow) {
+ version_pt low = (version_pt) calloc(1, sizeof(*low));
+ low->major = 1;
+ low->minor = 2;
+ low->micro = 3;
+ low->qualifier = nullptr;
+
+ version_pt high = (version_pt) calloc(1, sizeof(*high));
+ high->major = 1;
+ high->minor = 2;
+ high->micro = 3;
+ high->qualifier = nullptr;
+
+ version_range_pt range = nullptr;
+ EXPECT_EQ(CELIX_SUCCESS, versionRange_createVersionRange(low, true, high, false, &range));
+ char buffer[100];
+ int bufferLen = sizeof(buffer) / sizeof(buffer[0]);
+
+ EXPECT_EQ(1, versionRange_createLDAPFilterInPlace(range, "service.version", buffer, bufferLen));
+
+ EXPECT_STREQ(buffer, "(&(service.version>=1.2.3)(service.version<1.2.3))");
+
+ versionRange_destroy(range);
+}
+
+TEST_F(VersionRangeTestSuite, createLdapFilterInPlaceInclusiveHigh) {
+ version_pt low = (version_pt) calloc(1, sizeof(*low));
+ low->major = 1;
+ low->minor = 2;
+ low->micro = 3;
+ low->qualifier = nullptr;
+
+ version_pt high = (version_pt) calloc(1, sizeof(*high));
+ high->major = 1;
+ high->minor = 2;
+ high->micro = 3;
+ high->qualifier = nullptr;
+
+ version_range_pt range = nullptr;
+ EXPECT_EQ(CELIX_SUCCESS, versionRange_createVersionRange(low, false, high, true, &range));
+ char buffer[100];
+ int bufferLen = sizeof(buffer) / sizeof(buffer[0]);
+
+ EXPECT_EQ(1, versionRange_createLDAPFilterInPlace(range, "service.version", buffer, bufferLen));
+
+ EXPECT_STREQ(buffer, "(&(service.version>1.2.3)(service.version<=1.2.3))");
+
+ versionRange_destroy(range);
+}
+
+TEST_F(VersionRangeTestSuite, createLdapFilterInPlaceExclusiveBoth) {
+ version_pt low = (version_pt) calloc(1, sizeof(*low));
+ low->major = 1;
+ low->minor = 2;
+ low->micro = 3;
+ low->qualifier = nullptr;
+
+ version_pt high = (version_pt) calloc(1, sizeof(*high));
+ high->major = 1;
+ high->minor = 2;
+ high->micro = 3;
+ high->qualifier = nullptr;
+
+ version_range_pt range = nullptr;
+ EXPECT_EQ(CELIX_SUCCESS, versionRange_createVersionRange(low, false, high, false, &range));
+ char buffer[100];
+ int bufferLen = sizeof(buffer) / sizeof(buffer[0]);
+
+ EXPECT_EQ(1, versionRange_createLDAPFilterInPlace(range, "service.version", buffer, bufferLen));
+
+ EXPECT_STREQ(buffer, "(&(service.version>1.2.3)(service.version<1.2.3))");
+
+ versionRange_destroy(range);
+}
+
+TEST_F(VersionRangeTestSuite, createLdapFilterInPlaceInfiniteHigh) {
+ version_pt low = (version_pt) calloc(1, sizeof(*low));
+ low->major = 1;
+ low->minor = 2;
+ low->micro = 3;
+ low->qualifier = nullptr;
+
+ version_range_pt range = nullptr;
+ EXPECT_EQ(CELIX_SUCCESS, versionRange_createVersionRange(low, false, nullptr, false, &range));
+ char buffer[100];
+ int bufferLen = sizeof(buffer) / sizeof(buffer[0]);
+
+ EXPECT_EQ(1, versionRange_createLDAPFilterInPlace(range, "service.version", buffer, bufferLen));
+
+ EXPECT_STREQ(buffer, "(&(service.version>1.2.3))");
+
+ versionRange_destroy(range);
+}
diff --git a/libs/utils/include/array_list.h b/libs/utils/include/array_list.h
index e862a8c..d74237b 100644
--- a/libs/utils/include/array_list.h
+++ b/libs/utils/include/array_list.h
@@ -16,13 +16,6 @@
* specific language governing permissions and limitations
* under the License.
*/
-/**
- * array_list.h
- *
- * \date Aug 4, 2010
- * \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- * \copyright Apache License, Version 2.0
- */
#ifndef ARRAY_LIST_H_
#define ARRAY_LIST_H_
diff --git a/libs/utils/include/celix_utils.h b/libs/utils/include/celix_utils.h
index 2a7ba35..b62395c 100644
--- a/libs/utils/include/celix_utils.h
+++ b/libs/utils/include/celix_utils.h
@@ -48,6 +48,11 @@ unsigned int celix_utils_stringHash(const char* string);
*/
bool celix_utils_stringEquals(const char* a, const char* b);
+/**
+ * Check if a string is NULL or empty "".
+ */
+bool celix_utils_isStringNullOrEmpty(const char* s);
+
/**
diff --git a/libs/utils/include/celix_version_range.h b/libs/utils/include/celix_version_range.h
new file mode 100644
index 0000000..b8ed66a
--- /dev/null
+++ b/libs/utils/include/celix_version_range.h
@@ -0,0 +1,144 @@
+/*
+ * 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 CELIX_VERSION_RANGE_H_
+#define CELIX_VERSION_RANGE_H_
+
+#include "celixbool.h"
+#include "celix_errno.h"
+#include "celix_version.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Type definition for the celix_version_range_t abstract data type.
+ */
+typedef struct celix_version_range celix_version_range_t;
+
+/**
+ * Creates a new <code>celix_version_range_t*</code>.
+ *
+ * @param low Lower bound version
+ * @param isLowInclusive True if lower bound should be included in the range
+ * @param high Upper bound version
+ * @param isHighInclusive True if upper bound should be included in the range
+ * @param versionRange The created range
+ * @return The service range or NULL if the service range could not be created
+ */
+celix_version_range_t*
+celix_versionRange_createVersionRange(celix_version_t* low, bool isLowInclusive, celix_version_t* high, bool isHighInclusive);
+
+/**
+ * Creates an infinite version range using ::version_createEmptyVersion for the low version,
+ * NULL for the high version and high and low inclusive set to true.
+ *
+ * @return The created range
+ */
+celix_version_range_t* celix_versionRange_createInfiniteVersionRange();
+
+void celix_versionRange_destroy(celix_version_range_t* range);
+
+/**
+ * Determine if the specified version is part of the version range or not.
+ *
+ * @param versionRange The range to check <code>version</code> against.
+ * @param version The version to check.
+ * @return True if the specified version is included in this version range, false otherwise.
+ */
+bool celix_versionRange_isInRange(const celix_version_range_t* versionRange, const celix_version_t* version);
+
+/**
+ * Determines whether the lower bound is included in the given range
+ *
+ * @param versionRange The range to check
+ * @return true in case, the lower bound the lower bound is included, otherwise false.
+ */
+bool celix_versionRange_isLowInclusive(const celix_version_range_t* versionRange);
+
+/**
+ * Determines whether the higher bound is included in the given range
+ *
+ * @param versionRange The range to check.
+ * @return true in case, the lower bound the higher bound is included, otherwise false.
+ */
+bool celix_versionRange_isHighInclusive(const celix_version_range_t* versionRange);
+
+/**
+ * Retrieves whether the lower bound version from the given range
+ *
+ * @param versionRange The range
+ * @param The lower bound version.
+ */
+celix_version_t* celix_versionRange_getLowVersion(const celix_version_range_t* versionRange);
+
+/**
+ * Retrieves whether the upper bound version from the given range
+ *
+ * @param versionRange The range
+ * @return The upper bound version.
+ */
+celix_version_t* celix_versionRange_getHighVersion(const celix_version_range_t* versionRange);
+
+/**
+ * Parses a version range from the specified string.
+ *
+ * <p>
+ * Here is the grammar for version range strings.
+ *
+ * <pre>
+ * version-range ::= interval | atleast
+ * interval ::= ( '[' | '(' ) floor ',' ceiling ( ']' | ')' )
+ * atleast ::= version
+ * floor ::= version
+ * ceiling ::= version
+ * </pre>
+ *
+ * Examples: "[1,2)", "[1.1,1.2)"
+ *
+ * @param rangeString String representation of the version range.
+ * @return The created celix_version_range_t or NULL if the range string was invalid.
+ */
+celix_version_range_t* celix_versionRange_parse(const char *rangeString);
+
+/**
+ * Returns the LDAP filter for a version range. Caller is owner of the returned string.
+ *
+ * @param range The version range used as input for the LDAP filer
+ * @param serviceVersionPropertyName The service version name to be used in the filter (i.e. service.version)
+ * @return LDAP filter string if valid, NULL otherwise
+ */
+char* celix_versionRange_createLDAPFilter(const celix_version_range_t* range, const char *serviceVersionAttributeName);
+
+/**
+ * construct a LDAP filter for the provided version range.
+ * The string will be created in the provided buffer, if the buffer is big enough.
+ *
+ * @return True if parse successful, False otherwise.
+ */
+bool celix_versionRange_createLDAPFilterInPlace(const celix_version_range_t* range, const char *serviceVersionAttributeName, char* buffer, size_t bufferLength);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CELIX_VERSION_RANGE_H_ */
diff --git a/libs/utils/include/version_range.h b/libs/utils/include/version_range.h
index c549699..8372d4e 100644
--- a/libs/utils/include/version_range.h
+++ b/libs/utils/include/version_range.h
@@ -34,10 +34,11 @@
#ifdef __cplusplus
extern "C" {
#endif
+
/**
* Type definition for the version_range_pt abstract data type.
*/
-typedef struct versionRange *version_range_pt;
+typedef struct celix_version_range *version_range_pt;
/**
* Creates a new <code>version_range_pt</code>.
@@ -53,7 +54,7 @@ typedef struct versionRange *version_range_pt;
*/
celix_status_t
versionRange_createVersionRange(version_pt low, bool isLowInclusive, version_pt high, bool isHighInclusive,
- version_range_pt *versionRange);
+ version_range_pt *versionRange) ;
/**
* Creates an infinite version range using ::version_createEmptyVersion for the low version,
@@ -64,9 +65,9 @@ versionRange_createVersionRange(version_pt low, bool isLowInclusive, version_pt
* - CELIX_SUCCESS when no errors are encountered.
* - CELIX_ENOMEM If allocating memory for <code>range</code> failed.
*/
-celix_status_t versionRange_createInfiniteVersionRange(version_range_pt *range);
+celix_status_t versionRange_createInfiniteVersionRange(version_range_pt *range) ;
-celix_status_t versionRange_destroy(version_range_pt range);
+celix_status_t versionRange_destroy(version_range_pt range) ;
/**
* Determine if the specified version is part of the version range or not.
@@ -77,7 +78,7 @@ celix_status_t versionRange_destroy(version_range_pt range);
* @return Status code indication failure or success:
* - CELIX_SUCCESS when no errors are encountered.
*/
-celix_status_t versionRange_isInRange(version_range_pt versionRange, version_pt version, bool *inRange);
+celix_status_t versionRange_isInRange(version_range_pt versionRange, version_pt version, bool *inRange) ;
/**
* Determines whether the lower bound is included in the given range
@@ -88,7 +89,7 @@ celix_status_t versionRange_isInRange(version_range_pt versionRange, version_pt
* - CELIX_SUCCESS when no errors are encountered.
* - CELIX_ILLEGAL_ARGUMENT in case the versionRange is NULL
*/
-celix_status_t versionRange_isLowInclusive(version_range_pt versionRange, bool *isLowInclusive);
+celix_status_t versionRange_isLowInclusive(version_range_pt versionRange, bool *isLowInclusive) ;
/**
* Determines whether the higher bound is included in the given range
@@ -99,7 +100,7 @@ celix_status_t versionRange_isLowInclusive(version_range_pt versionRange, bool *
* - CELIX_SUCCESS when no errors are encountered.
* - CELIX_ILLEGAL_ARGUMENT in case the versionRange is NULL
*/
-celix_status_t versionRange_isHighInclusive(version_range_pt versionRange, bool *isHighInclusive);
+celix_status_t versionRange_isHighInclusive(version_range_pt versionRange, bool *isHighInclusive) ;
/**
* Retrieves whether the lower bound version from the given range
@@ -110,7 +111,7 @@ celix_status_t versionRange_isHighInclusive(version_range_pt versionRange, bool
* - CELIX_SUCCESS when no errors are encountered.
* - CELIX_ILLEGAL_ARGUMENT in case the versionRange is NULL
*/
-celix_status_t versionRange_getLowVersion(version_range_pt versionRange, version_pt *lowVersion);
+celix_status_t versionRange_getLowVersion(version_range_pt versionRange, version_pt *lowVersion) ;
/**
* Retrieves whether the upper bound version from the given range
@@ -121,7 +122,7 @@ celix_status_t versionRange_getLowVersion(version_range_pt versionRange, version
* - CELIX_SUCCESS when no errors are encountered.
* - CELIX_ILLEGAL_ARGUMENT in case the versionRange is NULL
*/
-celix_status_t versionRange_getHighVersion(version_range_pt versionRange, version_pt *highVersion);
+celix_status_t versionRange_getHighVersion(version_range_pt versionRange, version_pt *highVersion) ;
/**
* Parses a version range from the specified string.
@@ -145,7 +146,7 @@ celix_status_t versionRange_getHighVersion(version_range_pt versionRange, versio
* - CELIX_ILLEGAL_ARGUMENT If the numerical components are negative,
* the qualifier string is invalid or <code>versionStr</code> is impropertly formatted.
*/
-celix_status_t versionRange_parse(const char *rangeStr, version_range_pt *range);
+celix_status_t versionRange_parse(const char *rangeStr, version_range_pt *range) ;
/**
* Returns the LDAP filter for a version range. Caller is owner of the returned string.
@@ -154,7 +155,7 @@ celix_status_t versionRange_parse(const char *rangeStr, version_range_pt *range)
* @param serviceVersionPropertyName The service version name to be used in the filter (i.e. service.version)
* @return LDAP filter string if valid, NULL otherwise
*/
-char* versionRange_createLDAPFilter(version_range_pt range, const char *serviceVersionAttributeName);
+char* versionRange_createLDAPFilter(version_range_pt range, const char *serviceVersionAttributeName) ;
/**
* construct a LDAP filter for the provided version range.
@@ -162,7 +163,7 @@ char* versionRange_createLDAPFilter(version_range_pt range, const char *serviceV
*
* @return True if parse successful, False otherwise.
*/
-bool versionRange_createLDAPFilterInPlace(version_range_pt range, const char *serviceVersionAttributeName, char* buffer, size_t bufferLength);
+bool versionRange_createLDAPFilterInPlace(version_range_pt range, const char *serviceVersionAttributeName, char* buffer, size_t bufferLength) ;
#ifdef __cplusplus
diff --git a/libs/utils/private/test/utils_test.cpp b/libs/utils/private/test/utils_test.cpp
index dfd9066..405bb06 100644
--- a/libs/utils/private/test/utils_test.cpp
+++ b/libs/utils/private/test/utils_test.cpp
@@ -362,3 +362,14 @@ TEST(utils, extractLocalNameAndNamespaceTest) {
free(name);
free(ns);
}
+
+TEST(utils, isStringNullOrEmpty) {
+ bool empty = celix_utils_isStringNullOrEmpty(nullptr);
+ CHECK_TRUE(empty);
+ empty = celix_utils_isStringNullOrEmpty("");
+ CHECK_TRUE(empty);
+ empty = celix_utils_isStringNullOrEmpty(" ");
+ CHECK_FALSE(empty);
+ empty = celix_utils_isStringNullOrEmpty("foo");
+ CHECK_FALSE(empty);
+}
\ No newline at end of file
diff --git a/libs/utils/private/test/version_range_test.cpp b/libs/utils/private/test/version_range_test.cpp
deleted file mode 100644
index 796d916..0000000
--- a/libs/utils/private/test/version_range_test.cpp
+++ /dev/null
@@ -1,475 +0,0 @@
-/*
- * 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.
- */
-/**
- * version_range_test.cpp
- *
- * \date Dec 18, 2012
- * \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- * \copyright Apache License, Version 2.0
- */
-
-#include "CppUTest/TestHarness.h"
-#include "CppUTest/TestHarness_c.h"
-#include "CppUTest/CommandLineTestRunner.h"
-#include "string.h"
-
-extern "C"
-{
-#include "version_range_private.h"
-#include "version_private.h"
-}
-
-int main(int argc, char** argv) {
- MemoryLeakWarningPlugin::turnOffNewDeleteOverloads();
- return RUN_ALL_TESTS(argc, argv);
-}
-
-static char* my_strdup(const char* s) {
- if (s == NULL) {
- return NULL;
- }
-
- size_t len = strlen(s);
-
- char *d = (char*) calloc(len + 1, sizeof(char));
-
- if (d == NULL) {
- return NULL;
- }
-
- strncpy(d, s, len);
- return d;
-}
-
-//----------------------TESTGROUP DEFINES----------------------
-
-TEST_GROUP(version_range) {
-
- void setup(void) {
- }
-
- void teardown() {
- }
-};
-
-TEST(version_range, create) {
- celix_status_t status = CELIX_SUCCESS;
- version_range_pt range = NULL;
- version_pt low = (version_pt) calloc(1, sizeof(*low));
- version_pt high = (version_pt) calloc(1, sizeof(*high));
-
- status = versionRange_createVersionRange(low, false, high, true, &range);
- LONGS_EQUAL(CELIX_SUCCESS, status);
- CHECK_C((range != NULL));
- LONGS_EQUAL(true, range->isHighInclusive);
- LONGS_EQUAL(false, range->isLowInclusive);
- POINTERS_EQUAL(low, range->low);
- POINTERS_EQUAL(high, range->high);
-
- versionRange_destroy(range);
-}
-
-TEST(version_range, createInfinite) {
- celix_status_t status = CELIX_SUCCESS;
- version_range_pt range = NULL;
- version_pt version = (version_pt) calloc(1, sizeof(*version));
- version->major = 1;
- version->minor = 2;
- version->micro = 3;
-
- status = versionRange_createInfiniteVersionRange(&range);
- LONGS_EQUAL(CELIX_SUCCESS, status);
- CHECK_C(range != NULL);
- LONGS_EQUAL(true, range->isHighInclusive);
- LONGS_EQUAL(true, range->isLowInclusive);
- LONGS_EQUAL(range->low->major, 0);
- LONGS_EQUAL(range->low->minor, 0);
- LONGS_EQUAL(range->low->micro, 0);
- STRCMP_EQUAL(range->low->qualifier, "");
- POINTERS_EQUAL(NULL, range->high);
-
- versionRange_destroy(range);
- free(version);
-}
-
-TEST(version_range, isInRange) {
- bool result;
- version_pt version = (version_pt) calloc(1, sizeof(*version));
- version->major = 1;
- version->minor = 2;
- version->micro = 3;
-
- {
- version_range_pt range = NULL;
-
- version_pt low = (version_pt) calloc(1, sizeof(*low));
- low->major = 1;
- low->minor = 2;
- low->micro = 3;
- low->qualifier = NULL;
-
- version_pt high = (version_pt) calloc(1, sizeof(*high));
- high->major = 1;
- high->minor = 2;
- high->micro = 3;
- high->qualifier = NULL;
-
- LONGS_EQUAL(CELIX_SUCCESS, versionRange_createVersionRange(low, true, high, true, &range));
- LONGS_EQUAL(CELIX_SUCCESS, versionRange_isInRange(range, version, &result));
- LONGS_EQUAL(true, result);
-
- versionRange_destroy(range);
- }
-
- {
- version_range_pt range = NULL;
-
- version_pt low = (version_pt) calloc(1, sizeof(*low));
- low->major = 1;
- low->minor = 2;
- low->micro = 3;
-
- LONGS_EQUAL(CELIX_SUCCESS, versionRange_createVersionRange(low, true, NULL, true, &range));
- LONGS_EQUAL(CELIX_SUCCESS, versionRange_isInRange(range, version, &result));
- LONGS_EQUAL(true, result);
-
- versionRange_destroy(range);
- }
-
- {
- version_range_pt range = NULL;
-
- version_pt low = (version_pt) calloc(1, sizeof(*low));
- low->major = 1;
- low->minor = 2;
- low->micro = 3;
-
- version_pt high = (version_pt) calloc(1, sizeof(*high));
- high->major = 1;
- high->minor = 2;
- high->micro = 3;
-
- LONGS_EQUAL(CELIX_SUCCESS, versionRange_createVersionRange(low, false, high, true, &range));
- LONGS_EQUAL(CELIX_SUCCESS, versionRange_isInRange(range, version, &result));
- LONGS_EQUAL(false, result);
-
- versionRange_destroy(range);
- }
-
- {
- version_range_pt range = NULL;
-
- version_pt low = (version_pt) calloc(1, sizeof(*low));
- low->major = 1;
- low->minor = 2;
- low->micro = 3;
-
- version_pt high = (version_pt) calloc(1, sizeof(*high));
- high->major = 1;
- high->minor = 2;
- high->micro = 3;
-
- LONGS_EQUAL(CELIX_SUCCESS, versionRange_createVersionRange(low, true, high, false, &range));
- LONGS_EQUAL(CELIX_SUCCESS, versionRange_isInRange(range, version, &result));
- LONGS_EQUAL(false, result);
-
- versionRange_destroy(range);
- }
-
- {
- version_range_pt range = NULL;
-
- version_pt low = (version_pt) calloc(1, sizeof(*low));
- low->major = 1;
- low->minor = 2;
- low->micro = 3;
-
- version_pt high = (version_pt) calloc(1, sizeof(*high));
- high->major = 1;
- high->minor = 2;
- high->micro = 3;
-
- LONGS_EQUAL(CELIX_SUCCESS, versionRange_createVersionRange(low, false, high, false, &range));
- LONGS_EQUAL(CELIX_SUCCESS, versionRange_isInRange(range, version, &result));
- LONGS_EQUAL(false, result);
-
- versionRange_destroy(range);
- }
-
- free(version);
-}
-
-TEST(version_range, parse) {
- version_range_pt range = NULL;
- version_pt low = (version_pt) calloc(1, sizeof(*low));
- version_pt high = (version_pt) calloc(1, sizeof(*high));
- char * version = my_strdup("[1.2.3,7.8.9]");
- low->major = 1;
- low->minor = 2;
- low->micro = 3;
-
- high->major = 7;
- high->minor = 8;
- high->micro = 9;
-
- LONGS_EQUAL(CELIX_SUCCESS, versionRange_parse(version, &range));
-
- versionRange_destroy(range);
- free(version);
- version = my_strdup("[1.2.3");
-
- LONGS_EQUAL(CELIX_ILLEGAL_ARGUMENT, versionRange_parse(version, &range));
-
- free(version);
-
- free(high);
- free(low);
-}
-
-TEST(version_range, createLdapFilterInclusiveBoth) {
- version_pt low = (version_pt) calloc(1, sizeof(*low));
- low->major = 1;
- low->minor = 2;
- low->micro = 3;
- low->qualifier = NULL;
-
- version_pt high = (version_pt) calloc(1, sizeof(*high));
- high->major = 1;
- high->minor = 2;
- high->micro = 3;
- high->qualifier = NULL;
-
- version_range_pt range = NULL;
- LONGS_EQUAL(CELIX_SUCCESS, versionRange_createVersionRange(low, true, high, true, &range));
-
- auto filter = versionRange_createLDAPFilter(range, "service.version");
- STRCMP_EQUAL(filter, "(&(service.version>=1.2.3)(service.version<=1.2.3))");
-
- versionRange_destroy(range);
- free(filter);
-}
-
-TEST(version_range, createLdapFilterInclusiveLow) {
- version_pt low = (version_pt) calloc(1, sizeof(*low));
- low->major = 1;
- low->minor = 2;
- low->micro = 3;
- low->qualifier = NULL;
-
- version_pt high = (version_pt) calloc(1, sizeof(*high));
- high->major = 1;
- high->minor = 2;
- high->micro = 3;
- high->qualifier = NULL;
-
- version_range_pt range = NULL;
- LONGS_EQUAL(CELIX_SUCCESS, versionRange_createVersionRange(low, false, high, true, &range));
-
- auto filter = versionRange_createLDAPFilter(range, "service.version");
- STRCMP_EQUAL(filter, "(&(service.version>1.2.3)(service.version<=1.2.3))");
-
- versionRange_destroy(range);
- free(filter);
-}
-
-TEST(version_range, createLdapFilterInclusiveHigh) {
- version_pt low = (version_pt) calloc(1, sizeof(*low));
- low->major = 1;
- low->minor = 2;
- low->micro = 3;
- low->qualifier = NULL;
-
- version_pt high = (version_pt) calloc(1, sizeof(*high));
- high->major = 1;
- high->minor = 2;
- high->micro = 3;
- high->qualifier = NULL;
-
- version_range_pt range = NULL;
- LONGS_EQUAL(CELIX_SUCCESS, versionRange_createVersionRange(low, true, high, false, &range));
-
- auto filter = versionRange_createLDAPFilter(range, "service.version");
- STRCMP_EQUAL(filter, "(&(service.version>=1.2.3)(service.version<1.2.3))");
-
- versionRange_destroy(range);
- free(filter);
-}
-
-TEST(version_range, createLdapFilterExclusiveBoth) {
- version_pt low = (version_pt) calloc(1, sizeof(*low));
- low->major = 1;
- low->minor = 2;
- low->micro = 3;
- low->qualifier = NULL;
-
- version_pt high = (version_pt) calloc(1, sizeof(*high));
- high->major = 1;
- high->minor = 2;
- high->micro = 3;
- high->qualifier = NULL;
-
- version_range_pt range = NULL;
- LONGS_EQUAL(CELIX_SUCCESS, versionRange_createVersionRange(low, false, high, false, &range));
-
- auto filter = versionRange_createLDAPFilter(range, "service.version");
- STRCMP_EQUAL(filter, "(&(service.version>1.2.3)(service.version<1.2.3))");
-
- versionRange_destroy(range);
- free(filter);
-}
-
-TEST(version_range, createLdapFilterInfinite) {
- version_pt low = (version_pt) calloc(1, sizeof(*low));
- low->major = 1;
- low->minor = 2;
- low->micro = 3;
- low->qualifier = NULL;
-
- version_range_pt range = NULL;
- LONGS_EQUAL(CELIX_SUCCESS, versionRange_createVersionRange(low, true, NULL, true, &range));
-
- auto filter = versionRange_createLDAPFilter(range, "service.version");
- STRCMP_EQUAL(filter, "(&(service.version>=1.2.3))");
-
- versionRange_destroy(range);
- free(filter);
-}
-
-TEST(version_range, createLdapFilterInPlaceInclusiveBoth) {
- version_pt low = (version_pt) calloc(1, sizeof(*low));
- low->major = 1;
- low->minor = 2;
- low->micro = 3;
- low->qualifier = NULL;
-
- version_pt high = (version_pt) calloc(1, sizeof(*high));
- high->major = 1;
- high->minor = 2;
- high->micro = 3;
- high->qualifier = NULL;
-
- version_range_pt range = NULL;
- LONGS_EQUAL(CELIX_SUCCESS, versionRange_createVersionRange(low, true, high, true, &range));
- char buffer[100];
- int bufferLen = sizeof(buffer) / sizeof(buffer[0]);
-
- LONGS_EQUAL(1, versionRange_createLDAPFilterInPlace(range, "service.version", buffer, bufferLen));
-
- STRCMP_EQUAL(buffer, "(&(service.version>=1.2.3)(service.version<=1.2.3))");
-
- versionRange_destroy(range);
-}
-
-TEST(version_range, createLdapFilterInPlaceInclusiveLow) {
- version_pt low = (version_pt) calloc(1, sizeof(*low));
- low->major = 1;
- low->minor = 2;
- low->micro = 3;
- low->qualifier = NULL;
-
- version_pt high = (version_pt) calloc(1, sizeof(*high));
- high->major = 1;
- high->minor = 2;
- high->micro = 3;
- high->qualifier = NULL;
-
- version_range_pt range = NULL;
- LONGS_EQUAL(CELIX_SUCCESS, versionRange_createVersionRange(low, true, high, false, &range));
- char buffer[100];
- int bufferLen = sizeof(buffer) / sizeof(buffer[0]);
-
- LONGS_EQUAL(1, versionRange_createLDAPFilterInPlace(range, "service.version", buffer, bufferLen));
-
- STRCMP_EQUAL(buffer, "(&(service.version>=1.2.3)(service.version<1.2.3))");
-
- versionRange_destroy(range);
-}
-
-TEST(version_range, createLdapFilterInPlaceInclusiveHigh) {
- version_pt low = (version_pt) calloc(1, sizeof(*low));
- low->major = 1;
- low->minor = 2;
- low->micro = 3;
- low->qualifier = NULL;
-
- version_pt high = (version_pt) calloc(1, sizeof(*high));
- high->major = 1;
- high->minor = 2;
- high->micro = 3;
- high->qualifier = NULL;
-
- version_range_pt range = NULL;
- LONGS_EQUAL(CELIX_SUCCESS, versionRange_createVersionRange(low, false, high, true, &range));
- char buffer[100];
- int bufferLen = sizeof(buffer) / sizeof(buffer[0]);
-
- LONGS_EQUAL(1, versionRange_createLDAPFilterInPlace(range, "service.version", buffer, bufferLen));
-
- STRCMP_EQUAL(buffer, "(&(service.version>1.2.3)(service.version<=1.2.3))");
-
- versionRange_destroy(range);
-}
-
-TEST(version_range, createLdapFilterInPlaceExclusiveBoth) {
- version_pt low = (version_pt) calloc(1, sizeof(*low));
- low->major = 1;
- low->minor = 2;
- low->micro = 3;
- low->qualifier = NULL;
-
- version_pt high = (version_pt) calloc(1, sizeof(*high));
- high->major = 1;
- high->minor = 2;
- high->micro = 3;
- high->qualifier = NULL;
-
- version_range_pt range = NULL;
- LONGS_EQUAL(CELIX_SUCCESS, versionRange_createVersionRange(low, false, high, false, &range));
- char buffer[100];
- int bufferLen = sizeof(buffer) / sizeof(buffer[0]);
-
- LONGS_EQUAL(1, versionRange_createLDAPFilterInPlace(range, "service.version", buffer, bufferLen));
-
- STRCMP_EQUAL(buffer, "(&(service.version>1.2.3)(service.version<1.2.3))");
-
- versionRange_destroy(range);
-}
-
-TEST(version_range, createLdapFilterInPlaceInfiniteHigh) {
- version_pt low = (version_pt) calloc(1, sizeof(*low));
- low->major = 1;
- low->minor = 2;
- low->micro = 3;
- low->qualifier = NULL;
-
- version_range_pt range = NULL;
- LONGS_EQUAL(CELIX_SUCCESS, versionRange_createVersionRange(low, false, NULL, false, &range));
- char buffer[100];
- int bufferLen = sizeof(buffer) / sizeof(buffer[0]);
-
- LONGS_EQUAL(1, versionRange_createLDAPFilterInPlace(range, "service.version", buffer, bufferLen));
-
- STRCMP_EQUAL(buffer, "(&(service.version>1.2.3))");
-
- versionRange_destroy(range);
-}
-
-
-
-
diff --git a/libs/utils/private/test/version_test.cpp b/libs/utils/private/test/version_test.cpp
index 666a0af..1fa59e7 100644
--- a/libs/utils/private/test/version_test.cpp
+++ b/libs/utils/private/test/version_test.cpp
@@ -401,3 +401,14 @@ TEST(version,semanticCompatibility) {
version_destroy(incompatible_user_by_minor);
}
+TEST(version, compareEmptyAndNullQualifier) {
+ //nullptr or "" qualifier should be the same
+ auto* v1 = celix_version_createVersion(0, 0, 0, nullptr);
+ auto* v2 = celix_version_createVersion(0, 0, 0, "");
+ CHECK_EQUAL(0, celix_version_compareTo(v1, v1));
+ CHECK_EQUAL(0, celix_version_compareTo(v1, v2));
+ CHECK_EQUAL(0, celix_version_compareTo(v2, v2));
+
+ celix_version_destroy(v1);
+ celix_version_destroy(v2);
+}
\ No newline at end of file
diff --git a/libs/utils/src/utils.c b/libs/utils/src/utils.c
index f82bd26..5d5a860 100644
--- a/libs/utils/src/utils.c
+++ b/libs/utils/src/utils.c
@@ -61,6 +61,10 @@ bool celix_utils_stringEquals(const char* a, const char* b) {
}
}
+bool celix_utils_isStringNullOrEmpty(const char* s) {
+ return s == NULL || strlen(s) == 0;
+}
+
char * string_ndup(const char *s, size_t n) {
size_t len = strlen(s);
char *ret;
diff --git a/libs/utils/src/version.c b/libs/utils/src/version.c
index fc3ba9d..f67bacc 100644
--- a/libs/utils/src/version.c
+++ b/libs/utils/src/version.c
@@ -134,11 +134,7 @@ celix_version_t* celix_version_createVersion(int major, int minor, int micro, co
void celix_version_destroy(celix_version_t* version) {
if (version != NULL) {
- version->major = 0;
- version->minor = 0;
- version->micro = 0;
free(version->qualifier);
- version->qualifier = NULL;
free(version);
}
}
@@ -265,9 +261,9 @@ int celix_version_compareTo(const celix_version_t* version, const celix_version_
if (res != 0) {
result = res;
} else {
- if(version->qualifier == NULL && compare->qualifier == NULL) {
+ if(celix_utils_isStringNullOrEmpty(version->qualifier) && celix_utils_isStringNullOrEmpty(version->qualifier)) {
result = 0;
- } else if (version->qualifier == NULL || compare->qualifier == NULL) {
+ } else if (celix_utils_isStringNullOrEmpty(version->qualifier) || celix_utils_isStringNullOrEmpty(version->qualifier)) {
result = -1;
} else {
result = strcmp(version->qualifier, compare->qualifier);
diff --git a/libs/utils/src/version_range.c b/libs/utils/src/version_range.c
index 8d5a6ee..1a6a48a 100644
--- a/libs/utils/src/version_range.c
+++ b/libs/utils/src/version_range.c
@@ -16,13 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-/**
- * version_range.c
- *
- * \date Jul 12, 2010
- * \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>
@@ -30,102 +24,34 @@
#include <assert.h>
#include "version_private.h"
+#include "version_range.h"
+#include "celix_version_range.h"
#include "version_range_private.h"
+#include "celix_version_range.h"
celix_status_t versionRange_createVersionRange(version_pt low, bool isLowInclusive,
version_pt high, bool isHighInclusive, version_range_pt *range) {
- assert(low != high);
- celix_status_t status = CELIX_SUCCESS;
- *range = (version_range_pt) malloc(sizeof(**range));
- if (!*range) {
- status = CELIX_ENOMEM;
- } else {
- (*range)->low = low;
- (*range)->isLowInclusive = isLowInclusive;
- (*range)->high = high;
- (*range)->isHighInclusive = isHighInclusive;
- }
-
- return status;
+ *range = celix_versionRange_createVersionRange(low, isLowInclusive, high, isHighInclusive);
+ return CELIX_SUCCESS;
}
celix_status_t versionRange_destroy(version_range_pt range) {
- if (range->high != NULL) {
- version_destroy(range->high);
- }
- if (range->low != NULL) {
- version_destroy(range->low);
- }
-
- range->high = NULL;
- range->isHighInclusive = false;
- range->low = NULL;
- range->isLowInclusive = false;
-
- free(range);
-
+ celix_versionRange_destroy(range);
return CELIX_SUCCESS;
}
celix_status_t versionRange_createInfiniteVersionRange(version_range_pt *range) {
- celix_status_t status;
-
- version_pt version = NULL;
- status = version_createEmptyVersion(&version);
- if (status == CELIX_SUCCESS) {
- status = versionRange_createVersionRange(version, true, NULL, true, range);
- }
-
- return status;
+ *range = celix_versionRange_createInfiniteVersionRange();
+ return CELIX_SUCCESS;
}
celix_status_t versionRange_isInRange(version_range_pt versionRange, version_pt version, bool *inRange) {
- celix_status_t status;
- if (versionRange->high == NULL) {
- int cmp;
- status = version_compareTo(version, versionRange->low, &cmp);
- if (status == CELIX_SUCCESS) {
- *inRange = (cmp >= 0);
- }
- } else if (versionRange->isLowInclusive && versionRange->isHighInclusive) {
- int low, high;
- status = version_compareTo(version, versionRange->low, &low);
- if (status == CELIX_SUCCESS) {
- status = version_compareTo(version, versionRange->high, &high);
- if (status == CELIX_SUCCESS) {
- *inRange = (low >= 0) && (high <= 0);
- }
- }
- } else if (versionRange->isHighInclusive) {
- int low, high;
- status = version_compareTo(version, versionRange->low, &low);
- if (status == CELIX_SUCCESS) {
- status = version_compareTo(version, versionRange->high, &high);
- if (status == CELIX_SUCCESS) {
- *inRange = (low > 0) && (high <= 0);
- }
- }
- } else if (versionRange->isLowInclusive) {
- int low, high;
- status = version_compareTo(version, versionRange->low, &low);
- if (status == CELIX_SUCCESS) {
- status = version_compareTo(version, versionRange->high, &high);
- if (status == CELIX_SUCCESS) {
- *inRange = (low >= 0) && (high < 0);
- }
- }
+ if (versionRange != NULL && version != NULL) {
+ *inRange = celix_versionRange_isInRange(versionRange, version);
+ return CELIX_SUCCESS;
} else {
- int low, high;
- status = version_compareTo(version, versionRange->low, &low);
- if (status == CELIX_SUCCESS) {
- status = version_compareTo(version, versionRange->high, &high);
- if (status == CELIX_SUCCESS) {
- *inRange = (low > 0) && (high < 0);
- }
- }
+ return CELIX_ILLEGAL_ARGUMENT;
}
-
- return status;
}
celix_status_t versionRange_getLowVersion(version_range_pt versionRange, version_pt *lowVersion) {
@@ -182,61 +108,139 @@ celix_status_t versionRange_isHighInclusive(version_range_pt versionRange, bool
celix_status_t versionRange_parse(const char * rangeStr, version_range_pt *range) {
- celix_status_t status;
- if (strchr(rangeStr, ',') != NULL) {
- int vlowL = strcspn(rangeStr+1, ",");
- char * vlow = (char *) malloc(sizeof(char) * (vlowL + 1));
- if (!vlow) {
- status = CELIX_ENOMEM;
- } else {
- int vhighL;
- char * vhigh;
- vlow = strncpy(vlow, rangeStr+1, vlowL);
- vlow[vlowL] = '\0';
- vhighL = strlen(rangeStr+1) - vlowL - 2;
- vhigh = (char *) malloc(sizeof(char) * (vhighL+1));
- if (!vhigh) {
- status = CELIX_ENOMEM;
- } else {
- version_pt versionLow = NULL;
- int rangeL = strlen(rangeStr);
- char start = rangeStr[0];
- char end = rangeStr[rangeL-1];
-
- vhigh = strncpy(vhigh, rangeStr+vlowL+2, vhighL);
- vhigh[vhighL] = '\0';
- status = version_createVersionFromString(vlow, &versionLow);
- if (status == CELIX_SUCCESS) {
- version_pt versionHigh = NULL;
- status = version_createVersionFromString(vhigh, &versionHigh);
- if (status == CELIX_SUCCESS) {
- status = versionRange_createVersionRange(
- versionLow,
- start == '[',
- versionHigh,
- end ==']',
- range
- );
- }
- }
- free(vhigh);
- }
- free(vlow);
+ *range = celix_versionRange_parse(rangeStr);
+ if (*range == NULL) {
+ return CELIX_ILLEGAL_ARGUMENT;
+ } else {
+ return CELIX_SUCCESS;
+ }
+}
+char* versionRange_createLDAPFilter(version_range_pt range, const char *serviceVersionAttributeName) {
+ return celix_versionRange_createLDAPFilter(range, serviceVersionAttributeName);
+}
+
+
+
+bool versionRange_createLDAPFilterInPlace(version_range_pt range, const char *serviceVersionAttributeName, char* buffer, size_t bufferLength) {
+ return celix_versionRange_createLDAPFilterInPlace(range, serviceVersionAttributeName, buffer, bufferLength);
+}
+
+celix_version_range_t* celix_versionRange_createVersionRange(celix_version_t* low, bool isLowInclusive, celix_version_t* high, bool isHighInclusive) {
+ assert(low != high);
+ celix_version_range_t* range = malloc(sizeof(*range));
+ range->low = low;
+ range->isLowInclusive = isLowInclusive;
+ range->high = high;
+ range->isHighInclusive = isHighInclusive;
+ return range;
+}
+
+
+celix_version_range_t* celix_versionRange_createInfiniteVersionRange() {
+ return celix_versionRange_createVersionRange(celix_version_createEmptyVersion(), true, NULL, true);
+}
+
+void celix_versionRange_destroy(celix_version_range_t* range) {
+ if (range->high != NULL) {
+ celix_version_destroy(range->high);
+ }
+ if (range->low != NULL) {
+ celix_version_destroy(range->low);
+ }
+ free(range);
+}
+
+
+bool celix_versionRange_isInRange(const celix_version_range_t* versionRange, const celix_version_t* version) {
+ bool inRange = false;
+ int high;
+ int low;
+ if (versionRange->high != NULL) {
+ high = celix_version_compareTo(version, versionRange->high);
+ }
+ if (versionRange->low != NULL) {
+ low = celix_version_compareTo(version, versionRange->low);
+ }
+
+ if (versionRange->high == NULL) {
+ inRange = (low >= 0);
+ } else if (versionRange->isLowInclusive && versionRange->isHighInclusive) {
+ inRange = (low >= 0) && (high <= 0);
+ } else if (versionRange->isHighInclusive) {
+ inRange = (low > 0) && (high <= 0);
+ } else if (versionRange->isLowInclusive) {
+ inRange = (low >= 0) && (high < 0);
+ } else {
+ inRange = (low > 0) && (high < 0);
+ }
+
+ return inRange;
+}
+
+
+bool celix_versionRange_isLowInclusive(const celix_version_range_t* versionRange) {
+ return versionRange->isLowInclusive;
+}
+
+
+bool celix_versionRange_isHighInclusive(const celix_version_range_t* versionRange) {
+ return versionRange->isHighInclusive;
+}
+
+
+celix_version_t* celix_versionRange_getLowVersion(const celix_version_range_t* versionRange) {
+ return versionRange->low;
+}
+
+
+celix_version_t* celix_versionRange_getHighVersion(const celix_version_range_t* versionRange) {
+ return versionRange->high;
+}
+
+celix_version_range_t* celix_versionRange_parse(const char *rangeString) {
+ celix_version_range_t* range = NULL;
+ if (strchr(rangeString, ',') != NULL) {
+ int vlowL = strcspn(rangeString+1, ",");
+ char * vlow = malloc(sizeof(char) * (vlowL + 1));
+ int vhighL;
+ char * vhigh;
+ vlow = strncpy(vlow, rangeString+1, vlowL);
+ vlow[vlowL] = '\0';
+ vhighL = strlen(rangeString+1) - vlowL - 2;
+ vhigh = (char *) malloc(sizeof(char) * (vhighL+1));
+ int rangeL = strlen(rangeString);
+ char start = rangeString[0];
+ char end = rangeString[rangeL-1];
+
+ vhigh = strncpy(vhigh, rangeString+vlowL+2, vhighL);
+ vhigh[vhighL] = '\0';
+ celix_version_t* versionLow = celix_version_createVersionFromString(vlow);
+ if (versionLow != NULL) {
+ celix_version_t* versionHigh = celix_version_createVersionFromString(vhigh);
+ if (versionHigh != NULL) {
+ range = celix_versionRange_createVersionRange(
+ versionLow,
+ start == '[',
+ versionHigh,
+ end ==']'
+ );
+ }
}
+ free(vhigh);
+ free(vlow);
} else {
- version_pt version = NULL;
- status = version_createVersionFromString(rangeStr, &version);
- if (status == CELIX_SUCCESS) {
- status = versionRange_createVersionRange(version, true, NULL, false, range);
+ celix_version_t* version = celix_version_createVersionFromString(rangeString);
+ if (version != NULL) {
+ range = celix_versionRange_createVersionRange(version, true, NULL, false);
}
}
- return status;
+ return range;
}
-char* versionRange_createLDAPFilter(version_range_pt range, const char *serviceVersionAttributeName) {
- char *output;
+char* celix_versionRange_createLDAPFilter(const celix_version_range_t* range, const char *serviceVersionAttributeName) {
+ char *output = NULL;
int ret = -1;
if(range->high == NULL) {
@@ -258,9 +262,7 @@ char* versionRange_createLDAPFilter(version_range_pt range, const char *serviceV
return output;
}
-
-
-bool versionRange_createLDAPFilterInPlace(version_range_pt range, const char *serviceVersionAttributeName, char* buffer, size_t bufferLength) {
+bool celix_versionRange_createLDAPFilterInPlace(const celix_version_range_t* range, const char *serviceVersionAttributeName, char* buffer, size_t bufferLength) {
if(buffer == NULL || bufferLength == 0) {
return false;
}
diff --git a/libs/utils/src/version_range_private.h b/libs/utils/src/version_range_private.h
index bcd8296..757090f 100644
--- a/libs/utils/src/version_range_private.h
+++ b/libs/utils/src/version_range_private.h
@@ -16,23 +16,16 @@
* specific language governing permissions and limitations
* under the License.
*/
-/**
- * version_range_private.h
- *
- * \date Dec 18, 2012
- * \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- * \copyright Apache License, Version 2.0
- */
#ifndef VERSION_RANGE_PRIVATE_H_
#define VERSION_RANGE_PRIVATE_H_
-#include "version_range.h"
+#include "celix_version.h"
-struct versionRange {
- version_pt low;
+struct celix_version_range {
+ celix_version_t* low;
bool isLowInclusive;
- version_pt high;
+ celix_version_t* high;
bool isHighInclusive;
};