diff options
author | Naïm Favier <n@monade.li> | 2024-06-02 15:31:33 +0200 |
---|---|---|
committer | Birte Friesel <derf@chaosdorf.de> | 2024-06-30 11:40:06 +0200 |
commit | 08b269d172acc2b4cb9b9336e2cd8097d89ef6a7 (patch) | |
tree | ece7aca6a7eccf8ca37b863b6ce2dd6f4abf2402 /src | |
parent | 186dab662b50e7aa1e15674c468d35810a691409 (diff) |
cache stat(2) calls
When the user requests sorting by size or mtime, do a "soft preload" of
the file list that only calls stat(2) without loading images.
This avoids calling stat(2) repeatedly on the same files when sorting
the file list, and achieves faster startup on slow filesystems.
Diffstat (limited to 'src')
-rw-r--r-- | src/filelist.c | 95 | ||||
-rw-r--r-- | src/filelist.h | 10 | ||||
-rw-r--r-- | src/list.c | 2 | ||||
-rw-r--r-- | src/menu.c | 4 | ||||
-rw-r--r-- | src/slideshow.c | 8 |
5 files changed, 67 insertions, 52 deletions
diff --git a/src/filelist.c b/src/filelist.c index f1e820c..a5ad890 100644 --- a/src/filelist.c +++ b/src/filelist.c @@ -53,6 +53,8 @@ feh_file *feh_file_new(char *filename) newfile->name = estrdup(s + 1); else newfile->name = estrdup(filename); + newfile->size = -1; + newfile->mtime = 0; newfile->info = NULL; #ifdef HAVE_LIBEXIF newfile->ed = NULL; @@ -89,7 +91,6 @@ feh_file_info *feh_file_info_new(void) info->width = 0; info->height = 0; - info->size = 0; info->pixels = 0; info->has_alpha = 0; info->format = NULL; @@ -305,7 +306,7 @@ void delete_rm_files(void) return; } -gib_list *feh_file_info_preload(gib_list * list) +gib_list *feh_file_info_preload(gib_list * list, int load_images) { gib_list *l; feh_file *file = NULL; @@ -314,20 +315,27 @@ gib_list *feh_file_info_preload(gib_list * list) for (l = list; l; l = l->next) { file = FEH_FILE(l->data); D(("file %p, file->next %p, file->name %s\n", l, l->next, file->name)); - if (feh_file_info_load(file, NULL)) { - D(("Failed to load file %p\n", file)); - remove_list = gib_list_add_front(remove_list, l); - if (opt.verbose) - feh_display_status('x'); - } else if (((unsigned int)file->info->width < opt.min_width) - || ((unsigned int)file->info->width > opt.max_width) - || ((unsigned int)file->info->height < opt.min_height) - || ((unsigned int)file->info->height > opt.max_height)) { - remove_list = gib_list_add_front(remove_list, l); - if (opt.verbose) - feh_display_status('s'); - } else if (opt.verbose) - feh_display_status('.'); + if (load_images) { + if (feh_file_info_load(file, NULL)) { + D(("Failed to load file %p\n", file)); + remove_list = gib_list_add_front(remove_list, l); + if (opt.verbose) + feh_display_status('x'); + } else if (((unsigned int)file->info->width < opt.min_width) + || ((unsigned int)file->info->width > opt.max_width) + || ((unsigned int)file->info->height < opt.min_height) + || ((unsigned int)file->info->height > opt.max_height)) { + remove_list = gib_list_add_front(remove_list, l); + if (opt.verbose) + feh_display_status('s'); + } else if (opt.verbose) + feh_display_status('.'); + } else { + if (feh_file_stat(file)) { + D(("Failed to stat file %p\n", file)); + remove_list = gib_list_add_front(remove_list, l); + } + } if (sig_exit) { feh_display_status(0); exit(sig_exit); @@ -348,23 +356,36 @@ gib_list *feh_file_info_preload(gib_list * list) return(list); } -int feh_file_info_load(feh_file * file, Imlib_Image im) +int feh_file_stat(feh_file * file) { struct stat st; + + errno = 0; + if (stat(file->filename, &st)) { + feh_print_stat_error(file->filename); + return(1); + } + + file->mtime = st.st_mtime; + + file->size = st.st_size; + + return(0); +} + +int feh_file_info_load(feh_file * file, Imlib_Image im) +{ int need_free = 1; Imlib_Image im1; + if (feh_file_stat(file)) + return(1); + D(("im is %p\n", im)); if (im) need_free = 0; - errno = 0; - if (stat(file->filename, &st)) { - feh_print_stat_error(file->filename); - return(1); - } - if (im) im1 = im; else if (!feh_load_image(&im1, file) || !im1) @@ -381,8 +402,6 @@ int feh_file_info_load(feh_file * file, Imlib_Image im) file->info->format = estrdup(gib_imlib_image_format(im1)); - file->info->size = st.st_size; - if (need_free) gib_imlib_free_image_and_decache(im1); return(0); @@ -434,20 +453,8 @@ int feh_cmp_dirname(void *file1, void *file2) /* Return -1 if file1 is _newer_ than file2 */ int feh_cmp_mtime(void *file1, void *file2) { - struct stat s1, s2; - - if (stat(FEH_FILE(file1)->filename, &s1)) { - feh_print_stat_error(FEH_FILE(file1)->filename); - return(-1); - } - - if (stat(FEH_FILE(file2)->filename, &s2)) { - feh_print_stat_error(FEH_FILE(file2)->filename); - return(-1); - } - /* gib_list_sort is not stable, so explicitly return 0 as -1 */ - return(s1.st_mtime >= s2.st_mtime ? -1 : 1); + return(FEH_FILE(file1)->mtime >= FEH_FILE(file2)->mtime ? -1 : 1); } int feh_cmp_width(void *file1, void *file2) @@ -467,7 +474,7 @@ int feh_cmp_pixels(void *file1, void *file2) int feh_cmp_size(void *file1, void *file2) { - return((FEH_FILE(file1)->info->size - FEH_FILE(file2)->info->size)); + return((FEH_FILE(file1)->size - FEH_FILE(file2)->size)); } int feh_cmp_format(void *file1, void *file2) @@ -486,10 +493,16 @@ void feh_prepare_filelist(void) * is set and we're in thumbnail mode, we need to filter images first so * we can create a properly sized thumbnail list. */ - if (opt.list || opt.preload || opt.customlist || (opt.sort > SORT_MTIME) + if (opt.list || opt.preload || opt.customlist || (opt.sort >= SORT_WIDTH) || (opt.filter_by_dimensions && (opt.index || opt.thumbs || opt.bgmode))) { /* For these sort options, we have to preload images */ - filelist = feh_file_info_preload(filelist); + filelist = feh_file_info_preload(filelist, TRUE); + if (!gib_list_length(filelist)) + show_mini_usage(); + } else if (opt.sort >= SORT_SIZE) { + /* For these sort options, we need stat(2) information on the files, + * but there is no need to load the images. */ + filelist = feh_file_info_preload(filelist, FALSE); if (!gib_list_length(filelist)) show_mini_usage(); } diff --git a/src/filelist.h b/src/filelist.h index 7f263dc..e648262 100644 --- a/src/filelist.h +++ b/src/filelist.h @@ -36,6 +36,8 @@ struct __feh_file { char *name; /* info stuff */ + time_t mtime; + int size; feh_file_info *info; /* only set when needed */ #ifdef HAVE_LIBEXIF ExifData *ed; @@ -45,7 +47,6 @@ struct __feh_file { struct __feh_file_info { int width; int height; - int size; int pixels; unsigned char has_alpha; char *format; @@ -71,11 +72,11 @@ enum sort_type { SORT_NAME, SORT_FILENAME, SORT_DIRNAME, + SORT_SIZE, // everything after SORT_SIZE requires stat(2) information on the filelist SORT_MTIME, - SORT_WIDTH, + SORT_WIDTH, // everything after SORT_WIDTH requires preloading the images in the filelist SORT_HEIGHT, SORT_PIXELS, - SORT_SIZE, SORT_FORMAT }; @@ -88,7 +89,8 @@ int file_selector_all(const struct dirent *unused); void add_file_to_filelist_recursively(char *origpath, unsigned char level); void add_file_to_rm_filelist(char *file); void delete_rm_files(void); -gib_list *feh_file_info_preload(gib_list * list); +gib_list *feh_file_info_preload(gib_list * list, int load_images); +int feh_file_stat(feh_file * file); int feh_file_info_load(feh_file * file, Imlib_Image im); void feh_file_dirname(char *dst, feh_file * f, int maxlen); void feh_prepare_filelist(void); @@ -50,7 +50,7 @@ void init_list_mode(void) file->info->height, format_size(file->info->pixels)); printf("\t%s\t%c\t%s\n", - format_size(file->info->size), + format_size(file->size), file->info->has_alpha ? 'X' : '-', file->filename); } @@ -835,7 +835,7 @@ void feh_menu_draw_submenu_at(int x, int y, Imlib_Image dst, int ox, int oy) for (int i= 0; i <= 3; i++) { imlib_image_draw_line(x+i, y+3+i, x+i, y+9-i, 0); } - + return; } @@ -1401,7 +1401,7 @@ static feh_menu *feh_menu_func_gen_info(feh_menu * m) if (!file->info) feh_file_info_load(file, im); if (file->info) { - snprintf(buffer, sizeof(buffer), "Size: %dKb", file->info->size / 1024); + snprintf(buffer, sizeof(buffer), "Size: %dKb", file->size / 1024); feh_menu_add_entry(mm, buffer, NULL, 0, 0, NULL); snprintf(buffer, sizeof(buffer), "Dimensions: %dx%d", file->info->width, file->info->height); feh_menu_add_entry(mm, buffer, NULL, 0, 0, NULL); diff --git a/src/slideshow.c b/src/slideshow.c index a53749e..3944a68 100644 --- a/src/slideshow.c +++ b/src/slideshow.c @@ -496,14 +496,14 @@ char *feh_printf(char *str, feh_file * file, winwidget winwid) } break; case 's': - if (file && (file->info || !feh_file_info_load(file, NULL))) { - snprintf(buf, sizeof(buf), "%d", file->info->size); + if (file && (file->size >= 0 || !feh_file_stat(file))) { + snprintf(buf, sizeof(buf), "%d", file->size); strncat(ret, buf, sizeof(ret) - strlen(ret) - 1); } break; case 'S': - if (file && (file->info || !feh_file_info_load(file, NULL))) { - strncat(ret, format_size(file->info->size), sizeof(ret) - strlen(ret) - 1); + if (file && (file->size >= 0 || !feh_file_stat(file))) { + strncat(ret, format_size(file->size), sizeof(ret) - strlen(ret) - 1); } break; case 't': |