Re: [Zeitgeist] [Merge] lp:~tdfischer/zeitgeist/event-caching into lp:zeitgeist
Updated. I'll start working on providing some analysis. -- https://code.launchpad.net/~tdfischer/zeitgeist/event-caching/+merge/97450 Your team Zeitgeist Framework Team is subscribed to branch lp:zeitgeist. ___ Mailing list: https://launchpad.net/~zeitgeist Post to : zeitgeist@lists.launchpad.net Unsubscribe : https://launchpad.net/~zeitgeist More help : https://help.launchpad.net/ListHelp
[Zeitgeist] [Bug 799531] Re: API for deletion of events within a timerange?
** Changed in: zeitgeist Status: In Progress = Fix Committed -- You received this bug notification because you are a member of Activity Log Manager, which is the registrant for Activity Log Manager. https://bugs.launchpad.net/bugs/799531 Title: API for deletion of events within a timerange? Status in Activity Log Manager for Zeitgeist: Invalid Status in Zeitgeist Framework: Fix Committed Bug description: If I try to select date range more then a month it just freezes. $ activity-log-manager INFO:zeitgeist.client:Reconnected to Zeitgeist engine... Error from Zeitgeist engine: org.freedesktop.DBus.Python.sqlite3.OperationalError: Traceback (most recent call last): File /usr/lib/pymodules/python2.7/dbus/service.py, line 702, in _message_cb retval = candidate_method(self, *args, **keywords) File /usr/share/zeitgeist/_zeitgeist/engine/remote.py, line 337, in DeleteEvents timestamps = self._engine.delete_events(event_ids, sender=sender) File /usr/share/zeitgeist/_zeitgeist/engine/main.py, line 838, in delete_events % ,.join([?] * len(ids)), ids) File /usr/share/zeitgeist/_zeitgeist/engine/sql.py, line 74, in execute return super(UnicodeCursor, self).execute(statement, parameters) OperationalError: too many SQL variables Version: 0.8.0-0ubuntu1~ppa2~natty To manage notifications about this bug go to: https://bugs.launchpad.net/activity-log-manager/+bug/799531/+subscriptions ___ Mailing list: https://launchpad.net/~zeitgeist Post to : zeitgeist@lists.launchpad.net Unsubscribe : https://launchpad.net/~zeitgeist More help : https://help.launchpad.net/ListHelp
Re: [Zeitgeist] [Merge] lp:~tdfischer/zeitgeist/timerange-deletion-api into lp:zeitgeist
As noted in the original bug, simply querying all the event ids in a time range and then handing it to delete_events causes the SQL error described: Too many variables -- https://code.launchpad.net/~tdfischer/zeitgeist/timerange-deletion-api/+merge/97272 Your team Zeitgeist Framework Team is subscribed to branch lp:zeitgeist. ___ Mailing list: https://launchpad.net/~zeitgeist Post to : zeitgeist@lists.launchpad.net Unsubscribe : https://launchpad.net/~zeitgeist More help : https://help.launchpad.net/ListHelp
[Zeitgeist] [Merge] lp:~tdfischer/zeitgeist-explorer/latest-gi into lp:zeitgeist-explorer
Trever Fischer has proposed merging lp:~tdfischer/zeitgeist-explorer/latest-gi into lp:zeitgeist-explorer. Requested reviews: Zeitgeist Framework Team (zeitgeist) For more details, see: https://code.launchpad.net/~tdfischer/zeitgeist-explorer/latest-gi/+merge/97719 Uses named parameters for GtkTreeView constructors, allowing it to run on Fedora 15. -- https://code.launchpad.net/~tdfischer/zeitgeist-explorer/latest-gi/+merge/97719 Your team Zeitgeist Framework Team is requested to review the proposed merge of lp:~tdfischer/zeitgeist-explorer/latest-gi into lp:zeitgeist-explorer. === modified file 'zgexplorer/filtermanager.py' --- zgexplorer/filtermanager.py 2012-03-13 20:59:11 + +++ zgexplorer/filtermanager.py 2012-03-15 18:40:25 + @@ -55,7 +55,7 @@ for i in self.builtin: self.predefined_store.append([i, self.builtin[i][0]]) -self.predefined_view = Gtk.TreeView(self.predefined_store) +self.predefined_view = Gtk.TreeView(model=self.predefined_store) self.predefined_view.connect(cursor-changed, self.on_cursor_changed) column_pix_name = Gtk.TreeViewColumn(_('Name')) self.predefined_view.append_column(column_pix_name) @@ -86,7 +86,7 @@ self.custom_store = Gtk.ListStore(int, str) -self.custom_view = Gtk.TreeView(self.custom_store) +self.custom_view = Gtk.TreeView(model=self.custom_store) self.custom_view.connect(cursor-changed, self.on_custom_cursor_changed) column_pix_name = Gtk.TreeViewColumn(_('Name')) === modified file 'zgexplorer/monitorviewer.py' --- zgexplorer/monitorviewer.py 2012-03-12 20:57:29 + +++ zgexplorer/monitorviewer.py 2012-03-15 18:40:25 + @@ -93,7 +93,7 @@ # Event Id, TimeStamp, Interpretation, Manifestation, Actor self.store = Gtk.ListStore( int, str, str, str, str) -self.treeview = Gtk.TreeView(self.store) +self.treeview = Gtk.TreeView(model=self.store) self.treeview.connect(cursor-changed, self.on_event_selected) self.scroll.add(self.treeview) === modified file 'zgexplorer/window.py' --- zgexplorer/window.py 2012-03-13 20:59:11 + +++ zgexplorer/window.py 2012-03-15 18:40:25 + @@ -104,7 +104,7 @@ monitor_vbox = Gtk.VBox() list_vbox.pack_start(monitor_vbox, True, True, 0) self.monitors = Gtk.ListStore(int, str, bool) -self.monitor_tree = Gtk.TreeView(self.monitors) +self.monitor_tree = Gtk.TreeView(model=self.monitors) self.monitor_tree.connect(cursor-changed, self.on_treeview_selected) self.monitor_tree.set_size_request(200, 600) self.monitor_tree.set_border_width(1) ___ Mailing list: https://launchpad.net/~zeitgeist Post to : zeitgeist@lists.launchpad.net Unsubscribe : https://launchpad.net/~zeitgeist More help : https://help.launchpad.net/ListHelp
Re: [Zeitgeist] [Merge] lp:~tdfischer/zeitgeist/bluebird into lp:zeitgeist
Branch updated. -- https://code.launchpad.net/~tdfischer/zeitgeist/bluebird/+merge/97026 Your team Zeitgeist Framework Team is subscribed to branch lp:zeitgeist. ___ Mailing list: https://launchpad.net/~zeitgeist Post to : zeitgeist@lists.launchpad.net Unsubscribe : https://launchpad.net/~zeitgeist More help : https://help.launchpad.net/ListHelp
[Zeitgeist] [Merge] lp:~tdfischer/zeitgeist/event-caching into lp:zeitgeist
Trever Fischer has proposed merging lp:~tdfischer/zeitgeist/event-caching into lp:zeitgeist. Requested reviews: Zeitgeist Framework Team (zeitgeist) For more details, see: https://code.launchpad.net/~tdfischer/zeitgeist/event-caching/+merge/97450 Implements a LRU cache for events, to reduce hitting the database on every request. -- https://code.launchpad.net/~tdfischer/zeitgeist/event-caching/+merge/97450 Your team Zeitgeist Framework Team is requested to review the proposed merge of lp:~tdfischer/zeitgeist/event-caching into lp:zeitgeist. === modified file 'extensions/fts++/Makefile.am' --- extensions/fts++/Makefile.am 2012-02-12 20:17:52 + +++ extensions/fts++/Makefile.am 2012-03-14 16:35:57 + @@ -42,6 +42,7 @@ ontology-uris.vala \ mimetype.vala \ ext-dummies.vala \ + event-cache.vala \ $(NULL) libzeitgeist_internal_la_SOURCES = \ === modified file 'src/Makefile.am' --- src/Makefile.am 2012-02-15 19:55:59 + +++ src/Makefile.am 2012-03-14 16:35:57 + @@ -48,6 +48,7 @@ ontology.vala \ ontology-uris.vala \ mimetype.vala \ + event-cache.vala \ $(NULL) zeitgeist_daemon_SOURCES = \ === modified file 'src/db-reader.vala' --- src/db-reader.vala 2012-03-14 12:31:51 + +++ src/db-reader.vala 2012-03-14 16:35:57 + @@ -45,6 +45,8 @@ protected TableLookup mimetypes_table; protected TableLookup actors_table; +protected EventCache cache; + public DbReader () throws EngineError { Object (database: new Zeitgeist.SQLite.Database.read_only ()); @@ -59,6 +61,8 @@ manifestations_table = new TableLookup (database, manifestation); mimetypes_table = new TableLookup (database, mimetype); actors_table = new TableLookup (database, actor); + +cache = new EventCache(); } protected Event get_event_from_row (Sqlite.Statement stmt, uint32 event_id) @@ -117,7 +121,20 @@ if (event_ids.length == 0) return new GenericArrayEvent? (); -var sql_event_ids = database.get_sql_string_from_event_ids (event_ids); +var results = new GenericArrayEvent? (); +uint32[] uncached_ids = new uint32[0]; +for(int i = 0; i event_ids.length; i++) +{ +Event? e = cache.get_event (event_ids[i]); +if (e == null) { +results.set(i, e); +} else { +uncached_ids.resize(uncached_ids.length+1); +uncached_ids[uncached_ids.length-1] = event_ids[i]; +} +} + +var sql_event_ids = database.get_sql_string_from_event_ids (uncached_ids); string sql = SELECT * FROM event_view WHERE id IN (%s) @@ -149,12 +166,13 @@ } // Sort events according to the sequence of event_ids -var results = new GenericArrayEvent? (); results.length = event_ids.length; int i = 0; foreach (var id in event_ids) { -results.set(i++, events.lookup (id)); +Event e = events.lookup (id); +cache.cache_event (e); +results.set(i++, e); } return results; === modified file 'test/direct/Makefile.am' --- test/direct/Makefile.am 2012-02-15 18:55:42 + +++ test/direct/Makefile.am 2012-03-14 16:35:57 + @@ -11,6 +11,7 @@ TESTS = \ datamodel-test \ + event-cache-test \ marshalling-test \ mimetype-test \ query-operators-test \ @@ -36,8 +37,12 @@ $(top_srcdir)/src/ontology.vala \ $(top_srcdir)/src/ontology-uris.vala \ $(top_srcdir)/src/mimetype.vala \ + $(top_srcdir)/src/event-cache.vala \ $(NULL) +event-cache-test: event-cache-test.vala $(SRC_FILES) + $(VALA_V)$(VALAC) $(VALAFLAGS) -o $@ $^ + datamodel-test: datamodel-test.vala $(SRC_FILES) $(VALA_V)$(VALAC) $(VALAFLAGS) -o $@ $^ @@ -66,11 +71,13 @@ query-operators-test \ table-lookup-test \ where-clause-test \ + event-cache-test \ $(NULL) EXTRA_DIST = \ assertions.vapi \ datamodel-test.vala \ + event-cache-test.vala \ marshalling-test.vala \ mimetype-test.vala \ query-operators-test.vala \ ___ Mailing list: https://launchpad.net/~zeitgeist Post to : zeitgeist@lists.launchpad.net Unsubscribe : https://launchpad.net/~zeitgeist More help : https://help.launchpad.net/ListHelp
[Zeitgeist] [Merge] lp:~tdfischer/zeitgeist/common-where into lp:zeitgeist
Trever Fischer has proposed merging lp:~tdfischer/zeitgeist/common-where into lp:zeitgeist. Requested reviews: Zeitgeist Framework Team (zeitgeist) For more details, see: https://code.launchpad.net/~tdfischer/zeitgeist/common-where/+merge/97270 Consolidates a lot of WHERE SQL generation into a common method for re-use by other components. -- https://code.launchpad.net/~tdfischer/zeitgeist/common-where/+merge/97270 Your team Zeitgeist Framework Team is requested to review the proposed merge of lp:~tdfischer/zeitgeist/common-where into lp:zeitgeist. === modified file 'src/db-reader.vala' --- src/db-reader.vala 2012-02-05 14:52:13 + +++ src/db-reader.vala 2012-03-13 18:40:22 + @@ -160,47 +160,10 @@ return results; } -public uint32[] find_event_ids (TimeRange time_range, -GenericArrayEvent event_templates, -uint storage_state, uint max_events, uint result_type, +public uint32[] find_event_ids_for_clause (WhereClause where, +uint max_events, uint result_type, BusName? sender=null) throws EngineError { - -WhereClause where = new WhereClause (WhereClause.Type.AND); - -/** - * We are using the unary operator here to tell SQLite to not use - * the index on the timestamp column at the first place. This is a - * fix for (LP: #672965) based on some benchmarks, which suggest - * a performance win, but we might not oversee all implications. - * (See http://www.sqlite.org/optoverview.html, section 6.0). - *-- Markus Korn, 29/11/2010 - */ -if (time_range.start != 0) -where.add ((+timestamp = % + int64.FORMAT).printf( -time_range.start)); -if (time_range.end != 0) -where.add ((+timestamp = % + int64.FORMAT).printf( -time_range.end)); - -if (storage_state == StorageState.AVAILABLE || -storage_state == StorageState.NOT_AVAILABLE) -{ -where.add ((subj_storage_state=? OR subj_storage_state IS NULL), -storage_state.to_string ()); -} -else if (storage_state != StorageState.ANY) -{ -throw new EngineError.INVALID_ARGUMENT( -Unknown storage state '%u'.printf(storage_state)); -} - -WhereClause tpl_conditions = get_where_clause_from_event_templates ( -event_templates); -where.extend (tpl_conditions); -//if (!where.may_have_results ()) -//return new uint32[0]; - string sql = SELECT id FROM event_view ; string where_sql = ; if (!where.is_empty ()) @@ -352,6 +315,20 @@ return event_ids; } +public uint32[] find_event_ids (TimeRange time_range, +GenericArrayEvent event_templates, +uint storage_state, uint max_events, uint result_type, +BusName? sender=null) throws EngineError +{ +WhereClause where = get_where_clause_for_query (time_range, +event_templates, storage_state); + +//if (!where.may_have_results ()) +//return new uint32[0]; + +return find_event_ids_for_clause (where, max_events, result_type); +} + public GenericArrayEvent? find_events (TimeRange time_range, GenericArrayEvent event_templates, uint storage_state, uint max_events, uint result_type, @@ -361,6 +338,46 @@ storage_state, max_events, result_type)); } +public WhereClause get_where_clause_for_query (TimeRange time_range, +GenericArrayEvent event_templates, uint storage_state, +BusName? sender=null) throws EngineError +{ +WhereClause where = new WhereClause (WhereClause.Type.AND); + +/** + * We are using the unary operator here to tell SQLite to not use + * the index on the timestamp column at the first place. This is a + * fix for (LP: #672965) based on some benchmarks, which suggest + * a performance win, but we might not oversee all implications. + * (See http://www.sqlite.org/optoverview.html, section 6.0). + *-- Markus Korn, 29/11/2010 + */ +if (time_range.start != 0) +where.add ((+timestamp = % + int64.FORMAT).printf( +time_range.start)); +if (time_range.end != 0) +where.add ((+timestamp = % + int64.FORMAT).printf( +time_range.end)); + +if (storage_state == StorageState.AVAILABLE || +storage_state == StorageState.NOT_AVAILABLE) +{ +where.add ((subj_storage_state=? OR subj_storage_state IS NULL), +storage_state.to_string ()); +} +else if (storage_state != StorageState.ANY) +{ +throw new EngineError.INVALID_ARGUMENT( +Unknown storage state '%u'.printf(storage_state)); +} + +WhereClause tpl_conditions
[Zeitgeist] [Merge] lp:~tdfischer/zeitgeist/timerange-deletion-api into lp:zeitgeist
Trever Fischer has proposed merging lp:~tdfischer/zeitgeist/timerange-deletion-api into lp:zeitgeist with lp:~tdfischer/zeitgeist/common-where as a prerequisite. Requested reviews: Zeitgeist Framework Team (zeitgeist) Related bugs: Bug #799531 in Zeitgeist Framework: API for deletion of events within a timerange? https://bugs.launchpad.net/zeitgeist/+bug/799531 For more details, see: https://code.launchpad.net/~tdfischer/zeitgeist/timerange-deletion-api/+merge/97272 Fixes #799531 -- https://code.launchpad.net/~tdfischer/zeitgeist/timerange-deletion-api/+merge/97272 Your team Zeitgeist Framework Team is requested to review the proposed merge of lp:~tdfischer/zeitgeist/timerange-deletion-api into lp:zeitgeist. ___ Mailing list: https://launchpad.net/~zeitgeist Post to : zeitgeist@lists.launchpad.net Unsubscribe : https://launchpad.net/~zeitgeist More help : https://help.launchpad.net/ListHelp
Re: [Zeitgeist] [Merge] lp:~tdfischer/zeitgeist/common-where into lp:zeitgeist
Updated branch with removed arguments. -- https://code.launchpad.net/~tdfischer/zeitgeist/common-where/+merge/97270 Your team Zeitgeist Framework Team is subscribed to branch lp:zeitgeist. ___ Mailing list: https://launchpad.net/~zeitgeist Post to : zeitgeist@lists.launchpad.net Unsubscribe : https://launchpad.net/~zeitgeist More help : https://help.launchpad.net/ListHelp
Re: [Zeitgeist] [Merge] lp:~tdfischer/zeitgeist/bluebird into lp:zeitgeist
Finding an ID simply searches for an ID and returns -1 if one is not found. Getting an ID is defined as returning a valid ID number for the given string one way or another. Adding a default argument to a vala method that is public breaks source and binary compatability with users of the generated C code. -- https://code.launchpad.net/~tdfischer/zeitgeist/bluebird/+merge/97026 Your team Zeitgeist Framework Team is subscribed to branch lp:zeitgeist. ___ Mailing list: https://launchpad.net/~zeitgeist Post to : zeitgeist@lists.launchpad.net Unsubscribe : https://launchpad.net/~zeitgeist More help : https://help.launchpad.net/ListHelp
[Zeitgeist] [Merge] lp:~tdfischer/zeitgeist/bluebird into lp:zeitgeist
Trever Fischer has proposed merging lp:~tdfischer/zeitgeist/bluebird into lp:zeitgeist. Requested reviews: Seif Lotfy (seif) For more details, see: https://code.launchpad.net/~tdfischer/zeitgeist/bluebird/+merge/97026 Fixes #953041 -- https://code.launchpad.net/~tdfischer/zeitgeist/bluebird/+merge/97026 Your team Zeitgeist Framework Team is subscribed to branch lp:zeitgeist. === modified file 'extensions/ds-registry.vala' --- extensions/ds-registry.vala 2012-03-12 13:41:16 + +++ extensions/ds-registry.vala 2012-03-12 14:19:24 + @@ -144,7 +144,7 @@ return registry; } -private static Variant to_variant ( +public static Variant to_variant ( HashTablestring, DataSource sources) { var vb = new VariantBuilder (new VariantType (SIG_DATASOURCES)); === modified file 'src/db-reader.vala' --- src/db-reader.vala 2012-02-05 14:52:13 + +++ src/db-reader.vala 2012-03-12 14:19:24 + @@ -652,7 +652,7 @@ where.add_wildcard_condition (actor, val, negated); else where.add_match_condition (actor, -actors_table.get_id (val), negated); +actors_table.find_id (val), negated); } // Origin @@ -712,7 +712,7 @@ subj_mimetype, val, negated); else where.add_match_condition (subj_mimetype, -mimetypes_table.get_id (val), negated); +mimetypes_table.find_id (val), negated); } // URI @@ -851,14 +851,14 @@ if (symbols.length () == 1) { subwhere.add_match_condition (table_name, -lookup_table.get_id (_symbol)); +lookup_table.find_id (_symbol)); } else { var sb = new StringBuilder (); foreach (unowned string uri in symbols) { -sb.append_printf (%d,, lookup_table.get_id (uri)); +sb.append_printf (%d,, lookup_table.find_id (uri)); } sb.truncate (sb.len - 1); === modified file 'src/table-lookup.vala' --- src/table-lookup.vala 2012-02-13 20:14:41 + +++ src/table-lookup.vala 2012-03-12 14:19:24 + @@ -75,6 +75,25 @@ } } +/** + * Searches the table for the given ID, returns -1 if not found. + * + * @see get_id + */ +public int find_id (string name) +{ +int id = value_to_id.lookup (name); +if (id == 0) +return -1; +return id; +} + +/** + * Searches the table for the given ID, inserts a new one if not found. + * + * @see find_id + * + */ public int get_id (string name) { int id = value_to_id.lookup (name); ___ Mailing list: https://launchpad.net/~zeitgeist Post to : zeitgeist@lists.launchpad.net Unsubscribe : https://launchpad.net/~zeitgeist More help : https://help.launchpad.net/ListHelp
[Zeitgeist] [Bug 953041] [NEW] Extraneous actors are inserted into sqlite database during read-only operations
Public bug reported: Example code: import time, os from gi.repository import GObject from zeitgeist.client import ZeitgeistClient from zeitgeist.datamodel import Event, Subject, Interpretation zg = ZeitgeistClient() event_template = Event() event_template.actor = foo mainloop = GObject.MainLoop() def callback(events): print len(events) mainloop.quit() zg.find_events_for_templates([event_template], callback, num_events=100, result_type=0) mainloop.run() Searching the actors table in sqlite shows a foo actor after execution. ** Affects: zeitgeist Importance: Undecided Status: New -- You received this bug notification because you are a member of Zeitgeist Framework Team, which is subscribed to Zeitgeist Framework. https://bugs.launchpad.net/bugs/953041 Title: Extraneous actors are inserted into sqlite database during read-only operations Status in Zeitgeist Framework: New Bug description: Example code: import time, os from gi.repository import GObject from zeitgeist.client import ZeitgeistClient from zeitgeist.datamodel import Event, Subject, Interpretation zg = ZeitgeistClient() event_template = Event() event_template.actor = foo mainloop = GObject.MainLoop() def callback(events): print len(events) mainloop.quit() zg.find_events_for_templates([event_template], callback, num_events=100, result_type=0) mainloop.run() Searching the actors table in sqlite shows a foo actor after execution. To manage notifications about this bug go to: https://bugs.launchpad.net/zeitgeist/+bug/953041/+subscriptions ___ Mailing list: https://launchpad.net/~zeitgeist Post to : zeitgeist@lists.launchpad.net Unsubscribe : https://launchpad.net/~zeitgeist More help : https://help.launchpad.net/ListHelp
[Zeitgeist] [Bug 799531] Re: API for deletion of events within a timerange?
A potential solution? ** Patch added: bzr.patch https://bugs.launchpad.net/zeitgeist/+bug/799531/+attachment/2857018/+files/bzr.patch -- You received this bug notification because you are a member of Activity Log Manager, which is the registrant for Activity Log Manager. https://bugs.launchpad.net/bugs/799531 Title: API for deletion of events within a timerange? Status in Activity Log Manager for Zeitgeist: Invalid Status in Zeitgeist Framework: New Bug description: If I try to select date range more then a month it just freezes. $ activity-log-manager INFO:zeitgeist.client:Reconnected to Zeitgeist engine... Error from Zeitgeist engine: org.freedesktop.DBus.Python.sqlite3.OperationalError: Traceback (most recent call last): File /usr/lib/pymodules/python2.7/dbus/service.py, line 702, in _message_cb retval = candidate_method(self, *args, **keywords) File /usr/share/zeitgeist/_zeitgeist/engine/remote.py, line 337, in DeleteEvents timestamps = self._engine.delete_events(event_ids, sender=sender) File /usr/share/zeitgeist/_zeitgeist/engine/main.py, line 838, in delete_events % ,.join([?] * len(ids)), ids) File /usr/share/zeitgeist/_zeitgeist/engine/sql.py, line 74, in execute return super(UnicodeCursor, self).execute(statement, parameters) OperationalError: too many SQL variables Version: 0.8.0-0ubuntu1~ppa2~natty To manage notifications about this bug go to: https://bugs.launchpad.net/activity-log-manager/+bug/799531/+subscriptions ___ Mailing list: https://launchpad.net/~zeitgeist Post to : zeitgeist@lists.launchpad.net Unsubscribe : https://launchpad.net/~zeitgeist More help : https://help.launchpad.net/ListHelp
[Zeitgeist] libqzeitgeist is now in KDE git
Howdy, all. As I discussed with Seif earlier this week, libqzeitgeist has finished its move to KDE git. The new homepage for the project is https://projects.kde.org/projects/kdesupport/libqzeitgeist This move should inspire more KDE developers to begin to use Zeitgeist in their applications, now that the Qt library is part of KDE's development infrastructure including CIA, bugs.kde.org, Reviewboard, EBN, and others. signature.asc Description: This is a digitally signed message part. ___ Mailing list: https://launchpad.net/~zeitgeist Post to : zeitgeist@lists.launchpad.net Unsubscribe : https://launchpad.net/~zeitgeist More help : https://help.launchpad.net/ListHelp