CELIX-446: Adds celix_bundleContext_findService(s) implementation. Also adds support setting/getting different primitive types for the celix array list.
Project: http://git-wip-us.apache.org/repos/asf/celix/repo Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/48aada3a Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/48aada3a Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/48aada3a Branch: refs/heads/develop Commit: 48aada3abace985b22adbe082f9e754028d6362c Parents: ae09682 Author: Pepijn Noltes <[email protected]> Authored: Fri May 11 14:58:13 2018 +0200 Committer: Pepijn Noltes <[email protected]> Committed: Fri May 11 14:58:13 2018 +0200 ---------------------------------------------------------------------- .../src/dynamic_consumer_example.c | 9 +- .../src/dynamic_provider_example.c | 7 +- framework/include/bundle_context.h | 93 +++++++++--- framework/private/mock/bundle_context_mock.c | 30 ++++ framework/src/bundle_context.c | 94 ++++++++---- framework/src/service_tracker.c | 32 ++-- framework/tst/bundle_context_services_test.cpp | 35 ++++- utils/include/array_list.h | 43 +++++- utils/src/array_list.c | 152 +++++++++++++------ utils/src/array_list_private.h | 2 +- 10 files changed, 370 insertions(+), 127 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/celix/blob/48aada3a/examples/celix-examples/services_example_c/src/dynamic_consumer_example.c ---------------------------------------------------------------------- diff --git a/examples/celix-examples/services_example_c/src/dynamic_consumer_example.c b/examples/celix-examples/services_example_c/src/dynamic_consumer_example.c index 5a676d6..7a7f177 100644 --- a/examples/celix-examples/services_example_c/src/dynamic_consumer_example.c +++ b/examples/celix-examples/services_example_c/src/dynamic_consumer_example.c @@ -112,8 +112,8 @@ void * run(void *handle) { activator_data_t *data = handle; printf("starting consumer thread\n"); - celix_service_tracking_options_t opts; - opts.serviceName = EXAMPLE_CALC_NAME; + celix_service_tracking_options_t opts = CELIX_EMPTY_SERVICE_TRACKING_OPTIONS; + opts.filter.serviceName = EXAMPLE_CALC_NAME; opts.callbackHandle = data; opts.addWithProperties = (void*)addSvc; opts.removeWithProperties = (void*)removeSvc; @@ -128,10 +128,9 @@ void * run(void *handle) { gccExample(data); //gcc trampolines example (nested functions) - celix_service_use_options_t opts; - memset(&opts, 0, sizeof(opts)); + celix_service_use_options_t opts = CELIX_EMPTY_SERVICE_USE_OPTIONS; - opts.serviceName = EXAMPLE_CALC_NAME; + opts.filter.serviceName = EXAMPLE_CALC_NAME; opts.callbackHandle = data; opts.useWithProperties = (void*)useHighest; celix_bundleContext_useServiceWithOptions(data->ctx, &opts); http://git-wip-us.apache.org/repos/asf/celix/blob/48aada3a/examples/celix-examples/services_example_c/src/dynamic_provider_example.c ---------------------------------------------------------------------- diff --git a/examples/celix-examples/services_example_c/src/dynamic_provider_example.c b/examples/celix-examples/services_example_c/src/dynamic_provider_example.c index f322303..4127c4b 100644 --- a/examples/celix-examples/services_example_c/src/dynamic_provider_example.c +++ b/examples/celix-examples/services_example_c/src/dynamic_provider_example.c @@ -67,7 +67,8 @@ void * run(void *handle) { celix_properties_setLong(props, OSGI_FRAMEWORK_SERVICE_RANKING, rand()); data->svcIds[i++] = celix_bundleContext_registerService(data->ctx, EXAMPLE_CALC_NAME, &data->svc, NULL, props); } else { //down - celix_bundleContext_unregisterService(data->ctx, data->svcIds[i--]); + celix_bundleContext_unregisterService(data->ctx, data->svcIds[i]); + data->svcIds[--i] = -1L; } if (i == 99) { up = false; @@ -79,9 +80,7 @@ void * run(void *handle) { for (int i = 0; i < 100; ++i) { long id = data->svcIds[i]; - if (id >=0 ) { - celix_bundleContext_unregisterService(data->ctx, id); - } + celix_bundleContext_unregisterService(data->ctx, id); } printf("exiting service register thread\n"); http://git-wip-us.apache.org/repos/asf/celix/blob/48aada3a/framework/include/bundle_context.h ---------------------------------------------------------------------- diff --git a/framework/include/bundle_context.h b/framework/include/bundle_context.h index 44cca39..5daaff9 100644 --- a/framework/include/bundle_context.h +++ b/framework/include/bundle_context.h @@ -272,13 +272,51 @@ long celix_bundleContext_registerServiceFactorForLang(celix_bundle_context_t *ct void celix_bundleContext_unregisterService(celix_bundle_context_t *ctx, long serviceId); -//TODO -//typedef struct celix_service_find_filter_options { -// servicname, versionrange, filter, lang -//} celix_service_find_filter_options_t; -//celix_array_list_t* celix_bundleContext_findServices(celix_bundle_context_t *ctx, const char *serviceName); -//celix_array_list_t* celix_bundleContext_findServices(celix_bundle_context_t *ctx, const char *serviceName); -//alts WithOptions +typedef struct celix_service_filter_options { + const char* serviceName; //REQUIRED + const char* versionRange; + const char* filter; + const char* lang; //NULL -> 'CELIX_LANG_C' +} celix_service_filter_options_t; + +#define CELIX_EMPTY_SERVICE_FILTER_OPTIONS {.serviceName = NULL, .versionRange = NULL, .filter = NULL, .lang = NULL} + + +/** + * Finds the highest ranking service and returns the service id. + * + * @param ctx The bundle context + * @param serviceName The required service name + * @return If found a valid service id (>= 0) if not found -1. + */ +long celix_bundleContext_findService(celix_bundle_context_t *ctx, const char *serviceName); + +/** + * Finds the highest ranking service and returns the service id. + * + * @param ctx The bundle context + * @param opts The pointer to the filter options. + * @return If found a valid service id (>= 0) if not found -1. + */ +long celix_bundleContext_findServiceWithOptions(celix_bundle_context_t *ctx, const celix_service_filter_options_t *opts); + +/** + * Finds the services with the provided service name and returns a list of the found service ids. + * + * @param ctx The bundle context + * @param serviceName The required service name + * @return A array list with as value a long int. + */ +celix_array_list_t* celix_bundleContext_findServices(celix_bundle_context_t *ctx, const char *serviceName); + +/** + * Finds the services conform the provider filter options and returns a list of the found service ids. + * + * @param ctx The bundle context + * @param opts The pointer to the filter options. + * @return A array list with as value a long int. + */ +celix_array_list_t* celix_bundleContext_findServicesWithOptions(celix_bundle_context_t *ctx, const celix_service_filter_options_t *opts); /** @@ -323,11 +361,7 @@ long celix_bundleContext_trackServices( ); typedef struct celix_service_tracker_options { - //service filter options - const char* serviceName; - const char* versionRange; - const char* filter; - const char* lang; //NULL -> 'CELIX_LANG_C' + celix_service_filter_options_t filter; //callback options void* callbackHandle; @@ -335,19 +369,31 @@ typedef struct celix_service_tracker_options { void (*set)(void *handle, void *svc); //highest ranking void (*add)(void *handle, void *svc); void (*remove)(void *handle, void *svc); - void (*modified)(void *handle, void *svc); void (*setWithProperties)(void *handle, void *svc, const celix_properties_t *props); //highest ranking void (*addWithProperties)(void *handle, void *svc, const celix_properties_t *props); void (*removeWithProperties)(void *handle, void *svc, const celix_properties_t *props); - void (*modifiedWithProperties)(void *handle, void *svc, const celix_properties_t *props); void (*setWithOwner)(void *handle, void *svc, const celix_properties_t *props, const celix_bundle_t *svcOwner); //highest ranking void (*addWithOwner)(void *handle, void *svc, const celix_properties_t *props, const celix_bundle_t *svcOwner); void (*removeWithOwner)(void *handle, void *svc, const celix_properties_t *props, const celix_bundle_t *svcOwner); - void (*modifiedWithOwner)(void *handle, void *svc, const celix_properties_t *props, const celix_bundle_t *svcOwner); } celix_service_tracking_options_t; +#define CELIX_EMPTY_SERVICE_TRACKING_OPTIONS { .filter.serviceName = NULL, \ + .filter.versionRange = NULL, \ + .filter.filter = NULL, \ + .filter.lang = NULL, \ + .callbackHandle = NULL, \ + .set = NULL, \ + .add = NULL, \ + .remove = NULL, \ + .setWithProperties = NULL, \ + .addWithProperties = NULL, \ + .removeWithProperties = NULL, \ + .setWithOwner = NULL, \ + .addWithOwner = NULL, \ + .removeWithOwner = NULL} + /** * Tracks services using the provided tracker options. * The tracker options are only using during this call and can safely be freed/reused after this call returns. @@ -431,13 +477,7 @@ void celix_bundleContext_useServices( typedef struct celix_service_use_options { - /** - * service filter options. Note the serviceName is required. - */ - const char *serviceName; //REQUIRED - const char *versionRange; //default will be empty - const char *filter; //default will be empty - const char *lang; //default will be LANG_C + celix_service_filter_options_t filter; /** * Callback info @@ -449,6 +489,15 @@ typedef struct celix_service_use_options { void (*useWithOwner)(void *handle, void *svc, const celix_properties_t *props, const celix_bundle_t *svcOwner); } celix_service_use_options_t; +#define CELIX_EMPTY_SERVICE_USE_OPTIONS {.filter.serviceName = NULL, \ + .filter.versionRange = NULL, \ + .filter.filter = NULL, \ + .filter.lang = NULL, \ + .callbackHandle = NULL, \ + .use = NULL, \ + .useWithProperties = NULL, \ + .useWithOwner = NULL} + /** * Get and lock the current highest ranking service conform the service filter info from the provided options. * http://git-wip-us.apache.org/repos/asf/celix/blob/48aada3a/framework/private/mock/bundle_context_mock.c ---------------------------------------------------------------------- diff --git a/framework/private/mock/bundle_context_mock.c b/framework/private/mock/bundle_context_mock.c index 749e3ca..b763b5a 100644 --- a/framework/private/mock/bundle_context_mock.c +++ b/framework/private/mock/bundle_context_mock.c @@ -346,4 +346,34 @@ long celix_bundleContext_registerServiceFactorForLang(celix_bundle_context_t *ct ->withStringParameters("lang", lang) ->withPointerParameters("props", props); return mock_c()->returnValue().value.longIntValue; +} + +long celix_bundleContext_findService(celix_bundle_context_t *ctx, const char *serviceName) { + mock_c()->actualCall("celix_bundleContext_findService") + ->withPointerParameters("ctx", ctx) + ->withStringParameters("serviceName", serviceName); + return mock_c()->returnValue().value.longIntValue; +} + + +long celix_bundleContext_findServiceWithOptions(celix_bundle_context_t *ctx, const celix_service_filter_options_t *opts) { + mock_c()->actualCall("celix_bundleContext_findServiceWithOptions") + ->withPointerParameters("ctx", ctx) + ->withConstPointerParameters("opts", opts); + return mock_c()->returnValue().value.longIntValue; +} + + +celix_array_list_t* celix_bundleContext_findServices(celix_bundle_context_t *ctx, const char *serviceName) { + mock_c()->actualCall("celix_bundleContext_findServices") + ->withPointerParameters("ctx", ctx) + ->withStringParameters("serviceName", serviceName); + return mock_c()->returnValue().value.pointerValue; +} + +celix_array_list_t* celix_bundleContext_findServicesWithOptions(celix_bundle_context_t *ctx, const celix_service_filter_options_t *opts) { + mock_c()->actualCall("celix_bundleContext_findServicesWithOptions") + ->withPointerParameters("ctx", ctx) + ->withConstPointerParameters("opts", opts); + return mock_c()->returnValue().value.pointerValue; } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/celix/blob/48aada3a/framework/src/bundle_context.c ---------------------------------------------------------------------- diff --git a/framework/src/bundle_context.c b/framework/src/bundle_context.c index 7d5dea9..ffb1704 100644 --- a/framework/src/bundle_context.c +++ b/framework/src/bundle_context.c @@ -672,14 +672,13 @@ bool celix_bundleContext_useServiceWithId( const char *serviceName, void *callbackHandle, void (*use)(void *handle, void *svc)) { - celix_service_use_options_t opts; - memset(&opts, 0, sizeof(opts)); + celix_service_use_options_t opts = CELIX_EMPTY_SERVICE_USE_OPTIONS; char filter[64]; snprintf(filter, 64, "(%s=%li)", OSGI_FRAMEWORK_SERVICE_ID, serviceId); - opts.serviceName = serviceName; - opts.filter = filter; + opts.filter.serviceName = serviceName; + opts.filter.filter = filter; opts.callbackHandle = callbackHandle; opts.use = use; return celix_bundleContext_useServiceWithOptions(ctx, &opts); @@ -690,9 +689,8 @@ bool celix_bundleContext_useService( const char* serviceName, void *callbackHandle, void (*use)(void *handle, void *svc)) { - celix_service_use_options_t opts; - memset(&opts, 0, sizeof(opts)); - opts.serviceName = serviceName; + celix_service_use_options_t opts = CELIX_EMPTY_SERVICE_USE_OPTIONS; + opts.filter.serviceName = serviceName; opts.callbackHandle = callbackHandle; opts.use = use; return celix_bundleContext_useServiceWithOptions(ctx, &opts); @@ -704,9 +702,8 @@ void celix_bundleContext_useServices( const char* serviceName, void *callbackHandle, void (*use)(void *handle, void *svc)) { - celix_service_use_options_t opts; - memset(&opts, 0, sizeof(opts)); - opts.serviceName = serviceName; + celix_service_use_options_t opts = CELIX_EMPTY_SERVICE_USE_OPTIONS; + opts.filter.serviceName = serviceName; opts.callbackHandle = callbackHandle; opts.use = use; celix_bundleContext_useServicesWithOptions(ctx, &opts); @@ -721,10 +718,10 @@ bool celix_bundleContext_useServiceWithOptions( memset(&trkOpts, 0, sizeof(trkOpts)); if (opts != NULL) { - trkOpts.serviceName = opts->serviceName; + trkOpts.filter.serviceName = opts->filter.serviceName; trkOpts.filter = opts->filter; - trkOpts.versionRange = opts->versionRange; - trkOpts.lang = opts->lang; + trkOpts.filter.versionRange = opts->filter.versionRange; + trkOpts.filter.lang = opts->filter.lang; service_tracker_t *trk = celix_serviceTracker_createWithOptions(ctx, &trkOpts); if (trk != NULL) { @@ -737,7 +734,7 @@ bool celix_bundleContext_useServiceWithOptions( if (opts->useWithOwner != NULL) { } - called = celix_serviceTracker_useHighestRankingService(trk, opts->serviceName, opts->callbackHandle, opts->use, opts->useWithProperties, opts->useWithOwner); + called = celix_serviceTracker_useHighestRankingService(trk, opts->filter.serviceName, opts->callbackHandle, opts->use, opts->useWithProperties, opts->useWithOwner); celix_serviceTracker_destroy(trk); } } @@ -749,18 +746,17 @@ bool celix_bundleContext_useServiceWithOptions( void celix_bundleContext_useServicesWithOptions( celix_bundle_context_t *ctx, const celix_service_use_options_t *opts) { - celix_service_tracking_options_t trkOpts; - memset(&trkOpts, 0, sizeof(trkOpts)); + celix_service_tracking_options_t trkOpts = CELIX_EMPTY_SERVICE_TRACKING_OPTIONS; if (opts != NULL) { - trkOpts.serviceName = opts->serviceName; - trkOpts.filter = opts->filter; - trkOpts.versionRange = opts->versionRange; - trkOpts.lang = opts->lang; + trkOpts.filter.serviceName = opts->filter.serviceName; + trkOpts.filter.filter = opts->filter.filter; + trkOpts.filter.versionRange = opts->filter.versionRange; + trkOpts.filter.lang = opts->filter.lang; service_tracker_t *trk = celix_serviceTracker_createWithOptions(ctx, &trkOpts); if (trk != NULL) { - celix_serviceTracker_useServices(trk, opts->serviceName, opts->callbackHandle, opts->use, opts->useWithProperties, opts->useWithOwner); + celix_serviceTracker_useServices(trk, opts->filter.serviceName, opts->callbackHandle, opts->use, opts->useWithProperties, opts->useWithOwner); celix_serviceTracker_destroy(trk); } } @@ -772,9 +768,8 @@ long celix_bundleContext_trackService( const char* serviceName, void* callbackHandle, void (*set)(void* handle, void* svc)) { - celix_service_tracking_options_t opts; - memset(&opts, 0, sizeof(opts)); - opts.serviceName = serviceName; + celix_service_tracking_options_t opts = CELIX_EMPTY_SERVICE_TRACKING_OPTIONS; + opts.filter.serviceName = serviceName; opts.callbackHandle = callbackHandle; opts.set = set; return celix_bundleContext_trackServicesWithOptions(ctx, &opts); @@ -787,9 +782,8 @@ long celix_bundleContext_trackServices( void* callbackHandle, void (*add)(void* handle, void* svc), void (*remove)(void* handle, void* svc)) { - celix_service_tracking_options_t opts; - memset(&opts, 0, sizeof(opts)); - opts.serviceName = serviceName; + celix_service_tracking_options_t opts = CELIX_EMPTY_SERVICE_TRACKING_OPTIONS; + opts.filter.serviceName = serviceName; opts.callbackHandle = callbackHandle; opts.add = add; opts.remove = remove; @@ -831,4 +825,50 @@ long celix_bundleContext_registerServiceFactorForLang(celix_bundle_context_t *ct celixThreadMutex_unlock(&ctx->mutex); } return facId; +} + +long celix_bundleContext_findService(celix_bundle_context_t *ctx, const char *serviceName) { + celix_service_filter_options_t opts = CELIX_EMPTY_SERVICE_FILTER_OPTIONS; + opts.serviceName = serviceName; + return celix_bundleContext_findServiceWithOptions(ctx, &opts); +} + +static void bundleContext_retrieveSvcId(void *handle, void *svc __attribute__((unused)), const celix_properties_t *props) { + long *svcId = handle; + *svcId = celix_properties_getAsLong(props, OSGI_FRAMEWORK_SERVICE_ID, -1L); +} + +long celix_bundleContext_findServiceWithOptions(celix_bundle_context_t *ctx, const celix_service_filter_options_t *opts) { + long svcId = -1L; + celix_service_use_options_t useOpts = CELIX_EMPTY_SERVICE_USE_OPTIONS; + memcpy(&useOpts.filter, opts, sizeof(useOpts.filter)); + useOpts.callbackHandle = &svcId; + useOpts.useWithProperties = bundleContext_retrieveSvcId; + celix_bundleContext_useServiceWithOptions(ctx, &useOpts); + return svcId; +} + + +celix_array_list_t* celix_bundleContext_findServices(celix_bundle_context_t *ctx, const char *serviceName) { + celix_service_filter_options_t opts = CELIX_EMPTY_SERVICE_FILTER_OPTIONS; + opts.serviceName = serviceName; + return celix_bundleContext_findServicesWithOptions(ctx, &opts); +} + +static void bundleContext_retrieveSvcIds(void *handle, void *svc __attribute__((unused)), const celix_properties_t *props) { + celix_array_list_t *list = handle; + if (list != NULL) { + long svcId = celix_properties_getAsLong(props, OSGI_FRAMEWORK_SERVICE_ID, -1L); + celix_arrayList_addLong(list, svcId); + } +} + +celix_array_list_t* celix_bundleContext_findServicesWithOptions(celix_bundle_context_t *ctx, const celix_service_filter_options_t *opts) { + celix_array_list_t* list = celix_arrayList_create(); + celix_service_use_options_t useOpts = CELIX_EMPTY_SERVICE_USE_OPTIONS; + memcpy(&useOpts.filter, opts, sizeof(useOpts.filter)); + useOpts.callbackHandle = list; + useOpts.useWithProperties = bundleContext_retrieveSvcIds; + celix_bundleContext_useServicesWithOptions(ctx, &useOpts); + return list; } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/celix/blob/48aada3a/framework/src/service_tracker.c ---------------------------------------------------------------------- diff --git a/framework/src/service_tracker.c b/framework/src/service_tracker.c index c92efa3..56ad199 100644 --- a/framework/src/service_tracker.c +++ b/framework/src/service_tracker.c @@ -560,11 +560,10 @@ celix_service_tracker_t* celix_serviceTracker_create( const char *serviceName, const char *versionRange, const char *filter) { - celix_service_tracking_options_t opts; - memset(&opts, 0, sizeof(opts)); - opts.serviceName = serviceName; - opts.filter = filter; - opts.versionRange = versionRange; + celix_service_tracking_options_t opts = CELIX_EMPTY_SERVICE_TRACKING_OPTIONS; + opts.filter.serviceName = serviceName; + opts.filter.filter = filter; + opts.filter.versionRange = versionRange; return celix_serviceTracker_createWithOptions(ctx, &opts); } @@ -573,7 +572,7 @@ celix_service_tracker_t* celix_serviceTracker_createWithOptions( const celix_service_tracking_options_t *opts ) { celix_service_tracker_t *tracker = NULL; - if (ctx != NULL && opts != NULL && opts->serviceName != NULL) { + if (ctx != NULL && opts != NULL && opts->filter.serviceName != NULL) { tracker = calloc(1, sizeof(*tracker)); if (tracker != NULL) { tracker->context = ctx; @@ -586,44 +585,41 @@ celix_service_tracker_t* celix_serviceTracker_createWithOptions( tracker->set = opts->set; tracker->add = opts->add; tracker->remove = opts->remove; - tracker->modified = opts->modified; tracker->setWithProperties = opts->setWithProperties; tracker->addWithProperties = opts->addWithProperties; tracker->removeWithProperties = opts->removeWithProperties; - tracker->modifiedWithProperties = opts->modifiedWithProperties; tracker->setWithOwner = opts->setWithOwner; tracker->addWithOwner = opts->addWithOwner; tracker->removeWithOwner = opts->removeWithOwner; - tracker->modifiedWithOwner = opts->modifiedWithOwner; //highest service state celixThreadMutex_create(&tracker->mutex, NULL); tracker->currentHighestServiceId = -1; //setting lang - const char *lang = opts->lang; + const char *lang = opts->filter.lang; if (lang == NULL || strncmp("", lang, 1) == 0) { lang = CELIX_FRAMEWORK_SERVICE_C_LANGUAGE; } //setting filter - if (opts->filter != NULL && opts->versionRange != NULL) { + if (opts->filter.filter != NULL && opts->filter.versionRange != NULL) { //TODO version range - asprintf(&tracker->filter, "&((%s=%s)(%s=%s)%s)", OSGI_FRAMEWORK_OBJECTCLASS, opts->serviceName, CELIX_FRAMEWORK_SERVICE_LANGUAGE, lang, opts->filter); - } else if (opts->versionRange != NULL) { + asprintf(&tracker->filter, "&((%s=%s)(%s=%s)%s)", OSGI_FRAMEWORK_OBJECTCLASS, opts->filter.serviceName, CELIX_FRAMEWORK_SERVICE_LANGUAGE, lang, opts->filter.filter); + } else if (opts->filter.versionRange != NULL) { //TODO version range - asprintf(&tracker->filter, "&((%s=%s)(%s=%s))", OSGI_FRAMEWORK_OBJECTCLASS, opts->serviceName, CELIX_FRAMEWORK_SERVICE_LANGUAGE, lang); - } else if (opts->filter != NULL) { - asprintf(&tracker->filter, "(&(%s=%s)(%s=%s)%s)", OSGI_FRAMEWORK_OBJECTCLASS, opts->serviceName, CELIX_FRAMEWORK_SERVICE_LANGUAGE, lang, opts->filter); + asprintf(&tracker->filter, "&((%s=%s)(%s=%s))", OSGI_FRAMEWORK_OBJECTCLASS, opts->filter.serviceName, CELIX_FRAMEWORK_SERVICE_LANGUAGE, lang); + } else if (opts->filter.filter != NULL) { + asprintf(&tracker->filter, "(&(%s=%s)(%s=%s)%s)", OSGI_FRAMEWORK_OBJECTCLASS, opts->filter.serviceName, CELIX_FRAMEWORK_SERVICE_LANGUAGE, lang, opts->filter.filter); } else { - asprintf(&tracker->filter, "(&(%s=%s)(%s=%s))", OSGI_FRAMEWORK_OBJECTCLASS, opts->serviceName, CELIX_FRAMEWORK_SERVICE_LANGUAGE, lang); + asprintf(&tracker->filter, "(&(%s=%s)(%s=%s))", OSGI_FRAMEWORK_OBJECTCLASS, opts->filter.serviceName, CELIX_FRAMEWORK_SERVICE_LANGUAGE, lang); } //TODO open on other thread? serviceTracker_open(tracker); } } else { - if (opts != NULL && opts->serviceName == NULL) { + if (opts != NULL && opts->filter.serviceName == NULL) { framework_log(logger, OSGI_FRAMEWORK_LOG_ERROR, __FUNCTION__, __BASE_FILE__, __LINE__, "Error incorrect arguments. Missing service name."); } else { http://git-wip-us.apache.org/repos/asf/celix/blob/48aada3a/framework/tst/bundle_context_services_test.cpp ---------------------------------------------------------------------- diff --git a/framework/tst/bundle_context_services_test.cpp b/framework/tst/bundle_context_services_test.cpp index 2597ece..6fa1204 100644 --- a/framework/tst/bundle_context_services_test.cpp +++ b/framework/tst/bundle_context_services_test.cpp @@ -297,7 +297,7 @@ TEST(CelixBundleContextServicesTests, servicesTrackerInvalidArgsTest) { memset(&opts, 0, sizeof(opts)); trackerId = celix_bundleContext_trackServicesWithOptions(ctx, &opts); CHECK(trackerId < 0); //required opts->serviceName missing - opts.serviceName = "calc"; + opts.filter.serviceName = "calc"; trackerId = celix_bundleContext_trackServicesWithOptions(ctx, &opts); CHECK(trackerId >= 0); //valid celix_bundleContext_stopTracker(ctx, trackerId); @@ -361,7 +361,7 @@ TEST(CelixBundleContextServicesTests, servicesTrackerTestWithProperties) { celix_service_tracking_options_t opts; memset(&opts, 0, sizeof(opts)); - opts.serviceName = "calc"; + opts.filter.serviceName = "calc"; opts.callbackHandle = &count; opts.addWithProperties = add; opts.removeWithProperties = remove; @@ -401,7 +401,7 @@ TEST(CelixBundleContextServicesTests, servicesTrackerTestWithOwner) { celix_service_tracking_options_t opts; memset(&opts, 0, sizeof(opts)); - opts.serviceName = "calc"; + opts.filter.serviceName = "calc"; opts.callbackHandle = &count; opts.addWithOwner = add; opts.removeWithOwner = remove; @@ -557,7 +557,7 @@ TEST(CelixBundleContextServicesTests, servicesTrackerSetTest) { celix_service_tracking_options_t opts; memset(&opts, 0, sizeof(opts)); opts.callbackHandle = (void*)&count; - opts.serviceName = "NA"; + opts.filter.serviceName = "NA"; opts.set = set; long trackerId = celix_bundleContext_trackServicesWithOptions(ctx, &opts); CHECK(trackerId > 0); @@ -628,3 +628,30 @@ TEST(CelixBundleContextServicesTests, serviceFactoryTest) { celix_bundleContext_unregisterService(ctx, facId); } +TEST(CelixBundleContextServicesTests, findServicesTest) { + long svcId1 = celix_bundleContext_registerService(ctx, "example", (void*)0x100, NULL, NULL); + long svcId2 = celix_bundleContext_registerService(ctx, "example", (void*)0x100, NULL, NULL); + + long foundId = celix_bundleContext_findService(ctx, "non existing service name"); + CHECK_EQUAL(-1L, foundId); + + foundId = celix_bundleContext_findService(ctx, "example"); + CHECK_EQUAL(foundId, svcId1); //oldest should have highest ranking + + array_list_t *list = celix_bundleContext_findServices(ctx, "non existintg service name"); + CHECK_EQUAL(0, celix_arrayList_size(list)); + arrayList_destroy(list); + + list = celix_bundleContext_findServices(ctx, "example"); + CHECK_EQUAL(2, celix_arrayList_size(list)); + arrayList_destroy(list); + + celix_bundleContext_unregisterService(ctx, svcId1); + + celix_service_filter_options_t opts = CELIX_EMPTY_SERVICE_FILTER_OPTIONS; + opts.serviceName = "example"; + foundId = celix_bundleContext_findServiceWithOptions(ctx, &opts); + CHECK_EQUAL(foundId, svcId2); //only one left + + celix_bundleContext_unregisterService(ctx, svcId2); +} http://git-wip-us.apache.org/repos/asf/celix/blob/48aada3a/utils/include/array_list.h ---------------------------------------------------------------------- diff --git a/utils/include/array_list.h b/utils/include/array_list.h index 46a0697..fa8602b 100644 --- a/utils/include/array_list.h +++ b/utils/include/array_list.h @@ -30,11 +30,24 @@ #include "celixbool.h" #include "exports.h" #include "celix_errno.h" +#include "stdbool.h" #ifdef __cplusplus extern "C" { #endif +typedef union celix_array_list_entry { + void *voidPtrVal; + int intVal; + long int longVal; + unsigned int uintVal; + unsigned long ulongVal; + double doubleVal; + float floatVal; + bool boolVal; + size_t sizeVal; +} celix_array_list_entry_t; + typedef struct celix_arrayList celix_array_list_t; typedef struct celix_arrayList *array_list_pt; @@ -45,7 +58,7 @@ typedef struct arrayListIterator array_list_iterator_t; typedef celix_status_t (*array_list_element_equals_pt)(const void *, const void *, bool *equals); -typedef bool (*celix_arrayList_equals_fp)(const void *, const void *); +typedef bool (*celix_arrayList_equals_fp)(celix_array_list_entry_t, celix_array_list_entry_t); UTILS_EXPORT celix_status_t arrayList_create(array_list_pt *list); @@ -107,6 +120,7 @@ UTILS_EXPORT void arrayListIterator_remove(array_list_iterator_pt iterator); ********************************************************************************************************************** **********************************************************************************************************************/ + celix_array_list_t* celix_arrayList_create(); celix_array_list_t* celix_arrayList_createWithEquals(celix_arrayList_equals_fp equals); @@ -117,8 +131,31 @@ size_t celix_arrayList_size(const celix_array_list_t *list); void* celix_arrayList_get(const celix_array_list_t *list, int index); -//TODO rest - +//more of the same for the different entry types +int celix_arrayList_getInt(const celix_array_list_t *list, int index); +long int celix_arrayList_getLong(const celix_array_list_t *list, int index); +unsigned int celix_arrayList_getUInt(const celix_array_list_t *list, int index); +unsigned long int celix_arrayList_getULong(const celix_array_list_t *list, int index); +float celix_arrayList_getFloat(const celix_array_list_t *list, int index); +double celix_arrayList_getDouble(const celix_array_list_t *list, int index); +bool celix_arrayList_getBool(const celix_array_list_t *list, int index); +size_t celix_arrayList_getSize(const celix_array_list_t *list, int index); + +void celix_arrayList_add(celix_array_list_t *list, void* val); + +//more of the same for the different entry types +void celix_arrayList_addInt(celix_array_list_t *list, int val); +void celix_arrayList_addLong(celix_array_list_t *list, long val); +void celix_arrayList_addUInt(celix_array_list_t *list, unsigned int val); +void celix_arrayList_addULong(celix_array_list_t *list, unsigned long val); +void celix_arrayList_addFloat(celix_array_list_t *list, float val); +void celix_arrayList_addDouble(celix_array_list_t *list, double val); +void celix_arrayList_addBool(celix_array_list_t *list, bool val); +void celix_arrayList_addSize(celix_array_list_t *list, size_t val); + +int celix_arrayList_indexOf(celix_array_list_t *list, celix_array_list_entry_t entry); +void celix_arrayList_remove(celix_array_list_t *list, int index); +void celix_arrayList_removeEntry(celix_array_list_t *list, celix_array_list_entry_t entry); #ifdef __cplusplus } http://git-wip-us.apache.org/repos/asf/celix/blob/48aada3a/utils/src/array_list.c ---------------------------------------------------------------------- diff --git a/utils/src/array_list.c b/utils/src/array_list.c index 751712e..ca12798 100644 --- a/utils/src/array_list.c +++ b/utils/src/array_list.c @@ -31,8 +31,8 @@ #include "array_list_private.h" static celix_status_t arrayList_elementEquals(const void *a, const void *b, bool *equals); -static bool celix_arrayList_defaultEquals(const void *a, const void *b); -static bool celix_arrayList_equalsForElement(celix_array_list_t *list, void *a, void *b); +static bool celix_arrayList_defaultEquals(const celix_array_list_entry_t a, const celix_array_list_entry_t b); +static bool celix_arrayList_equalsForElement(celix_array_list_t *list, celix_array_list_entry_t a, celix_array_list_entry_t b); celix_status_t arrayList_create(array_list_pt *list) { @@ -57,15 +57,15 @@ static celix_status_t arrayList_elementEquals(const void *a, const void *b, bool return CELIX_SUCCESS; } -static bool celix_arrayList_defaultEquals(const void *a, const void *b) { - return a == b; +static bool celix_arrayList_defaultEquals(celix_array_list_entry_t a, celix_array_list_entry_t b) { + return a.longVal == b.longVal; //just compare as long int } -static bool celix_arrayList_equalsForElement(celix_array_list_t *list, void *a, void *b) { +static bool celix_arrayList_equalsForElement(celix_array_list_t *list, celix_array_list_entry_t a, celix_array_list_entry_t b) { bool equals = false; if (list != NULL) { if (list->equalsDeprecated != NULL) { - list->equalsDeprecated(a, b, &equals); + list->equalsDeprecated(a.voidPtrVal, b.voidPtrVal, &equals); } else if (list->equals != NULL) { equals = list->equals(a, b); } @@ -74,34 +74,32 @@ static bool celix_arrayList_equalsForElement(celix_array_list_t *list, void *a, } void arrayList_trimToSize(array_list_pt list) { - unsigned int oldCapacity; list->modCount++; - oldCapacity = list->capacity; + size_t oldCapacity = list->capacity; if (list->size < oldCapacity) { - void ** newList = (void **) realloc(list->elementData, sizeof(void *) * list->size); + celix_array_list_entry_t * newList = realloc(list->elementData, sizeof(void *) * list->size); list->capacity = list->size; list->elementData = newList; } } void arrayList_ensureCapacity(array_list_pt list, int capacity) { - void ** newList; - unsigned int oldCapacity; + celix_array_list_entry_t *newList; list->modCount++; - oldCapacity = list->capacity; + size_t oldCapacity = list->capacity; if (capacity > oldCapacity) { - unsigned int newCapacity = (oldCapacity * 3) / 2 + 1; + size_t newCapacity = (oldCapacity * 3) / 2 + 1; if (newCapacity < capacity) { newCapacity = capacity; } - newList = (void **) realloc(list->elementData, sizeof(void *) * newCapacity); + newList = realloc(list->elementData, sizeof(void *) * newCapacity); list->capacity = newCapacity; list->elementData = newList; } } unsigned int arrayList_size(array_list_pt list) { - return list->size; + return (int)list->size; } bool arrayList_isEmpty(array_list_pt list) { @@ -117,14 +115,15 @@ int arrayList_indexOf(array_list_pt list, void * element) { if (element == NULL) { unsigned int i = 0; for (i = 0; i < list->size; i++) { - if (list->elementData[i] == NULL) { + if (list->elementData[i].voidPtrVal == NULL) { return i; } } } else { unsigned int i = 0; for (i = 0; i < list->size; i++) { - bool equals = celix_arrayList_equalsForElement(list, element, list->elementData[i]); + celix_array_list_entry_t entry = { .voidPtrVal = element }; + bool equals = celix_arrayList_equalsForElement(list, entry, list->elementData[i]); if (equals) { return i; } @@ -136,17 +135,21 @@ int arrayList_indexOf(array_list_pt list, void * element) { int arrayList_lastIndexOf(array_list_pt list, void * element) { if (element == NULL) { int i = 0; - for (i = list->size - 1; i >= 0; i--) { - if (list->elementData[i] == NULL) { - return i; + int size = (int)list->size; + for (i = size - 1; i >= 0; i--) { + if (list->elementData[i].voidPtrVal == NULL) { + return (int)i; } } } else { int i = 0; - for (i = list->size - 1; i >= 0; i--) { - bool equals = celix_arrayList_equalsForElement(list, element, list->elementData[i]); + int size = (int)list->size; + for (i = size - 1; i >= 0; i--) { + celix_array_list_entry_t entry = { .voidPtrVal = element }; + + bool equals = celix_arrayList_equalsForElement(list, entry, list->elementData[i]); if (equals) { - return i; + return (int)i; } } } @@ -158,7 +161,7 @@ void * arrayList_get(array_list_pt list, unsigned int index) { return NULL; } - return list->elementData[index]; + return list->elementData[index].voidPtrVal; } void * arrayList_set(array_list_pt list, unsigned int index, void * element) { @@ -167,61 +170,63 @@ void * arrayList_set(array_list_pt list, unsigned int index, void * element) { return NULL; } - oldElement = list->elementData[index]; - list->elementData[index] = element; + oldElement = list->elementData[index].voidPtrVal; + memset(&list->elementData[index], 0, sizeof(celix_array_list_entry_t)); + list->elementData[index].voidPtrVal = element; return oldElement; } bool arrayList_add(array_list_pt list, void * element) { - arrayList_ensureCapacity(list, list->size + 1); - list->elementData[list->size++] = element; + arrayList_ensureCapacity(list, (int)list->size + 1); + memset(&list->elementData[list->size], 0, sizeof(celix_array_list_entry_t)); + list->elementData[list->size++].voidPtrVal = element; return true; } int arrayList_addIndex(array_list_pt list, unsigned int index, void * element) { - unsigned int numMoved; + size_t numMoved; if (index > list->size) { return -1; } - arrayList_ensureCapacity(list, list->size+1); + arrayList_ensureCapacity(list, (int)list->size+1); numMoved = list->size - index; memmove(list->elementData+(index+1), list->elementData+index, sizeof(void *) * numMoved); - list->elementData[index] = element; + list->elementData[index].voidPtrVal = element; list->size++; return 0; } void * arrayList_remove(array_list_pt list, unsigned int index) { void * oldElement; - unsigned int numMoved; + size_t numMoved; if (index >= list->size) { return NULL; } list->modCount++; - oldElement = list->elementData[index]; + oldElement = list->elementData[index].voidPtrVal; numMoved = list->size - index - 1; memmove(list->elementData+index, list->elementData+index+1, sizeof(void *) * numMoved); - list->elementData[--list->size] = NULL; + memset(&list->elementData[--list->size], 0, sizeof(celix_array_list_entry_t)); return oldElement; } void arrayList_fastRemove(array_list_pt list, unsigned int index) { - unsigned int numMoved; + size_t numMoved; list->modCount++; numMoved = list->size - index - 1; memmove(list->elementData+index, list->elementData+index+1, sizeof(void *) * numMoved); - list->elementData[--list->size] = NULL; + memset(&list->elementData[--list->size], 0, sizeof(celix_array_list_entry_t)); } bool arrayList_removeElement(array_list_pt list, void * element) { if (element == NULL) { unsigned int i = 0; for (i = 0; i < list->size; i++) { - if (list->elementData[i] == NULL) { + if (list->elementData[i].voidPtrVal == NULL) { arrayList_fastRemove(list, i); return true; } @@ -229,7 +234,9 @@ bool arrayList_removeElement(array_list_pt list, void * element) { } else { unsigned int i = 0; for (i = 0; i < list->size; i++) { - bool equals = celix_arrayList_equalsForElement(list, element, list->elementData[i]); + celix_array_list_entry_t entry; + entry.voidPtrVal = element; + bool equals = celix_arrayList_equalsForElement(list, entry, list->elementData[i]); if (equals) { arrayList_fastRemove(list, i); return true; @@ -245,7 +252,7 @@ void arrayList_clear(array_list_pt list) { for (i = 0; i < list->size; i++) { // free(list->elementData[i]); - list->elementData[i] = NULL; + memset(&list->elementData[i], 0, sizeof(celix_array_list_entry_t)); } list->size = 0; } @@ -375,15 +382,74 @@ size_t celix_arrayList_size(const celix_array_list_t *list) { return list->size; } -void* celix_arrayList_get(const celix_array_list_t *list, int index) { - void *el = NULL; +static celix_array_list_entry_t arrayList_getEntry(const celix_array_list_t *list, int index) { + celix_array_list_entry_t entry; + memset(&entry, 0, sizeof(entry)); if (index < list->size) { - el = list->elementData[index]; + entry = list->elementData[index]; } - return el; + return entry; +} + +void* celix_arrayList_get(const celix_array_list_t *list, int index) { + return arrayList_getEntry(list, index).voidPtrVal; +} + +int celix_arrayList_getInt(const celix_array_list_t *list, int index) { return arrayList_getEntry(list, index).intVal; } +long int celix_arrayList_getLong(const celix_array_list_t *list, int index) { return arrayList_getEntry(list, index).longVal; } +unsigned int celix_arrayList_getUInt(const celix_array_list_t *list, int index) { return arrayList_getEntry(list, index).uintVal; } +unsigned long int celix_arrayList_getULong(const celix_array_list_t *list, int index) { return arrayList_getEntry(list, index).ulongVal; } +float celix_arrayList_getFloat(const celix_array_list_t *list, int index) { return arrayList_getEntry(list, index).floatVal; } +double celix_arrayList_getDouble(const celix_array_list_t *list, int index) { return arrayList_getEntry(list, index).doubleVal; } +bool celix_arrayList_getBool(const celix_array_list_t *list, int index) { return arrayList_getEntry(list, index).boolVal; } +size_t celix_arrayList_getSize(const celix_array_list_t *list, int index) { return arrayList_getEntry(list, index).sizeVal; } + +static void arrayList_addEntry(celix_array_list_t *list, celix_array_list_entry_t entry) { + arrayList_ensureCapacity(list, (int)list->size + 1); + memset(&list->elementData[list->size], 0, sizeof(entry)); + list->elementData[list->size++] = entry; +} + +void celix_arrayList_add(celix_array_list_t *list, void * element) { + celix_array_list_entry_t entry = { .voidPtrVal = element }; + arrayList_addEntry(list, entry); } +void celix_arrayList_addInt(celix_array_list_t *list, int val) { celix_array_list_entry_t entry = { .intVal = val }; arrayList_addEntry(list, entry);} +void celix_arrayList_addLong(celix_array_list_t *list, long val) { celix_array_list_entry_t entry = { .longVal = val }; arrayList_addEntry(list, entry);} +void celix_arrayList_addUInt(celix_array_list_t *list, unsigned int val) { celix_array_list_entry_t entry = { .uintVal = val }; arrayList_addEntry(list, entry);} +void celix_arrayList_addULong(celix_array_list_t *list, unsigned long val) { celix_array_list_entry_t entry = { .ulongVal = val }; arrayList_addEntry(list, entry);} +void celix_arrayList_addFloat(celix_array_list_t *list, float val) { celix_array_list_entry_t entry = { .floatVal = val }; arrayList_addEntry(list, entry);} +void celix_arrayList_addDouble(celix_array_list_t *list, double val) { celix_array_list_entry_t entry = { .doubleVal = val }; arrayList_addEntry(list, entry);} +void celix_arrayList_addBool(celix_array_list_t *list, bool val) { celix_array_list_entry_t entry = { .boolVal = val }; arrayList_addEntry(list, entry);} +void celix_arrayList_addSize(celix_array_list_t *list, size_t val) { celix_array_list_entry_t entry = { .sizeVal = val }; arrayList_addEntry(list, entry);} + +int celix_arrayList_indexOf(celix_array_list_t *list, celix_array_list_entry_t entry) { + size_t size = celix_arrayList_size(list); + int i; + int index = -1; + for (i = 0 ; i < size ; ++i) { + bool eq = celix_arrayList_equalsForElement(list, entry, list->elementData[i]); + if (eq) { + index = i; + break; + } + } + return index; +} +void celix_arrayList_remove(celix_array_list_t *list, int index) { + if (index >= 0 && index < list->size) { + list->modCount++; + size_t numMoved = list->size - index - 1; + memmove(list->elementData+index, list->elementData+index+1, sizeof(void *) * numMoved); + memset(&list->elementData[--list->size], 0, sizeof(celix_array_list_entry_t)); + } +} +void celix_arrayList_removeEntry(celix_array_list_t *list, celix_array_list_entry_t entry) { + int index = celix_arrayList_indexOf(list, entry); + celix_arrayList_remove(list, index); +} http://git-wip-us.apache.org/repos/asf/celix/blob/48aada3a/utils/src/array_list_private.h ---------------------------------------------------------------------- diff --git a/utils/src/array_list_private.h b/utils/src/array_list_private.h index e5394cd..5f83605 100644 --- a/utils/src/array_list_private.h +++ b/utils/src/array_list_private.h @@ -30,7 +30,7 @@ #include "array_list.h" struct celix_arrayList { - void ** elementData; + celix_array_list_entry_t* elementData; size_t size; size_t capacity;
