incubator-celix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From abroekh...@apache.org
Subject svn commit: r1370759 - in /incubator/celix/trunk/framework: private/src/bundle_context.c private/src/framework.c public/include/bundle_context.h public/include/bundle_event.h public/include/bundle_listener.h public/include/framework.h
Date Wed, 08 Aug 2012 13:39:27 GMT
Author: abroekhuis
Date: Wed Aug  8 13:39:26 2012
New Revision: 1370759

URL: http://svn.apache.org/viewvc?rev=1370759&view=rev
Log:
Added bundle listener

Added:
    incubator/celix/trunk/framework/public/include/bundle_event.h
    incubator/celix/trunk/framework/public/include/bundle_listener.h
Modified:
    incubator/celix/trunk/framework/private/src/bundle_context.c
    incubator/celix/trunk/framework/private/src/framework.c
    incubator/celix/trunk/framework/public/include/bundle_context.h
    incubator/celix/trunk/framework/public/include/framework.h

Modified: incubator/celix/trunk/framework/private/src/bundle_context.c
URL: http://svn.apache.org/viewvc/incubator/celix/trunk/framework/private/src/bundle_context.c?rev=1370759&r1=1370758&r2=1370759&view=diff
==============================================================================
--- incubator/celix/trunk/framework/private/src/bundle_context.c (original)
+++ incubator/celix/trunk/framework/private/src/bundle_context.c Wed Aug  8 13:39:26 2012
@@ -278,6 +278,30 @@ celix_status_t bundleContext_removeServi
     return status;
 }
 
+celix_status_t bundleContext_addBundleListener(BUNDLE_CONTEXT context, bundle_listener_t
listener) {
+    celix_status_t status = CELIX_SUCCESS;
+
+    if (context != NULL && listener != NULL) {
+        fw_addBundleListener(context->framework, context->bundle, listener);
+    } else {
+        status = CELIX_ILLEGAL_ARGUMENT;
+    }
+
+    return status;
+}
+
+celix_status_t bundleContext_removeBundleListener(BUNDLE_CONTEXT context, bundle_listener_t
listener) {
+    celix_status_t status = CELIX_SUCCESS;
+
+    if (context != NULL && listener != NULL) {
+        fw_removeBundleListener(context->framework, context->bundle, listener);
+    } else {
+        status = CELIX_ILLEGAL_ARGUMENT;
+    }
+
+    return status;
+}
+
 celix_status_t bundleContext_getProperty(BUNDLE_CONTEXT context, const char *name, char **value)
{
 	celix_status_t status = CELIX_SUCCESS;
 

Modified: incubator/celix/trunk/framework/private/src/framework.c
URL: http://svn.apache.org/viewvc/incubator/celix/trunk/framework/private/src/framework.c?rev=1370759&r1=1370758&r2=1370759&view=diff
==============================================================================
--- incubator/celix/trunk/framework/private/src/framework.c (original)
+++ incubator/celix/trunk/framework/private/src/framework.c Wed Aug  8 13:39:26 2012
@@ -65,6 +65,7 @@ struct framework {
 	HASH_MAP installedBundleMap;
 	HASH_MAP installRequestMap;
 	ARRAY_LIST serviceListeners;
+	ARRAY_LIST bundleListeners;
 
 	long nextBundleId;
 	struct serviceRegistry * registry;
@@ -87,6 +88,11 @@ struct framework {
 	apr_pool_t *mp;
 
 	PROPERTIES configurationMap;
+
+	ARRAY_LIST requests;
+	apr_thread_cond_t *dispatcher;
+	apr_thread_mutex_t *dispatcherLock;
+	apr_thread_t *dispatcherThread;
 };
 
 struct activator {
@@ -117,6 +123,10 @@ celix_status_t fw_refreshBundle(FRAMEWOR
 
 celix_status_t fw_populateDependentGraph(FRAMEWORK framework, BUNDLE exporter, HASH_MAP *map);
 
+celix_status_t fw_fireBundleEvent(FRAMEWORK framework, bundle_event_type_e, BUNDLE bundle);
+static void *APR_THREAD_FUNC fw_eventDispatcher(apr_thread_t *thd, void *fw);
+celix_status_t fw_invokeBundleListener(FRAMEWORK framework, bundle_listener_t listener, bundle_event_t
event, BUNDLE bundle);
+
 struct fw_refreshHelper {
     FRAMEWORK framework;
     BUNDLE bundle;
@@ -135,6 +145,33 @@ struct fw_serviceListener {
 
 typedef struct fw_serviceListener * FW_SERVICE_LISTENER;
 
+struct fw_bundleListener {
+	apr_pool_t *pool;
+	BUNDLE bundle;
+	bundle_listener_t listener;
+};
+
+typedef struct fw_bundleListener * fw_bundle_listener_t;
+
+enum event_type {
+	FRAMEWORK_EVENT_TYPE,
+	BUNDLE_EVENT_TYPE,
+	EVENT_TYPE_SERVICE,
+};
+
+typedef enum event_type event_type_e;
+
+struct request {
+	event_type_e type;
+	ARRAY_LIST listeners;
+
+	int eventType;
+	BUNDLE bundle;
+
+	char *filter;
+};
+
+typedef struct request *request_t;
 
 celix_status_t framework_create(FRAMEWORK *framework, apr_pool_t *memoryPool, PROPERTIES
config) {
     celix_status_t status = CELIX_SUCCESS;
@@ -173,27 +210,39 @@ celix_status_t framework_create(FRAMEWOR
                                 if (apr_status != APR_SUCCESS) {
                                     status = CELIX_FRAMEWORK_EXCEPTION;
                                 } else {
-                                    (*framework)->bundle = bundle;
-
-                                    (*framework)->installedBundleMap = NULL;
-                                    (*framework)->registry = NULL;
-
-                                    (*framework)->interrupted = false;
-                                    (*framework)->shutdown = false;
-
-                                    (*framework)->globalLockWaitersList = NULL;
-                                    arrayList_create((*framework)->mp, &(*framework)->globalLockWaitersList);
-                                    (*framework)->globalLockCount = 0;
-                                    (*framework)->globalLockThread = 0;
-                                    (*framework)->nextBundleId = 1l;
-                                    (*framework)->cache = NULL;
-
-                                    (*framework)->installRequestMap = hashMap_create(string_hash,
string_hash, string_equals, string_equals);
-                                    (*framework)->serviceListeners = NULL;
-                                    (*framework)->shutdownGate = NULL;
-                                    (*framework)->configurationMap = config;
-
-                                    status = bundle_setFramework((*framework)->bundle,
(*framework));
+                                	apr_status_t apr_status = apr_thread_mutex_create(&(*framework)->dispatcherLock,
APR_THREAD_MUTEX_UNNESTED, (*framework)->mp);
+                                	if (apr_status != CELIX_SUCCESS) {
+										status = CELIX_FRAMEWORK_EXCEPTION;
+									} else {
+										apr_status_t apr_status = apr_thread_cond_create(&(*framework)->dispatcher,
(*framework)->mp);
+										if (apr_status != APR_SUCCESS) {
+											status = CELIX_FRAMEWORK_EXCEPTION;
+										} else {
+											(*framework)->bundle = bundle;
+
+											(*framework)->installedBundleMap = NULL;
+											(*framework)->registry = NULL;
+
+											(*framework)->interrupted = false;
+											(*framework)->shutdown = false;
+
+											(*framework)->globalLockWaitersList = NULL;
+											arrayList_create((*framework)->mp, &(*framework)->globalLockWaitersList);
+											(*framework)->globalLockCount = 0;
+											(*framework)->globalLockThread = 0;
+											(*framework)->nextBundleId = 1l;
+											(*framework)->cache = NULL;
+
+											(*framework)->installRequestMap = hashMap_create(string_hash, string_hash,
string_equals, string_equals);
+											(*framework)->serviceListeners = NULL;
+											(*framework)->bundleListeners = NULL;
+											(*framework)->requests = NULL;
+											(*framework)->shutdownGate = NULL;
+											(*framework)->configurationMap = config;
+
+											status = bundle_setFramework((*framework)->bundle, (*framework));
+										}
+									}
                                 }
                             }
                         }
@@ -244,6 +293,8 @@ celix_status_t framework_destroy(FRAMEWO
 
 	arrayList_destroy(framework->globalLockWaitersList);
 	arrayList_destroy(framework->serviceListeners);
+	arrayList_destroy(framework->bundleListeners);
+	arrayList_destroy(framework->requests);
 
 	hashMap_destroy(framework->installedBundleMap, false, false);
 
@@ -266,6 +317,12 @@ celix_status_t fw_init(FRAMEWORK framewo
 		return status;
 	}
 
+	framework->requests = NULL;
+	arrayList_create(framework->mp, &framework->requests);
+	if (apr_thread_create(&framework->dispatcherThread, NULL, fw_eventDispatcher, framework,
framework->mp) != APR_SUCCESS) {
+		return CELIX_FRAMEWORK_EXCEPTION;
+	}
+
 	bundle_getState(framework->bundle, &state);
 	if ((state == BUNDLE_INSTALLED) || (state == BUNDLE_RESOLVED)) {
 	    PROPERTIES props = properties_create();
@@ -391,6 +448,11 @@ celix_status_t fw_init(FRAMEWORK framewo
 
             framework->serviceListeners = NULL;
             arrayList_create(framework->mp, &framework->serviceListeners);
+            framework->bundleListeners = NULL;
+            arrayList_create(framework->mp, &framework->bundleListeners);
+            framework->requests = NULL;
+            arrayList_create(framework->mp, &framework->requests);
+
             framework_releaseBundleLock(framework, framework->bundle);
 
             status = CELIX_SUCCESS;
@@ -422,6 +484,7 @@ celix_status_t framework_start(FRAMEWORK
 	}
 
 	framework_releaseBundleLock(framework, framework->bundle);
+
 	return CELIX_SUCCESS;
 }
 
@@ -690,6 +753,8 @@ celix_status_t fw_startBundle(FRAMEWORK 
                 }
 
                 framework_setBundleStateAndNotify(framework, bundle, BUNDLE_ACTIVE);
+
+                fw_fireBundleEvent(framework, BUNDLE_EVENT_STARTED, bundle);
 			}
 
 			break;
@@ -874,14 +939,14 @@ celix_status_t fw_uninstallBundle(FRAMEW
             }
 
             framework_setBundleStateAndNotify(framework, bundle, BUNDLE_INSTALLED);
-            // TODO: fw_fireBundleEvent(framework BUNDLE_EVENT_UNRESOLVED, bundle);
+            fw_fireBundleEvent(framework, BUNDLE_EVENT_UNRESOLVED, bundle);
 
             framework_setBundleStateAndNotify(framework, bundle, BUNDLE_UNINSTALLED);
             status = bundleArchive_setLastModified(archive, time(NULL));
         }
         framework_releaseBundleLock(framework, bundle);
 
-        // TODO: fw_fireBundleEvent(framework BUNDLE_EVENT_UNINSTALLED, bundle);
+        fw_fireBundleEvent(framework, BUNDLE_EVENT_UNINSTALLED, bundle);
 
         locked = framework_acquireGlobalLock(framework);
         if (locked) {
@@ -1320,6 +1385,44 @@ void fw_removeServiceListener(FRAMEWORK 
 	}
 }
 
+celix_status_t fw_addBundleListener(FRAMEWORK framework, BUNDLE bundle, bundle_listener_t
listener) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	apr_pool_t *pool = NULL;
+	fw_bundle_listener_t bundleListener = NULL;
+
+	apr_pool_create(&pool, framework->mp);
+	bundleListener = apr_palloc(pool, sizeof(*bundleListener));
+	if (!bundleListener) {
+		status = CELIX_ENOMEM;
+	} else {
+		bundleListener->listener = listener;
+		bundleListener->bundle = bundle;
+		bundleListener->pool = pool;
+
+		arrayList_add(framework->bundleListeners, bundleListener);
+	}
+
+	return status;
+}
+
+celix_status_t fw_removeBundleListener(FRAMEWORK framework, BUNDLE bundle, bundle_listener_t
listener) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	int i;
+	fw_bundle_listener_t bundleListener;
+
+	for (i = 0; i < arrayList_size(framework->bundleListeners); i++) {
+		bundleListener = (fw_bundle_listener_t) arrayList_get(framework->bundleListeners, i);
+		if (bundleListener->listener == listener && bundleListener->bundle == bundle)
{
+			arrayList_remove(framework->bundleListeners, i);
+			apr_pool_destroy(bundleListener->pool);
+		}
+	}
+
+	return status;
+}
+
 void fw_serviceChanged(FRAMEWORK framework, SERVICE_EVENT_TYPE eventType, SERVICE_REGISTRATION
registration, PROPERTIES oldprops) {
 	unsigned int i;
 	FW_SERVICE_LISTENER element;
@@ -1782,6 +1885,105 @@ celix_status_t framework_getFrameworkBun
 	return status;
 }
 
+celix_status_t fw_fireBundleEvent(FRAMEWORK framework, bundle_event_type_e eventType, BUNDLE
bundle) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	if ((eventType != BUNDLE_EVENT_STARTING)
+			&& (eventType != BUNDLE_EVENT_STOPPING)
+			&& (eventType != BUNDLE_EVENT_LAZY_ACTIVATION)) {
+		request_t request = malloc(sizeof(*request));
+		if (!request) {
+			status = CELIX_ENOMEM;
+		} else {
+			request->bundle = bundle;
+			request->eventType = eventType;
+			request->filter = NULL;
+			request->listeners = framework->bundleListeners;
+			request->type = BUNDLE_EVENT_TYPE;
+
+			arrayList_add(framework->requests, request);
+			if (apr_thread_mutex_lock(framework->dispatcherLock != APR_SUCCESS)) {
+				status = CELIX_FRAMEWORK_EXCEPTION;
+			} else {
+				if (apr_thread_cond_broadcast(framework->dispatcher)) {
+					status = CELIX_FRAMEWORK_EXCEPTION;
+				} else {
+					if (apr_thread_mutex_unlock(framework->dispatcherLock)) {
+						status = CELIX_FRAMEWORK_EXCEPTION;
+					}
+				}
+			}
+		}
+	}
+
+	return status;
+}
+
+static void *APR_THREAD_FUNC fw_eventDispatcher(apr_thread_t *thd, void *fw) {
+	FRAMEWORK framework = (FRAMEWORK) fw;
+	request_t request = NULL;
+
+	while (true) {
+		if (apr_thread_mutex_lock(framework->dispatcherLock) != 0) {
+			celix_log("Error locking the dispatcher");
+			return NULL;
+		}
+
+		int size = arrayList_size(framework->requests);
+		while (size == 0 && !framework->shutdown) {
+			apr_status_t apr_status = apr_thread_cond_wait(framework->dispatcher, framework->dispatcherLock);
+			// Ignore status and just keep waiting
+			size = arrayList_size(framework->requests);
+		}
+
+		if (size == 0 && framework->shutdown) {
+			apr_thread_exit(thd, APR_SUCCESS);
+			return NULL;
+		}
+
+		request = arrayList_remove(framework->requests, 0);
+
+		apr_status_t status;
+		if ((status = apr_thread_mutex_unlock(framework->dispatcherLock)) != 0) {
+			celix_log("Error unlocking the dispatcher.");
+			apr_thread_exit(thd, status);
+			return NULL;
+		}
+
+		if (request != NULL) {
+			int i;
+			int size = arrayList_size(request->listeners);
+			for (i = 0; i < size; i++) {
+				if (request->type == BUNDLE_EVENT_TYPE) {
+					fw_bundle_listener_t listener = arrayList_get(request->listeners, i);
+					bundle_event_t event = apr_palloc(listener->listener->pool, sizeof(*event));
+					event->bundle = request->bundle;
+					event->type = request->type;
+
+					fw_invokeBundleListener(framework, listener->listener, event, listener->bundle);
+				}
+			}
+		}
+	}
+
+	apr_thread_exit(thd, APR_SUCCESS);
+
+	return NULL;
+
+}
+
+celix_status_t fw_invokeBundleListener(FRAMEWORK framework, bundle_listener_t listener, bundle_event_t
event, BUNDLE bundle) {
+	// We only support async bundle listeners for now
+	BUNDLE_STATE state;
+	bundle_getState(bundle, &state);
+	if (state == BUNDLE_STARTING || state == BUNDLE_ACTIVE) {
+
+		listener->bundleChanged(listener, event);
+	}
+
+	return CELIX_SUCCESS;
+}
+
 celix_status_t bundleActivator_start(void * userData, BUNDLE_CONTEXT context) {
 	// nothing to do
 	return CELIX_SUCCESS;

Modified: incubator/celix/trunk/framework/public/include/bundle_context.h
URL: http://svn.apache.org/viewvc/incubator/celix/trunk/framework/public/include/bundle_context.h?rev=1370759&r1=1370758&r2=1370759&view=diff
==============================================================================
--- incubator/celix/trunk/framework/public/include/bundle_context.h (original)
+++ incubator/celix/trunk/framework/public/include/bundle_context.h Wed Aug  8 13:39:26 2012
@@ -35,6 +35,7 @@ typedef struct bundleContext *BUNDLE_CON
 
 #include "service_factory.h"
 #include "service_listener.h"
+#include "bundle_listener.h"
 #include "properties.h"
 #include "array_list.h"
 
@@ -65,6 +66,9 @@ celix_status_t bundleContext_getBundleBy
 celix_status_t bundleContext_addServiceListener(BUNDLE_CONTEXT context, SERVICE_LISTENER
listener, char * filter);
 celix_status_t bundleContext_removeServiceListener(BUNDLE_CONTEXT context, SERVICE_LISTENER
listener);
 
+celix_status_t bundleContext_addBundleListener(BUNDLE_CONTEXT context, bundle_listener_t
listener);
+celix_status_t bundleContext_removeBundleListener(BUNDLE_CONTEXT context, bundle_listener_t
listener);
+
 celix_status_t bundleContext_getProperty(BUNDLE_CONTEXT context, const char *name, char **value);
 
 #endif /* BUNDLE_CONTEXT_H_ */

Added: incubator/celix/trunk/framework/public/include/bundle_event.h
URL: http://svn.apache.org/viewvc/incubator/celix/trunk/framework/public/include/bundle_event.h?rev=1370759&view=auto
==============================================================================
--- incubator/celix/trunk/framework/public/include/bundle_event.h (added)
+++ incubator/celix/trunk/framework/public/include/bundle_event.h Wed Aug  8 13:39:26 2012
@@ -0,0 +1,35 @@
+/*
+ * bundle_event.h
+ *
+ *  Created on: Jun 28, 2012
+ *      Author: alexander
+ */
+
+#ifndef BUNDLE_EVENT_H_
+#define BUNDLE_EVENT_H_
+
+typedef enum bundle_event_type bundle_event_type_e;
+typedef struct bundle_event *bundle_event_t;
+
+#include "service_reference.h"
+
+enum bundle_event_type
+{
+	BUNDLE_EVENT_INSTALLED = 0x00000001,
+	BUNDLE_EVENT_STARTED = 0x00000002,
+	BUNDLE_EVENT_STOPPED = 0x00000004,
+	BUNDLE_EVENT_UPDATED = 0x00000008,
+	BUNDLE_EVENT_UNINSTALLED = 0x00000010,
+	BUNDLE_EVENT_RESOLVED = 0x00000020,
+	BUNDLE_EVENT_UNRESOLVED = 0x00000040,
+	BUNDLE_EVENT_STARTING = 0x00000080,
+	BUNDLE_EVENT_STOPPING = 0x00000100,
+	BUNDLE_EVENT_LAZY_ACTIVATION = 0x00000200,
+};
+
+struct bundle_event {
+	BUNDLE bundle;
+	bundle_event_type_e type;
+};
+
+#endif /* BUNDLE_EVENT_H_ */

Added: incubator/celix/trunk/framework/public/include/bundle_listener.h
URL: http://svn.apache.org/viewvc/incubator/celix/trunk/framework/public/include/bundle_listener.h?rev=1370759&view=auto
==============================================================================
--- incubator/celix/trunk/framework/public/include/bundle_listener.h (added)
+++ incubator/celix/trunk/framework/public/include/bundle_listener.h Wed Aug  8 13:39:26 2012
@@ -0,0 +1,51 @@
+/*
+ *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.
+ */
+/**
+ *
+ * @defgroup BundleListener Bundle Listener
+ * @ingroup framework
+ * @{
+ *
+ *  \author    	Alexander Broekhuis
+ *  \date      	June 28, 2012
+ *  \copyright	Apache License, Version 2.0
+ */
+#ifndef BUNDLE_LISTENER_H_
+#define BUNDLE_LISTENER_H_
+
+#include <apr_general.h>
+
+typedef struct bundle_listener *bundle_listener_t;
+
+#include "celix_errno.h"
+#include "bundle_event.h"
+
+struct bundle_listener {
+	apr_pool_t *pool;
+	void * handle;
+	celix_status_t (*bundleChanged)(void * listener, bundle_event_t event);
+};
+
+
+
+#endif /* SERVICE_LISTENER_H_ */
+
+/**
+ * @}
+ */

Modified: incubator/celix/trunk/framework/public/include/framework.h
URL: http://svn.apache.org/viewvc/incubator/celix/trunk/framework/public/include/framework.h?rev=1370759&r1=1370758&r2=1370759&view=diff
==============================================================================
--- incubator/celix/trunk/framework/public/include/framework.h (original)
+++ incubator/celix/trunk/framework/public/include/framework.h Wed Aug  8 13:39:26 2012
@@ -37,6 +37,7 @@ typedef struct framework * FRAMEWORK;
 #include "service_factory.h"
 #include "bundle_archive.h"
 #include "service_listener.h"
+#include "bundle_listener.h"
 #include "service_registration.h"
 #include "bundle_context.h"
 
@@ -70,6 +71,10 @@ celix_status_t fw_getBundleServicesInUse
 
 void fw_addServiceListener(FRAMEWORK framework, BUNDLE bundle, SERVICE_LISTENER listener,
char * filter);
 void fw_removeServiceListener(FRAMEWORK framework, BUNDLE bundle, SERVICE_LISTENER listener);
+
+celix_status_t fw_addBundleListener(FRAMEWORK framework, BUNDLE bundle, bundle_listener_t
listener);
+celix_status_t fw_removeBundleListener(FRAMEWORK framework, BUNDLE bundle, bundle_listener_t
listener);
+
 void fw_serviceChanged(FRAMEWORK framework, SERVICE_EVENT_TYPE eventType, SERVICE_REGISTRATION
registration, PROPERTIES oldprops);
 
 celix_status_t fw_isServiceAssignable(FRAMEWORK fw, BUNDLE requester, SERVICE_REFERENCE reference,
bool *assignable);



Mime
View raw message