blob: 2ada02fd8110cadf7daf8a1247a05432afcfae18 [file] [log] [blame]
/**
*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.
*/
/*
* activator.c
*
* \date Sep 29, 2011
* \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
* \copyright Apache License, Version 2.0
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include "bundle_activator.h"
#include "log_service.h"
typedef log_service_pt LOG_SERVICE;
struct threadData {
char * service;
int threadId;
bundle_context_pt m_context;
bool running;
};
typedef struct threadData *thread_data_pt;
static celix_thread_t m_logTestThread;
//*******************************************************************************
// function prototypes
//*******************************************************************************
void startTestThread(thread_data_pt data);
void stopTestThread();
void pauseTestThread();
void alternativeLog(char *message, thread_data_pt data);
//*******************************************************************************
// global functions
//*******************************************************************************
celix_status_t bundleActivator_create(bundle_context_pt context, void **userData) {
celix_status_t status = CELIX_SUCCESS;
*userData = calloc(1, sizeof(struct threadData));
if (!userData) {
status = CELIX_ENOMEM;
} else {
((thread_data_pt) (*userData))->service = "chapter04-correct-lookup";
((thread_data_pt) (*userData))->threadId = 0;
((thread_data_pt) (*userData))->m_context = context;
((thread_data_pt) (*userData))->running = false;
}
return status;
}
celix_status_t bundleActivator_start(void * userData, bundle_context_pt context) {
thread_data_pt thread_data = (thread_data_pt) userData;
thread_data->m_context = context;
thread_data->running = true;
startTestThread(thread_data);
return CELIX_SUCCESS;
}
celix_status_t bundleActivator_stop(void * userData, bundle_context_pt context) {
thread_data_pt thread_data = (thread_data_pt) userData;
thread_data->running = false;
stopTestThread();
return CELIX_SUCCESS;
}
celix_status_t bundleActivator_destroy(void * userData, bundle_context_pt context) {
free(userData);
return CELIX_SUCCESS;
}
//------------------------------------------------------------------------------------------
// The rest of this is just support code, not meant to show any particular best practices
//------------------------------------------------------------------------------------------
// Test LogService by periodically sending a message
static void* LogServiceTest(void* argument) {
celix_status_t status = CELIX_SUCCESS;
thread_data_pt data = (thread_data_pt) argument;
bundle_context_pt m_context = data ->m_context;
while (data->running == true) {
service_reference_pt logServiceRef = NULL;
// lookup the current "best" LogService each time, just before we need to use it
status = bundleContext_getServiceReference(m_context, (char *) OSGI_LOGSERVICE_NAME, &logServiceRef);
// if the service reference is null then we know there's no log service available
if (status == CELIX_SUCCESS && logServiceRef != NULL) {
void *log = NULL;
LOG_SERVICE logService = NULL;
bundleContext_getService(m_context, logServiceRef, &log);
logService = (LOG_SERVICE) log;
// if the dereferenced instance is null then we know the service has been removed
if (logService != NULL) {
(*(logService->log))(logService->logger, OSGI_LOGSERVICE_INFO, "ping");
} else {
alternativeLog("LogService has gone", data);
}
} else {
alternativeLog("LogService has gone", data);
}
pauseTestThread();
}
return NULL;
}
void startTestThread(thread_data_pt data) {
// start separate worker thread to run the actual tests, managed by the bundle lifecycle
data->threadId++;
celixThread_create(&m_logTestThread, NULL, LogServiceTest, data);
}
void stopTestThread() {
celixThread_join(m_logTestThread, NULL);
}
void pauseTestThread() {
// sleep for a bit
sleep(5);
}
void alternativeLog(char *message, thread_data_pt data) {
// this provides similar style debug logging output for when the LogService disappears
celix_status_t status = CELIX_SUCCESS;
bundle_pt bundle = NULL;
char tid[20], bid[20];
long bundleId;
if (data->m_context != NULL) {
status = bundleContext_getBundle(data->m_context, &bundle);
if (status == CELIX_SUCCESS) {
status = bundle_getBundleId(bundle, &bundleId);
if (status == CELIX_SUCCESS) {
sprintf(tid, "thread=%d", data->threadId);
sprintf(bid, "bundle=%ld", bundleId);
printf("<--> %s, %s : %s\n", tid, bid, message);
} else {
printf("%s:%s:%d:getBundleId failed: %s\n", __FILE__, __FUNCTION__, __LINE__, message);
}
} else {
printf("%s:%s:%d:getBundle failed: %s\n", __FILE__, __FUNCTION__, __LINE__, message);
}
} else {
printf("%s:%s:%d:bundle context NULL: %s\n", __FILE__, __FUNCTION__, __LINE__, message);
}
}