Bug 41772 - TP Logger: Introduce TplLogWalker
Summary: TP Logger: Introduce TplLogWalker
Status: RESOLVED FIXED
Alias: None
Product: Telepathy
Classification: Unclassified
Component: logger (show other bugs)
Version: git master
Hardware: Other All
: medium enhancement
Assignee: Telepathy bugs list
QA Contact: Telepathy bugs list
URL: http://cgit.freedesktop.org/~debarshi...
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-10-13 17:10 UTC by Nicolas Dufresne
Modified: 2013-01-21 12:25 UTC (History)
3 users (show)

See Also:
i915 platform:
i915 features:


Attachments
log-walker: Add an example explaining how to use the API (4.49 KB, patch)
2012-08-29 20:32 UTC, Debarshi Ray
Details | Splinter Review

Description Nicolas Dufresne 2011-10-13 17:10:03 UTC
A concept that has been popularized in instant messaging window is the support for infinite scroll back. Currently the logger API is miss-adapted for this task. To solve this solution I'm proposing a new class, TplEventWalker, that would allow scrolling, thus loading more log as wanted.

Requirement:
- Allow walking from a specific date and load older and newer events as needed (log view)
- Allow walking a search from a specific date (log search)
- Allow walking around a specific event (search result context)
Comment 1 Guillaume Desmottes 2011-11-01 02:00:34 UTC
Ideally this API should allow us to get logs from meta-contacts rather than a single persona (see https://bugzilla.gnome.org/show_bug.cgi?id=653338 and https://bugzilla.gnome.org/show_bug.cgi?id=662983).

So either the logger should grow a dep on Folks and provide API to get logs from a FolksIndividual. Or it should provide API to get logs from a bunch of (TP account, contact ID) tuples and aggregate them together.
Comment 2 Nicolas Dufresne 2011-11-01 10:54:43 UTC
No, that's not possible to merge conversion from MSN and Google withing the same walker. The end-result would be a non-sense.
Comment 3 Debarshi Ray 2012-07-06 08:40:02 UTC
A review of the new API would be nice.
Comment 4 Nicolas Dufresne 2012-07-06 08:52:41 UTC
I'll have a look today, but it will be in the afternoon (EST).
Comment 5 Nicolas Dufresne 2012-07-09 16:54:28 UTC
I did an API only review.The log manager part seems fine to me, other method can be added later. For the TplLogWalker though I'd do some changes.

> void tpl_log_walker_get_filtered_events_async (TplLogWalker *walker,
>     guint num_events,
>     GAsyncReadyCallback callback,
>     gpointer user_data);
> 
> gboolean tpl_log_walker_get_filtered_events_finish (TplLogWalker *walker,
>     GAsyncResult *result,
>     GList **events,
>     GError **error);


In this one I'd clearly drop _filtered_, as the walker should not be that specific. Also the filter cannot be changed anyway. Wheter it's a search, a filtered search, or other type of data request does not matter here.

One of the thing that was important in the original design was the direction. This one I guess is forward, though I'd appreciate to see it in the method name. Going backward can be added later without break API.

> 
> gboolean tpl_log_walker_is_begin (TplLogWalker *walker);

This one make some sense, since we can't add event in the past. It might be worth looking around other API to see what would be the best naming. GList uses g_list_first() g_list_last() in a similar API, GHashTableIter does not provide such API.

> 
> gboolean tpl_log_walker_is_end (TplLogWalker *walker);

This one does not make as much sense, as new event could be added later. I think we should introduce an error type that says no more data, and the direction of the request would tell if it's first or last. We should also document that more data might be added later, there is a bug I think that suggest adding signals when new event are inserted.
Comment 6 Debarshi Ray 2012-07-09 19:44:36 UTC
(In reply to comment #5)
> I did an API only review.The log manager part seems fine to me, other method
> can be added later. For the TplLogWalker though I'd do some changes.

Thank you for the review!

I am, personally, a bit confused about what is forward and what is backward. eg., if we have 100 events, with 0 being the oldest and 99 being the most recent, then currently we return 95-99 in the first batch, 90-94 in the second batch and so on? Is this forward or backward?
Comment 7 Nicolas Dufresne 2012-07-09 20:34:43 UTC
(In reply to comment #6)
> (In reply to comment #5)
> > I did an API only review.The log manager part seems fine to me, other method
> > can be added later. For the TplLogWalker though I'd do some changes.
> 
> Thank you for the review!
> 
> I am, personally, a bit confused about what is forward and what is backward.
> eg., if we have 100 events, with 0 being the oldest and 99 being the most
> recent, then currently we return 95-99 in the first batch, 90-94 in the second
> batch and so on? Is this forward or backward?

Good point, as this return stuff from most recent, going forward would be getting older data. But that could be confusing.

The idea is that I don't want UI to keep all the data into RAM. So UIs need a way to forget some of the information, and request it later (in an efficient way).
Comment 8 Debarshi Ray 2012-07-10 22:19:30 UTC
(In reply to comment #7)
> The idea is that I don't want UI to keep all the data into RAM. So UIs need a
> way to forget some of the information, and request it later (in an efficient
> way).

Right.

I thought a bit on how this will be used in Empathy. As the user scrolls down, we can start forgetting some of the older logs, and then fetch them back as the user scrolls up.

For this to work, we need a way to tell TplLogWalker to rewind a few steps in the other direction. eg., if 0 is the oldest event, then ...
0 ---
1 ---
2 ---
3 ---
4 ---
5 ---
6 ---
7 ---
8 ---
9 ---
... at some point we might want to forget events 0 to 4, and tell the walker to rewind back to 4, so that the next time the users scrolls up we can again start fetching from 4. Question is, what should the API look like? Do we provide an offset or a message token? Or both?

Secondly, do we want to combine forward and backward iterating functionality into the same class(es)? Or do we want to keep them separate? C++ has them as separate types.
Comment 9 Nicolas Dufresne 2012-07-10 23:13:07 UTC
Maybe it's another crazy idea, but we could leave the caching to empathy by having bidirectional iterator. Empathy would create two iterator (tailIt, headIt). With headIt it would read a certain amount of information (the amount it wants to be cached. The iterator would have a method to go forward or backward without transfering the data. So if you want to go forward, you query n element from headIt, and advance tailIt of same amount of event.

This could also serve an internal design, as this might be too complicated. The Walker could be considered a cache, initialize with a cached size, and event list being accessible uppon request.

I definitely need to think about it, Guillaume, what did we concluded initially ?
Comment 10 Guillaume Desmottes 2012-07-11 11:23:37 UTC
I don't remember tbh.

 I don't think we'll want to remove older logs in Empathy's chat view, they will just stay there until the chat view is closed. I'm not sure it's worth for the walker too keep already returned events in memory. Why would the user app needs them? They are already displayed.
Comment 11 Debarshi Ray 2012-07-11 18:21:59 UTC
(In reply to comment #5)
> > void tpl_log_walker_get_filtered_events_async (TplLogWalker *walker,
> >     guint num_events,
> >     GAsyncReadyCallback callback,
> >     gpointer user_data);
> > 
> > gboolean tpl_log_walker_get_filtered_events_finish (TplLogWalker *walker,
> >     GAsyncResult *result,
> >     GList **events,
> >     GError **error);
> 
> 
> In this one I'd clearly drop _filtered_, as the walker should not be that
> specific. Also the filter cannot be changed anyway. Wheter it's a search, a
> filtered search, or other type of data request does not matter here.

Fixed. I have dropped "_filtered".
Comment 12 Debarshi Ray 2012-07-12 10:16:39 UTC
I have implemented a rewind method now:

void tpl_log_walker_rewind_async (TplLogWalker *walker,
    guint num_events,
    GAsyncReadyCallback callback,
    gpointer user_data);

gboolean tpl_log_walker_rewind_finish (TplLogWalker *walker,
    GAsyncResult *result,
    GError **error);
Comment 13 Nicolas Dufresne 2012-07-16 19:55:34 UTC
Code looks good. The only thing that is missing for this to be merged is unit tests. For the log manager part, we try and do a code coverage, and trigger some code related to multi-backend merging. And there is more serious tests for log store themeself. See tests/dbus folder.
Comment 14 Debarshi Ray 2012-08-12 14:59:02 UTC
(In reply to comment #13)
> Code looks good. The only thing that is missing for this to be merged is unit
> tests. For the log manager part, we try and do a code coverage, and trigger
> some code related to multi-backend merging. And there is more serious tests for
> log store themeself. See tests/dbus folder.

Could you please take a look again? I have added test cases for get_events. Now we need some for rewind.
Comment 15 Debarshi Ray 2012-08-13 14:55:12 UTC
> Could you please take a look again? I have added test cases for get_events. Now
> we need some for rewind.

Added test cases for rewind.
Comment 16 Debarshi Ray 2012-08-28 16:39:21 UTC
I have now changed the algorithm used by TplLogWalker so that multiple events with the same timestamp are handled better and the size of the event cache is constant.

Added some test cases for TplLogWalker's get_events and rewind API.
Comment 17 Nicolas Dufresne 2012-08-28 20:06:25 UTC
Good work. I have merged upstream this work. There is one last chance to influence this new API, look at this link: http://people.collabora.com/~nicolas/tp-logger/TplLogWalker.html

A release shall be made tomorrow, so it's really the last chance.
Comment 18 Guillaume Desmottes 2012-08-29 07:48:40 UTC
The API looks good to me but the method to create a new walker is missing from the doc.
Comment 19 Debarshi Ray 2012-08-29 08:12:32 UTC
(In reply to comment #18)
> The API looks good to me but the method to create a new walker is missing from
> the doc.

You can create a new walker from the manager using:

/**
 * tpl_log_manager_walk_filtered_events:
 * @manager: a #TplLogManager
 * @account: a #TpAccount
 * @target: a non-NULL #TplEntity
 * @type_mask: event type filter see #TplEventTypeMask
 * @filter: (scope call) (allow-none): an optional filter function
 * @filter_data: user data to pass to @filter
 *
 * Create a #TplLogWalker to traverse all the events exchanged with @target.

 * Returns: (transfer full): a #TplLogWalker
 */
TplLogWalker *
tpl_log_manager_walk_filtered_events (TplLogManager *manager,
    TpAccount *account,
    TplEntity *target,
    gint type_mask,
    TplLogEventFilter filter,
    gpointer filter_data)
Comment 20 Guillaume Desmottes 2012-08-29 08:23:26 UTC
Ah ok :) Maybe add some words in the walker doc explaining this then?

But yeah, the API looks all good to me!
Comment 21 Jonny Lamb 2012-08-29 13:04:24 UTC
(In reply to comment #20)
> Ah ok :) Maybe add some words in the walker doc explaining this then?

Yeah, an example at the top of this page would be cool.

There were some more discussions with people at GUADEC about this kind of thing but I can't remember what we said, so, great... Regardless, I think this API is fine and can be extended easily. Cool!

A couple of comments:

> gboolean            tpl_log_walker_is_begin             (TplLogWalker *walker);

_is_begin doesn't sound English to me? I'd say _is_beginning or _is_start (better).

In fact, I'm really confused about the use of this API. It talks about sequentially looking over logs, but then it can only be rewound, which feels weird. Perhaps some function renaming would be ideal, but more explanation will be thoroughly helpfully. I'd be happy with just some more docs tbh.

Nice work! I'm looking forward to making use of it!
Comment 22 Nicolas Dufresne 2012-08-29 15:36:25 UTC
(In reply to comment #21)
> > gboolean            tpl_log_walker_is_begin             (TplLogWalker *walker);
> 
> _is_begin doesn't sound English to me? I'd say _is_beginning or _is_start
> (better).
> 

yeah, I had the same thought, I'd be happy with _is_start() (the shortest).
Comment 23 Nicolas Dufresne 2012-08-29 15:37:15 UTC
(In reply to comment #21)
> Yeah, an example at the top of this page would be cool.

Defiantly, that would solve most of the confusion.
Comment 24 Nicolas Dufresne 2012-08-29 15:37:54 UTC
(In reply to comment #23)
> (In reply to comment #21)
> > Yeah, an example at the top of this page would be cool.
> 
> Defiantly, that would solve most of the confusion.

oops, I meant definitely.
Comment 25 Debarshi Ray 2012-08-29 20:32:50 UTC
Created attachment 66291 [details] [review]
log-walker: Add an example explaining how to use the API
Comment 26 Nicolas Dufresne 2012-08-29 21:08:12 UTC
(In reply to comment #25)
> Created attachment 66291 [details] [review] [review]
> log-walker: Add an example explaining how to use the API

Merged.


Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.