Add support for dynamic debug framework
authorMarcel Holtmann <marcel@holtmann.org>
Wed, 25 Nov 2009 15:54:47 +0000 (16:54 +0100)
committerMarcel Holtmann <marcel@holtmann.org>
Wed, 25 Nov 2009 15:54:47 +0000 (16:54 +0100)
include/log.h
src/connman.h
src/log.c
src/main.c
src/manager.c
test/test-manager

index 0ed8ee2..c48ad9d 100644 (file)
@@ -41,6 +41,21 @@ void connman_error(const char *format, ...)
 void connman_debug(const char *format, ...)
                                __attribute__((format(printf, 1, 2)));
 
+struct connman_debug_desc {
+       const char *name;
+       const char *file;
+#define CONNMAN_DEBUG_FLAG_DEFAULT (0)
+#define CONNMAN_DEBUG_FLAG_PRINT   (1 << 0)
+#define CONNMAN_DEBUG_FLAG_ALIAS   (1 << 1)
+       unsigned int flags;
+} __attribute__((aligned(8)));
+
+#define CONNMAN_DEBUG_DEFINE(name) \
+       static struct connman_debug_desc __debug_alias_ ## name \
+       __attribute__((used, section("__debug"), aligned(8))) = { \
+               #name, __FILE__, CONNMAN_DEBUG_FLAG_ALIAS \
+       };
+
 /**
  * DBG:
  * @fmt: format string
@@ -49,7 +64,15 @@ void connman_debug(const char *format, ...)
  * Simple macro around connman_debug() which also include the function
  * name it is called in.
  */
-#define DBG(fmt, arg...) connman_debug("%s:%s() " fmt, __FILE__, __FUNCTION__ , ## arg)
+#define DBG(fmt, arg...) do { \
+       static struct connman_debug_desc desc \
+       __attribute__((used, section("__debug"), aligned(8))) = { \
+               .file = __FILE__, .flags = CONNMAN_DEBUG_FLAG_DEFAULT, \
+       }; \
+       if (desc.flags & CONNMAN_DEBUG_FLAG_PRINT) \
+               connman_debug("%s:%s() " fmt, \
+                                       __FILE__, __FUNCTION__ , ## arg); \
+} while (0)
 
 #ifdef __cplusplus
 }
index 36a4e46..098bed5 100644 (file)
@@ -75,11 +75,11 @@ int __connman_agent_request_passphrase(struct connman_service *service,
 
 #include <connman/log.h>
 
-int __connman_log_init(gboolean detach, gboolean debug);
+int __connman_log_init(const char *debug, connman_bool_t detach);
 void __connman_log_cleanup(void);
 
-void __connman_toggle_debug(void);
-gboolean __connman_debug_enabled(void);
+void __connman_debug_list_available(DBusMessageIter *iter);
+void __connman_debug_list_enabled(DBusMessageIter *iter);
 
 #include <connman/option.h>
 
index dbc3f7c..5b5f82c 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -28,8 +28,6 @@
 
 #include "connman.h"
 
-static volatile gboolean debug_enabled = FALSE;
-
 /**
  * connman_info:
  * @format: format string
@@ -90,17 +88,11 @@ void connman_error(const char *format, ...)
  * @varargs: list of arguments
  *
  * Output debug message
- *
- * The actual output of the debug message is controlled via a command line
- * switch. If not enabled, these messages will be ignored.
  */
 void connman_debug(const char *format, ...)
 {
        va_list ap;
 
-       if (debug_enabled == FALSE)
-               return;
-
        va_start(ap, format);
 
        vsyslog(LOG_DEBUG, format, ap);
@@ -108,20 +100,81 @@ void connman_debug(const char *format, ...)
        va_end(ap);
 }
 
-void __connman_toggle_debug(void)
+extern struct connman_debug_desc __start___debug[];
+extern struct connman_debug_desc __stop___debug[];
+
+void __connman_debug_list_available(DBusMessageIter *iter)
+{
+       struct connman_debug_desc *desc;
+
+       for (desc = __start___debug; desc < __stop___debug; desc++) {
+               if ((desc->flags & CONNMAN_DEBUG_FLAG_ALIAS) &&
+                                               desc->name != NULL)
+                       dbus_message_iter_append_basic(iter,
+                                       DBUS_TYPE_STRING, &desc->name);
+       }
+}
+
+static gchar **enabled = NULL;
+
+void __connman_debug_list_enabled(DBusMessageIter *iter)
+{
+       int i;
+
+       if (enabled == NULL)
+               return;
+
+       for (i = 0; enabled[i] != NULL; i++)
+               dbus_message_iter_append_basic(iter,
+                                       DBUS_TYPE_STRING, &enabled[i]);
+}
+
+static connman_bool_t is_enabled(struct connman_debug_desc *desc)
 {
-       if (debug_enabled == TRUE) {
-               connman_info("Disabling debug output");
-               debug_enabled = FALSE;
-       } else {
-               connman_info("Enabling debug output");
-               debug_enabled = TRUE;
+       int i;
+
+       if (enabled == NULL)
+               return FALSE;
+
+       for (i = 0; enabled[i] != NULL; i++) {
+               if (desc->name != NULL && g_pattern_match_simple(enabled[i],
+                                                       desc->name) == TRUE)
+                       return TRUE;
+               if (desc->file != NULL && g_pattern_match_simple(enabled[i],
+                                                       desc->file) == TRUE)
+                       return TRUE;
        }
+
+       return FALSE;
 }
 
-int __connman_log_init(gboolean detach, gboolean debug)
+int __connman_log_init(const char *debug, connman_bool_t detach)
 {
        int option = LOG_NDELAY | LOG_PID;
+       struct connman_debug_desc *desc;
+       const char *name = NULL, *file = NULL;
+
+       if (debug != NULL)
+               enabled = g_strsplit_set(debug, ":, ", 0);
+
+       for (desc = __start___debug; desc < __stop___debug; desc++) {
+               if (desc->flags & CONNMAN_DEBUG_FLAG_ALIAS) {
+                       file = desc->file;
+                       name = desc->name;
+                       continue;
+               }
+
+               if (file != NULL || name != NULL) {
+                       if (g_strcmp0(desc->file, file) == 0) {
+                               if (desc->name == NULL)
+                                       desc->name = name;
+                       } else
+                               file = NULL;
+               }
+
+               if (is_enabled(desc) == TRUE)
+                       desc->flags |= CONNMAN_DEBUG_FLAG_PRINT;
+       }
 
        if (detach == FALSE)
                option |= LOG_PERROR;
@@ -130,9 +183,6 @@ int __connman_log_init(gboolean detach, gboolean debug)
 
        syslog(LOG_INFO, "Connection Manager version %s", VERSION);
 
-       if (debug == TRUE)
-               __connman_toggle_debug();
-
        return 0;
 }
 
@@ -141,9 +191,6 @@ void __connman_log_cleanup(void)
        syslog(LOG_INFO, "Exit");
 
        closelog();
-}
 
-gboolean __connman_debug_enabled(void)
-{
-       return debug_enabled;
+       g_strfreev(enabled);
 }
index ef9b017..312b823 100644 (file)
@@ -45,11 +45,6 @@ static void sig_term(int sig)
        g_main_loop_quit(main_loop);
 }
 
-static void sig_debug(int sig)
-{
-       __connman_toggle_debug();
-}
-
 static void disconnect_callback(DBusConnection *conn, void *user_data)
 {
        connman_error("D-Bus disconnect");
@@ -57,6 +52,7 @@ static void disconnect_callback(DBusConnection *conn, void *user_data)
        g_main_loop_quit(main_loop);
 }
 
+static gchar *option_debug = NULL;
 static gchar *option_device = NULL;
 static gchar *option_plugin = NULL;
 static gchar *option_nodevice = NULL;
@@ -64,11 +60,12 @@ static gchar *option_noplugin = NULL;
 static gchar *option_wifi = NULL;
 static gboolean option_detach = TRUE;
 static gboolean option_compat = FALSE;
-static gboolean option_debug = FALSE;
 static gboolean option_selftest = FALSE;
 static gboolean option_version = FALSE;
 
 static GOptionEntry options[] = {
+       { "debug", 'd', 0, G_OPTION_ARG_STRING, &option_debug,
+                               "Specify debug options to enable", "DEBUG" },
        { "device", 'i', 0, G_OPTION_ARG_STRING, &option_device,
                        "Specify networking device or interface", "DEV" },
        { "nodevice", 'I', 0, G_OPTION_ARG_STRING, &option_nodevice,
@@ -84,8 +81,6 @@ static GOptionEntry options[] = {
                                "Don't fork daemon to background" },
        { "compat", 'c', 0, G_OPTION_ARG_NONE, &option_compat,
                                "Enable Network Manager compatibility" },
-       { "debug", 'd', 0, G_OPTION_ARG_NONE, &option_debug,
-                               "Enable debug information output" },
        { "selftest", 't', 0, G_OPTION_ARG_NONE, &option_selftest,
                                "Run self testing routines" },
        { "version", 'v', 0, G_OPTION_ARG_NONE, &option_version,
@@ -189,7 +184,7 @@ int main(int argc, char *argv[])
                }
        }
 
-       __connman_log_init(option_detach, option_debug);
+       __connman_log_init(option_debug, option_detach);
 
        if (option_selftest == TRUE) {
                if (__connman_selftest() < 0) {
@@ -227,9 +222,6 @@ int main(int argc, char *argv[])
        sigaction(SIGINT, &sa, NULL);
        sigaction(SIGTERM, &sa, NULL);
 
-       sa.sa_handler = sig_debug;
-       sigaction(SIGUSR2, &sa, NULL);
-
        g_main_loop_run(main_loop);
 
        __connman_element_stop();
index e761ce8..1a114a4 100644 (file)
@@ -195,6 +195,54 @@ static void append_connected_technologies(DBusMessageIter *dict)
        dbus_message_iter_close_container(dict, &entry);
 }
 
+static void append_available_debugs(DBusMessageIter *dict)
+{
+       DBusMessageIter entry, value, iter;
+       const char *key = "AvailableDebugs";
+
+       dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
+                                                               NULL, &entry);
+
+       dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
+
+       dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
+                       DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
+                                                               &value);
+
+       dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
+                                       DBUS_TYPE_STRING_AS_STRING, &iter);
+       __connman_debug_list_available(&iter);
+       dbus_message_iter_close_container(&value, &iter);
+
+       dbus_message_iter_close_container(&entry, &value);
+
+       dbus_message_iter_close_container(dict, &entry);
+}
+
+static void append_enabled_debugs(DBusMessageIter *dict)
+{
+       DBusMessageIter entry, value, iter;
+       const char *key = "EnabledDebugs";
+
+       dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
+                                                               NULL, &entry);
+
+       dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
+
+       dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
+                       DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
+                                                               &value);
+
+       dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
+                                       DBUS_TYPE_STRING_AS_STRING, &iter);
+       __connman_debug_list_enabled(&iter);
+       dbus_message_iter_close_container(&value, &iter);
+
+       dbus_message_iter_close_container(&entry, &value);
+
+       dbus_message_iter_close_container(dict, &entry);
+}
+
 static DBusMessage *get_properties(DBusConnection *conn,
                                        DBusMessage *msg, void *data)
 {
@@ -252,6 +300,9 @@ static DBusMessage *get_properties(DBusConnection *conn,
                connman_dbus_dict_append_variant(&dict, "DefaultTechnology",
                                                DBUS_TYPE_STRING, &str);
 
+       append_available_debugs(&dict);
+       append_enabled_debugs(&dict);
+
        dbus_message_iter_close_container(&array, &dict);
 
        return reply;
index db9c12a..07e3d85 100755 (executable)
@@ -63,7 +63,8 @@ for key in properties.keys():
        if key in ["Profiles", "Devices", "Connections", "Services"]:
                print_properties(key, properties[key])
        elif key in ["AvailableTechnologies", "EnabledTechnologies",
-                                               "ConnectedTechnologies"]:
+                                       "ConnectedTechnologies",
+                               "AvailableDebugs", "EnabledDebugs"]:
                print "%s" % (key)
                list = ""
                for val in properties[key]: