From 712d88dbf04bd78dabdc0a2065c01a8bc3ed3d4f Mon Sep 17 00:00:00 2001 From: "Carsten Haitzler (Rasterman)" Date: Sat, 29 Jul 2017 00:54:12 +0900 Subject: [PATCH] rage browser mode thumbs - imrpove handling of child thum processes dont overload the machin and leave thumb procs around and handle their death better with tmp files+ atomic rename etc. --- src/bin/albumart.c | 22 +++-- src/bin/thumb.c | 43 ++++++--- src/bin/videothumb.c | 211 ++++++++++++++++++++++++++++--------------- 3 files changed, 183 insertions(+), 93 deletions(-) diff --git a/src/bin/albumart.c b/src/bin/albumart.c index f98ee51..abdc4da 100644 --- a/src/bin/albumart.c +++ b/src/bin/albumart.c @@ -17,6 +17,7 @@ static Eina_Strbuf *sb_result = NULL; static Eina_Bool fetch_image = EINA_FALSE; static char *fetchfile = NULL; static char *fetchpath = NULL; +static char *fetchpath2 = NULL; static FILE *fout = NULL; static void (*_fetch_done) (void *data) = NULL; static void *_fetch_data = NULL; @@ -113,10 +114,14 @@ _cb_http_complete(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) fetch_image = EINA_FALSE; fclose(fout); fout = NULL; - if (ecore_file_size(fetchpath) < 0) - { - ecore_file_unlink(fetchpath); - } + if (ecore_file_size(fetchpath2) < 0) + ecore_file_unlink(fetchpath2); + else + ecore_file_mv(fetchpath2, fetchpath); + free(fetchpath); + free(fetchpath2); + fetchpath = NULL; + fetchpath2 = NULL; } else { @@ -156,7 +161,7 @@ _cb_http_complete(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) } if (ok) { - char *path; + char *path, *path2; ecore_con_url_free(fetch); fetch = NULL; @@ -164,13 +169,18 @@ _cb_http_complete(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) path = _thumbpath(fetchfile); if (path) { - fout = fopen(path, "wb"); + path2 = alloca(strlen(path) + 4 + 1); + sprintf(path2, "%s.tmo", path); + + fout = fopen(path2, "wb"); if (fout) { fetch_image = EINA_TRUE; fetch = _fetch(sb); free(fetchpath); + free(fetchpath2); fetchpath = strdup(path); + fetchpath2 = strdup(path2); } free(path); } diff --git a/src/bin/thumb.c b/src/bin/thumb.c index deddeef..e961785 100644 --- a/src/bin/thumb.c +++ b/src/bin/thumb.c @@ -25,7 +25,7 @@ _cb_fetched(void *data EINA_UNUSED) int w, h; evas_object_image_file_set(im, path, NULL); evas_object_image_size_get(im, &w, &h); - if ((w < 1) || (h < 0)) ecore_file_unlink(path); + if ((w < 1) || (h < 1)) ecore_file_unlink(path); free(path); } exit(0); @@ -33,7 +33,7 @@ _cb_fetched(void *data EINA_UNUSED) static Evas_Object * _media_artwork(Evas_Object *obj, const char *path) -{ +{ emotion_object_file_set(obj, path); Evas_Object *art = emotion_file_meta_artwork_get(obj, path, EMOTION_ARTWORK_PREVIEW_IMAGE); if (!art) art = emotion_file_meta_artwork_get(obj, path, EMOTION_ARTWORK_IMAGE); @@ -48,7 +48,7 @@ _cb_loaded(void *data, Evas_Object *obj, void *info EINA_UNUSED) if (vid_timeout) ecore_timer_del(vid_timeout); vid_timeout = NULL; - + file = data; title = emotion_object_meta_info_get(obj, EMOTION_META_INFO_TRACK_TITLE); artist = emotion_object_meta_info_get(obj, EMOTION_META_INFO_TRACK_ARTIST); @@ -90,6 +90,7 @@ _cb_loaded(void *data, Evas_Object *obj, void *info EINA_UNUSED) { char buf_base[PATH_MAX]; char buf_file[PATH_MAX]; + char buf_file2[PATH_MAX]; unsigned int pos; vidimage = evas_object_image_filled_add(evas_object_evas_get(subwin)); @@ -101,7 +102,7 @@ _cb_loaded(void *data, Evas_Object *obj, void *info EINA_UNUSED) if (!efreet_cache_home_get()) exit(3); snprintf(buf_base, sizeof(buf_base), "%s/rage/thumb/%02x", efreet_cache_home_get(), sum[0]); - snprintf(buf_file, sizeof(buf_base), + snprintf(buf_file, sizeof(buf_file), "%s/%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" "%02x%02x%02x%02x%02x%02x%02x%02x.eet", buf_base, @@ -110,8 +111,9 @@ _cb_loaded(void *data, Evas_Object *obj, void *info EINA_UNUSED) sum[8], sum[9], sum[10], sum[11], sum[12], sum[13], sum[14], sum[15], sum[16], sum[17], sum[18], sum[19]); + snprintf(buf_file2, sizeof(buf_file2), "%s.tmp", buf_file); if (!ecore_file_mkpath(buf_base)) exit(4); - ef = eet_open(buf_file, EET_FILE_MODE_WRITE); + ef = eet_open(buf_file2, EET_FILE_MODE_WRITE); if (!ef) exit(5); pos = 0; for (pos = 0; ; pos += incr) @@ -125,16 +127,16 @@ _cb_loaded(void *data, Evas_Object *obj, void *info EINA_UNUSED) evas_object_image_size_get(vidimage, &iw, &ih); if ((iw <= 1) || (ih <= 1)) { - eet_close(ef); - exit(6); + if (pos <= 0) goto err; + else goto ok; } w = 320; h = (ih * 320) / iw; if (h < 1) h = 1; if ((w > 4096) || (h > 4096)) { - eet_close(ef); - exit(6); + if (pos <= 0) goto err; + else goto ok; } evas_object_resize(vidimage, w, h); evas_object_resize(subwin, w, h); @@ -145,12 +147,19 @@ _cb_loaded(void *data, Evas_Object *obj, void *info EINA_UNUSED) 0, 0, 70, EET_IMAGE_JPEG); else { - eet_close(ef); - exit(6); + if (pos <= 0) goto err; + else goto ok; } evas_object_image_data_set(image, pixels); } +ok: eet_close(ef); + ecore_file_mv(buf_file2, buf_file); + exit(0); +err: + eet_close(ef); + ecore_file_unlink(buf_file2); + exit(6); } } @@ -169,7 +178,7 @@ _local_artwork_poster(Evas_Object *win, const char *path_to_file) emotion_object_init(em, NULL); emotion_object_file_set(em, path_to_file); - + char *path = albumart_file_get(path_to_file); if (path) { @@ -182,10 +191,14 @@ _local_artwork_poster(Evas_Object *win, const char *path_to_file) Evas_Object *artwork = _media_artwork(em, path_to_file); if (artwork) { - evas_object_image_save(artwork, path, NULL, NULL); + char *path2 = alloca(strlen(path) + 4 + 1); + + sprintf(path2, "%s.tmp", path); + evas_object_image_save(artwork, path2, NULL, NULL); evas_object_del(artwork); free(path); /* This speeds things up */ + ecore_file_mv(path2, path); exit(0); } @@ -236,9 +249,9 @@ elm_main(int argc, char **argv) } } - if (poster && _local_artwork_poster(win, file)) + if ((poster) && (_local_artwork_poster(win, file))) { - goto out; + goto out; } if (emotion_object_init(vid, NULL)) diff --git a/src/bin/videothumb.c b/src/bin/videothumb.c index fab434c..51b39df 100644 --- a/src/bin/videothumb.c +++ b/src/bin/videothumb.c @@ -4,13 +4,13 @@ #include "albumart.h" typedef struct _Videothumb Videothumb; +typedef struct _Pending Pending; struct _Videothumb { Evas_Object_Smart_Clipped_Data __clipped_data; Evas_Object *o_img, *o_img2; - Ecore_Exe *thumb_exe; - Ecore_Event_Handler *exe_handler; + Pending *pending; Ecore_Timer *cycle_timer; Ecore_Timer *launch_timer; const char *file; @@ -20,49 +20,115 @@ struct _Videothumb unsigned int realpos; int iw, ih; Evas_Coord w, h; + int tried; Eina_Bool seen : 1; Eina_Bool poster_mode : 1; Eina_Bool poster : 1; }; +struct _Pending +{ + Ecore_Exe *exe; + Evas_Object *obj; + Eina_Stringshare *realpath; +}; + static Evas_Smart *_smart = NULL; static Evas_Smart_Class _parent_sc = EVAS_SMART_CLASS_INIT_NULL; +static Ecore_Event_Handler *exe_handler = NULL; static Eina_List *busy_thumbs = NULL; static Eina_List *vidthumbs = NULL; -static int _thumb_running = 0; - static Eina_Bool _cb_thumb_exe(void *data, int type EINA_UNUSED, void *event); +static void _videothumb_image_load(Evas_Object *obj); static void _videothumb_eval(Evas_Object *obj, Eina_Bool force); static void _smart_calculate(Evas_Object *obj); -static Eina_Bool -_busy_add(const char *file) +static Pending * +_busy_realpath_find(const char *realpath) { Eina_List *l; - const char *s; + Pending *p; - EINA_LIST_FOREACH(busy_thumbs, l, s) + EINA_LIST_FOREACH(busy_thumbs, l, p) { - if (!strcmp(file, s)) return EINA_FALSE; + if (!strcmp(realpath, p->realpath)) return p; } - busy_thumbs = eina_list_append(busy_thumbs, eina_stringshare_add(file)); - return EINA_TRUE; + return NULL; +} + +static Pending * +_busy_exe_find(Ecore_Exe *exe) +{ + Eina_List *l; + Pending *p; + + EINA_LIST_FOREACH(busy_thumbs, l, p) + { + if (exe == p->exe) return p; + } + return NULL; +} + +static Pending * +_busy_add(Evas_Object *obj, Ecore_Exe *exe, const char *realpath) +{ + Pending *p; + + p = calloc(1, sizeof(Pending)); + if (!p) return NULL; + p->exe = exe; + p->obj = obj; + p->realpath = eina_stringshare_add(realpath); + busy_thumbs = eina_list_append(busy_thumbs, p); + return p; +} + +static void +_busy_pending_del(Pending *p) +{ + eina_stringshare_del(p->realpath); + free(p); + busy_thumbs = eina_list_remove(busy_thumbs, p); } static Eina_Bool -_busy_del(const char *file) +_busy_del(Ecore_Exe *exe) { Eina_List *l; - const char *s; + Pending *p; - EINA_LIST_FOREACH(busy_thumbs, l, s) + EINA_LIST_FOREACH(busy_thumbs, l, p) { - if (!strcmp(file, s)) + if (p->exe == exe) { - eina_stringshare_del(s); - busy_thumbs = eina_list_remove_list(busy_thumbs, l); + _busy_pending_del(p); + return EINA_TRUE; + } + } + return EINA_FALSE; +} + +static void +_busy_kill(Pending *p) +{ + ecore_exe_kill(p->exe); + ecore_exe_free(p->exe); + _busy_pending_del(p); +} + +static Eina_Bool +_busy_obj_del(Evas_Object *obj) +{ + Eina_List *l; + Pending *p; + + EINA_LIST_FOREACH(busy_thumbs, l, p) + { + if (p->obj == obj) + { + _busy_kill(p); return EINA_TRUE; } } @@ -73,18 +139,21 @@ static void _thumb_update(Evas_Object *obj) { Videothumb *sd = evas_object_smart_data_get(obj); + Evas_Object *o; char buf[PATH_MAX]; if (!sd) return; snprintf(buf, sizeof(buf), "%u", sd->realpos); - if (sd->o_img2) + o = sd->o_img; + if (o) { - evas_object_image_file_set(sd->o_img2, NULL, NULL); - evas_object_image_file_set(sd->o_img2, sd->realfile, + evas_object_image_file_set(o, NULL, NULL); + evas_object_image_file_set(o, sd->realfile, sd->poster ? NULL : buf); - evas_object_image_preload(sd->o_img2, EINA_FALSE); + evas_object_image_preload(o, EINA_FALSE); evas_object_smart_callback_call(obj, "loaded", NULL); } + _videothumb_image_load(obj); } static void @@ -107,34 +176,37 @@ _videothumb_launch_do(Evas_Object *obj) if (!sd) return; ecore_exe_run_priority_set(10); - if (sd->thumb_exe) + if (sd->pending) { - _busy_del(sd->realpath); - ecore_exe_kill(sd->thumb_exe); - ecore_exe_free(sd->thumb_exe); - sd->thumb_exe = NULL; - _thumb_running--; + while (_busy_obj_del(obj)); + sd->pending = NULL; } + // tried too many times BEFORE... DON'T TRY AGAIN. + if (sd->tried > 5) return; s = ecore_file_escape_name(sd->realpath); if (s) { libdir = elm_app_lib_dir_get(); if (libdir) { - if (_busy_add(sd->realpath)) + if (!_busy_realpath_find(sd->realpath)) { - if (!sd->exe_handler) - sd->exe_handler = ecore_event_handler_add(ECORE_EXE_EVENT_DEL, - _cb_thumb_exe, obj); + Ecore_Exe *exe; + + if (!exe_handler) + exe_handler = ecore_event_handler_add(ECORE_EXE_EVENT_DEL, + _cb_thumb_exe, NULL); snprintf(buf, sizeof(buf), - "%s/rage/utils/rage_thumb %s 10000 %i 1> /dev/null 2>&1", + "%s/rage/utils/rage_thumb %s 10000 %i", libdir, s, sd->poster_mode ? 1 : 0); - sd->thumb_exe = ecore_exe_pipe_run(buf, - ECORE_EXE_USE_SH | - ECORE_EXE_TERM_WITH_PARENT | - ECORE_EXE_NOT_LEADER, - obj); - _thumb_running++; + exe = ecore_exe_pipe_run(buf, + ECORE_EXE_TERM_WITH_PARENT | + ECORE_EXE_NOT_LEADER, + obj); + if (exe) + { + sd->pending = _busy_add(obj, exe, sd->realpath); + } } else return; } @@ -154,7 +226,7 @@ _have_active_thumb(const char *path) if (sd) { - if ((sd->thumb_exe) && (!strcmp(path, sd->realpath))) + if ((sd->pending) && (!strcmp(path, sd->realpath))) return EINA_TRUE; } } @@ -166,9 +238,9 @@ _cb_videothumb_delay(void *data) { Evas_Object *obj = data; Videothumb *sd = evas_object_smart_data_get(obj); - int maxnum = (eina_cpu_count() / 2) + 1; + unsigned int maxnum = (eina_cpu_count() / 2) + 1; if (!sd) return EINA_FALSE; - if (_thumb_running < maxnum) + if (eina_list_count(busy_thumbs) < maxnum) { if (!_have_active_thumb(sd->realpath)) { @@ -192,35 +264,35 @@ _videothumb_launch(Evas_Object *obj) if (!sd) return; if (sd->launch_timer) return; - sd->launch_timer = ecore_timer_add(0.5, _cb_videothumb_delay, obj); + sd->launch_timer = ecore_timer_add(0.2, _cb_videothumb_delay, obj); } static Eina_Bool -_cb_thumb_exe(void *data, int type EINA_UNUSED, void *event) +_cb_thumb_exe(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) { - Ecore_Exe_Event_Del *ev; - Videothumb *sd = evas_object_smart_data_get(data); + Ecore_Exe_Event_Del *ev = event; + Pending *p = _busy_exe_find(ev->exe); - if (!sd) return EINA_TRUE; - ev = event; - if (ev->exe == sd->thumb_exe) + if (p) { Eina_List *l; - Evas_Object *o; + Evas_Object *o, *o2 = p->obj; + + if (o2) + { + Videothumb *sd = evas_object_smart_data_get(o2); + if (sd) + { + sd->pending = NULL; + sd->tried++; + } + } - _busy_del(sd->realpath); - sd->thumb_exe = NULL; - _thumb_running--; EINA_LIST_FOREACH(vidthumbs, l, o) { - _thumb_match_update(o, sd->realpath); + _thumb_match_update(o, p->realpath); } - if (sd->exe_handler) - { - ecore_event_handler_del(sd->exe_handler); - sd->exe_handler = NULL; - } - return EINA_FALSE; + _busy_del(p->exe); } return EINA_TRUE; } @@ -234,7 +306,9 @@ _cb_preload(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void if (sd->o_img) evas_object_del(sd->o_img); sd->o_img = sd->o_img2; sd->o_img2 = NULL; - evas_object_image_size_get(sd->o_img, &(sd->iw), &(sd->ih)); + sd->iw = 0; + sd->ih = 0; + if (sd->o_img) evas_object_image_size_get(sd->o_img, &(sd->iw), &(sd->ih)); if ((sd->iw <= 0) || (sd->ih <= 0)) { if (sd->cycle_timer) @@ -246,7 +320,7 @@ _cb_preload(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void else { sd->pos = 0.0; - if (!sd->thumb_exe) _videothumb_eval(data, EINA_TRUE); + if (!sd->pending) _videothumb_eval(data, EINA_TRUE); } } else @@ -291,6 +365,7 @@ _videothumb_image_load(Evas_Object *obj) if (!sd) return; if (!sd->file) return; + if (sd->pending) return; sd->o_img2 = evas_object_image_filled_add(evas_object_evas_get(obj)); evas_object_image_load_head_skip_set(sd->o_img2, EINA_TRUE); evas_object_smart_member_add(sd->o_img2, obj); @@ -415,29 +490,21 @@ _smart_del(Evas_Object *obj) if (!sd) return; vidthumbs = eina_list_remove(vidthumbs, obj); - if (sd->thumb_exe) - { - if (sd->realpath) _busy_del(sd->realpath); - _thumb_running--; - ecore_exe_kill(sd->thumb_exe); - ecore_exe_free(sd->thumb_exe); - } + while (_busy_obj_del(obj)); if (sd->launch_timer) ecore_timer_del(sd->launch_timer); if (sd->file) eina_stringshare_del(sd->file); if (sd->realfile) eina_stringshare_del(sd->realfile); if (sd->realpath) free(sd->realpath); if (sd->o_img) evas_object_del(sd->o_img); if (sd->o_img2) evas_object_del(sd->o_img2); - if (sd->exe_handler) ecore_event_handler_del(sd->exe_handler); if (sd->cycle_timer) ecore_timer_del(sd->cycle_timer); - sd->thumb_exe = NULL; + sd->pending = NULL; sd->file = NULL; sd->realfile = NULL; sd->realpath = NULL; sd->o_img = NULL; sd->o_img2 = NULL; - sd->exe_handler = NULL; sd->cycle_timer = NULL; _parent_sc.del(obj); @@ -563,7 +630,7 @@ _cb_cycle(void *data) return EINA_FALSE; } sd->pos += 10.0; - if (!sd->thumb_exe) + if (!sd->pending) { _videothumb_eval(obj, EINA_TRUE); if (sd->iw <= 0)