1
/* zeitgeist-daemon.vala
3
* Copyright © 2011 Seif Lotfy <seif@lotfy.com>
4
* Copyright © 2011 Michal Hruby <michal.mhr@gmail.com>
5
* Copyright © 2011 Collabora Ltd.
6
* By Siegfried-Angel Gevatter Pujals <siegfried@gevatter.com>
7
* By Seif Lotfy <seif@lotfy.com>
9
* This program is free software: you can redistribute it and/or modify
10
* it under the terms of the GNU Lesser General Public License as published by
11
* the Free Software Foundation, either version 2.1 of the License, or
12
* (at your option) any later version.
14
* This program is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
19
* You should have received a copy of the GNU Lesser General Public License
20
* along with this program. If not, see <http://www.gnu.org/licenses/>.
27
[DBus (name = "org.freedesktop.DBus")]
28
public interface RemoteDBus : Object
30
public abstract bool name_has_owner (string name) throws IOError;
33
public class Daemon : Object, RemoteLog
35
const string DBUS_NAME = "org.gnome.zeitgeist.Engine";
36
private static bool show_version_info = false;
37
private static bool show_options = false;
38
private static bool no_datahub = false;
39
private static bool replace_mode = false;
40
private static bool quit_daemon = false;
41
private static string log_level = "";
43
const OptionEntry[] options =
46
"version", 'v', 0, OptionArg.NONE, out show_version_info,
47
"Print program's version number and exit", null
50
"no-datahub", 0, 0, OptionArg.NONE, out no_datahub,
51
"Do not start zeitgeist-datahub automatically", null
54
"no-passive-loggers", 0, OptionFlags.HIDDEN, OptionArg.NONE,
55
out no_datahub, null, null
58
"replace", 'r', 0, OptionArg.NONE, out replace_mode,
59
"If another Zeitgeist instance is already running, replace it",
63
"quit", 0, 0, OptionArg.NONE, out quit_daemon,
64
"Quit running Zeitgeist daemon instance", null
67
"log-level", 0, 0, OptionArg.STRING, out log_level,
68
"How much information should be printed; possible values: " +
69
"DEBUG, INFO, WARNING, ERROR, CRITICAL", "LEVEL"
72
"shell-completion", 0, OptionFlags.HIDDEN, OptionArg.NONE,
73
out show_options, null, null
80
private static Daemon? instance;
81
private static MainLoop mainloop;
82
private static bool name_acquired = false;
84
private Engine engine;
85
private MonitorManager notifications;
87
private uint log_register_id;
88
private unowned DBusConnection connection;
90
public string[] extensions
94
string[] ext = engine.get_extension_names ();
99
public VersionStruct version
103
var s = VersionStruct ();
104
string[] ver = Config.VERSION.split (".");
107
s.major = int.parse (ver[0]);
108
s.minor = int.parse (ver[1]);
109
s.micro = int.parse (ver[2]);
113
warning ("Unable to parse version info!");
122
public Daemon () throws EngineError
124
engine = new Engine ();
125
notifications = new MonitorManager ();
128
public Variant get_events (uint32[] event_ids, BusName sender)
131
var timer = new Timer ();
132
GenericArray<Event> events = engine.get_events (event_ids);
133
debug ("%s executed in %f seconds", Log.METHOD, timer.elapsed ());
134
return Events.to_variant (events);
137
public string[] find_related_uris (Variant time_range,
138
Variant event_templates,
139
Variant result_event_templates,
140
uint storage_state, uint num_events, uint result_type,
141
BusName sender) throws Error
143
return engine.find_related_uris (
144
new TimeRange.from_variant (time_range),
145
Events.from_variant (event_templates),
146
Events.from_variant (result_event_templates),
147
storage_state, num_events, result_type);
150
public uint32[] find_event_ids (Variant time_range,
151
Variant event_templates,
152
uint storage_state, uint num_events, uint result_type,
153
BusName sender) throws Error
155
return engine.find_event_ids (
156
new TimeRange.from_variant (time_range),
157
Events.from_variant(event_templates),
158
storage_state, num_events, result_type, sender);
161
public Variant find_events (Variant time_range,
162
Variant event_templates,
163
uint storage_state, uint num_events, uint result_type,
164
BusName sender) throws Error
166
var timer = new Timer ();
167
var events = engine.find_events (
168
new TimeRange.from_variant (time_range),
169
Events.from_variant (event_templates),
170
storage_state, num_events, result_type, sender);
171
debug ("%s executed in %f seconds", Log.METHOD, timer.elapsed ());
172
return Events.to_variant (events);
175
public uint32[] insert_events (
177
BusName sender) throws Error
179
var events = Events.from_variant (vevents);
181
uint32[] event_ids = engine.insert_events (events, sender);
182
var min_timestamp = int64.MAX;
183
var max_timestamp = int64.MIN;
184
for (int i = 0; i < events.length; i++)
186
if (events[i] == null) continue;
187
min_timestamp = int64.min (min_timestamp, events[i].timestamp);
188
max_timestamp = int64.max (max_timestamp, events[i].timestamp);
191
if (min_timestamp < int64.MAX)
193
notifications.notify_insert (
194
new TimeRange (min_timestamp, max_timestamp), events);
196
/* else { there's not even one valid event } */
201
public Variant delete_events (uint32[] event_ids, BusName sender)
204
TimeRange? time_range = engine.delete_events (event_ids, sender);
205
if (time_range != null)
207
notifications.notify_delete (time_range, event_ids);
211
// All the given event_ids are invalod or the events
212
// have already been deleted before!
213
time_range = new TimeRange (-1, -1);
215
return time_range.to_variant ();
218
public void quit () throws Error
223
private void do_quit ()
229
public void install_monitor (ObjectPath monitor_path,
231
Variant event_templates,
232
BusName owner) throws Error
234
notifications.install_monitor (owner, monitor_path,
235
new TimeRange.from_variant (time_range),
236
Events.from_variant (event_templates));
239
public void remove_monitor (ObjectPath monitor_path, BusName owner)
242
notifications.remove_monitor (owner, monitor_path);
245
public void register_dbus_object (DBusConnection conn) throws IOError
248
log_register_id = conn.register_object<RemoteLog> (
249
"/org/gnome/zeitgeist/log/activity", this);
252
public void unregister_dbus_object ()
254
if (log_register_id != 0)
256
connection.unregister_object (log_register_id);
261
private static bool quit_running_instance (DBusConnection conn)
265
var running_instance = conn.get_proxy_sync<RemoteLog> (
266
DBUS_NAME, "/org/gnome/zeitgeist/log/activity");
267
running_instance.quit ();
272
warning ("%s", err.message);
278
private static void name_acquired_callback (DBusConnection conn)
280
name_acquired = true;
282
// only run datahub when we acquire bus name
287
Process.spawn_command_line_async ("zeitgeist-datahub");
289
catch (SpawnError err)
291
warning ("%s", err.message);
296
private static void name_lost_callback (DBusConnection? conn)
300
// something happened to our bus connection
303
else if (instance != null && !name_acquired)
305
// we acquired bus connection, but couldn't own the name
310
debug ("Waiting 10 seconds to acquire name...");
311
// we already called Quit, let's wait a while
312
// for the running instance to quit, bail out
314
Timeout.add (10000, () =>
318
warning ("Timeout reached, unable to acquire name!");
324
else if (instance != null && name_acquired)
326
// we owned the name and we lost it... what to do?
333
DBusConnection connection;
337
connection = Bus.get_sync (BusType.SESSION);
338
var proxy = connection.get_proxy_sync<RemoteDBus> (
339
"org.freedesktop.DBus", "/org/freedesktop/DBus",
340
DBusProxyFlags.DO_NOT_LOAD_PROPERTIES);
341
name_owned = proxy.name_has_owner (DBUS_NAME);
345
critical ("%s", err.message);
350
if (replace_mode || quit_daemon)
352
quit_running_instance (connection);
356
critical ("An existing instance was found. Please use " +
357
"--replace to stop it and start a new instance.");
362
/* don't do anything else if we were called with --quit param */
363
if (quit_daemon) return;
365
/* setup Engine instance and register objects on dbus */
368
instance = new Daemon ();
369
instance.register_dbus_object (connection);
373
critical ("%s", err.message);
377
uint owner_id = Bus.own_name_on_connection (connection,
379
BusNameOwnerFlags.NONE,
380
name_acquired_callback,
383
mainloop = new MainLoop ();
386
if (instance != null)
388
Bus.unown_name (owner_id);
389
instance.unregister_dbus_object ();
392
// make sure we send quit reply
395
connection.flush_sync ();
399
warning ("%s", e.message);
404
static void safe_exit ()
409
static int main (string[] args)
411
Posix.signal (Posix.SIGHUP, safe_exit);
412
Posix.signal (Posix.SIGINT, safe_exit);
413
Posix.signal (Posix.SIGTERM, safe_exit);
415
var opt_context = new OptionContext (" - Zeitgeist daemon");
416
opt_context.add_main_entries (options, null);
420
opt_context.parse (ref args);
422
if (show_version_info)
424
stdout.printf (Config.VERSION + "\n");
429
foreach (unowned OptionEntry? entry in options)
431
if (entry.long_name != null)
432
stdout.printf ("--%s ", entry.long_name);
433
if (entry.short_name != 0)
434
stdout.printf ("-%c ", entry.short_name);
436
stdout.printf ("--help\n");
444
warning ("%s", err.message);
453
// vim:expandtab:ts=4:sw=4