# HG changeset patch # User nadvornik # Date 1239044995 0 # Node ID 4eed0789a8283038f3803d48a3529c293316f8cb # Parent 5986d49c62f9428eaa4f944b604309d1f48c9bdf optimized sidecar file check diff -r 5986d49c62f9 -r 4eed0789a828 src/filedata.c --- a/src/filedata.c Sun Apr 05 09:46:49 2009 +0000 +++ b/src/filedata.c Mon Apr 06 19:09:55 2009 +0000 @@ -25,6 +25,7 @@ static GHashTable *file_data_pool = NULL; static GHashTable *file_data_planned_change_hash = NULL; +static GHashTable *file_data_basename_hash = NULL; static gint sidecar_file_priority(const gchar *path); @@ -136,7 +137,7 @@ */ FileData *file_data_merge_sidecar_files(FileData *target, FileData *source); -static void file_data_check_sidecars(FileData *fd); +static void file_data_check_sidecars(FileData *fd, gboolean stat_sidecars); FileData *file_data_disconnect_sidecar_file(FileData *target, FileData *sfd); @@ -151,6 +152,50 @@ } } +static void file_data_basename_hash_insert(FileData *fd) +{ + GList *list; + const gchar *ext = extension_from_path(fd->path); + gchar *basename = ext ? g_strndup(fd->path, ext - fd->path) : g_strdup(fd->path); + if (!file_data_basename_hash) + file_data_basename_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); + + list = g_hash_table_lookup(file_data_basename_hash, basename); + + if (!g_list_find(list, fd)) + { + list = g_list_prepend(list, fd); + g_hash_table_insert(file_data_basename_hash, basename, list); + } + else + { + g_free(basename); + } +} + +static void file_data_basename_hash_remove(FileData *fd) +{ + GList *list; + const gchar *ext = extension_from_path(fd->path); + gchar *basename = ext ? g_strndup(fd->path, ext - fd->path) : g_strdup(fd->path); + if (!file_data_basename_hash) + file_data_basename_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); + + list = g_hash_table_lookup(file_data_basename_hash, basename); + + list = g_list_remove(list, fd); + + if (list) + { + g_hash_table_insert(file_data_basename_hash, basename, list); + } + else + { + g_hash_table_remove(file_data_basename_hash, basename); + g_free(basename); + } +} + static void file_data_set_collate_keys(FileData *fd) { gchar *caseless_name; @@ -175,6 +220,8 @@ g_assert(path /* && *path*/); /* view_dir_tree uses FileData with zero length path */ g_assert(file_data_pool); + if (fd->path) file_data_basename_hash_remove(fd); + g_free(fd->path); if (fd->original_path) @@ -227,6 +274,8 @@ fd->extension = fd->name + strlen(fd->name); } + file_data_basename_hash_insert(fd); /* we can ignore the special cases above - they don't have extensions */ + file_data_set_collate_keys(fd); } @@ -295,7 +344,7 @@ file_data_disconnect_sidecar_file(fd, sfd); } - if (sfd) file_data_check_sidecars(sfd); /* this will group the sidecars back together */ + if (sfd) file_data_check_sidecars(sfd, FALSE); /* this will group the sidecars back together */ file_data_send_notification(fd, NOTIFY_REREAD); } else @@ -306,11 +355,11 @@ return ret; } -static FileData *file_data_new(const gchar *path_utf8, struct stat *st, gboolean check_sidecars) +static FileData *file_data_new(const gchar *path_utf8, struct stat *st, gboolean check_sidecars, gboolean stat_sidecars) { FileData *fd; - DEBUG_2("file_data_new: '%s' %d", path_utf8, check_sidecars); + DEBUG_2("file_data_new: '%s' %d %d", path_utf8, check_sidecars, stat_sidecars); if (!file_data_pool) file_data_pool = g_hash_table_new(g_str_hash, g_str_equal); @@ -341,7 +390,7 @@ else changed = file_data_check_changed_files_recursive(fd, st); if (changed && check_sidecars && sidecar_file_priority(fd->extension)) - file_data_check_sidecars(fd); + file_data_check_sidecars(fd, stat_sidecars); DEBUG_2("file_data_pool hit: '%s' %s", fd->path, changed ? "(changed)" : ""); return fd; @@ -358,23 +407,30 @@ file_data_set_path(fd, path_utf8); /* set path, name, collate_key_*, original_path */ if (check_sidecars) - file_data_check_sidecars(fd); + file_data_check_sidecars(fd, stat_sidecars); return fd; } -static void file_data_check_sidecars(FileData *fd) +static void file_data_check_sidecars(FileData *fd, gboolean stat_sidecars) { gint base_len; GString *fname; FileData *parent_fd = NULL; GList *work; + GList *basename_list = NULL; if (fd->disable_grouping || !sidecar_file_priority(fd->extension)) return; base_len = fd->extension - fd->path; fname = g_string_new_len(fd->path, base_len); + + if (!stat_sidecars) + { + basename_list = g_hash_table_lookup(file_data_basename_hash, fname->str); + } + work = sidecar_ext_get_list(); while (work) @@ -396,13 +452,32 @@ } else { - struct stat nst; - g_string_truncate(fname, base_len); - - if (!stat_utf8_case_insensitive_ext(fname, ext, &nst)) - continue; - - new_fd = file_data_new(fname->str, &nst, FALSE); + if (stat_sidecars) + { + struct stat nst; + g_string_truncate(fname, base_len); + if (!stat_utf8_case_insensitive_ext(fname, ext, &nst)) + continue; + new_fd = file_data_new(fname->str, &nst, FALSE, FALSE); + } + else + { + GList *work2 = basename_list; + new_fd = NULL; + + while (work2) + { + FileData *sfd = work2->data; + if (g_ascii_strcasecmp(ext, sfd->extension) == 0) + { + new_fd = file_data_ref(sfd); + break; + } + work2 = work2->next; + } + + if (!new_fd) continue; + } if (new_fd->disable_grouping) { @@ -422,10 +497,10 @@ } -static FileData *file_data_new_local(const gchar *path, struct stat *st, gboolean check_sidecars) +static FileData *file_data_new_local(const gchar *path, struct stat *st, gboolean check_sidecars, gboolean stat_sidecars) { gchar *path_utf8 = path_to_utf8(path); - FileData *ret = file_data_new(path_utf8, st, check_sidecars); + FileData *ret = file_data_new(path_utf8, st, check_sidecars, stat_sidecars); g_free(path_utf8); return ret; @@ -441,7 +516,7 @@ st.st_mtime = 0; } - return file_data_new(path_utf8, &st, TRUE); + return file_data_new(path_utf8, &st, TRUE, TRUE); } FileData *file_data_add_sidecar_file(FileData *target, FileData *sfd) @@ -503,6 +578,7 @@ g_assert(fd->magick == 0x12345678); g_assert(fd->ref == 0); + if (fd->path) file_data_basename_hash_remove(fd); g_hash_table_remove(file_data_pool, fd->original_path); g_free(fd->path); @@ -618,13 +694,13 @@ file_data_send_notification(sfd, NOTIFY_GROUPING); } file_data_send_notification(fd, NOTIFY_GROUPING); - file_data_check_sidecars((FileData *)sidecar_files->data); /* this will group the sidecars back together */ + file_data_check_sidecars((FileData *)sidecar_files->data, FALSE); /* this will group the sidecars back together */ filelist_free(sidecar_files); } } else { - file_data_check_sidecars(fd); + file_data_check_sidecars(fd, FALSE); file_data_send_notification(fd, NOTIFY_GROUPING); } } @@ -887,14 +963,14 @@ strcmp(name, GQ_CACHE_LOCAL_METADATA) != 0 && strcmp(name, THUMB_FOLDER_LOCAL) != 0) { - dlist = g_list_prepend(dlist, file_data_new_local(filepath, &ent_sbuf, FALSE)); + dlist = g_list_prepend(dlist, file_data_new_local(filepath, &ent_sbuf, FALSE, FALSE)); } } else { if (files && filter_name_exists(name)) { - flist = g_list_prepend(flist, file_data_new_local(filepath, &ent_sbuf, TRUE)); + flist = g_list_prepend(flist, file_data_new_local(filepath, &ent_sbuf, TRUE, FALSE)); } } }