You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by ab...@apache.org on 2014/08/27 14:14:30 UTC
svn commit: r1620872 - in /celix/trunk: framework/private/include/
framework/private/src/ framework/public/include/ shell/private/src/
shell_tui/private/src/
Author: abroekhuis
Date: Wed Aug 27 12:14:30 2014
New Revision: 1620872
URL: http://svn.apache.org/r1620872
Log:
Fixed a race condition in the registry. Introduced a new API call to unget ServiceReferences.
Modified:
celix/trunk/framework/private/include/framework_private.h
celix/trunk/framework/private/include/service_registration_private.h
celix/trunk/framework/private/include/service_registry_private.h
celix/trunk/framework/private/src/bundle_context.c
celix/trunk/framework/private/src/framework.c
celix/trunk/framework/private/src/service_reference.c
celix/trunk/framework/private/src/service_registration.c
celix/trunk/framework/private/src/service_registry.c
celix/trunk/framework/public/include/bundle_context.h
celix/trunk/framework/public/include/service_registry.h
celix/trunk/shell/private/src/log_command.c
celix/trunk/shell_tui/private/src/shell_tui.c
Modified: celix/trunk/framework/private/include/framework_private.h
URL: http://svn.apache.org/viewvc/celix/trunk/framework/private/include/framework_private.h?rev=1620872&r1=1620871&r2=1620872&view=diff
==============================================================================
--- celix/trunk/framework/private/include/framework_private.h (original)
+++ celix/trunk/framework/private/include/framework_private.h Wed Aug 27 12:14:30 2014
@@ -103,6 +103,7 @@ FRAMEWORK_EXPORT celix_status_t fw_regis
FRAMEWORK_EXPORT void fw_unregisterService(service_registration_pt registration);
FRAMEWORK_EXPORT celix_status_t fw_getServiceReferences(framework_pt framework, array_list_pt *references, bundle_pt bundle, const char * serviceName, char * filter);
+FRAMEWORK_EXPORT celix_status_t framework_ungetServiceReference(framework_pt framework, bundle_pt bundle, service_reference_pt reference);
FRAMEWORK_EXPORT celix_status_t fw_getService(framework_pt framework, bundle_pt bundle, service_reference_pt reference, void **service);
FRAMEWORK_EXPORT celix_status_t framework_ungetService(framework_pt framework, bundle_pt bundle, service_reference_pt reference, bool *result);
FRAMEWORK_EXPORT celix_status_t fw_getBundleRegisteredServices(framework_pt framework, bundle_pt bundle, array_list_pt *services);
Modified: celix/trunk/framework/private/include/service_registration_private.h
URL: http://svn.apache.org/viewvc/celix/trunk/framework/private/include/service_registration_private.h?rev=1620872&r1=1620871&r2=1620872&view=diff
==============================================================================
--- celix/trunk/framework/private/include/service_registration_private.h (original)
+++ celix/trunk/framework/private/include/service_registration_private.h Wed Aug 27 12:14:30 2014
@@ -38,7 +38,6 @@ struct service {
struct serviceRegistration {
service_registry_pt registry;
char * className;
- array_list_pt references;
bundle_pt bundle;
properties_pt properties;
void * svcObj;
Modified: celix/trunk/framework/private/include/service_registry_private.h
URL: http://svn.apache.org/viewvc/celix/trunk/framework/private/include/service_registry_private.h?rev=1620872&r1=1620871&r2=1620872&view=diff
==============================================================================
--- celix/trunk/framework/private/include/service_registry_private.h (original)
+++ celix/trunk/framework/private/include/service_registry_private.h Wed Aug 27 12:14:30 2014
@@ -42,6 +42,8 @@ struct serviceRegistry {
celix_thread_mutex_t mutex;
celix_thread_mutexattr_t mutexAttr;
+
+ celix_thread_mutex_t referencesMapMutex;
};
struct usageCount {
Modified: celix/trunk/framework/private/src/bundle_context.c
URL: http://svn.apache.org/viewvc/celix/trunk/framework/private/src/bundle_context.c?rev=1620872&r1=1620871&r2=1620872&view=diff
==============================================================================
--- celix/trunk/framework/private/src/bundle_context.c (original)
+++ celix/trunk/framework/private/src/bundle_context.c Wed Aug 27 12:14:30 2014
@@ -208,6 +208,20 @@ celix_status_t bundleContext_getServiceR
return status;
}
+celix_status_t bundleContext_ungetServiceReference(bundle_context_pt context, service_reference_pt reference) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ if (context != NULL && reference != NULL) {
+ status = framework_ungetServiceReference(context->framework, context->bundle, reference);
+ } else {
+ status = CELIX_ILLEGAL_ARGUMENT;
+ }
+
+ framework_logIfError(logger, status, NULL, "Failed to unget service_reference");
+
+ return status;
+}
+
celix_status_t bundleContext_getService(bundle_context_pt context, service_reference_pt reference, void **service_instance) {
celix_status_t status = CELIX_SUCCESS;
Modified: celix/trunk/framework/private/src/framework.c
URL: http://svn.apache.org/viewvc/celix/trunk/framework/private/src/framework.c?rev=1620872&r1=1620871&r2=1620872&view=diff
==============================================================================
--- celix/trunk/framework/private/src/framework.c (original)
+++ celix/trunk/framework/private/src/framework.c Wed Aug 27 12:14:30 2014
@@ -859,32 +859,22 @@ celix_status_t fw_stopBundle(framework_p
status = CELIX_DO_IF(status, activator->destroy(activator->userData, context));
}
}
-// }
-
-// status = CELIX_DO_IF(status, bundle_getCurrentModule(bundle, &module));
-// if (status == CELIX_SUCCESS) {
-// if (strcmp(module_getId(module), "0") != 0) {
-// if (activator != NULL) {
-// activator->start = NULL;
-// activator->stop = NULL;
-// activator->userData = NULL;
-// //free(activator);
-//// status = CELIX_DO_IF(status, bundle_setActivator(bundle, NULL));
-// }
if (id != 0) {
status = CELIX_DO_IF(status, serviceRegistry_unregisterServices(framework->registry, bundle));
if (status == CELIX_SUCCESS) {
+ module_pt module = NULL;
+ char *symbolicName = NULL;
+ long id = 0;
+ bundle_getCurrentModule(bundle, &module);
+ module_getSymbolicName(module, &symbolicName);
+ bundle_getBundleId(bundle, &id);
+
serviceRegistry_ungetServices(framework->registry, bundle);
+ serviceRegistry_ungetServiceReferences(framework->registry, bundle);
}
// #TODO remove listeners for bundle
-// if (wasActive) {
-// if (activator->destroy != NULL) {
-// status = CELIX_DO_IF(status, activator->destroy(activator->userData, context));
-// }
-// }
-
if (context != NULL) {
status = CELIX_DO_IF(status, bundleContext_destroy(context));
status = CELIX_DO_IF(status, bundle_setContext(bundle, NULL));
@@ -894,12 +884,6 @@ celix_status_t fw_stopBundle(framework_p
}
}
-// if (id == 0) {
-// if (activator->destroy != NULL) {
-// status = CELIX_DO_IF(status, activator->destroy(activator->userData, context));
-// }
-// }
-
if (activator != NULL) {
bundle_setActivator(bundle, NULL);
free(activator);
@@ -1247,7 +1231,7 @@ celix_status_t fw_registerService(framew
bool ungetResult = false;
- status = CELIX_DO_IF(status, serviceRegistry_createServiceReference(framework->registry, *registration, &ref));
+ status = CELIX_DO_IF(status, serviceRegistry_createServiceReference(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);
@@ -1299,7 +1283,7 @@ celix_status_t fw_getServiceReferences(f
filter = filter_create(sfilter);
}
- status = CELIX_DO_IF(status, serviceRegistry_getServiceReferences(framework->registry, serviceName, filter, references));
+ status = CELIX_DO_IF(status, serviceRegistry_getServiceReferences(framework->registry, bundle, serviceName, filter, references));
if (filter != NULL) {
filter_destroy(filter);
@@ -1328,6 +1312,10 @@ celix_status_t fw_getServiceReferences(f
return status;
}
+celix_status_t framework_ungetServiceReference(framework_pt framework, bundle_pt bundle, service_reference_pt reference) {
+ return serviceRegistry_ungetServiceReference(framework->registry, bundle, reference);
+}
+
celix_status_t fw_getService(framework_pt framework, bundle_pt bundle, service_reference_pt reference, void **service) {
return serviceRegistry_getService(framework->registry, bundle, reference, service);
}
@@ -1364,7 +1352,7 @@ void fw_addServiceListener(framework_pt
fwListener->listener = listener;
arrayList_add(framework->serviceListeners, fwListener);
- serviceRegistry_getListenerHooks(framework->registry, &listenerHooks);
+ serviceRegistry_getListenerHooks(framework->registry, framework->bundle, &listenerHooks);
info = (listener_hook_info_pt) malloc(sizeof(*info));
@@ -1434,7 +1422,7 @@ void fw_removeServiceListener(framework_
if (info != NULL) {
unsigned int i;
array_list_pt listenerHooks = NULL;
- serviceRegistry_getListenerHooks(framework->registry, &listenerHooks);
+ serviceRegistry_getListenerHooks(framework->registry, framework->bundle, &listenerHooks);
for (i = 0; i < arrayList_size(listenerHooks); i++) {
service_reference_pt ref = (service_reference_pt) arrayList_get(listenerHooks, i);
@@ -1559,7 +1547,7 @@ void fw_serviceChanged(framework_pt fram
event = (service_event_pt) malloc(sizeof(*event));
- serviceRegistry_createServiceReference(framework->registry, registration, &reference);
+ serviceRegistry_createServiceReference(framework->registry, element->bundle, registration, &reference);
event->type = eventType;
event->reference = reference;
@@ -1581,7 +1569,7 @@ void fw_serviceChanged(framework_pt fram
service_reference_pt reference = NULL;
service_event_pt endmatch = (service_event_pt) malloc(sizeof(*endmatch));
- serviceRegistry_createServiceReference(framework->registry, registration, &reference);
+ serviceRegistry_createServiceReference(framework->registry, element->bundle, registration, &reference);
endmatch->reference = reference;
endmatch->type = OSGI_FRAMEWORK_SERVICE_EVENT_MODIFIED_ENDMATCH;
Modified: celix/trunk/framework/private/src/service_reference.c
URL: http://svn.apache.org/viewvc/celix/trunk/framework/private/src/service_reference.c?rev=1620872&r1=1620871&r2=1620872&view=diff
==============================================================================
--- celix/trunk/framework/private/src/service_reference.c (original)
+++ celix/trunk/framework/private/src/service_reference.c Wed Aug 27 12:14:30 2014
@@ -55,7 +55,6 @@ celix_status_t serviceReference_create(b
}
celix_status_t serviceReference_destroy(service_reference_pt reference) {
- serviceRegistry_removeReference(reference);
reference->bundle = NULL;
reference->registration = NULL;
free(reference);
Modified: celix/trunk/framework/private/src/service_registration.c
URL: http://svn.apache.org/viewvc/celix/trunk/framework/private/src/service_registration.c?rev=1620872&r1=1620871&r2=1620872&view=diff
==============================================================================
--- celix/trunk/framework/private/src/service_registration.c (original)
+++ celix/trunk/framework/private/src/service_registration.c Wed Aug 27 12:14:30 2014
@@ -63,8 +63,6 @@ celix_status_t serviceRegistration_creat
(*registration)->registry = registry;
(*registration)->className = strdup(serviceName);
(*registration)->bundle = bundle;
- (*registration)->references = NULL;
- arrayList_create(&(*registration)->references);
(*registration)->serviceId = serviceId;
(*registration)->svcObj = serviceObject;
@@ -74,8 +72,6 @@ celix_status_t serviceRegistration_creat
(*registration)->serviceFactory = NULL;
}
- // serviceReference_create(pool, bundle, *registration, &(*registration)->reference);
-
(*registration)->isUnregistering = false;
celixThreadMutex_create(&(*registration)->mutex, NULL);
@@ -93,7 +89,6 @@ celix_status_t serviceRegistration_destr
registration->registry = NULL;
properties_destroy(registration->properties);
- arrayList_destroy(registration->references);
celixThreadMutex_destroy(®istration->mutex);
@@ -141,8 +136,6 @@ celix_status_t serviceRegistration_unreg
}
celixThreadMutex_unlock(®istration->mutex);
-// bundle_pt bundle = NULL;
-// status = serviceReference_getBundle(registration->reference, &bundle);
if (status == CELIX_SUCCESS) {
serviceRegistry_unregisterService(registration->registry, registration->bundle, registration);
}
@@ -204,7 +197,7 @@ celix_status_t serviceRegistration_getSe
celix_status_t status = CELIX_SUCCESS;
if (registration != NULL && *references == NULL) {
- *references = registration->references;
+ serviceRegistry_getServiceReferencesForRegistration(registration->registry, registration, references);
} else {
status = CELIX_ILLEGAL_ARGUMENT;
}
Modified: celix/trunk/framework/private/src/service_registry.c
URL: http://svn.apache.org/viewvc/celix/trunk/framework/private/src/service_registry.c?rev=1620872&r1=1620871&r2=1620872&view=diff
==============================================================================
--- celix/trunk/framework/private/src/service_registry.c (original)
+++ celix/trunk/framework/private/src/service_registry.c Wed Aug 27 12:14:30 2014
@@ -37,6 +37,10 @@
#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, 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);
@@ -54,15 +58,13 @@ celix_status_t serviceRegistry_create(fr
(*registry)->serviceRegistrations = hashMap_create(NULL, NULL, NULL, NULL);
(*registry)->framework = framework;
(*registry)->currentServiceId = 1l;
- (*registry)->serviceReferences = NULL;
+ (*registry)->serviceReferences = hashMap_create(NULL, NULL, NULL, NULL);;
arrayList_create(&(*registry)->listenerHooks);
- celix_thread_mutexattr_t attr;
-
status = celixThreadMutexAttr_create(&(*registry)->mutexAttr);
status = CELIX_DO_IF(status, celixThreadMutexAttr_settype(&(*registry)->mutexAttr, CELIX_THREAD_MUTEX_RECURSIVE));
- status = CELIX_DO_IF(status, celixThreadMutex_create(&(*registry)->mutex, &(*registry)->mutexAttr));
+ status = CELIX_DO_IF(status, celixThreadMutex_create(&(*registry)->referencesMapMutex, NULL));
}
framework_logIfError(logger, status, NULL, "Cannot create service registry");
@@ -73,9 +75,11 @@ celix_status_t serviceRegistry_create(fr
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);
celixThreadMutex_destroy(®istry->mutex);
celixThreadMutexAttr_destroy(®istry->mutexAttr);
+ celixThreadMutex_destroy(®istry->referencesMapMutex);
registry->framework = NULL;
registry->inUseMap = NULL;
registry->listenerHooks = NULL;
@@ -86,19 +90,14 @@ celix_status_t serviceRegistry_destroy(s
return CELIX_SUCCESS;
}
-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_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);
- // @TODO use reference_equals!
bool equals = false;
-// serviceReference_equals(usage->reference, reference, &equals);
- if (usage->reference == reference) {
- *usageCount = usage;
- break;
- }
+ serviceReference_equals(usage->reference, reference, &equals);
if (equals) {
*usageCount = usage;
break;
@@ -107,7 +106,7 @@ celix_status_t serviceRegistry_getUsageC
return CELIX_SUCCESS;
}
-celix_status_t serviceRegistry_addUsageCount(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, usage_count_pt *usageCount) {
array_list_pt usages = hashMap_get(registry->inUseMap, bundle);
usage_count_pt usage = malloc(sizeof(*usage));
usage->reference = reference;
@@ -115,9 +114,7 @@ celix_status_t serviceRegistry_addUsageC
usage->service = NULL;
if (usages == NULL) {
- module_pt mod = NULL;
arrayList_create(&usages);
- bundle_getCurrentModule(bundle, &mod);
}
arrayList_add(usages, usage);
hashMap_put(registry->inUseMap, bundle, usages);
@@ -125,13 +122,15 @@ celix_status_t serviceRegistry_addUsageC
return CELIX_SUCCESS;
}
-celix_status_t serviceRegistry_flushUsageCount(service_registry_pt registry, bundle_pt bundle, service_reference_pt reference) {
+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);
- if (usage->reference == reference) {
+ bool equals = false;
+ serviceReference_equals(usage->reference, reference, &equals);
+ if (equals) {
arrayListIterator_remove(iter);
free(usage);
}
@@ -150,6 +149,7 @@ celix_status_t serviceRegistry_flushUsag
celix_status_t serviceRegistry_getRegisteredServices(service_registry_pt registry, bundle_pt bundle, array_list_pt *services) {
celix_status_t status = CELIX_SUCCESS;
+ celixThreadMutex_lock(®istry->mutex);
array_list_pt regs = (array_list_pt) hashMap_get(registry->serviceRegistrations, bundle);
if (regs != NULL) {
unsigned int i;
@@ -159,13 +159,14 @@ celix_status_t serviceRegistry_getRegist
service_registration_pt reg = arrayList_get(regs, i);
if (serviceRegistration_isValid(reg)) {
service_reference_pt reference = NULL;
- status = serviceRegistry_createServiceReference(registry, reg, &reference);
+ status = serviceRegistry_createServiceReference(registry, bundle, reg, &reference);
if (status == CELIX_SUCCESS) {
arrayList_add(*services, reference);
}
}
}
}
+ celixThreadMutex_unlock(®istry->mutex);
framework_logIfError(logger, status, NULL, "Cannot get registered services");
@@ -255,11 +256,9 @@ celix_status_t serviceRegistry_unregiste
}
arrayList_destroy(clients);
- // Disabled since a reference normally already is destroyed here.
- // Compared to Java OSGi, this might result in crashes, since the references for the service are all destroyed
- // Anyone still holding a pointer to such a reference is in risk, hence, always use a service tracker or similar!
-// serviceReference_invalidate(reference);
+ serviceReference_invalidate(reference);
}
+ //TODO not needed, the registration is destroyed, any reference to the registration is invalid and will result in a segfault
serviceRegistration_invalidate(registration);
serviceRegistration_destroy(registration);
@@ -284,7 +283,9 @@ celix_status_t serviceRegistry_unregiste
}
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;
}
@@ -297,29 +298,66 @@ celix_status_t serviceRegistry_unregiste
}
-celix_status_t serviceRegistry_createServiceReference(service_registry_pt registry, service_registration_pt registration, service_reference_pt *reference) {
+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;
bundle_pt bundle = NULL;
- array_list_pt references = NULL;
serviceRegistration_getBundle(registration, &bundle);
serviceReference_create(bundle, registration, reference);
- serviceRegistration_getServiceReferences(registration, &references);
- arrayList_add(references, *reference);
+ // Lock
+ celixThreadMutex_lock(®istry->referencesMapMutex);
+ array_list_pt references = hashMap_get(registry->serviceReferences, bundle);
+ if (references == NULL) {
+ arrayList_create(&references);
+ }
+ arrayList_add(references, reference);
+ hashMap_put(registry->serviceReferences, bundle, references);
+
+ // 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, const char *serviceName, filter_pt filter, array_list_pt *references) {
+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);
+ serviceReference_getServiceRegistration(reference, ®);
+ if (reg == registration) {
+ arrayList_add(*references, reference);
+ }
+ }
+ }
+ celixThreadMutex_unlock(®istry->referencesMapMutex);
+
+ return status;
+}
+
+celix_status_t serviceRegistry_getServiceReferences(service_registry_pt registry, bundle_pt owner, const char *serviceName, filter_pt filter, array_list_pt *references) {
celix_status_t status = CELIX_SUCCESS;
hash_map_values_pt registrations;
hash_map_iterator_pt iterator;
arrayList_create(references);
+ celixThreadMutex_lock(®istry->mutex);
registrations = hashMapValues_create(registry->serviceRegistrations);
iterator = hashMapValues_iterator(registrations);
while (hashMapIterator_hasNext(iterator)) {
@@ -352,7 +390,7 @@ celix_status_t serviceRegistry_getServic
if (matched) {
if (serviceRegistration_isValid(registration)) {
service_reference_pt reference = NULL;
- serviceRegistry_createServiceReference(registry, registration, &reference);
+ serviceRegistry_createServiceReference(registry, owner, registration, &reference);
arrayList_add(*references, reference);
}
}
@@ -361,26 +399,62 @@ celix_status_t serviceRegistry_getServic
}
hashMapIterator_destroy(iterator);
hashMapValues_destroy(registrations);
+ celixThreadMutex_unlock(®istry->mutex);
framework_logIfError(logger, status, NULL, "Cannot get service references");
return status;
}
-celix_status_t serviceRegistry_removeReference(service_reference_pt reference) {
- service_registration_pt registration = NULL;
- serviceReference_getServiceRegistration(reference, ®istration);
+celix_status_t serviceRegistry_ungetServiceReference(service_registry_pt registry, bundle_pt owner, service_reference_pt reference) {
+ celix_status_t status = CELIX_SUCCESS;
- if (registration != NULL) {
- array_list_pt references = NULL;
- serviceRegistration_getServiceReferences(registration, &references);
- arrayList_removeElement(references, reference);
- }
+ bool valid = false;
+ serviceRefernce_isValid(reference, &valid);
+ if (valid) {
+ bool ungetResult = true;
+ while (ungetResult) {
+ serviceRegistry_ungetService(registry, owner, reference, &ungetResult);
+ }
+ }
+
+ celixThreadMutex_lock(®istry->referencesMapMutex);
+ array_list_pt references = hashMap_get(registry->serviceReferences, owner);
+ if (references != NULL) {
+ arrayList_removeElement(references, 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);
+ }
+ }
+ celixThreadMutex_unlock(®istry->referencesMapMutex);
- return CELIX_SUCCESS;
+ return status;
+}
+
+celix_status_t serviceRegistry_ungetServiceReferences(service_registry_pt registry, bundle_pt owner) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ celixThreadMutex_lock(®istry->referencesMapMutex);
+ array_list_pt references = hashMap_get(registry->serviceReferences, owner);
+ celixThreadMutex_unlock(®istry->referencesMapMutex);
+
+ 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);
+ }
+ }
+
+ return status;
}
celix_status_t serviceRegistry_getServicesInUse(service_registry_pt registry, bundle_pt bundle, array_list_pt *services) {
+ celixThreadMutex_lock(®istry->mutex);
array_list_pt usages = hashMap_get(registry->inUseMap, bundle);
if (usages != NULL) {
unsigned int i;
@@ -391,6 +465,7 @@ celix_status_t serviceRegistry_getServic
arrayList_add(*services, usage->reference);
}
}
+ celixThreadMutex_unlock(®istry->mutex);
return CELIX_SUCCESS;
}
@@ -444,10 +519,9 @@ celix_status_t serviceRegistry_ungetServ
usage->count--;
- if ((serviceRegistration_isValid(registration)) || (usage->count <= 0)) {
+ if ((!serviceRegistration_isValid(registration)) || (usage->count <= 0)) {
usage->service = NULL;
serviceRegistry_flushUsageCount(registry, bundle, reference);
- serviceReference_destroy(reference);
}
celixThreadMutex_unlock(®istry->mutex);
@@ -489,6 +563,8 @@ array_list_pt serviceRegistry_getUsingBu
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);
@@ -497,12 +573,15 @@ array_list_pt serviceRegistry_getUsingBu
unsigned int i;
for (i = 0; i < arrayList_size(usages); i++) {
usage_count_pt usage = arrayList_get(usages, i);
- if (usage->reference == reference) {
+ bool equals = false;
+ serviceReference_equals(usage->reference, reference, &equals);
+ if (equals) {
arrayList_add(bundles, bundle);
}
}
}
hashMapIterator_destroy(iter);
+ celixThreadMutex_unlock(®istry->mutex);
return bundles;
}
@@ -510,7 +589,9 @@ celix_status_t serviceRegistry_addHooks(
celix_status_t status = CELIX_SUCCESS;
if (strcmp(OSGI_FRAMEWORK_LISTENER_HOOK_SERVICE_NAME, serviceName) == 0) {
+ celixThreadMutex_lock(®istry->mutex);
arrayList_add(registry->listenerHooks, registration);
+ celixThreadMutex_unlock(®istry->mutex);
}
return status;
@@ -524,13 +605,15 @@ celix_status_t serviceRegistry_removeHoo
serviceRegistration_getProperties(registration, &props);
serviceName = properties_get(props, (char *) OSGI_FRAMEWORK_OBJECTCLASS);
if (strcmp(OSGI_FRAMEWORK_LISTENER_HOOK_SERVICE_NAME, serviceName) == 0) {
+ celixThreadMutex_lock(®istry->mutex);
arrayList_removeElement(registry->listenerHooks, registration);
+ celixThreadMutex_unlock(®istry->mutex);
}
return status;
}
-celix_status_t serviceRegistry_getListenerHooks(service_registry_pt registry, array_list_pt *hooks) {
+celix_status_t serviceRegistry_getListenerHooks(service_registry_pt registry, bundle_pt owner, array_list_pt *hooks) {
celix_status_t status = CELIX_SUCCESS;
if (registry == NULL || *hooks != NULL) {
@@ -539,12 +622,14 @@ celix_status_t serviceRegistry_getListen
status = arrayList_create(hooks);
if (status == CELIX_SUCCESS) {
unsigned int i;
+ celixThreadMutex_lock(®istry->mutex);
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, registration, &reference);
+ serviceRegistry_createServiceReference(registry, owner, registration, &reference);
arrayList_add(*hooks, reference);
}
+ celixThreadMutex_unlock(®istry->mutex);
}
}
Modified: celix/trunk/framework/public/include/bundle_context.h
URL: http://svn.apache.org/viewvc/celix/trunk/framework/public/include/bundle_context.h?rev=1620872&r1=1620871&r2=1620872&view=diff
==============================================================================
--- celix/trunk/framework/public/include/bundle_context.h (original)
+++ celix/trunk/framework/public/include/bundle_context.h Wed Aug 27 12:14:30 2014
@@ -58,6 +58,7 @@ FRAMEWORK_EXPORT celix_status_t bundleCo
FRAMEWORK_EXPORT celix_status_t bundleContext_getServiceReferences(bundle_context_pt context, const char * serviceName, char * filter, array_list_pt *service_references);
FRAMEWORK_EXPORT celix_status_t bundleContext_getServiceReference(bundle_context_pt context, char * serviceName, service_reference_pt *service_reference);
+FRAMEWORK_EXPORT celix_status_t bundleContext_ungetServiceReference(bundle_context_pt context, service_reference_pt reference);
FRAMEWORK_EXPORT celix_status_t bundleContext_getService(bundle_context_pt context, service_reference_pt reference, void **service_instance);
FRAMEWORK_EXPORT celix_status_t bundleContext_ungetService(bundle_context_pt context, service_reference_pt reference, bool *result);
Modified: celix/trunk/framework/public/include/service_registry.h
URL: http://svn.apache.org/viewvc/celix/trunk/framework/public/include/service_registry.h?rev=1620872&r1=1620871&r2=1620872&view=diff
==============================================================================
--- celix/trunk/framework/public/include/service_registry.h (original)
+++ celix/trunk/framework/public/include/service_registry.h Wed Aug 27 12:14:30 2014
@@ -47,17 +47,19 @@ celix_status_t serviceRegistry_registerS
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_getServiceReferences(service_registry_pt registry, const char *serviceName, filter_pt filter, array_list_pt *references);
+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_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, service_registration_pt registration, service_reference_pt *reference);
-celix_status_t serviceRegistry_removeReference(service_reference_pt reference);
+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_getListenerHooks(service_registry_pt registry, array_list_pt *hooks);
+celix_status_t serviceRegistry_getListenerHooks(service_registry_pt registry, bundle_pt bundle, array_list_pt *hooks);
celix_status_t serviceRegistry_servicePropertiesModified(service_registry_pt registry, service_registration_pt registration, properties_pt oldprops);
Modified: celix/trunk/shell/private/src/log_command.c
URL: http://svn.apache.org/viewvc/celix/trunk/shell/private/src/log_command.c?rev=1620872&r1=1620871&r2=1620872&view=diff
==============================================================================
--- celix/trunk/shell/private/src/log_command.c (original)
+++ celix/trunk/shell/private/src/log_command.c Wed Aug 27 12:14:30 2014
@@ -93,10 +93,13 @@ void logCommand_execute(command_pt comma
}
}
linkedListIterator_destroy(iter);
+ bool result = true;
+ bundleContext_ungetService(command->bundleContext, readerService, &result);
apr_pool_destroy(memory_pool);
} else {
out("Log reader service: out of memory!\n");
}
+ bundleContext_ungetServiceReference(command->bundleContext, readerService);
} else {
out("No log reader available\n");
}
Modified: celix/trunk/shell_tui/private/src/shell_tui.c
URL: http://svn.apache.org/viewvc/celix/trunk/shell_tui/private/src/shell_tui.c?rev=1620872&r1=1620871&r2=1620872&view=diff
==============================================================================
--- celix/trunk/shell_tui/private/src/shell_tui.c (original)
+++ celix/trunk/shell_tui/private/src/shell_tui.c Wed Aug 27 12:14:30 2014
@@ -96,10 +96,13 @@ void shellTui_initializeService(shell_tu
void shellTui_serviceChanged(service_listener_pt listener, service_event_pt event) {
bool result = false;
shell_tui_activator_pt act = (shell_tui_activator_pt) listener->handle;
+ bool equals = false;
+
+ serviceReference_equals(act->reference, event->reference, &equals);
if ((event->type == OSGI_FRAMEWORK_SERVICE_EVENT_REGISTERED) && (act->reference == NULL)) {
shellTui_initializeService(act);
- } else if ((event->type == OSGI_FRAMEWORK_SERVICE_EVENT_UNREGISTERING) && (act->reference == event->reference)) {
+ } else if ((event->type == OSGI_FRAMEWORK_SERVICE_EVENT_UNREGISTERING) && (equals)) {
bundleContext_ungetService(act->context, act->reference, &result);
act->reference = NULL;
act->shell = NULL;