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.
This commit is contained in:
Carsten Haitzler 2017-07-29 00:54:12 +09:00
parent a6e000b2e8
commit 712d88dbf0
3 changed files with 183 additions and 93 deletions

View File

@ -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);
}

View File

@ -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))

View File

@ -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)