1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
4 * Copyright (C) 2000-2003, Ximian, Inc.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU Lesser General Public
8 * License as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
20 * Author: Nat Friedman (nat@ximian.com)
27 /* define this if you need/want to be able to send USR2 to server and
28 get a list of the active backends */
29 /*#define DEBUG_BACKENDS*/
37 #include <glib/gi18n.h>
38 #include <libgnome/gnome-init.h>
39 #include <bonobo-activation/bonobo-activation.h>
40 #include <libgnomevfs/gnome-vfs-init.h>
41 #include <bonobo/bonobo-main.h>
42 #include <bonobo/bonobo-exception.h>
43 #include <bonobo/bonobo-generic-factory.h>
44 #include <gconf/gconf-client.h>
46 #include <libedataserver/e-data-server-module.h>
47 #include <libedata-book/e-data-book-factory.h>
49 #include <libedata-cal/e-data-cal-factory.h>
53 #include <libedataserver/e-data-server-util.h>
56 #include "server-interface-check.h"
57 #include "server-logging.h"
58 #include "offline-listener.h"
60 #define E_DATA_SERVER_INTERFACE_CHECK_OAF_ID "OAFIID:GNOME_Evolution_DataServer_InterfaceCheck"
61 #define E_DATA_SERVER_LOGGING_OAF_ID "OAFIID:GNOME_Evolution_DataServer_Logging"
63 #define E_DATA_CAL_FACTORY_OAF_ID "OAFIID:GNOME_Evolution_DataServer_CalFactory:" API_VERSION
64 #define E_DATA_BOOK_FACTORY_OAF_ID "OAFIID:GNOME_Evolution_DataServer_BookFactory:" API_VERSION
66 /* The and addressbook calendar factories */
69 static EDataCalFactory *e_data_cal_factory;
72 static EDataBookFactory *e_data_book_factory;
74 /* The other interfaces we implement */
76 static ServerLogging *logging_iface;
77 static ServerInterfaceCheck *interface_check_iface;
79 /* Timeout interval in milliseconds for termination */
80 #define EXIT_TIMEOUT 5000
82 /* Timeout ID for termination handler */
83 static guint termination_handler_id;
85 static GStaticMutex termination_lock = G_STATIC_MUTEX_INIT;
88 static pthread_mutex_t segv_mutex = PTHREAD_MUTEX_INITIALIZER;
89 static pthread_t main_thread;
92 gnome_segv_handler (int signo)
94 const char *gnome_segv_path;
95 static int in_segv = 0;
98 if (pthread_self() != main_thread) {
99 /* deadlock intentionally in the sub-threads */
100 pthread_kill(main_thread, signo);
101 pthread_mutex_lock(&segv_mutex);
106 /* The fprintf() was segfaulting, we are just totally hosed */
108 } else if (in_segv > 1) {
109 /* dialog display isn't working out */
110 fprintf (stderr, _("Multiple segmentation faults occurred; cannot display error dialog\n"));
114 gnome_segv_path = GNOMEUI_SERVERDIR "/gnome_segv2";
116 exec = g_strdup_printf ("%s \"" PACKAGE "-" BASE_VERSION "\" %d \"" VERSION "\"",
117 gnome_segv_path, signo);
125 setup_segv_handler (void)
130 sigemptyset (&sa.sa_mask);
131 sa.sa_handler = gnome_segv_handler;
132 sigaction (SIGSEGV, &sa, NULL);
133 sigaction (SIGBUS, &sa, NULL);
134 sigaction (SIGFPE, &sa, NULL);
136 main_thread = pthread_self();
137 pthread_mutex_lock(&segv_mutex);
144 /* Termination handler. Checks if both factories have zero running backends,
145 * and if so terminates the program.
148 termination_handler (gpointer data)
153 count += e_data_cal_factory_get_n_backends (e_data_cal_factory);
155 count += e_data_book_factory_get_n_backends (e_data_book_factory);
158 g_message ("termination_handler(): Terminating the Server. Have a nice day.");
162 termination_handler_id = 0;
166 /* Queues a timeout for handling termination of Server */
168 queue_termination (void)
170 g_static_mutex_lock (&termination_lock);
171 if (termination_handler_id)
172 g_source_remove (termination_handler_id);
174 termination_handler_id = g_timeout_add (EXIT_TIMEOUT, termination_handler, NULL);
175 g_static_mutex_unlock (&termination_lock);
181 last_book_gone_cb (EDataBookFactory *factory, gpointer data)
183 queue_termination ();
189 e_data_book_factory = e_data_book_factory_new ();
191 if (!e_data_book_factory)
194 e_data_book_factory_register_backends (e_data_book_factory);
196 g_signal_connect (e_data_book_factory,
198 G_CALLBACK (last_book_gone_cb),
201 if (!e_data_book_factory_activate (e_data_book_factory, E_DATA_BOOK_FACTORY_OAF_ID)) {
202 bonobo_object_unref (BONOBO_OBJECT (e_data_book_factory));
203 e_data_book_factory = NULL;
211 /* Personal calendar server */
214 /* Callback used when the calendar factory has no more running backends */
216 last_calendar_gone_cb (EDataCalFactory *factory, gpointer data)
218 queue_termination ();
221 /* Creates the calendar factory object and registers it */
225 e_data_cal_factory = e_data_cal_factory_new ();
227 if (!e_data_cal_factory) {
228 g_warning (G_STRLOC ": Could not create the calendar factory");
232 e_data_cal_factory_register_backends (e_data_cal_factory);
234 if (!e_data_cal_factory_register_storage (e_data_cal_factory, E_DATA_CAL_FACTORY_OAF_ID)) {
235 bonobo_object_unref (BONOBO_OBJECT (e_data_cal_factory));
236 e_data_cal_factory = NULL;
240 g_signal_connect (G_OBJECT (e_data_cal_factory),
241 "last_calendar_gone",
242 G_CALLBACK (last_calendar_gone_cb),
263 logging_iface = server_logging_new ();
265 server_logging_register_domain (logging_iface, NULL);
266 server_logging_register_domain (logging_iface, "Gdk");
267 server_logging_register_domain (logging_iface, "Gtk");
268 server_logging_register_domain (logging_iface, "GdkPixbuf");
269 server_logging_register_domain (logging_iface, "GLib");
270 server_logging_register_domain (logging_iface, "GModule");
271 server_logging_register_domain (logging_iface, "GLib-GObject");
272 server_logging_register_domain (logging_iface, "GThread");
274 server_logging_register_domain (logging_iface, "evolution-data-server");
275 server_logging_register_domain (logging_iface, "libebookbackend");
276 server_logging_register_domain (logging_iface, "libecalbackendfile");
278 result = bonobo_activation_active_server_register (E_DATA_SERVER_LOGGING_OAF_ID,
279 BONOBO_OBJREF (logging_iface));
281 return result == Bonobo_ACTIVATION_REG_SUCCESS;
285 /* Interface check iface. */
288 setup_interface_check (void)
292 interface_check_iface = server_interface_check_new ();
293 result = bonobo_activation_active_server_register (E_DATA_SERVER_INTERFACE_CHECK_OAF_ID,
294 BONOBO_OBJREF (interface_check_iface));
296 return result == Bonobo_ACTIVATION_REG_SUCCESS;
300 #ifdef DEBUG_BACKENDS
302 dump_backends (int signal)
304 e_data_book_factory_dump_active_backends (e_data_book_factory);
306 e_data_cal_factory_dump_active_backends (e_data_cal_factory);
312 #undef EVOLUTION_LOCALEDIR
313 #define EVOLUTION_LOCALEDIR e_util_get_localedir ()
315 /* Used in GNOME_PROGRAM_STANDARD_PROPERTIES: */
317 #define PREFIX e_util_get_prefix ()
322 return e_util_replace_prefix (PREFIX,
323 e_util_get_prefix (),
327 #define SYSCONFDIR sysconfdir ()
332 return e_util_replace_prefix (PREFIX,
333 e_util_get_prefix (),
337 #define DATADIR datadir ()
342 return e_util_replace_prefix (PREFIX,
343 e_util_get_prefix (),
347 #define LIBDIR libdir ()
352 main (int argc, char **argv)
354 gboolean did_books=FALSE, did_cals=FALSE;
355 OfflineListener *offline_listener = NULL;
357 bindtextdomain (GETTEXT_PACKAGE, EVOLUTION_LOCALEDIR);
358 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
359 textdomain (GETTEXT_PACKAGE);
361 printf ("evolution-data-server-Message: Starting server\n");
363 #ifdef DEBUG_BACKENDS
364 signal (SIGUSR2, dump_backends);
367 gnome_program_init (PACKAGE, VERSION,
370 GNOME_PROGRAM_STANDARD_PROPERTIES, NULL);
372 bonobo_init_full (&argc, argv,
373 bonobo_activation_orb_get(),
377 setup_segv_handler ();
379 e_data_server_module_init ();
381 if (!( (did_books = setup_books ())
382 && (did_cals = setup_cals ())
385 const gchar *failed = NULL;
392 g_warning (G_STRLOC ": could not initialize Server service \"%s\"; terminating", failed);
394 if (e_data_book_factory) {
395 bonobo_object_unref (BONOBO_OBJECT (e_data_book_factory));
396 e_data_book_factory = NULL;
400 if (e_data_cal_factory) {
401 bonobo_object_unref (BONOBO_OBJECT (e_data_cal_factory));
402 e_data_cal_factory = NULL;
409 offline_listener = offline_listener_new (e_data_book_factory, e_data_cal_factory);
411 offline_listener = offline_listener_new (e_data_book_factory);
414 if ( setup_logging ()) {
415 if ( setup_interface_check ()) {
416 g_message ("Server up and running");
420 g_error (G_STRLOC "Cannot register DataServer::InterfaceCheck object");
422 g_error (G_STRLOC "Cannot register DataServer::Logging object");
424 g_object_unref (offline_listener);
427 bonobo_object_unref (BONOBO_OBJECT (e_data_cal_factory));
428 e_data_cal_factory = NULL;
431 bonobo_object_unref (BONOBO_OBJECT (e_data_book_factory));
432 e_data_book_factory = NULL;
434 bonobo_object_unref (BONOBO_OBJECT (logging_iface));
435 logging_iface = NULL;
437 bonobo_object_unref (BONOBO_OBJECT (interface_check_iface));
438 interface_check_iface = NULL;
440 gnome_vfs_shutdown ();