Return-Path: X-Original-To: apmail-incubator-celix-commits-archive@minotaur.apache.org Delivered-To: apmail-incubator-celix-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 6C4189C8C for ; Wed, 8 Aug 2012 13:40:28 +0000 (UTC) Received: (qmail 336 invoked by uid 500); 8 Aug 2012 13:40:28 -0000 Delivered-To: apmail-incubator-celix-commits-archive@incubator.apache.org Received: (qmail 316 invoked by uid 500); 8 Aug 2012 13:40:28 -0000 Mailing-List: contact celix-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: celix-dev@incubator.apache.org Delivered-To: mailing list celix-commits@incubator.apache.org Received: (qmail 305 invoked by uid 99); 8 Aug 2012 13:40:27 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 08 Aug 2012 13:40:27 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 08 Aug 2012 13:40:23 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 8CE262388906; Wed, 8 Aug 2012 13:39:27 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit 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 -0000 To: celix-commits@incubator.apache.org From: abroekhuis@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20120808133927.8CE262388906@eris.apache.org> 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 + +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);