Mercurial > geeqie.yaz
comparison src/filedata.c @ 1518:4eed0789a828
optimized sidecar file check
author | nadvornik |
---|---|
date | Mon, 06 Apr 2009 19:09:55 +0000 |
parents | 5f49f305a6b6 |
children | 24a12aa0cb54 |
comparison
equal
deleted
inserted
replaced
1517:5986d49c62f9 | 1518:4eed0789a828 |
---|---|
23 #include "histogram.h" | 23 #include "histogram.h" |
24 | 24 |
25 | 25 |
26 static GHashTable *file_data_pool = NULL; | 26 static GHashTable *file_data_pool = NULL; |
27 static GHashTable *file_data_planned_change_hash = NULL; | 27 static GHashTable *file_data_planned_change_hash = NULL; |
28 static GHashTable *file_data_basename_hash = NULL; | |
28 | 29 |
29 static gint sidecar_file_priority(const gchar *path); | 30 static gint sidecar_file_priority(const gchar *path); |
30 | 31 |
31 | 32 |
32 /* | 33 /* |
134 * file info struct | 135 * file info struct |
135 *----------------------------------------------------------------------------- | 136 *----------------------------------------------------------------------------- |
136 */ | 137 */ |
137 | 138 |
138 FileData *file_data_merge_sidecar_files(FileData *target, FileData *source); | 139 FileData *file_data_merge_sidecar_files(FileData *target, FileData *source); |
139 static void file_data_check_sidecars(FileData *fd); | 140 static void file_data_check_sidecars(FileData *fd, gboolean stat_sidecars); |
140 FileData *file_data_disconnect_sidecar_file(FileData *target, FileData *sfd); | 141 FileData *file_data_disconnect_sidecar_file(FileData *target, FileData *sfd); |
141 | 142 |
142 | 143 |
143 void file_data_increment_version(FileData *fd) | 144 void file_data_increment_version(FileData *fd) |
144 { | 145 { |
146 fd->valid_marks = 0; | 147 fd->valid_marks = 0; |
147 if (fd->parent) | 148 if (fd->parent) |
148 { | 149 { |
149 fd->parent->version++; | 150 fd->parent->version++; |
150 fd->parent->valid_marks = 0; | 151 fd->parent->valid_marks = 0; |
152 } | |
153 } | |
154 | |
155 static void file_data_basename_hash_insert(FileData *fd) | |
156 { | |
157 GList *list; | |
158 const gchar *ext = extension_from_path(fd->path); | |
159 gchar *basename = ext ? g_strndup(fd->path, ext - fd->path) : g_strdup(fd->path); | |
160 if (!file_data_basename_hash) | |
161 file_data_basename_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); | |
162 | |
163 list = g_hash_table_lookup(file_data_basename_hash, basename); | |
164 | |
165 if (!g_list_find(list, fd)) | |
166 { | |
167 list = g_list_prepend(list, fd); | |
168 g_hash_table_insert(file_data_basename_hash, basename, list); | |
169 } | |
170 else | |
171 { | |
172 g_free(basename); | |
173 } | |
174 } | |
175 | |
176 static void file_data_basename_hash_remove(FileData *fd) | |
177 { | |
178 GList *list; | |
179 const gchar *ext = extension_from_path(fd->path); | |
180 gchar *basename = ext ? g_strndup(fd->path, ext - fd->path) : g_strdup(fd->path); | |
181 if (!file_data_basename_hash) | |
182 file_data_basename_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); | |
183 | |
184 list = g_hash_table_lookup(file_data_basename_hash, basename); | |
185 | |
186 list = g_list_remove(list, fd); | |
187 | |
188 if (list) | |
189 { | |
190 g_hash_table_insert(file_data_basename_hash, basename, list); | |
191 } | |
192 else | |
193 { | |
194 g_hash_table_remove(file_data_basename_hash, basename); | |
195 g_free(basename); | |
151 } | 196 } |
152 } | 197 } |
153 | 198 |
154 static void file_data_set_collate_keys(FileData *fd) | 199 static void file_data_set_collate_keys(FileData *fd) |
155 { | 200 { |
173 static void file_data_set_path(FileData *fd, const gchar *path) | 218 static void file_data_set_path(FileData *fd, const gchar *path) |
174 { | 219 { |
175 g_assert(path /* && *path*/); /* view_dir_tree uses FileData with zero length path */ | 220 g_assert(path /* && *path*/); /* view_dir_tree uses FileData with zero length path */ |
176 g_assert(file_data_pool); | 221 g_assert(file_data_pool); |
177 | 222 |
223 if (fd->path) file_data_basename_hash_remove(fd); | |
224 | |
178 g_free(fd->path); | 225 g_free(fd->path); |
179 | 226 |
180 if (fd->original_path) | 227 if (fd->original_path) |
181 { | 228 { |
182 g_hash_table_remove(file_data_pool, fd->original_path); | 229 g_hash_table_remove(file_data_pool, fd->original_path); |
225 if (fd->extension == NULL) | 272 if (fd->extension == NULL) |
226 { | 273 { |
227 fd->extension = fd->name + strlen(fd->name); | 274 fd->extension = fd->name + strlen(fd->name); |
228 } | 275 } |
229 | 276 |
277 file_data_basename_hash_insert(fd); /* we can ignore the special cases above - they don't have extensions */ | |
278 | |
230 file_data_set_collate_keys(fd); | 279 file_data_set_collate_keys(fd); |
231 } | 280 } |
232 | 281 |
233 static gboolean file_data_check_changed_files_recursive(FileData *fd, struct stat *st) | 282 static gboolean file_data_check_changed_files_recursive(FileData *fd, struct stat *st) |
234 { | 283 { |
293 sfd = work->data; | 342 sfd = work->data; |
294 work = work->next; | 343 work = work->next; |
295 | 344 |
296 file_data_disconnect_sidecar_file(fd, sfd); | 345 file_data_disconnect_sidecar_file(fd, sfd); |
297 } | 346 } |
298 if (sfd) file_data_check_sidecars(sfd); /* this will group the sidecars back together */ | 347 if (sfd) file_data_check_sidecars(sfd, FALSE); /* this will group the sidecars back together */ |
299 file_data_send_notification(fd, NOTIFY_REREAD); | 348 file_data_send_notification(fd, NOTIFY_REREAD); |
300 } | 349 } |
301 else | 350 else |
302 { | 351 { |
303 ret |= file_data_check_changed_files_recursive(fd, &st); | 352 ret |= file_data_check_changed_files_recursive(fd, &st); |
304 } | 353 } |
305 | 354 |
306 return ret; | 355 return ret; |
307 } | 356 } |
308 | 357 |
309 static FileData *file_data_new(const gchar *path_utf8, struct stat *st, gboolean check_sidecars) | 358 static FileData *file_data_new(const gchar *path_utf8, struct stat *st, gboolean check_sidecars, gboolean stat_sidecars) |
310 { | 359 { |
311 FileData *fd; | 360 FileData *fd; |
312 | 361 |
313 DEBUG_2("file_data_new: '%s' %d", path_utf8, check_sidecars); | 362 DEBUG_2("file_data_new: '%s' %d %d", path_utf8, check_sidecars, stat_sidecars); |
314 | 363 |
315 if (!file_data_pool) | 364 if (!file_data_pool) |
316 file_data_pool = g_hash_table_new(g_str_hash, g_str_equal); | 365 file_data_pool = g_hash_table_new(g_str_hash, g_str_equal); |
317 | 366 |
318 fd = g_hash_table_lookup(file_data_pool, path_utf8); | 367 fd = g_hash_table_lookup(file_data_pool, path_utf8); |
339 if (fd->parent) | 388 if (fd->parent) |
340 changed = file_data_check_changed_files(fd); | 389 changed = file_data_check_changed_files(fd); |
341 else | 390 else |
342 changed = file_data_check_changed_files_recursive(fd, st); | 391 changed = file_data_check_changed_files_recursive(fd, st); |
343 if (changed && check_sidecars && sidecar_file_priority(fd->extension)) | 392 if (changed && check_sidecars && sidecar_file_priority(fd->extension)) |
344 file_data_check_sidecars(fd); | 393 file_data_check_sidecars(fd, stat_sidecars); |
345 DEBUG_2("file_data_pool hit: '%s' %s", fd->path, changed ? "(changed)" : ""); | 394 DEBUG_2("file_data_pool hit: '%s' %s", fd->path, changed ? "(changed)" : ""); |
346 | 395 |
347 return fd; | 396 return fd; |
348 } | 397 } |
349 | 398 |
356 fd->magick = 0x12345678; | 405 fd->magick = 0x12345678; |
357 | 406 |
358 file_data_set_path(fd, path_utf8); /* set path, name, collate_key_*, original_path */ | 407 file_data_set_path(fd, path_utf8); /* set path, name, collate_key_*, original_path */ |
359 | 408 |
360 if (check_sidecars) | 409 if (check_sidecars) |
361 file_data_check_sidecars(fd); | 410 file_data_check_sidecars(fd, stat_sidecars); |
362 | 411 |
363 return fd; | 412 return fd; |
364 } | 413 } |
365 | 414 |
366 static void file_data_check_sidecars(FileData *fd) | 415 static void file_data_check_sidecars(FileData *fd, gboolean stat_sidecars) |
367 { | 416 { |
368 gint base_len; | 417 gint base_len; |
369 GString *fname; | 418 GString *fname; |
370 FileData *parent_fd = NULL; | 419 FileData *parent_fd = NULL; |
371 GList *work; | 420 GList *work; |
421 GList *basename_list = NULL; | |
372 | 422 |
373 if (fd->disable_grouping || !sidecar_file_priority(fd->extension)) | 423 if (fd->disable_grouping || !sidecar_file_priority(fd->extension)) |
374 return; | 424 return; |
375 | 425 |
376 base_len = fd->extension - fd->path; | 426 base_len = fd->extension - fd->path; |
377 fname = g_string_new_len(fd->path, base_len); | 427 fname = g_string_new_len(fd->path, base_len); |
428 | |
429 if (!stat_sidecars) | |
430 { | |
431 basename_list = g_hash_table_lookup(file_data_basename_hash, fname->str); | |
432 } | |
433 | |
378 work = sidecar_ext_get_list(); | 434 work = sidecar_ext_get_list(); |
379 | 435 |
380 while (work) | 436 while (work) |
381 { | 437 { |
382 /* check for possible sidecar files; | 438 /* check for possible sidecar files; |
394 { | 450 { |
395 new_fd = fd; /* processing the original file */ | 451 new_fd = fd; /* processing the original file */ |
396 } | 452 } |
397 else | 453 else |
398 { | 454 { |
399 struct stat nst; | 455 if (stat_sidecars) |
400 g_string_truncate(fname, base_len); | 456 { |
401 | 457 struct stat nst; |
402 if (!stat_utf8_case_insensitive_ext(fname, ext, &nst)) | 458 g_string_truncate(fname, base_len); |
403 continue; | 459 if (!stat_utf8_case_insensitive_ext(fname, ext, &nst)) |
404 | 460 continue; |
405 new_fd = file_data_new(fname->str, &nst, FALSE); | 461 new_fd = file_data_new(fname->str, &nst, FALSE, FALSE); |
462 } | |
463 else | |
464 { | |
465 GList *work2 = basename_list; | |
466 new_fd = NULL; | |
467 | |
468 while (work2) | |
469 { | |
470 FileData *sfd = work2->data; | |
471 if (g_ascii_strcasecmp(ext, sfd->extension) == 0) | |
472 { | |
473 new_fd = file_data_ref(sfd); | |
474 break; | |
475 } | |
476 work2 = work2->next; | |
477 } | |
478 | |
479 if (!new_fd) continue; | |
480 } | |
406 | 481 |
407 if (new_fd->disable_grouping) | 482 if (new_fd->disable_grouping) |
408 { | 483 { |
409 file_data_unref(new_fd); | 484 file_data_unref(new_fd); |
410 continue; | 485 continue; |
420 } | 495 } |
421 g_string_free(fname, TRUE); | 496 g_string_free(fname, TRUE); |
422 } | 497 } |
423 | 498 |
424 | 499 |
425 static FileData *file_data_new_local(const gchar *path, struct stat *st, gboolean check_sidecars) | 500 static FileData *file_data_new_local(const gchar *path, struct stat *st, gboolean check_sidecars, gboolean stat_sidecars) |
426 { | 501 { |
427 gchar *path_utf8 = path_to_utf8(path); | 502 gchar *path_utf8 = path_to_utf8(path); |
428 FileData *ret = file_data_new(path_utf8, st, check_sidecars); | 503 FileData *ret = file_data_new(path_utf8, st, check_sidecars, stat_sidecars); |
429 | 504 |
430 g_free(path_utf8); | 505 g_free(path_utf8); |
431 return ret; | 506 return ret; |
432 } | 507 } |
433 | 508 |
439 { | 514 { |
440 st.st_size = 0; | 515 st.st_size = 0; |
441 st.st_mtime = 0; | 516 st.st_mtime = 0; |
442 } | 517 } |
443 | 518 |
444 return file_data_new(path_utf8, &st, TRUE); | 519 return file_data_new(path_utf8, &st, TRUE, TRUE); |
445 } | 520 } |
446 | 521 |
447 FileData *file_data_add_sidecar_file(FileData *target, FileData *sfd) | 522 FileData *file_data_add_sidecar_file(FileData *target, FileData *sfd) |
448 { | 523 { |
449 sfd->parent = target; | 524 sfd->parent = target; |
501 static void file_data_free(FileData *fd) | 576 static void file_data_free(FileData *fd) |
502 { | 577 { |
503 g_assert(fd->magick == 0x12345678); | 578 g_assert(fd->magick == 0x12345678); |
504 g_assert(fd->ref == 0); | 579 g_assert(fd->ref == 0); |
505 | 580 |
581 if (fd->path) file_data_basename_hash_remove(fd); | |
506 g_hash_table_remove(file_data_pool, fd->original_path); | 582 g_hash_table_remove(file_data_pool, fd->original_path); |
507 | 583 |
508 g_free(fd->path); | 584 g_free(fd->path); |
509 g_free(fd->original_path); | 585 g_free(fd->original_path); |
510 g_free(fd->collate_key_name); | 586 g_free(fd->collate_key_name); |
616 work = work->next; | 692 work = work->next; |
617 file_data_disconnect_sidecar_file(fd, sfd); | 693 file_data_disconnect_sidecar_file(fd, sfd); |
618 file_data_send_notification(sfd, NOTIFY_GROUPING); | 694 file_data_send_notification(sfd, NOTIFY_GROUPING); |
619 } | 695 } |
620 file_data_send_notification(fd, NOTIFY_GROUPING); | 696 file_data_send_notification(fd, NOTIFY_GROUPING); |
621 file_data_check_sidecars((FileData *)sidecar_files->data); /* this will group the sidecars back together */ | 697 file_data_check_sidecars((FileData *)sidecar_files->data, FALSE); /* this will group the sidecars back together */ |
622 filelist_free(sidecar_files); | 698 filelist_free(sidecar_files); |
623 } | 699 } |
624 } | 700 } |
625 else | 701 else |
626 { | 702 { |
627 file_data_check_sidecars(fd); | 703 file_data_check_sidecars(fd, FALSE); |
628 file_data_send_notification(fd, NOTIFY_GROUPING); | 704 file_data_send_notification(fd, NOTIFY_GROUPING); |
629 } | 705 } |
630 } | 706 } |
631 | 707 |
632 /* compare name without extension */ | 708 /* compare name without extension */ |
885 !(name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'))) && | 961 !(name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'))) && |
886 strcmp(name, GQ_CACHE_LOCAL_THUMB) != 0 && | 962 strcmp(name, GQ_CACHE_LOCAL_THUMB) != 0 && |
887 strcmp(name, GQ_CACHE_LOCAL_METADATA) != 0 && | 963 strcmp(name, GQ_CACHE_LOCAL_METADATA) != 0 && |
888 strcmp(name, THUMB_FOLDER_LOCAL) != 0) | 964 strcmp(name, THUMB_FOLDER_LOCAL) != 0) |
889 { | 965 { |
890 dlist = g_list_prepend(dlist, file_data_new_local(filepath, &ent_sbuf, FALSE)); | 966 dlist = g_list_prepend(dlist, file_data_new_local(filepath, &ent_sbuf, FALSE, FALSE)); |
891 } | 967 } |
892 } | 968 } |
893 else | 969 else |
894 { | 970 { |
895 if (files && filter_name_exists(name)) | 971 if (files && filter_name_exists(name)) |
896 { | 972 { |
897 flist = g_list_prepend(flist, file_data_new_local(filepath, &ent_sbuf, TRUE)); | 973 flist = g_list_prepend(flist, file_data_new_local(filepath, &ent_sbuf, TRUE, FALSE)); |
898 } | 974 } |
899 } | 975 } |
900 } | 976 } |
901 g_free(filepath); | 977 g_free(filepath); |
902 } | 978 } |