move the bulk of the non-summary searching stuff here. we aggregate up to
2003-02-16 Chris Toshok <toshok@ximian.com> * backend/pas/pas-backend-file.c (pas_backend_file_search_timeout): move the bulk of the non-summary searching stuff here. we aggregate up to our threshold, then send them to the front end and register a timeout to do another batch. This keeps us from totally spamming the UI, making things a bit more responsive. (pas_backend_file_search): set up the closure and call the timeout in an idle func. svn path=/trunk/; revision=19920
This commit is contained in:
committed by
Chris Toshok
parent
8c40386245
commit
d239d2b112
@ -1,3 +1,14 @@
|
||||
2003-02-16 Chris Toshok <toshok@ximian.com>
|
||||
|
||||
* backend/pas/pas-backend-file.c
|
||||
(pas_backend_file_search_timeout): move the bulk of the
|
||||
non-summary searching stuff here. we aggregate up to our
|
||||
threshold, then send them to the front end and register a timeout
|
||||
to do another batch. This keeps us from totally spamming the UI,
|
||||
making things a bit more responsive.
|
||||
(pas_backend_file_search): set up the closure and call the timeout
|
||||
in an idle func.
|
||||
|
||||
2003-02-16 Chris Toshok <toshok@ximian.com>
|
||||
|
||||
* gui/component/select-names/e-select-names-manager.c
|
||||
|
||||
@ -347,6 +347,106 @@ ecard_matches_search (const PASBackendFileBookView *view, ECard *card)
|
||||
return pas_backend_card_sexp_match_ecard (view->card_sexp, card);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
PASBackendFile *bf;
|
||||
PASBook *book;
|
||||
const PASBackendFileBookView *view;
|
||||
DBC *dbc;
|
||||
|
||||
int card_count;
|
||||
int card_threshold;
|
||||
int card_threshold_max;
|
||||
GList *cards;
|
||||
|
||||
gboolean done_first;
|
||||
gboolean search_needed;
|
||||
} FileBackendSearchClosure;
|
||||
|
||||
static void
|
||||
free_search_closure (FileBackendSearchClosure *closure)
|
||||
{
|
||||
g_list_foreach (closure->cards, (GFunc)g_free, NULL);
|
||||
g_list_free (closure->cards);
|
||||
g_free (closure);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pas_backend_file_search_timeout (gpointer data)
|
||||
{
|
||||
FileBackendSearchClosure *closure = data;
|
||||
int db_error = 0;
|
||||
DBT id_dbt, vcard_dbt;
|
||||
int file_version_name_len;
|
||||
DBC *dbc = closure->dbc;
|
||||
|
||||
file_version_name_len = strlen (PAS_BACKEND_FILE_VERSION_NAME);
|
||||
|
||||
memset (&id_dbt, 0, sizeof (id_dbt));
|
||||
memset (&vcard_dbt, 0, sizeof (vcard_dbt));
|
||||
|
||||
if (closure->done_first) {
|
||||
db_error = dbc->c_get(dbc, &id_dbt, &vcard_dbt, DB_NEXT);
|
||||
}
|
||||
else {
|
||||
db_error = dbc->c_get(dbc, &id_dbt, &vcard_dbt, DB_FIRST);
|
||||
closure->done_first = TRUE;
|
||||
}
|
||||
|
||||
while (db_error == 0) {
|
||||
|
||||
/* don't include the version in the list of cards */
|
||||
if (id_dbt.size != file_version_name_len+1
|
||||
|| strcmp (id_dbt.data, PAS_BACKEND_FILE_VERSION_NAME)) {
|
||||
char *vcard_string = vcard_dbt.data;
|
||||
|
||||
/* check if the vcard matches the search sexp */
|
||||
if ((!closure->search_needed) || vcard_matches_search (closure->view, vcard_string)) {
|
||||
closure->cards = g_list_prepend (closure->cards, g_strdup (vcard_string));
|
||||
closure->card_count ++;
|
||||
}
|
||||
|
||||
/* If we've accumulated a number of checks, pass them off to the client. */
|
||||
if (closure->card_count >= closure->card_threshold) {
|
||||
pas_book_view_notify_add (closure->view->book_view, closure->cards);
|
||||
/* Clean up the handed-off data. */
|
||||
g_list_foreach (closure->cards, (GFunc)g_free, NULL);
|
||||
g_list_free (closure->cards);
|
||||
closure->cards = NULL;
|
||||
closure->card_count = 0;
|
||||
|
||||
/* Yeah, this scheme is overly complicated. But I like it. */
|
||||
if (closure->card_threshold < closure->card_threshold_max) {
|
||||
closure->card_threshold = MIN (2*closure->card_threshold, closure->card_threshold_max);
|
||||
}
|
||||
|
||||
/* return here, we'll do the next lump in the next callback */
|
||||
g_timeout_add (200, pas_backend_file_search_timeout, closure);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
db_error = dbc->c_get(dbc, &id_dbt, &vcard_dbt, DB_NEXT);
|
||||
}
|
||||
|
||||
dbc->c_close (dbc);
|
||||
|
||||
if (db_error != DB_NOTFOUND) {
|
||||
g_warning ("pas_backend_file_search: error building list\n");
|
||||
free_search_closure (closure);
|
||||
}
|
||||
|
||||
if (closure->card_count)
|
||||
pas_book_view_notify_add (closure->view->book_view, closure->cards);
|
||||
|
||||
pas_book_view_notify_complete (closure->view->book_view, GNOME_Evolution_Addressbook_BookViewListener_Success);
|
||||
|
||||
free_search_closure (closure);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pas_backend_file_search (PASBackendFile *bf,
|
||||
PASBook *book,
|
||||
@ -382,74 +482,24 @@ pas_backend_file_search (PASBackendFile *bf,
|
||||
do_summary_query (bf, view, completion_search);
|
||||
}
|
||||
else {
|
||||
gint card_count = 0, card_threshold = 20, card_threshold_max = 3000;
|
||||
int db_error = 0;
|
||||
GList *cards = NULL;
|
||||
DB *db = bf->priv->file_db;
|
||||
DBC *dbc;
|
||||
DBT id_dbt, vcard_dbt;
|
||||
int file_version_name_len;
|
||||
FileBackendSearchClosure *closure = g_new0 (FileBackendSearchClosure, 1);
|
||||
DB *db = bf->priv->file_db;
|
||||
int db_error;
|
||||
|
||||
file_version_name_len = strlen (PAS_BACKEND_FILE_VERSION_NAME);
|
||||
closure->card_threshold = 20;
|
||||
closure->card_threshold_max = 3000;
|
||||
closure->search_needed = search_needed;
|
||||
closure->view = view;
|
||||
closure->bf = bf;
|
||||
closure->book = book;
|
||||
|
||||
db_error = db->cursor (db, NULL, &dbc, 0);
|
||||
|
||||
memset (&id_dbt, 0, sizeof (id_dbt));
|
||||
memset (&vcard_dbt, 0, sizeof (vcard_dbt));
|
||||
db_error = db->cursor (db, NULL, &closure->dbc, 0);
|
||||
|
||||
if (db_error != 0) {
|
||||
g_warning ("pas_backend_file_search: error building list\n");
|
||||
} else {
|
||||
db_error = dbc->c_get(dbc, &id_dbt, &vcard_dbt, DB_FIRST);
|
||||
|
||||
while (db_error == 0) {
|
||||
|
||||
/* don't include the version in the list of cards */
|
||||
if (id_dbt.size != file_version_name_len+1
|
||||
|| strcmp (id_dbt.data, PAS_BACKEND_FILE_VERSION_NAME)) {
|
||||
char *vcard_string = vcard_dbt.data;
|
||||
|
||||
/* check if the vcard matches the search sexp */
|
||||
if ((!search_needed) || vcard_matches_search (view, vcard_string)) {
|
||||
cards = g_list_prepend (cards, g_strdup (vcard_string));
|
||||
card_count ++;
|
||||
}
|
||||
|
||||
/* If we've accumulated a number of checks, pass them off to the client. */
|
||||
if (card_count >= card_threshold) {
|
||||
pas_book_view_notify_add (view->book_view, cards);
|
||||
/* Clean up the handed-off data. */
|
||||
g_list_foreach (cards, (GFunc)g_free, NULL);
|
||||
g_list_free (cards);
|
||||
cards = NULL;
|
||||
card_count = 0;
|
||||
|
||||
/* Yeah, this scheme is overly complicated. But I like it. */
|
||||
if (card_threshold < card_threshold_max) {
|
||||
card_threshold = MIN (2*card_threshold, card_threshold_max);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
db_error = dbc->c_get(dbc, &id_dbt, &vcard_dbt, DB_NEXT);
|
||||
}
|
||||
dbc->c_close (dbc);
|
||||
|
||||
if (db_error != DB_NOTFOUND) {
|
||||
g_warning ("pas_backend_file_search: error building list\n");
|
||||
}
|
||||
g_idle_add (pas_backend_file_search_timeout, closure);
|
||||
}
|
||||
|
||||
if (card_count)
|
||||
pas_book_view_notify_add (view->book_view, cards);
|
||||
|
||||
pas_book_view_notify_complete (view->book_view, GNOME_Evolution_Addressbook_BookViewListener_Success);
|
||||
|
||||
/*
|
||||
** It's fine to do this now since the data has been handed off.
|
||||
*/
|
||||
g_list_foreach (cards, (GFunc)g_free, NULL);
|
||||
g_list_free (cards);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user