Return-Path: X-Original-To: apmail-celix-commits-archive@www.apache.org Delivered-To: apmail-celix-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 7622C18505 for ; Wed, 11 Nov 2015 12:58:08 +0000 (UTC) Received: (qmail 97744 invoked by uid 500); 11 Nov 2015 12:58:08 -0000 Delivered-To: apmail-celix-commits-archive@celix.apache.org Received: (qmail 97678 invoked by uid 500); 11 Nov 2015 12:58:08 -0000 Mailing-List: contact commits-help@celix.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@celix.apache.org Delivered-To: mailing list commits@celix.apache.org Received: (qmail 97604 invoked by uid 99); 11 Nov 2015 12:58:08 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 11 Nov 2015 12:58:08 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id E2B5FE0A98; Wed, 11 Nov 2015 12:58:07 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: pnoltes@apache.org To: commits@celix.apache.org Date: Wed, 11 Nov 2015 12:58:11 -0000 Message-Id: <8dcea9124a754734aabca97c679b6b5d@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [5/7] celix git commit: CELIX-272: Refactoring of ServiceRegistry. Added warning log of incorrect handling service refs/regs CELIX-272: Refactoring of ServiceRegistry. Added warning log of incorrect handling service refs/regs Project: http://git-wip-us.apache.org/repos/asf/celix/repo Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/592d65f9 Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/592d65f9 Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/592d65f9 Branch: refs/heads/feature/CELIX-272_synchronization_service_registry Commit: 592d65f900e6193b8b74d5dac0c2875bfa7e355f Parents: 5fbd1f5 Author: Pepijn Noltes Authored: Wed Nov 11 13:24:55 2015 +0100 Committer: Pepijn Noltes Committed: Wed Nov 11 13:24:55 2015 +0100 ---------------------------------------------------------------------- .../private/src/dm_component_impl.c | 15 +- .../private/src/provider_activator.c | 1 + .../private/include/service_reference_private.h | 19 +- .../private/include/service_registry_private.h | 4 +- .../service_tracker_customizer_private.h | 4 + framework/private/src/bundle_context.c | 2 +- framework/private/src/framework.c | 32 +- framework/private/src/properties.c | 2 + framework/private/src/service_reference.c | 180 +++++-- framework/private/src/service_registration.c | 17 - framework/private/src/service_registry.c | 476 +++++++------------ framework/private/src/service_tracker.c | 155 +++--- framework/public/include/service_reference.h | 2 - framework/public/include/service_registration.h | 1 - framework/public/include/service_registry.h | 19 +- 15 files changed, 449 insertions(+), 480 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/celix/blob/592d65f9/dependency_manager/private/src/dm_component_impl.c ---------------------------------------------------------------------- diff --git a/dependency_manager/private/src/dm_component_impl.c b/dependency_manager/private/src/dm_component_impl.c index aa34389..fe782bb 100644 --- a/dependency_manager/private/src/dm_component_impl.c +++ b/dependency_manager/private/src/dm_component_impl.c @@ -1093,14 +1093,13 @@ celix_status_t component_registerServices(dm_component_pt component) { celix_status_t status = CELIX_SUCCESS; if (component->context) { - unsigned int i; - - for (i = 0; i < arrayList_size(component->dm_interfaces); i++) { - dm_interface_t *interface = arrayList_get(component->dm_interfaces, i); - properties_pt regProps = NULL; - properties_copy(interface->properties, ®Props); - bundleContext_registerService(component->context, interface->serviceName, interface->service, regProps, &interface->registration); - } + unsigned int i; + for (i = 0; i < arrayList_size(component->dm_interfaces); i++) { + dm_interface_t *interface = arrayList_get(component->dm_interfaces, i); + properties_pt regProps = NULL; + properties_copy(interface->properties, ®Props); + bundleContext_registerService(component->context, interface->serviceName, interface->service, regProps, &interface->registration); + } } return status; http://git-wip-us.apache.org/repos/asf/celix/blob/592d65f9/examples/locking/math_provider/private/src/provider_activator.c ---------------------------------------------------------------------- diff --git a/examples/locking/math_provider/private/src/provider_activator.c b/examples/locking/math_provider/private/src/provider_activator.c index 319980f..0407005 100644 --- a/examples/locking/math_provider/private/src/provider_activator.c +++ b/examples/locking/math_provider/private/src/provider_activator.c @@ -73,6 +73,7 @@ celix_status_t bundleActivator_create(bundle_context_pt context, void **userData activator->context = context; activator->benchmarkName = NULL; activator->freqService = NULL; + activator->registration = NULL; activator->freqRegistration = NULL; activator->updateFrequency = 0; activator->nrOfThreads = 0; http://git-wip-us.apache.org/repos/asf/celix/blob/592d65f9/framework/private/include/service_reference_private.h ---------------------------------------------------------------------- diff --git a/framework/private/include/service_reference_private.h b/framework/private/include/service_reference_private.h index 114eae1..2ac4ee5 100644 --- a/framework/private/include/service_reference_private.h +++ b/framework/private/include/service_reference_private.h @@ -31,19 +31,28 @@ #include "service_reference.h" struct serviceReference { - bundle_pt bundle; + bundle_pt referenceOwner; struct serviceRegistration * registration; + bundle_pt registrationBundle; size_t refCount; - celix_thread_mutex_t mutex; //protects refCount + size_t usageCount; + + celix_thread_rwlock_t lock; }; -celix_status_t serviceReference_create(bundle_pt bundle, service_registration_pt registration, service_reference_pt *reference); +celix_status_t serviceReference_create(bundle_pt referenceOwner, service_registration_pt registration, service_reference_pt *reference); + +celix_status_t serviceReference_retain(service_reference_pt ref); +celix_status_t serviceReference_release(service_reference_pt ref, bool *destroyed); -void serviceReference_retain(service_reference_pt ref); -void serviceReference_release(service_reference_pt ref); +celix_status_t serviceReference_increaseUsage(service_reference_pt ref); +celix_status_t serviceReference_decreaseUsage(service_reference_pt ref); celix_status_t serviceReference_invalidate(service_reference_pt reference); celix_status_t serviceReference_isValid(service_reference_pt reference, bool *result); +celix_status_t serviceReference_getUsageCount(service_reference_pt reference, size_t *count); +celix_status_t serviceReference_getReferenceCount(service_reference_pt reference, size_t *count); + #endif /* SERVICE_REFERENCE_PRIVATE_H_ */ http://git-wip-us.apache.org/repos/asf/celix/blob/592d65f9/framework/private/include/service_registry_private.h ---------------------------------------------------------------------- diff --git a/framework/private/include/service_registry_private.h b/framework/private/include/service_registry_private.h index d89f28e..c5a731c 100644 --- a/framework/private/include/service_registry_private.h +++ b/framework/private/include/service_registry_private.h @@ -33,8 +33,7 @@ struct serviceRegistry { framework_pt framework; hash_map_pt serviceRegistrations; - hash_map_pt serviceReferences; - hash_map_pt inUseMap; + hash_map_pt serviceReferences; //key = bundle, value = map (key = registration, value = reference) serviceChanged_function_pt serviceChanged; long currentServiceId; @@ -44,6 +43,7 @@ struct serviceRegistry { celix_thread_mutexattr_t mutexAttr; celix_thread_mutex_t referencesMapMutex; + }; struct usageCount { http://git-wip-us.apache.org/repos/asf/celix/blob/592d65f9/framework/private/include/service_tracker_customizer_private.h ---------------------------------------------------------------------- diff --git a/framework/private/include/service_tracker_customizer_private.h b/framework/private/include/service_tracker_customizer_private.h index bda3cde..61fb52f 100644 --- a/framework/private/include/service_tracker_customizer_private.h +++ b/framework/private/include/service_tracker_customizer_private.h @@ -38,7 +38,11 @@ struct serviceTrackerCustomizer { celix_status_t (*addingService)(void * handle, service_reference_pt reference, void **service); celix_status_t (*addedService)(void * handle, service_reference_pt reference, void * service); celix_status_t (*modifiedService)(void * handle, service_reference_pt reference, void * service); + + /*TODO rename to removingService. because it is invoke during remove not after!*/ celix_status_t (*removedService)(void * handle, service_reference_pt reference, void * service); + + /*TODO add removed function ? invoked after the remove ?? */ }; http://git-wip-us.apache.org/repos/asf/celix/blob/592d65f9/framework/private/src/bundle_context.c ---------------------------------------------------------------------- diff --git a/framework/private/src/bundle_context.c b/framework/private/src/bundle_context.c index 35d27ce..f84d767 100644 --- a/framework/private/src/bundle_context.c +++ b/framework/private/src/bundle_context.c @@ -133,7 +133,7 @@ celix_status_t bundleContext_registerService(bundle_context_pt context, char * s status = CELIX_ILLEGAL_ARGUMENT; } - framework_logIfError(logger, status, NULL, "Failed to register service"); + framework_logIfError(logger, status, NULL, "Failed to register service. serviceName '%s'", serviceName); return status; } http://git-wip-us.apache.org/repos/asf/celix/blob/592d65f9/framework/private/src/framework.c ---------------------------------------------------------------------- diff --git a/framework/private/src/framework.c b/framework/private/src/framework.c index 47aabb3..7e66dbe 100644 --- a/framework/private/src/framework.c +++ b/framework/private/src/framework.c @@ -910,7 +910,7 @@ celix_status_t fw_stopBundle(framework_pt framework, bundle_pt bundle, bool reco } if (id != 0) { - status = CELIX_DO_IF(status, serviceRegistry_unregisterServices(framework->registry, bundle)); + status = CELIX_DO_IF(status, serviceRegistry_clearServiceRegistrations(framework->registry, bundle)); if (status == CELIX_SUCCESS) { module_pt module = NULL; char *symbolicName = NULL; @@ -919,8 +919,7 @@ celix_status_t fw_stopBundle(framework_pt framework, bundle_pt bundle, bool reco module_getSymbolicName(module, &symbolicName); bundle_getBundleId(bundle, &id); - serviceRegistry_ungetServices(framework->registry, bundle); - serviceRegistry_ungetServiceReferences(framework->registry, bundle); + serviceRegistry_clearReferencesFor(framework->registry, bundle); } // #TODO remove listeners for bundle @@ -1294,14 +1293,13 @@ celix_status_t fw_registerService(framework_pt framework, service_registration_p } } - bool ungetResult = false; - - status = CELIX_DO_IF(status, serviceRegistry_createServiceReference(framework->registry, framework->bundle, *registration, &ref)); + status = CELIX_DO_IF(status, serviceRegistry_getServiceReference(framework->registry, framework->bundle, + *registration, &ref)); status = CELIX_DO_IF(status, fw_getService(framework,framework->bundle, ref, (void **) &hook)); if (status == CELIX_SUCCESS) { hook->added(hook->handle, infos); } - status = CELIX_DO_IF(status, serviceRegistry_ungetService(framework->registry, framework->bundle, ref, &ungetResult)); + status = CELIX_DO_IF(status, serviceRegistry_ungetService(framework->registry, framework->bundle, ref, NULL)); status = CELIX_DO_IF(status, serviceRegistry_ungetServiceReference(framework->registry, framework->bundle, ref)); int i = 0; @@ -1633,15 +1631,21 @@ void fw_serviceChanged(framework_pt framework, service_event_type_e eventType, s event = (service_event_pt) malloc(sizeof(*event)); - serviceRegistry_createServiceReference(framework->registry, element->bundle, registration, &reference); + serviceRegistry_getServiceReference(framework->registry, element->bundle, registration, &reference); event->type = eventType; event->reference = reference; element->listener->serviceChanged(element->listener, event); - free(event); - //TODO cleanup service reference + if (eventType != OSGI_FRAMEWORK_SERVICE_EVENT_REGISTERED) { + serviceRegistry_ungetServiceReference(framework->registry, element->bundle, reference); + } + if (eventType == OSGI_FRAMEWORK_SERVICE_EVENT_UNREGISTERING) { + serviceRegistry_ungetServiceReference(framework->registry, element->bundle, reference); + } + + free(event); } else if (eventType == OSGI_FRAMEWORK_SERVICE_EVENT_MODIFIED) { bool matchResult = false; @@ -1654,14 +1658,16 @@ void fw_serviceChanged(framework_pt framework, service_event_type_e eventType, s service_reference_pt reference = NULL; service_event_pt endmatch = (service_event_pt) malloc(sizeof(*endmatch)); - serviceRegistry_createServiceReference(framework->registry, element->bundle, registration, &reference); + serviceRegistry_getServiceReference(framework->registry, element->bundle, registration, &reference); endmatch->reference = reference; endmatch->type = OSGI_FRAMEWORK_SERVICE_EVENT_MODIFIED_ENDMATCH; element->listener->serviceChanged(element->listener, endmatch); - //TODO clean up serviceReference after serviceChanged update - } + serviceRegistry_ungetServiceReference(framework->registry, element->bundle, reference); + free(endmatch); + + } } } } http://git-wip-us.apache.org/repos/asf/celix/blob/592d65f9/framework/private/src/properties.c ---------------------------------------------------------------------- diff --git a/framework/private/src/properties.c b/framework/private/src/properties.c index 271eed1..5f1b67e 100644 --- a/framework/private/src/properties.c +++ b/framework/private/src/properties.c @@ -200,6 +200,8 @@ celix_status_t properties_copy(properties_pt properties, properties_pt *out) { if (status == CELIX_SUCCESS) { *out = copy; } + + return status; } char * properties_get(properties_pt properties, char * key) { http://git-wip-us.apache.org/repos/asf/celix/blob/592d65f9/framework/private/src/service_reference.c ---------------------------------------------------------------------- diff --git a/framework/private/src/service_reference.c b/framework/private/src/service_reference.c index 24fdc99..73e9778 100644 --- a/framework/private/src/service_reference.c +++ b/framework/private/src/service_reference.c @@ -41,79 +41,145 @@ #include "celix_log.h" static void serviceReference_destroy(service_reference_pt); +static void serviceReference_logWarningUsageCountBelowZero(service_reference_pt ref); -celix_status_t serviceReference_create(bundle_pt bundle, service_registration_pt registration, service_reference_pt *out) { +celix_status_t serviceReference_create(bundle_pt referenceOwner, service_registration_pt registration, service_reference_pt *out) { celix_status_t status = CELIX_SUCCESS; service_reference_pt ref = calloc(1, sizeof(*ref)); if (!ref) { status = CELIX_ENOMEM; } else { - ref->bundle = bundle; + serviceRegistration_retain(registration); + ref->referenceOwner = referenceOwner; ref->registration = registration; - celixThreadMutex_create(&ref->mutex, NULL); + serviceRegistration_getBundle(registration, &ref->registrationBundle); + celixThreadRwlock_create(&ref->lock, NULL); ref->refCount = 1; + ref->usageCount = 0; } if (status == CELIX_SUCCESS) { *out = ref; - } else { - framework_logIfError(logger, status, NULL, "Cannot create service reference"); } + framework_logIfError(logger, status, NULL, "Cannot create service reference"); + return status; } -void serviceReference_retain(service_reference_pt ref) { - celixThreadMutex_lock(&ref->mutex); +celix_status_t serviceReference_retain(service_reference_pt ref) { + celixThreadRwlock_writeLock(&ref->lock); ref->refCount += 1; - celixThreadMutex_unlock(&ref->mutex); + celixThreadRwlock_unlock(&ref->lock); + return CELIX_SUCCESS; } -void serviceReference_release(service_reference_pt ref) { - celixThreadMutex_lock(&ref->mutex); +celix_status_t serviceReference_release(service_reference_pt ref, bool *out) { + bool destroyed = false; + celixThreadRwlock_writeLock(&ref->lock); assert(ref->refCount > 0); ref->refCount -= 1; if (ref->refCount == 0) { serviceReference_destroy(ref); + destroyed = true; + } else { + celixThreadRwlock_unlock(&ref->lock); + } + + if (out) { + *out = destroyed; + } + return CELIX_SUCCESS; +} + +celix_status_t serviceReference_increaseUsage(service_reference_pt ref) { + celixThreadRwlock_writeLock(&ref->lock); + ref->usageCount += 1; + celixThreadRwlock_unlock(&ref->lock); + return CELIX_SUCCESS; +} + +celix_status_t serviceReference_decreaseUsage(service_reference_pt ref) { + celix_status_t status = CELIX_SUCCESS; + celixThreadRwlock_writeLock(&ref->lock); + if (ref->usageCount == 0) { + serviceReference_logWarningUsageCountBelowZero(ref); + status = CELIX_BUNDLE_EXCEPTION; } else { - celixThreadMutex_unlock(&ref->mutex); + ref->usageCount -= 1; } + celixThreadRwlock_unlock(&ref->lock); + return status; +} + +static void serviceReference_logWarningUsageCountBelowZero(service_reference_pt ref) { + fw_log(logger, OSGI_FRAMEWORK_LOG_WARNING, "Cannot decrease service usage count below 0\n"); +} + + +celix_status_t serviceReference_getUsageCount(service_reference_pt ref, size_t *count) { + celix_status_t status = CELIX_SUCCESS; + celixThreadRwlock_readLock(&ref->lock); + *count = ref->usageCount; + celixThreadRwlock_unlock(&ref->lock); + return status; +} + +celix_status_t serviceReference_getReferenceCount(service_reference_pt ref, size_t *count) { + celix_status_t status = CELIX_SUCCESS; + celixThreadRwlock_readLock(&ref->lock); + *count = ref->refCount; + celixThreadRwlock_unlock(&ref->lock); + return status; } static void serviceReference_destroy(service_reference_pt ref) { assert(ref->refCount == 0); - celixThreadMutex_destroy(&ref->mutex); - ref->bundle = NULL; + celixThreadRwlock_destroy(&ref->lock); ref->registration = NULL; free(ref); } -celix_status_t serviceReference_getBundle(service_reference_pt reference, bundle_pt *bundle) { - *bundle = reference->bundle; - return CELIX_SUCCESS; +celix_status_t serviceReference_getBundle(service_reference_pt ref, bundle_pt *bundle) { + celix_status_t status = CELIX_SUCCESS; + celixThreadRwlock_readLock(&ref->lock); + if (ref->registration != NULL) { + *bundle = ref->registrationBundle; + } + celixThreadRwlock_unlock(&ref->lock); + return status; } -celix_status_t serviceReference_getServiceRegistration(service_reference_pt reference, service_registration_pt *registration) { - *registration = reference->registration; - return CELIX_SUCCESS; +celix_status_t serviceReference_getServiceRegistration(service_reference_pt ref, service_registration_pt *out) { + celixThreadRwlock_readLock(&ref->lock); + *out = ref->registration; + celixThreadRwlock_unlock(&ref->lock); + return CELIX_SUCCESS; } -celix_status_t serviceReference_getProperty(service_reference_pt reference, char *key, char **value) { +celix_status_t serviceReference_getProperty(service_reference_pt ref, char *key, char **value) { celix_status_t status = CELIX_SUCCESS; properties_pt props = NULL; - - serviceRegistration_getProperties(reference->registration, &props); - *value = properties_get(props, key); - + celixThreadRwlock_readLock(&ref->lock); + if (ref->registration != NULL) { + status = serviceRegistration_getProperties(ref->registration, &props); + if (status == CELIX_SUCCESS) { + *value = properties_get(props, key); + } + } else { + *value = NULL; + } + celixThreadRwlock_unlock(&ref->lock); return status; } -FRAMEWORK_EXPORT celix_status_t serviceReference_getPropertyKeys(service_reference_pt reference, char **keys[], unsigned int *size) { +FRAMEWORK_EXPORT celix_status_t serviceReference_getPropertyKeys(service_reference_pt ref, char **keys[], unsigned int *size) { celix_status_t status = CELIX_SUCCESS; properties_pt props = NULL; - serviceRegistration_getProperties(reference->registration, &props); + celixThreadRwlock_readLock(&ref->lock); + serviceRegistration_getProperties(ref->registration, &props); hash_map_iterator_pt it; int i = 0; int vsize = hashMap_size(props); @@ -125,18 +191,30 @@ FRAMEWORK_EXPORT celix_status_t serviceReference_getPropertyKeys(service_referen i++; } hashMapIterator_destroy(it); - + celixThreadRwlock_unlock(&ref->lock); return status; } -celix_status_t serviceReference_invalidate(service_reference_pt reference) { - reference->registration = NULL; - return CELIX_SUCCESS; +celix_status_t serviceReference_invalidate(service_reference_pt ref) { + assert(ref != NULL); + celix_status_t status = CELIX_SUCCESS; + service_registration_pt reg = NULL; + celixThreadRwlock_writeLock(&ref->lock); + reg = ref->registration; + ref->registration = NULL; + celixThreadRwlock_unlock(&ref->lock); + + if (reg != NULL) { + serviceRegistration_release(reg); + } + return status; } -celix_status_t serviceReference_isValid(service_reference_pt reference, bool *result) { - (*result) = reference->registration != NULL; - return CELIX_SUCCESS; +celix_status_t serviceReference_isValid(service_reference_pt ref, bool *result) { + celixThreadRwlock_readLock(&ref->lock); + (*result) = ref->registration != NULL; + celixThreadRwlock_unlock(&ref->lock); + return CELIX_SUCCESS; } bool serviceReference_isAssignableTo(service_reference_pt reference, bundle_pt requester, char * serviceName) { @@ -148,19 +226,12 @@ bool serviceReference_isAssignableTo(service_reference_pt reference, bundle_pt r return allow; } -celix_status_t serviceReference_getUsingBundles(service_reference_pt reference, array_list_pt *bundles) { - celix_status_t status = CELIX_SUCCESS; - - service_registry_pt registry = NULL; - serviceRegistration_getRegistry(reference->registration, ®istry); - - *bundles = serviceRegistry_getUsingBundles(registry, reference); - - return status; -} - celix_status_t serviceReference_equals(service_reference_pt reference, service_reference_pt compareTo, bool *equal) { - *equal = (reference->registration == compareTo->registration); + service_registration_pt reg1; + service_registration_pt reg2; + serviceReference_getServiceRegistration(reference, ®1); + serviceReference_getServiceRegistration(compareTo, ®2); + *equal = (reg1 == reg2); return CELIX_SUCCESS; } @@ -196,14 +267,25 @@ celix_status_t serviceReference_compareTo(service_reference_pt reference, servic } unsigned int serviceReference_hashCode(void *referenceP) { - service_reference_pt reference = referenceP; + service_reference_pt ref = referenceP; + bundle_pt bundle = NULL; + service_registration_pt reg = NULL; + + if (ref != NULL) { + celixThreadRwlock_readLock(&ref->lock); + bundle = ref->registrationBundle; + reg = ref->registration; + celixThreadRwlock_unlock(&ref->lock); + } + + int prime = 31; int result = 1; result = prime * result; - if (reference != NULL) { - intptr_t bundleA = (intptr_t) reference->bundle; - intptr_t registrationA = (intptr_t) reference->registration; + if (bundle != NULL && reg != NULL) { + intptr_t bundleA = (intptr_t) bundle; + intptr_t registrationA = (intptr_t) reg; result += bundleA + registrationA; } http://git-wip-us.apache.org/repos/asf/celix/blob/592d65f9/framework/private/src/service_registration.c ---------------------------------------------------------------------- diff --git a/framework/private/src/service_registration.c b/framework/private/src/service_registration.c index 718a633..3bd9ddd 100644 --- a/framework/private/src/service_registration.c +++ b/framework/private/src/service_registration.c @@ -112,11 +112,8 @@ static celix_status_t serviceRegistration_destroy(service_registration_pt regist registration->registry = NULL; properties_destroy(registration->properties); - celixThreadMutex_destroy(®istration->mutex); - free(registration); - registration = NULL; return CELIX_SUCCESS; } @@ -227,20 +224,6 @@ celix_status_t serviceRegistration_getRegistry(service_registration_pt registrat return status; } -celix_status_t serviceRegistration_getServiceReferences(service_registration_pt registration, array_list_pt *references) { - celix_status_t status = CELIX_SUCCESS; - - if (registration != NULL && *references == NULL) { - serviceRegistry_getServiceReferencesForRegistration(registration->registry, registration, references); - } else { - status = CELIX_ILLEGAL_ARGUMENT; - } - - framework_logIfError(logger, status, NULL, "Cannot get service reference"); - - return status; -} - celix_status_t serviceRegistration_getBundle(service_registration_pt registration, bundle_pt *bundle) { celix_status_t status = CELIX_SUCCESS; http://git-wip-us.apache.org/repos/asf/celix/blob/592d65f9/framework/private/src/service_registry.c ---------------------------------------------------------------------- diff --git a/framework/private/src/service_registry.c b/framework/private/src/service_registry.c index ec72f6d..d38b07e 100644 --- a/framework/private/src/service_registry.c +++ b/framework/private/src/service_registry.c @@ -37,15 +37,12 @@ #include "framework_private.h" #include "celix_log.h" -static celix_status_t serviceRegistry_getUsageCount(service_registry_pt registry, bundle_pt bundle, service_reference_pt reference, usage_count_pt *usageCount); -static celix_status_t serviceRegistry_addUsageCount(service_registry_pt registry, bundle_pt bundle, - service_reference_pt reference, - service_registration_pt registration, usage_count_pt *usageCount); -static celix_status_t serviceRegistry_flushUsageCount(service_registry_pt registry, bundle_pt bundle, service_reference_pt reference); - celix_status_t serviceRegistry_registerServiceInternal(service_registry_pt registry, bundle_pt bundle, char * serviceName, void * serviceObject, properties_pt dictionary, bool isFactory, service_registration_pt *registration); celix_status_t serviceRegistry_addHooks(service_registry_pt registry, char *serviceName, void *serviceObject, service_registration_pt registration); celix_status_t serviceRegistry_removeHook(service_registry_pt registry, service_registration_pt registration); +static void serviceRegistry_logWarningServiceReferenceUsageCount(service_registry_pt registry, size_t usageCount, size_t refCount); +static void serviceRegistry_logWarningServiceRegistration(service_registry_pt registry, service_registration_pt reg); + celix_status_t serviceRegistry_create(framework_pt framework, serviceChanged_function_pt serviceChanged, service_registry_pt *registry) { celix_status_t status = CELIX_SUCCESS; @@ -56,7 +53,6 @@ celix_status_t serviceRegistry_create(framework_pt framework, serviceChanged_fun } else { (*registry)->serviceChanged = serviceChanged; - (*registry)->inUseMap = hashMap_create(NULL, NULL, NULL, NULL); (*registry)->serviceRegistrations = hashMap_create(NULL, NULL, NULL, NULL); (*registry)->framework = framework; (*registry)->currentServiceId = 1l; @@ -76,7 +72,6 @@ celix_status_t serviceRegistry_create(framework_pt framework, serviceChanged_fun } celix_status_t serviceRegistry_destroy(service_registry_pt registry) { - hashMap_destroy(registry->inUseMap, false, false); hashMap_destroy(registry->serviceRegistrations, false, false); hashMap_destroy(registry->serviceReferences, false, false); arrayList_destroy(registry->listenerHooks); @@ -84,7 +79,6 @@ celix_status_t serviceRegistry_destroy(service_registry_pt registry) { celixThreadMutexAttr_destroy(®istry->mutexAttr); celixThreadMutex_destroy(®istry->referencesMapMutex); registry->framework = NULL; - registry->inUseMap = NULL; registry->listenerHooks = NULL; registry->serviceChanged = NULL; registry->serviceReferences = NULL; @@ -94,68 +88,6 @@ celix_status_t serviceRegistry_destroy(service_registry_pt registry) { return CELIX_SUCCESS; } -static celix_status_t serviceRegistry_getUsageCount(service_registry_pt registry, bundle_pt bundle, service_reference_pt reference, usage_count_pt *usageCount) { - array_list_pt usages = (array_list_pt) hashMap_get(registry->inUseMap, bundle); - *usageCount = NULL; - unsigned int i; - for (i = 0; (usages != NULL) && (i < arrayList_size(usages)); i++) { - usage_count_pt usage = (usage_count_pt) arrayList_get(usages, i); - bool equals = false; - serviceReference_equals(usage->reference, reference, &equals); - if (equals) { - *usageCount = usage; - break; - } - } - return CELIX_SUCCESS; -} - -static celix_status_t serviceRegistry_addUsageCount(service_registry_pt registry, bundle_pt bundle, - service_reference_pt reference, - service_registration_pt registration, usage_count_pt *usageCount) { - array_list_pt usages = hashMap_get(registry->inUseMap, bundle); - usage_count_pt usage = malloc(sizeof(*usage)); - usage->reference = reference; - usage->count = 0; - usage->service = NULL; - usage->registration = registration; - - serviceRegistration_retain(registration); - - if (usages == NULL) { - arrayList_create(&usages); - } - arrayList_add(usages, usage); - hashMap_put(registry->inUseMap, bundle, usages); - *usageCount = usage; - return CELIX_SUCCESS; -} - -static celix_status_t serviceRegistry_flushUsageCount(service_registry_pt registry, bundle_pt bundle, service_reference_pt reference) { - array_list_pt usages = hashMap_get(registry->inUseMap, bundle); - if (usages != NULL) { - array_list_iterator_pt iter = arrayListIterator_create(usages); - while (arrayListIterator_hasNext(iter)) { - usage_count_pt usage = arrayListIterator_next(iter); - bool equals = false; - serviceReference_equals(usage->reference, reference, &equals); - if (equals) { - arrayListIterator_remove(iter); - serviceRegistration_release(usage->registration); - free(usage); - } - } - arrayListIterator_destroy(iter); - if (arrayList_size(usages) > 0) { - hashMap_put(registry->inUseMap, bundle, usages); - } else { - array_list_pt removed = hashMap_remove(registry->inUseMap, bundle); - arrayList_destroy(removed); - } - } - return CELIX_SUCCESS; -} - celix_status_t serviceRegistry_getRegisteredServices(service_registry_pt registry, bundle_pt bundle, array_list_pt *services) { celix_status_t status = CELIX_SUCCESS; @@ -169,7 +101,7 @@ celix_status_t serviceRegistry_getRegisteredServices(service_registry_pt registr service_registration_pt reg = arrayList_get(regs, i); if (serviceRegistration_isValid(reg)) { service_reference_pt reference = NULL; - status = serviceRegistry_createServiceReference(registry, bundle, reg, &reference); + status = serviceRegistry_getServiceReference(registry, bundle, reg, &reference); if (status == CELIX_SUCCESS) { arrayList_add(*services, reference); } @@ -227,9 +159,7 @@ celix_status_t serviceRegistry_registerServiceInternal(service_registry_pt regis celix_status_t serviceRegistry_unregisterService(service_registry_pt registry, bundle_pt bundle, service_registration_pt registration) { // array_list_t clients; - unsigned int i; array_list_pt regs; - array_list_pt references = NULL; celixThreadMutex_lock(®istry->mutex); @@ -238,7 +168,6 @@ celix_status_t serviceRegistry_unregisterService(service_registry_pt registry, b regs = (array_list_pt) hashMap_get(registry->serviceRegistrations, bundle); if (regs != NULL) { arrayList_removeElement(regs, registration); - hashMap_put(registry->serviceRegistrations, bundle, regs); } celixThreadMutex_unlock(®istry->mutex); @@ -248,27 +177,17 @@ celix_status_t serviceRegistry_unregisterService(service_registry_pt registry, b } celixThreadMutex_lock(®istry->mutex); - // unget service - - serviceRegistration_getServiceReferences(registration, &references); - for (i = 0; i < arrayList_size(references); i++) { - service_reference_pt reference = (service_reference_pt) arrayList_get(references, i); - array_list_pt clients = NULL; - unsigned int j; - - clients = serviceRegistry_getUsingBundles(registry, reference); - for (j = 0; (clients != NULL) && (j < arrayList_size(clients)); j++) { - bundle_pt client = (bundle_pt) arrayList_get(clients, j); - bool ungetResult = true; - while (ungetResult) { - serviceRegistry_ungetService(registry, client, reference, &ungetResult); - } - } - arrayList_destroy(clients); - serviceReference_invalidate(reference); - } - arrayList_destroy(references); + //invalidate service references + hash_map_iterator_pt iter = hashMapIterator_create(registry->serviceReferences); + while (hashMapIterator_hasNext(iter)) { + hash_map_pt refsMap = hashMapIterator_nextValue(iter); + service_reference_pt ref = hashMap_get(refsMap, registration); + if (ref != NULL) { + serviceReference_invalidate(ref); + } + } + hashMapIterator_destroy(iter); serviceRegistration_invalidate(registration); serviceRegistration_release(registration); @@ -278,94 +197,87 @@ celix_status_t serviceRegistry_unregisterService(service_registry_pt registry, b return CELIX_SUCCESS; } -celix_status_t serviceRegistry_unregisterServices(service_registry_pt registry, bundle_pt bundle) { - array_list_pt regs = NULL; - unsigned int i; - celixThreadMutex_lock(®istry->mutex); - regs = (array_list_pt) hashMap_get(registry->serviceRegistrations, bundle); - celixThreadMutex_unlock(®istry->mutex); - - for (i = 0; (regs != NULL) && i < arrayList_size(regs); i++) { - service_registration_pt reg = arrayList_get(regs, i); - if (serviceRegistration_isValid(reg)) { - serviceRegistration_unregister(reg); - } - } +celix_status_t serviceRegistry_clearServiceRegistrations(service_registry_pt registry, bundle_pt bundle) { + celix_status_t status = CELIX_SUCCESS; + array_list_pt registrations = NULL; - if (regs != NULL && arrayList_isEmpty(regs)) { - celixThreadMutex_lock(®istry->mutex); - array_list_pt removed = hashMap_remove(registry->serviceRegistrations, bundle); - celixThreadMutex_unlock(®istry->mutex); - arrayList_destroy(removed); - removed = NULL; - } - celixThreadMutex_lock(®istry->mutex); - hashMap_remove(registry->serviceRegistrations, bundle); - celixThreadMutex_unlock(®istry->mutex); + celixThreadMutex_lock(®istry->mutex); - return CELIX_SUCCESS; -} + registrations = hashMap_get(registry->serviceRegistrations, bundle); + while (registrations != NULL && arrayList_size(registrations) > 0) { + service_registration_pt reg = arrayList_get(registrations, 0); + serviceRegistry_logWarningServiceRegistration(registry, reg); -celix_status_t serviceRegistry_createServiceReference(service_registry_pt registry, bundle_pt owner, service_registration_pt registration, service_reference_pt *reference) { - celix_status_t status = CELIX_SUCCESS; + if (serviceRegistration_isValid(reg)) { + serviceRegistration_unregister(reg); + } + serviceRegistration_release(reg); + } + hashMap_remove(registry->serviceRegistrations, bundle); - bundle_pt bundle = NULL; + celixThreadMutex_unlock(®istry->mutex); - serviceRegistration_getBundle(registration, &bundle); - serviceReference_create(bundle, registration, reference); - // Lock - celixThreadMutex_lock(®istry->referencesMapMutex); - array_list_pt references = hashMap_get(registry->serviceReferences, owner); - if (references == NULL) { - arrayList_create(&references); - } - arrayList_add(references, *reference); - hashMap_put(registry->serviceReferences, owner, references); + return status; +} - // Unlock - celixThreadMutex_unlock(®istry->referencesMapMutex); +static void serviceRegistry_logWarningServiceRegistration(service_registry_pt registry, service_registration_pt reg) { + char *servName = NULL; + serviceRegistration_getServiceName(reg, &servName); + fw_log(logger, OSGI_FRAMEWORK_LOG_WARNING, "Dangling service registration for service %s. Look for missing serviceRegistration_unregister", servName); +} - framework_logIfError(logger, status, NULL, "Cannot create service reference"); +celix_status_t serviceRegistry_getServiceReference(service_registry_pt registry, bundle_pt owner, + service_registration_pt registration, + service_reference_pt *out) { + celix_status_t status = CELIX_SUCCESS; + bundle_pt bundle = NULL; + service_reference_pt ref = NULL; + hash_map_pt references = NULL; - return status; -} + // Lock + celixThreadMutex_lock(®istry->referencesMapMutex); + + references = hashMap_get(registry->serviceReferences, owner); + if (references == NULL) { + references = hashMap_create(NULL, NULL, NULL, NULL); + if (references != NULL) { + hashMap_put(registry->serviceReferences, owner, references); + } else { + status = CELIX_BUNDLE_EXCEPTION; + framework_logIfError(logger, status, NULL, "Cannot create hash map"); + } + } -celix_status_t serviceRegistry_getServiceReferencesForRegistration(service_registry_pt registry, service_registration_pt registration, array_list_pt *references) { - celix_status_t status = CELIX_SUCCESS; - hash_map_values_pt referenceValues = NULL; - hash_map_iterator_pt iterator = NULL; - - arrayList_create(references); - - celixThreadMutex_lock(®istry->referencesMapMutex); - referenceValues = hashMapValues_create(registry->serviceReferences); - iterator = hashMapValues_iterator(referenceValues); - while (hashMapIterator_hasNext(iterator)) { - array_list_pt refs = (array_list_pt) hashMapIterator_nextValue(iterator); - unsigned int refIdx; - for (refIdx = 0; (refs != NULL) && refIdx < arrayList_size(refs); refIdx++) { - service_registration_pt reg = NULL; - service_reference_pt reference = (service_reference_pt) arrayList_get(refs, refIdx); - bool valid = false; - serviceReference_isValid(reference, &valid); - if (valid) { - serviceReference_getServiceRegistration(reference, ®); - if (reg == registration) { - arrayList_add(*references, reference); - } + if (status == CELIX_SUCCESS) { + ref = hashMap_get(references, registration); + if (ref == NULL) { + status = serviceRegistration_getBundle(registration, &bundle); + if (status == CELIX_SUCCESS) { + status = serviceReference_create(owner, registration, &ref); } + if (status == CELIX_SUCCESS) { + hashMap_put(references, registration, ref); + } + } else { + serviceReference_retain(ref); } } - hashMapIterator_destroy(iterator); - hashMapValues_destroy(referenceValues); - celixThreadMutex_unlock(®istry->referencesMapMutex); + if (status == CELIX_SUCCESS) { + *out = ref; + } - return status; + // Unlock + celixThreadMutex_unlock(®istry->referencesMapMutex); + + framework_logIfError(logger, status, NULL, "Cannot create service reference"); + + + return status; } celix_status_t serviceRegistry_getServiceReferences(service_registry_pt registry, bundle_pt owner, const char *serviceName, filter_pt filter, array_list_pt *references) { @@ -407,7 +319,7 @@ celix_status_t serviceRegistry_getServiceReferences(service_registry_pt registry if (matched) { if (serviceRegistration_isValid(registration)) { service_reference_pt reference = NULL; - serviceRegistry_createServiceReference(registry, owner, registration, &reference); + serviceRegistry_getServiceReference(registry, owner, registration, &reference); arrayList_add(*references, reference); } } @@ -423,195 +335,131 @@ celix_status_t serviceRegistry_getServiceReferences(service_registry_pt registry return status; } -celix_status_t serviceRegistry_ungetServiceReference(service_registry_pt registry, bundle_pt owner, service_reference_pt reference) { +celix_status_t serviceRegistry_ungetServiceReference(service_registry_pt registry, bundle_pt bundle, service_reference_pt reference) { celix_status_t status = CELIX_SUCCESS; + bool destroyed = false; + size_t count = 0; + service_registration_pt reg = NULL; - bool valid = false; - serviceReference_isValid(reference, &valid); - if (valid) { - bool ungetResult = true; - while (ungetResult) { - serviceRegistry_ungetService(registry, owner, reference, &ungetResult); + celixThreadMutex_lock(®istry->mutex); + serviceReference_getUsageCount(reference, &count); + serviceReference_getServiceRegistration(reference, ®); + serviceReference_release(reference, &destroyed); + if (destroyed) { + if (count > 0) { + serviceRegistry_logWarningServiceReferenceUsageCount(registry, 0, count); } + hash_map_pt refsMap = hashMap_get(registry->serviceReferences, bundle); + hashMap_remove(refsMap, reg); } + celixThreadMutex_unlock(®istry->mutex); + return status; +} - celixThreadMutex_lock(®istry->referencesMapMutex); - array_list_pt references = hashMap_get(registry->serviceReferences, owner); - if (references != NULL) { - arrayList_removeElement(references, reference); - serviceReference_release(reference); - if (arrayList_size(references) > 0) { - hashMap_put(registry->serviceReferences, owner, references); - } else { - array_list_pt removed = hashMap_remove(registry->serviceReferences, owner); - arrayList_destroy(removed); - } +void serviceRegistry_logWarningServiceReferenceUsageCount(service_registry_pt registry, size_t usageCount, size_t refCount) { + if (usageCount > 0) { + fw_log(logger, OSGI_FRAMEWORK_LOG_WARNING, "Service Reference destroyed will usage count is %zu. Look for missing bundleContext_ungetService calls", usageCount); + } + if (refCount > 0) { + fw_log(logger, OSGI_FRAMEWORK_LOG_WARNING, "Dangling service reference. Reference count is %zu. Look for missing bundleContext_ungetServiceReference", refCount); } - celixThreadMutex_unlock(®istry->referencesMapMutex); - - return status; } -celix_status_t serviceRegistry_ungetServiceReferences(service_registry_pt registry, bundle_pt owner) { + +celix_status_t serviceRegistry_clearReferencesFor(service_registry_pt registry, bundle_pt bundle) { celix_status_t status = CELIX_SUCCESS; - celixThreadMutex_lock(®istry->referencesMapMutex); - array_list_pt references = hashMap_get(registry->serviceReferences, owner); - celixThreadMutex_unlock(®istry->referencesMapMutex); + celixThreadMutex_lock(®istry->mutex); + hash_map_pt refsMap = hashMap_remove(registry->serviceReferences, bundle); + celixThreadMutex_unlock(®istry->mutex); + + if (refsMap != NULL) { + hash_map_iterator_pt iter = hashMapIterator_create(refsMap); + while (hashMapIterator_hasNext(iter)) { + service_reference_pt ref = hashMapIterator_nextValue(iter); + size_t refCount; + size_t usageCount; + + serviceReference_getUsageCount(ref, &usageCount); + serviceReference_getReferenceCount(ref, &refCount); + + serviceRegistry_logWarningServiceReferenceUsageCount(registry, usageCount, refCount); + + while (usageCount > 0) { + serviceReference_decreaseUsage(ref); + serviceReference_getUsageCount(ref, &usageCount); + } + + bool destroyed = false; + while (!destroyed) { + serviceReference_release(ref, &destroyed); + } - if (references != NULL) { - array_list_pt referencesClone = arrayList_clone(references); - int refIdx = 0; - for (refIdx = 0; refIdx < arrayList_size(referencesClone); refIdx++) { - service_reference_pt reference = arrayList_get(referencesClone, refIdx); - serviceRegistry_ungetServiceReference(registry, owner, reference); } - arrayList_destroy(referencesClone); + hashMapIterator_destroy(iter); } return status; } -celix_status_t serviceRegistry_getServicesInUse(service_registry_pt registry, bundle_pt bundle, array_list_pt *services) { + +celix_status_t serviceRegistry_getServicesInUse(service_registry_pt registry, bundle_pt bundle, array_list_pt *out) { + + array_list_pt result = NULL; + arrayList_create(&result); + + //LOCK celixThreadMutex_lock(®istry->mutex); - array_list_pt usages = hashMap_get(registry->inUseMap, bundle); - if (usages != NULL) { - unsigned int i; - arrayList_create(services); - - for (i = 0; i < arrayList_size(usages); i++) { - usage_count_pt usage = arrayList_get(usages, i); - arrayList_add(*services, usage->reference); - } - } + + hash_map_pt refsMap = hashMap_get(registry->serviceReferences, bundle); + + hash_map_iterator_pt iter = hashMapIterator_create(refsMap); + while (hashMapIterator_hasNext(iter)) { + service_reference_pt ref = hashMapIterator_nextValue(iter); + arrayList_add(result, ref); + } + hashMapIterator_destroy(iter); + + //UNLOCK celixThreadMutex_unlock(®istry->mutex); + + *out = result; + return CELIX_SUCCESS; } -celix_status_t serviceRegistry_getService(service_registry_pt registry, bundle_pt bundle, service_reference_pt reference, void **service) { +celix_status_t serviceRegistry_getService(service_registry_pt registry, bundle_pt bundle, service_reference_pt reference, void **out) { celix_status_t status = CELIX_SUCCESS; service_registration_pt registration = NULL; - *service = NULL; - usage_count_pt usage = NULL; + serviceReference_getServiceRegistration(reference, ®istration); celixThreadMutex_lock(®istry->mutex); if (serviceRegistration_isValid(registration)) { - status = serviceRegistry_getUsageCount(registry, bundle, reference, &usage); - if (usage == NULL) { - status = serviceRegistry_addUsageCount(registry, bundle, reference, registration, &usage); - } - usage->count++; - *service = usage->service; - } - celixThreadMutex_unlock(®istry->mutex); - - if ((usage != NULL) && (*service == NULL)) { - status = serviceRegistration_getService(registration, bundle, service); - } - celixThreadMutex_lock(®istry->mutex); - if ((!serviceRegistration_isValid(registration)) || (*service == NULL)) { - serviceRegistry_flushUsageCount(registry, bundle, reference); + serviceReference_increaseUsage(reference); + serviceRegistration_getService(registration, bundle, out); } else { - usage->service = *service; - } + *out = NULL; //invalid service registration + } + celixThreadMutex_unlock(®istry->mutex); + return status; } celix_status_t serviceRegistry_ungetService(service_registry_pt registry, bundle_pt bundle, service_reference_pt reference, bool *result) { celix_status_t status = CELIX_SUCCESS; - service_registration_pt registration = NULL; - usage_count_pt usage = NULL; - serviceReference_getServiceRegistration(reference, ®istration); - - celixThreadMutex_lock(®istry->mutex); - - status = serviceRegistry_getUsageCount(registry, bundle, reference, &usage); - if (usage == NULL) { - celixThreadMutex_unlock(®istry->mutex); - if (result) { - *result = false; - } - return CELIX_SUCCESS; - } - - if (usage->count == 1) { - serviceRegistration_ungetService(registration, bundle, &usage->service); - } - usage->count--; - - if ((!serviceRegistration_isValid(registration)) || (usage->count <= 0)) { - usage->service = NULL; - serviceRegistry_flushUsageCount(registry, bundle, reference); - } - - celixThreadMutex_unlock(®istry->mutex); - - if (result) { - *result = true; - } + celix_status_t subStatus = serviceReference_decreaseUsage(reference); + if (result) { + *result = (subStatus == CELIX_SUCCESS); + } return status; } -void serviceRegistry_ungetServices(service_registry_pt registry, bundle_pt bundle) { - array_list_pt fusages; - array_list_pt usages; - unsigned int i; - - celixThreadMutex_lock(®istry->mutex); - usages = hashMap_get(registry->inUseMap, bundle); - celixThreadMutex_unlock(®istry->mutex); - - if (usages == NULL || arrayList_isEmpty(usages)) { - return; - } - - // usage arrays? - fusages = arrayList_clone(usages); - - for (i = 0; i < arrayList_size(fusages); i++) { - usage_count_pt usage = arrayList_get(fusages, i); - service_reference_pt reference = usage->reference; - bool ungetResult = true; - while (ungetResult) { - serviceRegistry_ungetService(registry, bundle, reference, &ungetResult); - } - } - - arrayList_destroy(fusages); -} - -array_list_pt serviceRegistry_getUsingBundles(service_registry_pt registry, service_reference_pt reference) { - array_list_pt bundles = NULL; - hash_map_iterator_pt iter; - arrayList_create(&bundles); - - celixThreadMutex_lock(®istry->mutex); - iter = hashMapIterator_create(registry->inUseMap); - while (hashMapIterator_hasNext(iter)) { - hash_map_entry_pt entry = hashMapIterator_nextEntry(iter); - bundle_pt bundle = hashMapEntry_getKey(entry); - array_list_pt usages = hashMapEntry_getValue(entry); - unsigned int i; - for (i = 0; i < arrayList_size(usages); i++) { - usage_count_pt usage = arrayList_get(usages, i); - bool equals = false; - serviceReference_equals(usage->reference, reference, &equals); - if (equals) { - arrayList_add(bundles, bundle); - } - } - } - hashMapIterator_destroy(iter); - celixThreadMutex_unlock(®istry->mutex); - return bundles; -} - celix_status_t serviceRegistry_addHooks(service_registry_pt registry, char *serviceName, void *serviceObject, service_registration_pt registration) { celix_status_t status = CELIX_SUCCESS; @@ -653,7 +501,7 @@ celix_status_t serviceRegistry_getListenerHooks(service_registry_pt registry, bu for (i = 0; i < arrayList_size(registry->listenerHooks); i++) { service_registration_pt registration = arrayList_get(registry->listenerHooks, i); service_reference_pt reference = NULL; - serviceRegistry_createServiceReference(registry, owner, registration, &reference); + serviceRegistry_getServiceReference(registry, owner, registration, &reference); arrayList_add(*hooks, reference); } celixThreadMutex_unlock(®istry->mutex); http://git-wip-us.apache.org/repos/asf/celix/blob/592d65f9/framework/private/src/service_tracker.c ---------------------------------------------------------------------- diff --git a/framework/private/src/service_tracker.c b/framework/private/src/service_tracker.c index b81b4d0..b5edbd6 100644 --- a/framework/private/src/service_tracker.c +++ b/framework/private/src/service_tracker.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include "service_tracker_private.h" #include "bundle_context.h" @@ -33,9 +35,15 @@ #include "service_reference.h" #include "celix_log.h" -static celix_status_t serviceTracker_addingService(service_tracker_pt tracker, service_reference_pt reference, void **service); +static celix_status_t serviceTracker_invokeAddingService(service_tracker_pt tracker, service_reference_pt reference, + void **service); static celix_status_t serviceTracker_track(service_tracker_pt tracker, service_reference_pt reference, service_event_pt event); static celix_status_t serviceTracker_untrack(service_tracker_pt tracker, service_reference_pt reference, service_event_pt event); +static celix_status_t serviceTracker_invokeAddService(service_tracker_pt tracker, service_reference_pt ref, void *service); +static celix_status_t serviceTracker_invokeModifiedService(service_tracker_pt tracker, service_reference_pt ref, void *service); + +static celix_status_t serviceTracker_invokeRemovingService(service_tracker_pt tracker, service_reference_pt ref, + void *service); celix_status_t serviceTracker_create(bundle_context_pt context, char * service, service_tracker_customizer_pt customizer, service_tracker_pt *tracker) { celix_status_t status = CELIX_SUCCESS; @@ -214,6 +222,8 @@ void serviceTracker_serviceChanged(service_listener_pt listener, service_event_p service_tracker_pt tracker = listener->handle; switch (event->type) { case OSGI_FRAMEWORK_SERVICE_EVENT_REGISTERED: + serviceTracker_track(tracker, event->reference, event); + break; case OSGI_FRAMEWORK_SERVICE_EVENT_MODIFIED: serviceTracker_track(tracker, event->reference, event); break; @@ -221,6 +231,7 @@ void serviceTracker_serviceChanged(service_listener_pt listener, service_event_p serviceTracker_untrack(tracker, event->reference, event); break; case OSGI_FRAMEWORK_SERVICE_EVENT_MODIFIED_ENDMATCH: + //TODO break; } } @@ -229,51 +240,32 @@ static celix_status_t serviceTracker_track(service_tracker_pt tracker, service_r celix_status_t status = CELIX_SUCCESS; tracked_pt tracked = NULL; - int found = -1; + bool found = false; unsigned int i; for (i = 0; i < arrayList_size(tracker->tracked); i++) { bool equals = false; tracked = (tracked_pt) arrayList_get(tracker->tracked, i); serviceReference_equals(reference, tracked->reference, &equals); if (equals) { - found = 0; + found = true; break; } } - if (found) { + if (!found /*new*/) { void * service = NULL; - status = serviceTracker_addingService(tracker, reference, &service); + status = serviceTracker_invokeAddingService(tracker, reference, &service); if (status == CELIX_SUCCESS) { if (service != NULL) { - tracked = (tracked_pt) malloc(sizeof(*tracked)); + tracked = (tracked_pt) calloc(1, sizeof(*tracked)); tracked->reference = reference; tracked->service = service; arrayList_add(tracker->tracked, tracked); - if (tracker->customizer != NULL) { - void *handle = NULL; - added_callback_pt function = NULL; - - serviceTrackerCustomizer_getHandle(tracker->customizer, &handle); - serviceTrackerCustomizer_getAddedFunction(tracker->customizer, &function); - if (function != NULL) { - function(handle, reference, service); - } - } + serviceTracker_invokeAddService(tracker, reference, service); } } } else { - if (tracker->customizer != NULL) { - void *handle = NULL; - modified_callback_pt function = NULL; - - serviceTrackerCustomizer_getHandle(tracker->customizer, &handle); - serviceTrackerCustomizer_getModifiedFunction(tracker->customizer, &function); - - if (function != NULL) { - function(handle, reference, tracked->service); - } - } + status = serviceTracker_invokeModifiedService(tracker, reference, tracked->service); } framework_logIfError(logger, status, NULL, "Cannot track reference"); @@ -281,7 +273,39 @@ static celix_status_t serviceTracker_track(service_tracker_pt tracker, service_r return status; } -static celix_status_t serviceTracker_addingService(service_tracker_pt tracker, service_reference_pt reference, void **service) { +static celix_status_t serviceTracker_invokeModifiedService(service_tracker_pt tracker, service_reference_pt ref, void *service) { + celix_status_t status = CELIX_SUCCESS; + if (tracker->customizer != NULL) { + void *handle = NULL; + modified_callback_pt function = NULL; + + serviceTrackerCustomizer_getHandle(tracker->customizer, &handle); + serviceTrackerCustomizer_getModifiedFunction(tracker->customizer, &function); + + if (function != NULL) { + function(handle, ref, service); + } + } + return status; +} + +static celix_status_t serviceTracker_invokeAddService(service_tracker_pt tracker, service_reference_pt ref, void *service) { + celix_status_t status = CELIX_SUCCESS; + if (tracker->customizer != NULL) { + void *handle = NULL; + added_callback_pt function = NULL; + + serviceTrackerCustomizer_getHandle(tracker->customizer, &handle); + serviceTrackerCustomizer_getAddedFunction(tracker->customizer, &function); + if (function != NULL) { + function(handle, ref, service); + } + } + return status; +} + +static celix_status_t serviceTracker_invokeAddingService(service_tracker_pt tracker, service_reference_pt reference, + void **service) { celix_status_t status = CELIX_SUCCESS; if (tracker->customizer != NULL) { @@ -289,19 +313,21 @@ static celix_status_t serviceTracker_addingService(service_tracker_pt tracker, adding_callback_pt function = NULL; status = serviceTrackerCustomizer_getHandle(tracker->customizer, &handle); + + if (status == CELIX_SUCCESS) { + status = serviceTrackerCustomizer_getAddingFunction(tracker->customizer, &function); + } + if (status == CELIX_SUCCESS) { - status = serviceTrackerCustomizer_getAddingFunction(tracker->customizer, &function); - if (status == CELIX_SUCCESS) { - if (function != NULL) { - status = function(handle, reference, service); - } else { - status = bundleContext_getService(tracker->context, reference, service); - } - } + if (function != NULL) { + status = function(handle, reference, service); + } else { + status = bundleContext_getService(tracker->context, reference, service); + } } } else { - status = bundleContext_getService(tracker->context, reference, service); - } + status = bundleContext_getService(tracker->context, reference, service); + } framework_logIfError(logger, status, NULL, "Cannot handle addingService"); @@ -312,7 +338,6 @@ static celix_status_t serviceTracker_untrack(service_tracker_pt tracker, service celix_status_t status = CELIX_SUCCESS; tracked_pt tracked = NULL; unsigned int i; - bool result = false; for (i = 0; i < arrayList_size(tracker->tracked); i++) { bool equals; @@ -320,28 +345,10 @@ static celix_status_t serviceTracker_untrack(service_tracker_pt tracker, service serviceReference_equals(reference, tracked->reference, &equals); if (equals) { arrayList_remove(tracker->tracked, i); - if (status == CELIX_SUCCESS) { - if (tracker->customizer != NULL) { - void *handle = NULL; - removed_callback_pt function = NULL; - - serviceTrackerCustomizer_getHandle(tracker->customizer, &handle); - serviceTrackerCustomizer_getRemovedFunction(tracker->customizer, &function); - - if (function != NULL) { - status = function(handle, reference, tracked->service); - } else { - status = bundleContext_ungetService(tracker->context, reference, &result); - } - } else { - status = bundleContext_ungetService(tracker->context, reference, &result); - } - - // ungetServiceReference - bundleContext_ungetServiceReference(tracker->context, reference); - //break; - } + serviceTracker_invokeRemovingService(tracker, tracked->reference, tracked->service); + bundleContext_ungetService(tracker->context, tracked->reference, tracked->service); free(tracked); + break; } } @@ -349,3 +356,31 @@ static celix_status_t serviceTracker_untrack(service_tracker_pt tracker, service return status; } + +static celix_status_t serviceTracker_invokeRemovingService(service_tracker_pt tracker, service_reference_pt ref, void *service) { + celix_status_t status = CELIX_SUCCESS; + bool ungetSuccess = true; + if (tracker->customizer != NULL) { + void *handle = NULL; + removed_callback_pt function = NULL; + + serviceTrackerCustomizer_getHandle(tracker->customizer, &handle); + serviceTrackerCustomizer_getRemovedFunction(tracker->customizer, &function); + + if (function != NULL) { + status = function(handle, ref, service); + } + if (status == CELIX_SUCCESS) { + status = bundleContext_ungetService(tracker->context, ref, &ungetSuccess); + } + } else { + status = bundleContext_ungetService(tracker->context, ref, &ungetSuccess); + } + + if (!ungetSuccess) { + framework_log(logger, OSGI_FRAMEWORK_LOG_ERROR, __FUNCTION__, __FILE__, __LINE__, "Error ungetting service"); + status = CELIX_BUNDLE_EXCEPTION; + } + + return status; +} http://git-wip-us.apache.org/repos/asf/celix/blob/592d65f9/framework/public/include/service_reference.h ---------------------------------------------------------------------- diff --git a/framework/public/include/service_reference.h b/framework/public/include/service_reference.h index f1e1427..b99359e 100644 --- a/framework/public/include/service_reference.h +++ b/framework/public/include/service_reference.h @@ -39,8 +39,6 @@ FRAMEWORK_EXPORT celix_status_t serviceReference_getBundle(service_reference_pt FRAMEWORK_EXPORT bool serviceReference_isAssignableTo(service_reference_pt reference, bundle_pt requester, char * serviceName); -FRAMEWORK_EXPORT celix_status_t serviceReference_getUsingBundles(service_reference_pt reference, array_list_pt *bundles); - FRAMEWORK_EXPORT celix_status_t serviceReference_getProperty(service_reference_pt reference, char *key, char **value); FRAMEWORK_EXPORT celix_status_t serviceReference_getPropertyKeys(service_reference_pt reference, char **keys[], unsigned int *size); http://git-wip-us.apache.org/repos/asf/celix/blob/592d65f9/framework/public/include/service_registration.h ---------------------------------------------------------------------- diff --git a/framework/public/include/service_registration.h b/framework/public/include/service_registration.h index 5775154..22685a9 100644 --- a/framework/public/include/service_registration.h +++ b/framework/public/include/service_registration.h @@ -40,6 +40,5 @@ typedef struct serviceRegistration * service_registration_pt; FRAMEWORK_EXPORT celix_status_t serviceRegistration_unregister(service_registration_pt registration); FRAMEWORK_EXPORT celix_status_t serviceRegistration_getProperties(service_registration_pt registration, properties_pt *properties); FRAMEWORK_EXPORT celix_status_t serviceRegistration_setProperties(service_registration_pt registration, properties_pt properties); -FRAMEWORK_EXPORT celix_status_t serviceRegistration_getServiceReferences(service_registration_pt registration, array_list_pt *references); #endif /* SERVICE_REGISTRATION_H_ */ http://git-wip-us.apache.org/repos/asf/celix/blob/592d65f9/framework/public/include/service_registry.h ---------------------------------------------------------------------- diff --git a/framework/public/include/service_registry.h b/framework/public/include/service_registry.h index 7a33f37..5c013cc 100644 --- a/framework/public/include/service_registry.h +++ b/framework/public/include/service_registry.h @@ -43,21 +43,24 @@ celix_status_t serviceRegistry_destroy(service_registry_pt registry); celix_status_t serviceRegistry_getRegisteredServices(service_registry_pt registry, bundle_pt bundle, array_list_pt *services); celix_status_t serviceRegistry_getServicesInUse(service_registry_pt registry, bundle_pt bundle, array_list_pt *services); + celix_status_t serviceRegistry_registerService(service_registry_pt registry, bundle_pt bundle, char * serviceName, void * serviceObject, properties_pt dictionary, service_registration_pt *registration); celix_status_t serviceRegistry_registerServiceFactory(service_registry_pt registry, bundle_pt bundle, char * serviceName, service_factory_pt factory, properties_pt dictionary, service_registration_pt *registration); + celix_status_t serviceRegistry_unregisterService(service_registry_pt registry, bundle_pt bundle, service_registration_pt registration); -celix_status_t serviceRegistry_unregisterServices(service_registry_pt registry, bundle_pt bundle); +celix_status_t serviceRegistry_clearServiceRegistrations(service_registry_pt registry, bundle_pt bundle); + +celix_status_t serviceRegistry_getServiceReference(service_registry_pt registry, bundle_pt bundle, service_registration_pt registration, service_reference_pt *reference); celix_status_t serviceRegistry_getServiceReferences(service_registry_pt registry, bundle_pt bundle, const char *serviceName, filter_pt filter, array_list_pt *references); +celix_status_t serviceRegistry_ungetServiceReference(service_registry_pt registry, bundle_pt bundle, service_reference_pt reference); + celix_status_t serviceRegistry_getService(service_registry_pt registry, bundle_pt bundle, service_reference_pt reference, void **service); celix_status_t serviceRegistry_ungetService(service_registry_pt registry, bundle_pt bundle, service_reference_pt reference, bool *result); -void serviceRegistry_ungetServices(service_registry_pt registry, bundle_pt bundle); -array_list_pt serviceRegistry_getUsingBundles(service_registry_pt registry, service_reference_pt reference); -service_registration_pt serviceRegistry_findRegistration(service_registry_pt registry, service_reference_pt reference); -celix_status_t serviceRegistry_ungetServiceReference(service_registry_pt registry, bundle_pt bundle, service_reference_pt reference); -celix_status_t serviceRegistry_ungetServiceReferences(service_registry_pt registry, bundle_pt bundle); -celix_status_t serviceRegistry_createServiceReference(service_registry_pt registry, bundle_pt bundle, service_registration_pt registration, service_reference_pt *reference); -celix_status_t serviceRegistry_getServiceReferencesForRegistration(service_registry_pt registry, service_registration_pt registration, array_list_pt *references); +celix_status_t serviceRegistry_clearReferencesFor(service_registry_pt registry, bundle_pt bundle); + + +service_registration_pt serviceRegistry_findRegistration(service_registry_pt registry, service_reference_pt reference); celix_status_t serviceRegistry_getListenerHooks(service_registry_pt registry, bundle_pt bundle, array_list_pt *hooks);