Jimmy Huang wrote:
On Wed, 2008-07-30 at 15:48 -0700, Rusty Lynch wrote:
Looking through the DBUS introspection at
http://svn.gnome.org/svn/tracker/trunk/data/tracker-introspect.xml, I do
not see a mechanism for notification of new files?
Is the expectation that the app has to re-initiate all of it's searches
each time a new IndexingFinished signal is caught?
For example... a photo app is viewing a UI displaying all photos from
Christmas 2006 (i.e. search for all objects with Image:Date in a given
range) that are tagged with "Family" and "Snow" (i.e. with User:Keyword
containing "Family" or "Snow"), while at the same time some new photo's
show up.
It would be nice if there was some mechanism to have an outstanding
query returning new results on new found data.
Tracker doesn't have a way to know "what files" are indexed, it only
knows "when" files are indexed. So yes, I would say that application
will need to call out a new search after each IndexFinished signal.
It would seem reasonable to extend the tracker API to accommodate such
a mechanism. Pseudo code for such an API could be as follows:
/* start a new search by creating a new search object with a specific
* query. */
ContentSearch *search = content_new_search(query)
/* Configure the search to be continuous, and to send back
* notification of results every time_granularity milliseconds IFF
* the search has collected a hit within that time period */
content_search_set_continuous(search, time_granularity)
/* Hook up the callback for search results */
g_signal_connect(search, "search_results_available",
search_results_available, search)
/* Activate the search */
content_search_execute(search);
...
void search_results_available(..., ContentSearch *search)
{
GList *results = content_search_get_results(search);
GList *tmp = results;
while (tmp) {
printf("Result: %s\n", content_search_result_get_text(
CONTENT_SEARCH_RESULT(tmp->data)));
tmp = tmp->next;
}
...
}
The key concept is that the results should be provided asynchronous
and iteratively. In this way, a long running search that might take a
second to complete could return partial results every 100 milliseconds
as the search is processed allowing a much more dynamic and fluid user
experience.
The daemon can then manage long running searches; as new data is added
to the system, the data can be passed through the search -- if it
matches, it gets added to the results pool and returned at the next
time interval.
Supporting the above becomes more necessary when we think about
external storage devices, where the indexing of content is not
necessarily going to be able to complete rapidly -- however the UI
needs to be responsive and return results as they are found.
For example, if you take a 2G microSD card populated with 500 photos
you took on your cell phone over the last 9 months and plug it into a
device running the Moblin photo management suite, we want the new
photos to start showing up interactively in the UI without requiring
the user to copy all of the photos onto the local device storage.
There would need to be a symmetric API for match-deletions (eg., the
user unplugs the storage device and all of that content disappears, or
the user switches to a different application and deletes the content
from local storage, or deletes a tag from the media that was part of
the filtered search)
To support this, the daemon would have to keep a cache of all the
results provided to the caller so that it would know if a specific
element had already been sent to a continuous search. If details
about a piece of content change such that it does not match the
search, it would need to notify the caller that a specific result is
no longer valid.
It's possible for the app to only update its view by doing a search for
hitcount, and if the hitcount has changed, then perform a new search to
return the newly added content. Instead of doing a search after every
IndexFinished Sigal.
So the pseudo code for that would be:
int last_count;
GList *old_results;
g_signal_connect(tracker, "IndexFinished", finished)
...
void finished()
{
int new_count;
GList *new_results;
new_count = tracker_search_count(tracker, query);
if (last_count != new_count) {
new_results = tracker_search_get_results(tracker,
query);
/* walk new_results comparing to old_results to find
* new elements to add to UI */
...
}
}
We do not want to have to re-execute an entire search multiple times,
or return full data sets when we're only interested in the delta
between what was given before and what is new.
If a search takes 150ms to execute (I don't know if it would -- how
fast is a search through 15k content elements in tracker?), using the
above approach could require 1/3 of a second round trip every time an
item is added to the database -- completely consuming the CPU with
database queries...
Tracker seems to be an active project; it would be great to know if
the maintainers would consider patches to tracker to accommodate the
above type functionality, or if perhaps it already handles it (I am
not really familiar with the existing libtracker APIs)
We also need to work out a mechanism for asynchronous thumb nailing
and thumbnail-loading-to-texture, providing the user experience seen
in this post to the playground:
http://moblin.org/playground/?q=node/2)
James
_______________________________________________
dev mailing list
[email protected]
https://www.moblin.org/mailman/listinfo/dev