celix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pnol...@apache.org
Subject [05/38] celix git commit: CELIX-272: Refactoring of ServiceRegistry. Added warning log of incorrect handling service refs/regs
Date Tue, 17 Nov 2015 11:57:22 GMT
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/develop
Commit: 592d65f900e6193b8b74d5dac0c2875bfa7e355f
Parents: 5fbd1f5
Author: Pepijn Noltes <pepijnnoltes@gmail.com>
Authored: Wed Nov 11 13:24:55 2015 +0100
Committer: Pepijn Noltes <pepijnnoltes@gmail.com>
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, &regProps);
-            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, &regProps);
+                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, &registry);
-
-	*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, &reg1);
+    serviceReference_getServiceRegistration(compareTo, &reg2);
+	*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(&registration->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(&registry->mutexAttr);
     celixThreadMutex_destroy(&registry->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(&registry->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(&registry->mutex);
@@ -248,27 +177,17 @@ celix_status_t serviceRegistry_unregisterService(service_registry_pt registry, b
 	}
 
 	celixThreadMutex_lock(&registry->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(&registry->mutex);
-	regs = (array_list_pt) hashMap_get(registry->serviceRegistrations, bundle);
-	celixThreadMutex_unlock(&registry->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(&registry->mutex);
-		array_list_pt removed = hashMap_remove(registry->serviceRegistrations, bundle);
-		celixThreadMutex_unlock(&registry->mutex);
-		arrayList_destroy(removed);
-		removed = NULL;
-	}
 
-	celixThreadMutex_lock(&registry->mutex);
-	hashMap_remove(registry->serviceRegistrations, bundle);
-	celixThreadMutex_unlock(&registry->mutex);
+    celixThreadMutex_lock(&registry->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(&registry->mutex);
 
-	serviceRegistration_getBundle(registration, &bundle);
-	serviceReference_create(bundle, registration, reference);
 
-	// Lock
-	celixThreadMutex_lock(&registry->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(&registry->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(&registry->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(&registry->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, &reg);
-                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(&registry->referencesMapMutex);
+    if (status == CELIX_SUCCESS) {
+        *out = ref;
+    }
 
-    return status;
+    // Unlock
+	celixThreadMutex_unlock(&registry->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(&registry->mutex);
+    serviceReference_getUsageCount(reference, &count);
+    serviceReference_getServiceRegistration(reference, &reg);
+    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(&registry->mutex);
+    return status;
+}
 
-    celixThreadMutex_lock(&registry->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(&registry->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(&registry->referencesMapMutex);
-    array_list_pt references = hashMap_get(registry->serviceReferences, owner);
-    celixThreadMutex_unlock(&registry->referencesMapMutex);
+    celixThreadMutex_lock(&registry->mutex);
+    hash_map_pt refsMap = hashMap_remove(registry->serviceReferences, bundle);
+    celixThreadMutex_unlock(&registry->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(&registry->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(&registry->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, &registration);
 	
 	celixThreadMutex_lock(&registry->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(&registry->mutex);
-
-	if ((usage != NULL) && (*service == NULL)) {
-		status = serviceRegistration_getService(registration, bundle, service);
-	}
-	celixThreadMutex_lock(&registry->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(&registry->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, &registration);
-
-	celixThreadMutex_lock(&registry->mutex);
-
-	status = serviceRegistry_getUsageCount(registry, bundle, reference, &usage);
-	if (usage == NULL) {
-		celixThreadMutex_unlock(&registry->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(&registry->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(&registry->mutex);
-	usages = hashMap_get(registry->inUseMap, bundle);
-	celixThreadMutex_unlock(&registry->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(&registry->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(&registry->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(&registry->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 <stdlib.h>
 #include <string.h>
 #include <stdio.h>
+#include <service_reference_private.h>
+#include <framework_private.h>
 
 #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);
 


Mime
View raw message