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 }