CELIX-272: Refactoring of ServiceRegistry. Added warning log of incorrect 
handling service refs/regs


Project: http://git-wip-us.apache.org/repos/asf/celix/repo
Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/592d65f9
Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/592d65f9
Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/592d65f9

Branch: refs/heads/feature/CELIX-272_synchronization_service_registry
Commit: 592d65f900e6193b8b74d5dac0c2875bfa7e355f
Parents: 5fbd1f5
Author: Pepijn Noltes <[email protected]>
Authored: Wed Nov 11 13:24:55 2015 +0100
Committer: Pepijn Noltes <[email protected]>
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);
 

Reply via email to