"Fossies" - the Fresh Open Source Software archive

Member "evolution-brutus-1.2.35/server/brutus_debug.c" of archive evolution-brutus-1.2.35.tar.gz:


/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/*
 *    Brutus debug variable initialization
 *    Copyright (C) 2007 OMC Denmark ApS.
 *
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 2 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <glib.h>
#include <glib/gstdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <unistd.h>
#include <string.h>
#include <semaphore.h>
#include <fcntl.h>
#include <errno.h>
#include <pthread.h>

#include <server/brutus_corba.h>
#include <server/brutus_util.h>
#include <log/brutus-logd.h>
#include <log/brutus-log.h>

#include "brutus.h"

#ifdef BRUTUS_DEBUG

static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static char *fifo_file_path = NULL;
static char *do_debug_file = NULL;
static int log_fifo = -1;

/**********************
 *  Helper functions  *
 **********************/

static inline int
open_fifo(const char *fifo)
{
	if (!fifo)
		return -1;

	return g_open(fifo, O_WRONLY, S_IRUSR | S_IWUSR);
}

/*******************************************
 *  Init/destroy the log daemon framework  *
 ******************************************/

/* start the logging framework */
static void
init_log(void)
{
	while (pthread_mutex_trylock(&mutex))
		g_usleep(10);

	if (!fifo_file_path)
		fifo_file_path = g_strconcat(getenv("HOME"), "/", BRUTUS_LOGD_FIFO_FILE_NAME, NULL);

	brutus_start_daemon(E_BRUTUS_LOG_DAEMON);

	// check and maybe wait for 1 second for the log daemon to start
	if (!g_file_test(fifo_file_path, G_FILE_TEST_EXISTS))
		g_usleep(G_USEC_PER_SEC);

	if (-1 == log_fifo)
		log_fifo = open_fifo(fifo_file_path);

	pthread_mutex_unlock(&mutex);
}

/* stop the logging framework */
static void
fini_log(void)
{
	while (pthread_mutex_trylock(&mutex))
		g_usleep(10);

	if (-1 != log_fifo) {
		close(log_fifo);
		log_fifo = -1;
	}

	pthread_mutex_unlock(&mutex);
}

/* total restart of logging framework - should be invoked in case of CORBA exceptions */
static void
restart_log(void)
{
	fini_log();

	/* ensure that a fresh log daemon is up and running */
	brutus_kill_daemon(E_BRUTUS_LOG_DAEMON);

	init_log();
}


/*******************************
 *  Commits to the log daemon  *
 ******************************/

static gboolean
commit_to_log(char log_entry[])
{
	if (!log_entry)
		return FALSE;

	while (pthread_mutex_trylock(&mutex))
		g_usleep(10);
	if (!do_debug_file)
		do_debug_file = g_strconcat(getenv("HOME"), "/", BRUTUS_DO_DEBUG_FILE_NAME, NULL);
	pthread_mutex_unlock(&mutex);
	if (!g_file_test(do_debug_file, G_FILE_TEST_EXISTS))
		goto out;

	// do not overfill the buffer
	if (BRUTUS_LOGD_FIFO_MAX_BUF < (sizeof(char) * strlen(log_entry)))
		log_entry[BRUTUS_LOGD_FIFO_MAX_BUF] = '\0';

	init_log();

	// do not write the terminating null character
	if (-1 == write(log_fifo, log_entry, (sizeof(char) * strlen(log_entry)))) {
		restart_log();
		if (-1 == write(log_fifo, log_entry, (sizeof(char) * strlen(log_entry))))
			; // to avoid compiler warning
	}
	fflush(NULL);

	fini_log();

out:
	g_free(log_entry);

	return FALSE;
}


/*********************************
 *  Macro wrapped log functions  *
 ********************************/

void
brutus_DRAW(const char *dbg_msg)
{
	if (!dbg_msg)
		return;

	commit_to_log(g_strdup(dbg_msg));
}

void
brutus_print_orbit2_ex(const int line,
		       const char *file,
		       const char *function,
		       const CORBA_Environment *ev)
{
	char time_buf[26] = { '\0' };
	gchar *log_entry = NULL;
	time_t cur_time;
	struct tm gmt;

	if (!ev)
		return;

	time(&cur_time);
	gmtime_r(&cur_time, &gmt);
	asctime_r(&gmt, time_buf);
	g_strchomp(time_buf);

	switch (ev->_major) {
	case CORBA_NO_EXCEPTION :
		log_entry = g_strdup_printf(DEBUG_PREFIX" [%s] %s(%d) %s() - No exception\n",
					    time_buf, file, line, function);
		break;
	case CORBA_USER_EXCEPTION :
		log_entry = g_strdup_printf(DEBUG_PREFIX" [%s] %s(%d) %s() - User Exception : %s\n",
					    time_buf, file, line, function, CORBA_exception_id((CORBA_Environment*)ev));
		break;
	case CORBA_SYSTEM_EXCEPTION :
		log_entry = g_strdup_printf(DEBUG_PREFIX" [%s] %s(%d) %s() - System Exception : %s\n",
					    time_buf, file, line, function, CORBA_exception_id((CORBA_Environment*)ev));
		break;
	default :
		break;
	}

	if (log_entry) 
		commit_to_log(log_entry);
}

void
brutus_print_if_orbit2_ex(const int line,
			  const char *file,
			  const char *function,
			  const CORBA_Environment *ev)
{
	char time_buf[26] = { '\0' };
	gchar *log_entry = NULL;
	time_t cur_time;
	struct tm gmt;

	if (!ev || (CORBA_NO_EXCEPTION == ev->_major))
		return;

	time(&cur_time);
	gmtime_r(&cur_time, &gmt);
	asctime_r(&gmt, time_buf);
	g_strchomp(time_buf);

	switch (ev->_major) {
	case CORBA_USER_EXCEPTION :
		log_entry = g_strdup_printf(DEBUG_PREFIX" [%s] %s(%d) %s() - User Exception : %s\n",
					    time_buf, file, line, function, CORBA_exception_id((CORBA_Environment*)ev));
		break;
	case CORBA_SYSTEM_EXCEPTION :
		log_entry = g_strdup_printf(DEBUG_PREFIX" [%s] %s(%d) %s() - System Exception : %s\n",
					    time_buf, file, line, function, CORBA_exception_id((CORBA_Environment*)ev));
		break;
	default :
		log_entry = g_strdup_printf(DEBUG_PREFIX" [%s] %s(%d) %s() - Unknown CORBA Exception : %s\n",
					    time_buf, file, line, function, CORBA_exception_id((CORBA_Environment*)ev));
		break;
	}

	if (log_entry) 
		commit_to_log(log_entry);
}

void
brutus_D(const int line,
	 const char *file,
	 const char *function,
	 const char *dbg_msg)
{
	char time_buf[26] = { '\0' };
	gchar *log_entry = NULL;
	time_t cur_time;
	struct tm gmt;

	if (!dbg_msg)
		return;

	time(&cur_time);
	gmtime_r(&cur_time, &gmt);
	asctime_r(&gmt, time_buf);
	g_strchomp(time_buf);

	log_entry = g_strdup_printf(DEBUG_PREFIX" [%s] %s(%d) %s() - %s\n",
				    time_buf, file, line, function, dbg_msg);
	if (log_entry) 
		commit_to_log(log_entry);
}

void
brutus_DBT(const int line,
	   const char *file,
	   const char *function)
{
	char time_buf[26] = { '\0' };
	char *log_entry = NULL;
	time_t cur_time;
	struct tm gmt;
	void *array[20];
	size_t size;
	size_t i;
	char **strings;

	time(&cur_time);
	gmtime_r(&cur_time, &gmt);
	asctime_r(&gmt, time_buf);
	g_strchomp(time_buf);

	size = backtrace(array, 20);
	strings = backtrace_symbols(array, size);
	log_entry = (char*)g_strdup_printf(DEBUG_PREFIX" [%s] %s(%d) %s() - %s\n\n",
					   time_buf, file, line, function, "Printing stack backtrace..");
	for (i = 0; i < size; i++)
		brutus_append_to_string(&log_entry,"\t%s\n", strings[i]);
	free(strings);

	if (log_entry) 
		commit_to_log(log_entry);
}

void 
brutus_decode_ior(const char *ior_str)
{
#ifdef HAVE_IOR_DECODE_2
	int status;
	gchar *std_out = NULL;
	gchar *std_err = NULL;
	char *argv[] = {
		"/usr/bin/ior-decode-2",
		(char *)ior_str,
		NULL,
	};

	g_spawn_sync(NULL,
		     argv,
		     NULL,
		     0,
		     NULL,
		     NULL,
		     &std_out,
		     &std_err,
		     &status,
		     NULL);
	d(std_out);
	d(std_err);

	g_free(std_out);
	g_free(std_err);
#endif
}


#endif // BRUTUS_DEBUG