]> arthur.barton.de Git - netatalk.git/blob - etc/afpd/afpstats.c
AFP statistics via dbus IPC
[netatalk.git] / etc / afpd / afpstats.c
1 /*
2  * Copyright (c) 2013 Frank Lahm <franklahm@gmail.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  */
14
15 #ifdef HAVE_CONFIG_H
16 #include "config.h"
17 #endif /* HAVE_CONFIG_H */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <errno.h>
23 #include <pthread.h>
24 #include <glib.h>
25 #include <gio/gio.h>
26 #include <dbus/dbus-glib.h>
27
28 #include <atalk/logger.h>
29 #include <atalk/compat.h>
30 #include <atalk/errchk.h>
31 #include <atalk/server_child.h>
32
33 #include "afpstats_obj.h"
34 #include "afpstats_service_glue.h"
35
36 /*
37  * Beware: this struct is accessed and modified from the main thread
38  * and from this thread, thus be careful to lock and unlock the mutex.
39  */
40 static server_child_t *childs;
41
42 static gpointer afpstats_thread(gpointer _data)
43 {
44     DBusGConnection *bus;
45     DBusGProxy *bus_proxy;
46     GError *error = NULL;
47     GMainLoop *thread_loop;
48     guint request_name_result;
49     sigset_t sigs;
50
51     /* Block all signals in this thread */
52     sigfillset(&sigs);
53     pthread_sigmask(SIG_BLOCK, &sigs, NULL);
54
55     dbus_g_object_type_install_info(AFPSTATS_TYPE_OBJECT, &dbus_glib_afpstats_obj_object_info);
56
57     thread_loop = g_main_loop_new(NULL, FALSE);
58    
59     if (!(bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error))) {
60         LOG(log_error, logtype_afpd,"Couldn't connect to system bus: %s", error->message);
61         return NULL;
62     }
63
64     if (!(bus_proxy = dbus_g_proxy_new_for_name(bus, "org.freedesktop.DBus",
65                                                 "/org/freedesktop/DBus",
66                                                 "org.freedesktop.DBus"))) {
67         LOG(log_error, logtype_afpd,"Couldn't create bus proxy");
68         return NULL;
69     }
70
71     if (!dbus_g_proxy_call(bus_proxy, "RequestName", &error,
72                            G_TYPE_STRING, "org.netatalk.AFPStats",
73                            G_TYPE_UINT, 0,
74                            G_TYPE_INVALID,
75                            G_TYPE_UINT, &request_name_result,
76                            G_TYPE_INVALID)) {
77         LOG(log_error, logtype_afpd, "Failed to acquire DBUS name: %s", error->message);
78         return NULL;
79     }
80
81     AFPStatsObj *obj = g_object_new(AFPSTATS_TYPE_OBJECT, NULL);
82     dbus_g_connection_register_g_object(bus, "/org/netatalk/AFPStats", G_OBJECT(obj));
83
84     g_main_loop_run(thread_loop);
85     return thread_loop;
86 }
87
88 static void my_glib_log(const gchar *log_domain,
89                         GLogLevelFlags log_level,
90                         const gchar *message,
91                         gpointer user_data)
92 {
93     LOG(log_error, logtype_afpd, "%s: %s", log_domain, message);
94 }
95
96 server_child_t *afpstats_get_and_lock_childs(void)
97 {
98     pthread_mutex_lock(&childs->servch_lock);
99     return childs;
100 }
101
102 void afpstats_unlock_childs(void)
103 {
104     pthread_mutex_unlock(&childs->servch_lock);
105 }
106
107 int afpstats_init(server_child_t *childs_in)
108 {
109     GThread *thread;
110
111     childs = childs_in;
112     g_type_init();
113     (void)g_log_set_default_handler(my_glib_log, NULL);
114     g_thread_init(NULL);
115     thread = g_thread_create(afpstats_thread, NULL, TRUE, NULL);
116
117     return 0;
118 }