You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pn...@apache.org on 2015/11/16 16:16:33 UTC

celix git commit: CELIX-272: Add callback structure for serv reg/ref instead of dependency to serv registry. Fix in serviceRegistry_destroy

Repository: celix
Updated Branches:
  refs/heads/feature/CELIX-272_synchronization_service_registry 5e3020914 -> eae936a3b


CELIX-272: Add callback structure for serv reg/ref instead of dependency to serv registry. Fix in serviceRegistry_destroy


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

Branch: refs/heads/feature/CELIX-272_synchronization_service_registry
Commit: eae936a3b8e0501c68bb7f4964288ed34cccff7c
Parents: 5e30209
Author: Pepijn Noltes <pe...@gmail.com>
Authored: Mon Nov 16 16:15:45 2015 +0100
Committer: Pepijn Noltes <pe...@gmail.com>
Committed: Mon Nov 16 16:15:45 2015 +0100

----------------------------------------------------------------------
 .../private/include/registry_callback_private.h |  42 ++++++++
 .../private/include/service_reference_private.h |   5 +-
 .../include/service_registration_private.h      |   7 +-
 .../private/include/service_registry_private.h  |   2 +
 framework/private/src/service_reference.c       |  37 ++++++-
 framework/private/src/service_registration.c    |   2 +-
 framework/private/src/service_registry.c        | 106 +++++++++++++------
 framework/public/include/service_reference.h    |   1 +
 8 files changed, 157 insertions(+), 45 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/celix/blob/eae936a3/framework/private/include/registry_callback_private.h
----------------------------------------------------------------------
diff --git a/framework/private/include/registry_callback_private.h b/framework/private/include/registry_callback_private.h
new file mode 100644
index 0000000..146a1d1
--- /dev/null
+++ b/framework/private/include/registry_callback_private.h
@@ -0,0 +1,42 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+/*
+ * service_reference_private.h
+ *
+ *  \date       Nov 16, 2015
+ *  \author     <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright  Apache License, Version 2.0
+ */
+
+
+#ifndef REGISTRY_CALLBACK_H_
+#define REGISTRY_CALLBACK_H_
+
+#include "celix_errno.h"
+#include "service_reference.h"
+#include "service_registration.h"
+
+typedef struct registry_callback_struct {
+	void *handle;
+    celix_status_t (*getUsingBundles)(void *handle, service_registration_pt reg, array_list_pt *bundles);
+	celix_status_t (*unregister)(void *handle, bundle_pt bundle, service_registration_pt reg);
+	celix_status_t (*modified)(void *handle, service_registration_pt registration, properties_pt oldProperties);
+} registry_callback_t;
+
+#endif /* REGISTRY_CALLBACK_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/eae936a3/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 7eea45e..b0b8afb 100644
--- a/framework/private/include/service_reference_private.h
+++ b/framework/private/include/service_reference_private.h
@@ -28,9 +28,12 @@
 #ifndef SERVICE_REFERENCE_PRIVATE_H_
 #define SERVICE_REFERENCE_PRIVATE_H_
 
+#include "registry_callback_private.h"
 #include "service_reference.h"
 
+
 struct serviceReference {
+    registry_callback_t callback;
 	bundle_pt referenceOwner;
 	struct serviceRegistration * registration;
     bundle_pt registrationBundle;
@@ -42,7 +45,7 @@ struct serviceReference {
     celix_thread_rwlock_t lock;
 };
 
-celix_status_t serviceReference_create(bundle_pt referenceOwner, service_registration_pt registration, service_reference_pt *reference);
+celix_status_t serviceReference_create(registry_callback_t callback, 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);

http://git-wip-us.apache.org/repos/asf/celix/blob/eae936a3/framework/private/include/service_registration_private.h
----------------------------------------------------------------------
diff --git a/framework/private/include/service_registration_private.h b/framework/private/include/service_registration_private.h
index 2b1bf6c..4b48e70 100644
--- a/framework/private/include/service_registration_private.h
+++ b/framework/private/include/service_registration_private.h
@@ -28,14 +28,9 @@
 #ifndef SERVICE_REGISTRATION_PRIVATE_H_
 #define SERVICE_REGISTRATION_PRIVATE_H_
 
+#include "registry_callback_private.h"
 #include "service_registration.h"
 
-typedef struct registry_callback_struct {
-	void *handle;
-	celix_status_t (*unregister)(void *handle, bundle_pt bundle, service_registration_pt reg);
-	celix_status_t (*modified)(void *handle, service_registration_pt registration, properties_pt oldProperties);
-} registry_callback_t;
-
 struct serviceRegistration {
     registry_callback_t callback;
 

http://git-wip-us.apache.org/repos/asf/celix/blob/eae936a3/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 f3edd17..28c6148 100644
--- a/framework/private/include/service_registry_private.h
+++ b/framework/private/include/service_registry_private.h
@@ -28,10 +28,12 @@
 #ifndef SERVICE_REGISTRY_PRIVATE_H_
 #define SERVICE_REGISTRY_PRIVATE_H_
 
+#include "registry_callback_private.h"
 #include "service_registry.h"
 
 struct serviceRegistry {
 	framework_pt framework;
+	registry_callback_t callback;
 
 	hash_map_pt serviceRegistrations; //key = bundle (reg owner), value = registration
 	hash_map_pt serviceReferences; //key = bundle, value = map (key = registration, value = reference)

http://git-wip-us.apache.org/repos/asf/celix/blob/eae936a3/framework/private/src/service_reference.c
----------------------------------------------------------------------
diff --git a/framework/private/src/service_reference.c b/framework/private/src/service_reference.c
index 2f829c2..dfbafd0 100644
--- a/framework/private/src/service_reference.c
+++ b/framework/private/src/service_reference.c
@@ -38,14 +38,14 @@
 static void serviceReference_destroy(service_reference_pt);
 static void serviceReference_logWarningUsageCountBelowZero(service_reference_pt ref);
 
-celix_status_t serviceReference_create(bundle_pt referenceOwner, service_registration_pt registration,  service_reference_pt *out) {
+celix_status_t serviceReference_create(registry_callback_t callback, 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 {
-        serviceRegistration_retain(registration);
+        ref->callback = callback;
 		ref->referenceOwner = referenceOwner;
 		ref->registration = registration;
         ref->service = NULL;
@@ -95,7 +95,7 @@ celix_status_t serviceReference_release(service_reference_pt ref, bool *out) {
 }
 
 celix_status_t serviceReference_increaseUsage(service_reference_pt ref, size_t *out) {
-    fw_log(logger, OSGI_FRAMEWORK_LOG_DEBUG, "Destroying service reference %p\n", ref);
+    //fw_log(logger, OSGI_FRAMEWORK_LOG_DEBUG, "Destroying service reference %p\n", ref);
     size_t local = 0;
     celixThreadRwlock_writeLock(&ref->lock);
     ref->usageCount += 1;
@@ -321,3 +321,34 @@ unsigned int serviceReference_hashCode(void *referenceP) {
 	return result;
 }
 
+
+celix_status_t serviceReference_getUsingBundles(service_reference_pt ref, array_list_pt *out) {
+    celix_status_t status = CELIX_SUCCESS;
+    service_registration_pt reg = NULL;
+    registry_callback_t callback;
+
+    callback.getUsingBundles = NULL;
+
+
+    celixThreadRwlock_readLock(&ref->lock);
+    reg = ref->registration;
+    if (reg != NULL) {
+        serviceRegistration_retain(reg);
+        callback.handle = ref->callback.handle;
+        callback.getUsingBundles = ref->callback.getUsingBundles;
+    }
+    celixThreadRwlock_unlock(&ref->lock);
+
+    if (reg != NULL) {
+        if (callback.getUsingBundles != NULL) {
+            status = callback.getUsingBundles(callback.handle, reg, out);
+        } else {
+            fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "getUsingBundles callback not set");
+            status = CELIX_BUNDLE_EXCEPTION;
+        }
+        serviceRegistration_release(reg);
+    }
+
+    return status;
+}
+

http://git-wip-us.apache.org/repos/asf/celix/blob/eae936a3/framework/private/src/service_registration.c
----------------------------------------------------------------------
diff --git a/framework/private/src/service_registration.c b/framework/private/src/service_registration.c
index dc8ae9b..f1fea32 100644
--- a/framework/private/src/service_registration.c
+++ b/framework/private/src/service_registration.c
@@ -103,7 +103,7 @@ void serviceRegistration_release(service_registration_pt registration) {
 }
 
 static celix_status_t serviceRegistration_destroy(service_registration_pt registration) {
-	fw_log(logger, OSGI_FRAMEWORK_LOG_DEBUG, "Destroying service registration %p\n", registration);
+	//fw_log(logger, OSGI_FRAMEWORK_LOG_DEBUG, "Destroying service registration %p\n", registration);
     free(registration->className);
 	registration->className = NULL;
 

http://git-wip-us.apache.org/repos/asf/celix/blob/eae936a3/framework/private/src/service_registry.c
----------------------------------------------------------------------
diff --git a/framework/private/src/service_registry.c b/framework/private/src/service_registry.c
index 13fe01a..9f90025 100644
--- a/framework/private/src/service_registry.c
+++ b/framework/private/src/service_registry.c
@@ -26,6 +26,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <assert.h>
 
 #include "service_registry_private.h"
 #include "service_registration_private.h"
@@ -44,6 +45,9 @@ static celix_status_t serviceRegistry_checkReference(service_registry_pt registr
 static void serviceRegistry_logIllegalReference(service_registry_pt registry, service_reference_pt reference,
                                                    reference_status_t refStatus);
 
+static celix_status_t serviceRegistry_setReferenceStatus(service_registry_pt registry, service_reference_pt reference,
+                                                  bool deleted);
+
 celix_status_t serviceRegistry_create(framework_pt framework, serviceChanged_function_pt serviceChanged, service_registry_pt *out) {
 	celix_status_t status;
 
@@ -51,7 +55,13 @@ celix_status_t serviceRegistry_create(framework_pt framework, serviceChanged_fun
 	if (reg == NULL) {
 		status = CELIX_ENOMEM;
 	} else {
-		reg->serviceChanged = serviceChanged;
+
+        reg->callback.handle = reg;
+        reg->callback.getUsingBundles = NULL; /*TODO*/
+        reg->callback.unregister = (void *) serviceRegistry_unregisterService;
+        reg->callback.modified = (void *) serviceRegistry_servicePropertiesModified;
+
+        reg->serviceChanged = serviceChanged;
 		reg->serviceRegistrations = hashMap_create(NULL, NULL, NULL, NULL);
 		reg->framework = framework;
 		reg->currentServiceId = 1l;
@@ -73,16 +83,25 @@ celix_status_t serviceRegistry_create(framework_pt framework, serviceChanged_fun
 }
 
 celix_status_t serviceRegistry_destroy(service_registry_pt registry) {
-	celixThreadRwlock_writeLock(&registry->lock);
+    celixThreadRwlock_writeLock(&registry->lock);
+
+    //destroy service registration map
+    int size = hashMap_size(registry->serviceRegistrations);
+    assert(size == 0);
     hashMap_destroy(registry->serviceRegistrations, false, false);
+
+    //destroy service references (double) map);
+    size = hashMap_size(registry->serviceReferences);
+    assert(size == 0);
     hashMap_destroy(registry->serviceReferences, false, false);
+
+    //destroy listener hooks
+    size = arrayList_size(registry->listenerHooks);
+    if (size == 0);
     arrayList_destroy(registry->listenerHooks);
 
-    registry->framework = NULL;
-    registry->listenerHooks = NULL;
-    registry->serviceChanged = NULL;
-    registry->serviceReferences = NULL;
-    registry->serviceRegistrations = NULL;
+    hashMap_destroy(registry->deletedServiceReferences, false, false);
+
     free(registry);
 
     return CELIX_SUCCESS;
@@ -128,15 +147,10 @@ celix_status_t serviceRegistry_registerServiceFactory(service_registry_pt regist
 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) {
 	array_list_pt regs;
 
-    registry_callback_t callback;
-    callback.handle = registry;
-    callback.unregister = (void *) serviceRegistry_unregisterService;
-    callback.modified = (void *) serviceRegistry_servicePropertiesModified;
-
 	if (isFactory) {
-	    *registration = serviceRegistration_createServiceFactory(callback, bundle, serviceName, ++registry->currentServiceId, serviceObject, dictionary);
+	    *registration = serviceRegistration_createServiceFactory(registry->callback, bundle, serviceName, ++registry->currentServiceId, serviceObject, dictionary);
 	} else {
-	    *registration = serviceRegistration_create(callback, bundle, serviceName, ++registry->currentServiceId, serviceObject, dictionary);
+	    *registration = serviceRegistration_create(registry->callback, bundle, serviceName, ++registry->currentServiceId, serviceObject, dictionary);
 	}
 
 	serviceRegistry_addHooks(registry, serviceName, serviceObject, *registration);
@@ -183,7 +197,8 @@ celix_status_t serviceRegistry_unregisterService(service_registry_pt registry, b
     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);
+        service_reference_pt ref = refsMap != NULL ?
+                                   hashMap_get(refsMap, registration) : NULL;
         if (ref != NULL) {
             serviceReference_invalidate(ref);
         }
@@ -247,7 +262,7 @@ celix_status_t serviceRegistry_getServiceReference(service_registry_pt registry,
     if (ref == NULL) {
         status = serviceRegistration_getBundle(registration, &bundle);
         if (status == CELIX_SUCCESS) {
-            status = serviceReference_create(owner, registration, &ref);
+            status = serviceReference_create(registry->callback, owner, registration, &ref);
         }
         if (status == CELIX_SUCCESS) {
             hashMap_put(references, registration, ref);
@@ -314,6 +329,7 @@ celix_status_t serviceRegistry_getServiceReferences(service_registry_pt registry
 				}
 				if (matched) {
 					if (serviceRegistration_isValid(registration)) {
+                        serviceRegistration_retain(registration);
                         arrayList_add(matchingRegistrations, registration);
 					}
 				}
@@ -328,12 +344,13 @@ celix_status_t serviceRegistry_getServiceReferences(service_registry_pt registry
         for (i = 0; i < size; i += 1) {
             service_registration_pt reg = arrayList_get(matchingRegistrations, i);
             service_reference_pt reference = NULL;
-            status = serviceRegistry_getServiceReference(registry, owner, reg, &reference);
-            if (status == CELIX_SUCCESS) {
+            celix_status_t subStatues = serviceRegistry_getServiceReference(registry, owner, reg, &reference);
+            if (subStatues == CELIX_SUCCESS) {
                 arrayList_add(references, reference);
             } else {
-                break;
+                status = CELIX_BUNDLE_EXCEPTION;
             }
+            serviceRegistration_release(reg);
         }
         arrayList_destroy(matchingRegistrations);
     }
@@ -357,6 +374,7 @@ celix_status_t serviceRegistry_ungetServiceReference(service_registry_pt registr
     service_registration_pt reg = NULL;
     reference_status_t refStatus;
 
+    celixThreadRwlock_writeLock(&registry->lock);
     serviceRegistry_checkReference(registry, reference, &refStatus);
     if (refStatus == REF_ACTIVE) {
         serviceReference_getUsageCount(reference, &count);
@@ -368,19 +386,32 @@ celix_status_t serviceRegistry_ungetServiceReference(service_registry_pt registr
             }
 
 
-            celixThreadRwlock_writeLock(&registry->lock);
             hash_map_pt refsMap = hashMap_get(registry->serviceReferences, bundle);
             hashMap_remove(refsMap, reg);
-            hashMap_put(registry->deletedServiceReferences, reference, (void *)true);
-            celixThreadRwlock_unlock(&registry->lock);
+            int size = hashMap_size(refsMap);
+            if (size == 0) {
+                hashMap_destroy(refsMap, false, false);
+                hashMap_remove(registry->serviceReferences, bundle);
+            }
+            serviceRegistry_setReferenceStatus(registry, reference, true);
         }
     } else {
         serviceRegistry_logIllegalReference(registry, reference, refStatus);
     }
+    celixThreadRwlock_unlock(&registry->lock);
 
     return status;
 }
 
+celix_status_t serviceRegistry_setReferenceStatus(service_registry_pt registry, service_reference_pt reference,
+                                                  bool deleted) {
+    //precondition write locked on registry->lock
+    if (registry->checkDeletedReferences) {
+        hashMap_put(registry->deletedServiceReferences, reference, (void *) deleted);
+    }
+    return CELIX_SUCCESS;
+}
+
 static void serviceRegistry_logIllegalReference(service_registry_pt registry __attribute__((unused)), service_reference_pt reference,
                                                    reference_status_t refStatus) {
 
@@ -389,17 +420,21 @@ static void serviceRegistry_logIllegalReference(service_registry_pt registry __a
 
 celix_status_t serviceRegistry_checkReference(service_registry_pt registry, service_reference_pt ref,
                                               reference_status_t *out) {
+    //precondition read or write locked on registry->lock
     celix_status_t status = CELIX_SUCCESS;
-    reference_status_t refStatus = REF_UNKNOWN;
 
-    celixThreadRwlock_readLock(&registry->lock);
-    if (hashMap_containsKey(registry->deletedServiceReferences, ref)) {
-        bool deleted = (bool) hashMap_get(registry->deletedServiceReferences, ref);
-        refStatus = deleted ? REF_DELETED : REF_ACTIVE;
-    }
-    celixThreadRwlock_unlock(&registry->lock);
+    if (registry->checkDeletedReferences) {
+        reference_status_t refStatus = REF_UNKNOWN;
 
-    *out = refStatus;
+        if (hashMap_containsKey(registry->deletedServiceReferences, ref)) {
+            bool deleted = (bool) hashMap_get(registry->deletedServiceReferences, ref);
+            refStatus = deleted ? REF_DELETED : REF_ACTIVE;
+        }
+
+        *out = refStatus;
+    } else {
+        *out = REF_ACTIVE;
+    }
 
     return status;
 }
@@ -440,7 +475,7 @@ celix_status_t serviceRegistry_clearReferencesFor(service_registry_pt registry,
             while (!destroyed) {
                 serviceReference_release(ref, &destroyed);
             }
-            hashMap_put(registry->deletedServiceReferences, ref, (void *)true);
+            serviceRegistry_setReferenceStatus(registry, ref, true);
 
         }
         hashMapIterator_destroy(iter);
@@ -484,10 +519,11 @@ celix_status_t serviceRegistry_getService(service_registry_pt registry, bundle_p
     void *service = NULL;
     reference_status_t refStatus;
 
-    serviceRegistry_checkReference(registry, reference, &refStatus);
 
+
+    celixThreadRwlock_readLock(&registry->lock);
+    serviceRegistry_checkReference(registry, reference, &refStatus);
     if (refStatus == REF_ACTIVE) {
-        celixThreadRwlock_readLock(&registry->lock);
         serviceReference_getServiceRegistration(reference, &registration);
 
         if (serviceRegistration_isValid(registration)) {
@@ -501,11 +537,11 @@ celix_status_t serviceRegistry_getService(service_registry_pt registry, bundle_p
         } else {
             *out = NULL; //invalid service registration
         }
-        celixThreadRwlock_unlock(&registry->lock);
     } else {
         serviceRegistry_logIllegalReference(registry, reference, refStatus);
         status = CELIX_BUNDLE_EXCEPTION;
     }
+    celixThreadRwlock_unlock(&registry->lock);
 
 	return status;
 }
@@ -518,7 +554,9 @@ celix_status_t serviceRegistry_ungetService(service_registry_pt registry, bundle
     celix_status_t subStatus = CELIX_SUCCESS;
     reference_status_t refStatus;
 
+    celixThreadRwlock_readLock(&registry->lock);
     serviceRegistry_checkReference(registry, reference, &refStatus);
+    celixThreadRwlock_unlock(&registry->lock);
 
     if (refStatus == REF_ACTIVE) {
         subStatus = serviceReference_decreaseUsage(reference, &count);

http://git-wip-us.apache.org/repos/asf/celix/blob/eae936a3/framework/public/include/service_reference.h
----------------------------------------------------------------------
diff --git a/framework/public/include/service_reference.h b/framework/public/include/service_reference.h
index b99359e..f6cb9e5 100644
--- a/framework/public/include/service_reference.h
+++ b/framework/public/include/service_reference.h
@@ -48,5 +48,6 @@ FRAMEWORK_EXPORT celix_status_t serviceReference_equals(service_reference_pt ref
 FRAMEWORK_EXPORT unsigned int serviceReference_hashCode(void *referenceP);
 FRAMEWORK_EXPORT int serviceReference_equals2(void *reference1, void *reference2);
 FRAMEWORK_EXPORT celix_status_t serviceReference_compareTo(service_reference_pt reference, service_reference_pt compareTo, int *compare);
+FRAMEWORK_EXPORT celix_status_t serviceReference_getUsingBundles(service_reference_pt ref, array_list_pt *out);
 
 #endif /* SERVICE_REFERENCE_H_ */