aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/evas/src/bin/evas_cserve_main.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--libraries/evas/src/bin/evas_cserve_main.c1684
1 files changed, 1684 insertions, 0 deletions
diff --git a/libraries/evas/src/bin/evas_cserve_main.c b/libraries/evas/src/bin/evas_cserve_main.c
new file mode 100644
index 0000000..7d4d95a
--- /dev/null
+++ b/libraries/evas/src/bin/evas_cserve_main.c
@@ -0,0 +1,1684 @@
1#ifdef HAVE_CONFIG_H
2# include "config.h"
3#endif
4
5#include <signal.h>
6#include <sys/time.h>
7#include <time.h>
8#ifdef _WIN32
9# include <windows.h>
10#endif
11
12#ifdef BUILD_PTHREAD
13#include <pthread.h>
14#endif
15
16#include "Evas.h"
17#include "evas_cs.h"
18
19#define D(...) EINA_LOG_DOM_DBG(_evas_cserve_bin_log_dom, __VA_ARGS__)
20#ifdef ERR
21#undef ERR
22#endif
23#define ERR(...) EINA_LOG_DOM_ERR(_evas_cserve_bin_log_dom, __VA_ARGS__)
24#ifdef DBG
25#undef DBG
26#endif
27#define DBG(...) EINA_LOG_DOM_DBG(_evas_cserve_bin_log_dom, __VA_ARGS__)
28#ifdef WRN
29#undef WRN
30#endif
31#define WRN(...) EINA_LOG_DOM_WARN(_evas_cserve_bin_log_dom, __VA_ARGS__)
32
33#ifdef CSERVE_BIN_DEFAULT_COLOR
34#undef CSERVE_BIN_DEFAULT_COLOR
35#endif
36#define CSERVE_BIN_DEFAULT_COLOR EINA_COLOR_BLUE
37// fixme:'s
38//
39// preload - make it work (both)
40
41//
42// pants!
43
44typedef struct _Img Img;
45typedef struct _Lopt Lopt;
46typedef struct _Load_Inf Load_Inf;
47
48struct _Lopt
49{
50 int scale_down_by; // if > 1 then use this
51 double dpi; // if > 0.0 use this
52 int w, h; // if > 0 use this
53 struct {
54 int x, y, w, h;
55 } region;
56};
57
58struct _Img
59{
60 Image_Entry ie;
61 int ref;
62 int dref;
63 int usage;
64 Mem *mem;
65 const char *key;
66 time_t cached;
67 struct {
68 const char *file;
69 const char *key;
70 time_t modtime;
71 time_t last_stat;
72 } file;
73 struct {
74 int load1saved, load2saved;
75 double load1, load2;
76 } stats;
77 Lopt load_opts;
78 struct {
79 int w, h;
80 void *data;
81 Eina_Bool alpha : 1;
82 } image;
83 int incache;
84 LK(lock);
85 Eina_Bool dead : 1;
86 Eina_Bool active : 1;
87 Eina_Bool useless : 1;
88 Eina_Bool killme : 1;
89};
90
91struct _Load_Inf
92{
93 Img *img;
94 Client *c;
95};
96
97// config
98static int stat_res_interval = 2;
99
100static time_t t_now = 0;
101
102static int server_id = 0;
103
104LK(strshr_freeme_lock);
105static int strshr_freeme_count = 0;
106static int strshr_freeme_alloc = 0;
107static const char **strshr_freeme = NULL;
108
109static int cache_cleanme = 0;
110static Evas_Cache_Image *cache = NULL;
111
112static Eina_Hash *active_images = NULL;
113LK(cache_lock);
114static Eina_List *cache_images = NULL;
115static int cache_usage = 0;
116static int cache_max_usage = 1 * 1024;
117static int cache_max_adjust = 0;
118static int cache_item_timeout = -1;
119static int cache_item_timeout_check = -1;
120static Mem *stat_mem = NULL;
121static int _evas_cserve_bin_log_dom = -1;
122static Eina_List *stat_mems = NULL;
123
124static void cache_clean(void);
125
126#ifndef _WIN32
127static double
128get_time(void)
129{
130 struct timeval timev;
131
132 gettimeofday(&timev, NULL);
133 return (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000);
134}
135#else
136static double
137get_time(void)
138{
139 return (double)GetTickCount()/1000.0;
140}
141#endif
142
143static int mem_total = 0;
144static int mem_free = 0;
145static int mem_buffers = 0;
146static int mem_cached = 0;
147
148static void
149meminfo_check(void)
150{
151 FILE *f;
152 char buf[1024];
153 int v;
154
155 f = fopen("/proc/meminfo", "r");
156 if (!f) return;
157 if (!fgets(buf, sizeof(buf), f)) goto done;
158 v = 0; if (sscanf(buf, "%*s %i %*s", &v) != 1) goto done;
159 mem_total = v;
160 if (!fgets(buf, sizeof(buf), f)) goto done;
161 v = 0; if (sscanf(buf, "%*s %i %*s", &v) != 1) goto done;
162 mem_free = v;
163 if (!fgets(buf, sizeof(buf), f)) goto done;
164 v = 0; if (sscanf(buf, "%*s %i %*s", &v) != 1) goto done;
165 mem_buffers = v;
166 if (!fgets(buf, sizeof(buf), f)) goto done;
167 v = 0; if (sscanf(buf, "%*s %i %*s", &v) != 1) goto done;
168 mem_cached = v;
169 done:
170 fclose(f);
171}
172
173static int stats_dirty = 0;
174static int saved_loads = 0;
175static double saved_load_time = 0;
176static double saved_load_lifetime = 0;
177
178static int saved_loaddatas = 0;
179static double saved_loaddata_time = 0;
180static double saved_loaddata_lifetime = 0;
181
182static int saved_memory = 0;
183static int saved_memory_peak = 0;
184static int alloced_memory = 0;
185static int alloced_memory_peak = 0;
186static int real_memory = 0;
187static int real_memory_peak = 0;
188
189static Eina_Bool
190stats_hash_image_cb(const Eina_Hash *hash __UNUSED__,
191 const void *key __UNUSED__,
192 void *data, void *fdata __UNUSED__)
193{
194 Img *img = data;
195
196
197 saved_load_time += img->stats.load1 * img->stats.load1saved;
198 saved_loaddata_time += img->stats.load2 * img->stats.load2saved;
199 if (img->ref > 1)
200 saved_memory += img->image.w * img->image.h * sizeof(DATA32) * (img->ref - 1);
201 if (img->mem)
202 {
203 alloced_memory += img->image.w * img->image.h * sizeof(DATA32);
204 real_memory += (((img->image.w * img->image.h * sizeof(DATA32)) + 4095) >> 12) << 12;
205 }
206 return 1;
207}
208
209static void
210stats_calc(void)
211{
212 Img *img;
213 Eina_List *l;
214
215 if (!stats_dirty) return;
216 stats_dirty = 0;
217 saved_loads = 0;
218 saved_load_time = 0;
219 saved_loaddatas = 0;
220 saved_loaddata_time = 0;
221 saved_memory = 0;
222 alloced_memory = 0;
223 real_memory = 0;
224
225 if (active_images)
226 eina_hash_foreach(active_images, stats_hash_image_cb, NULL);
227 LKL(cache_lock);
228 EINA_LIST_FOREACH(cache_images, l, img)
229 {
230 saved_loads += img->stats.load1saved;
231 saved_load_time += img->stats.load1 * img->stats.load1saved;
232 saved_loaddatas += img->stats.load2saved;
233 saved_loaddata_time += img->stats.load2 * img->stats.load2saved;
234 if (img->mem)
235 {
236 alloced_memory += img->image.w * img->image.h * sizeof(DATA32);
237 real_memory += (((img->image.w * img->image.h * sizeof(DATA32)) + 4095) >> 12) << 12;
238 }
239 }
240 LKU(cache_lock);
241 if (saved_memory > saved_memory_peak)
242 saved_memory_peak = saved_memory;
243 if (real_memory > real_memory_peak)
244 real_memory_peak = real_memory;
245 if (alloced_memory > alloced_memory_peak)
246 alloced_memory_peak = alloced_memory;
247}
248
249static void
250stats_update(void)
251{
252 stats_dirty = 1;
253}
254
255static void
256stats_lifetime_update(Img *img)
257{
258 saved_load_lifetime += img->stats.load1 * img->stats.load1saved;
259 saved_loaddata_lifetime += img->stats.load2 * img->stats.load2saved;
260}
261
262static void
263stat_clean(Mem *m)
264{
265 int *ints;
266 int size, pid, *ids, count, i;
267
268 ints = (int *)m->data;
269 size = ints[0];
270 if (!evas_cserve_mem_resize(m, size)) return;
271 ints = (int *)m->data;
272 pid = ints[1];
273 count = (size - (2 * sizeof(int))) / sizeof(int);
274 ids = ints + 2;
275 for (i = 0; i < count; i++)
276 evas_cserve_mem_del(pid, ids[i]);
277}
278
279static int
280stat_init(Mem *m)
281{
282 int *ints;
283
284 ints = (int *)m->data;
285
286 if (!evas_cserve_mem_resize(m, 2 * sizeof(int))) return 0;
287 ints[0] = 2 * sizeof(int);
288 ints[1] = getpid();
289 msync(m->data, 2 * sizeof(int), MS_SYNC | MS_INVALIDATE);
290 return 1;
291}
292
293static int
294stat_update(Mem *m)
295{
296 Eina_List *l;
297 Mem *m2;
298 int *ints, *ids, i;
299
300 ints = (int *)m->data;
301 ints[0] = (2 * sizeof(int)) + (eina_list_count(stat_mems) * sizeof(int));
302 if (!evas_cserve_mem_resize(m, ints[0])) return 0;
303 ints = (int *)m->data;
304 ids = ints + 2;
305 i = 0;
306 EINA_LIST_FOREACH(stat_mems, l, m2)
307 {
308 ids[i] = m2->id;
309 i++;
310 }
311 msync(m->data, ints[0], MS_SYNC | MS_INVALIDATE);
312 return 1;
313}
314
315static Image_Entry *
316_img_alloc(void)
317{
318 Img *img;
319
320 img = calloc(1, sizeof(Img));
321 LKI(img->lock);
322 return (Image_Entry *)img;
323}
324
325static void
326_img_dealloc(Image_Entry *ie)
327{
328 Img *img = (Img *)ie;
329 LKD(img->lock);
330 free(img);
331}
332
333static int
334_img_surface_alloc(Image_Entry *ie, unsigned int w, unsigned int h)
335{
336 Img *img = (Img *)ie;
337
338 img->mem = evas_cserve_mem_new(w * h * sizeof(DATA32), NULL);
339 if (!img->mem) return -1;
340 img->image.data = img->mem->data + img->mem->offset;
341
342 stat_mems = eina_list_append(stat_mems, img->mem);
343 stat_update(stat_mem);
344 return 0;
345}
346
347static void
348_img_surface_delete(Image_Entry *ie)
349{
350 Img *img = (Img *)ie;
351
352 if (!img->mem) return;
353
354 stat_mems = eina_list_remove(stat_mems, img->mem);
355 stat_update(stat_mem);
356
357 evas_cserve_mem_free(img->mem);
358 img->mem = NULL;
359 img->image.data = NULL;
360}
361
362static DATA32 *
363_img_surface_pixels(Image_Entry *ie)
364{
365 Img *img = (Img *)ie;
366
367 return img->image.data;
368}
369
370static int
371_img_load(Image_Entry *ie)
372{
373 return evas_common_load_rgba_image_module_from_file(ie);
374}
375
376static void
377_img_unload(Image_Entry *ie __UNUSED__)
378{
379}
380
381static void
382_img_dirty_region(Image_Entry *ie __UNUSED__, unsigned int x __UNUSED__, unsigned int y __UNUSED__, unsigned int w __UNUSED__, unsigned int h __UNUSED__)
383{
384}
385
386static int
387_img_dirty(Image_Entry *dst __UNUSED__, const Image_Entry *src __UNUSED__)
388{
389 return 0;
390}
391
392static int
393_img_size_set(Image_Entry *dst __UNUSED__, const Image_Entry *src __UNUSED__, unsigned int w __UNUSED__, unsigned int h __UNUSED__)
394{
395 return 0;
396}
397
398static int
399_img_copied_data(Image_Entry *ie __UNUSED__, unsigned int w __UNUSED__, unsigned int h __UNUSED__, DATA32 *image_data __UNUSED__, int alpha __UNUSED__, int cspace __UNUSED__)
400{
401 return 0;
402}
403
404static int
405_img_data(Image_Entry *ie __UNUSED__, unsigned int w __UNUSED__, unsigned int h __UNUSED__, DATA32 *image_data __UNUSED__, int alpha __UNUSED__, int cspace __UNUSED__)
406{
407 return 0;
408}
409
410static int
411_img_color_space(Image_Entry *ie __UNUSED__, int cspace __UNUSED__)
412{
413 return 0;
414}
415
416static int
417_img_load_data(Image_Entry *ie)
418{
419 return evas_common_load_rgba_image_data_from_file(ie);
420}
421
422static int
423_img_mem_size_get(Image_Entry *ie __UNUSED__)
424{
425 return 1;
426}
427
428static void
429img_init(void)
430{
431 const Evas_Cache_Image_Func cache_funcs =
432 {
433 _img_alloc,//Image_Entry *(*alloc)(void);
434 _img_dealloc,//void (*dealloc)(Image_Entry *im);
435 /* The cache provide some helpers for surface manipulation. */
436 _img_surface_alloc,//int (*surface_alloc)(Image_Entry *im, unsigned int w, unsigned int h);
437 _img_surface_delete,//void (*surface_delete)(Image_Entry *im);
438 _img_surface_pixels,//DATA32 *(*surface_pixels)(Image_Entry *im);
439 /* The cache is doing the allocation and deallocation, you must just do the rest. */
440 _img_load,//int (*constructor)(Image_Entry *im);
441 _img_unload,//void (*destructor)(Image_Entry *im);
442 _img_dirty_region,//void (*dirty_region)(Image_Entry *im, unisnged int x, unisnged int y, unisnged int w, unsigned int h);
443 /* Only called when references > 0. Need to provide a fresh copie of im. */
444 /* The destination surface does have a surface, but no allocated pixel data. */
445 _img_dirty,//int (*dirty)(Image_Entry *dst, const Image_Entry *src);
446 /* Only called when references == 1. We will call drop on im'. */
447 /* The destination surface does not have any surface. */
448 _img_size_set,//int (*size_set)(Image_Entry *dst, const Image_Entry *src, unisnged int w, unisnged int h);
449 /* The destination surface does not have any surface. */
450 _img_copied_data,//int (*copied_data)(Image_Entry *dst, unisnged int w, unisnged int h, DATA32 *image_data, int alpha, int cspace);
451 /* The destination surface does not have any surface. */
452 _img_data,//int (*data)(Image_Entry *dst, unsigned int w, unisgned int h, DATA32 *image_data, int alpha, int cspace);
453 _img_color_space,//int (*color_space)(Image_Entry *dst, int cspace);
454 /* This function need to update im->w and im->h. */
455 _img_load_data,//int (*load)(Image_Entry *im);
456 _img_mem_size_get,//int (*mem_size_get)(Image_Entry *im);
457 NULL,//void (*debug)(const char *context, Image_Entry *im);
458 };
459
460 active_images = eina_hash_string_superfast_new(NULL);
461 cache = evas_cache_image_init(&cache_funcs);
462 LKI(cache_lock);
463 LKI(strshr_freeme_lock);
464}
465
466static void
467img_shutdown(void)
468{
469 evas_cache_image_shutdown(cache);
470 cache = NULL;
471 // FIXME: shutdown properly
472 LKD(strshr_freeme_lock);
473 LKI(cache_lock);
474}
475
476static Img *
477img_new(const char *file, const char *key, RGBA_Image_Loadopts *load_opts, const char *bufkey)
478{
479 Img *img;
480 struct stat st;
481 int ret;
482 Image_Entry *ie;
483 int err = 0;
484 double t;
485
486 DBG("... stat %s", file);
487 ret = stat(file, &st);
488 if (ret < 0) return NULL;
489 DBG("... load header");
490 t = get_time();
491 ie = evas_cache_image_request(cache, file, key, load_opts, &err);
492 t = get_time() - t;
493 DBG("... header done");
494 if (!ie) return NULL;
495 DBG("... ie->cache = %p", ie->cache);
496 img = (Img *)ie;
497 img->stats.load1 = t;
498 img->key = eina_stringshare_add(bufkey);
499 img->file.modtime = st.st_mtime;
500 img->file.last_stat = t_now;
501 img->file.file = eina_stringshare_add(file);
502 if (key) img->file.key = eina_stringshare_add(key);
503 img->load_opts.scale_down_by = load_opts->scale_down_by;
504 img->load_opts.dpi = load_opts->dpi;
505 img->load_opts.w = load_opts->w;
506 img->load_opts.h = load_opts->h;
507 img->image.w = ie->w;
508 img->image.h = ie->h;
509 img->image.alpha = ie->flags.alpha;
510 img->ref = 1;
511 img->active = 1;
512 img->usage = sizeof(Img) + strlen(img->key) + 1 +
513 strlen(img->file.file) + 1;
514 if (img->file.key) img->usage += strlen(img->file.key) + 1;
515 eina_hash_direct_add(active_images, img->key, img);
516 return img;
517}
518
519static void
520img_loaddata(Img *img)
521{
522 double t;
523
524 if (img->mem) return;
525 t = get_time();
526 LKL(cache_lock);
527 evas_cache_image_load_data((Image_Entry *)img);
528 t = get_time() - t;
529 img->stats.load2 = t;
530 if (img->image.data)
531 msync(img->image.data, img->image.w * img->image.h * sizeof(DATA32), MS_SYNC | MS_INVALIDATE);
532 if (!img->active) cache_usage -= img->usage;
533 img->usage +=
534 (4096 * (((img->image.w * img->image.h * sizeof(DATA32)) + 4095) / 4096)) +
535 sizeof(Mem);
536 if (!img->active) cache_usage += img->usage;
537 LKU(cache_lock);
538 cache_clean();
539}
540
541static void
542img_free(Img *img)
543{
544 if (img->incache > 0)
545 {
546 ERR("EEEEEEEEEEEEEEEEK!");
547 ERR("EEEEEEEEEEEEEEEEK! %p '%s' still in cache",
548 img, img->file.file);
549 ERR("EEEEEEEEEEEEEEEEK!");
550 return;
551 }
552 stats_lifetime_update(img);
553 stats_update();
554
555 LKL(strshr_freeme_lock);
556 strshr_freeme_count += 3;
557 if (strshr_freeme_count > strshr_freeme_alloc)
558 {
559 const char **tmp;
560
561 strshr_freeme_alloc += 32;
562 tmp = realloc(strshr_freeme, strshr_freeme_alloc * sizeof(const char **));
563 if (tmp) strshr_freeme = tmp;
564 else
565 {
566 ERR("realloc of strshr_freeme failed for %i items",
567 strshr_freeme_alloc);
568 strshr_freeme_alloc -= 32;
569 strshr_freeme_count -= 3;
570 return;
571 }
572 }
573 strshr_freeme[strshr_freeme_count - 3] = img->key;
574 strshr_freeme[strshr_freeme_count - 2] = img->file.file;
575 strshr_freeme[strshr_freeme_count - 1] = img->file.key;
576 LKU(strshr_freeme_lock);
577
578 evas_cache_image_drop((Image_Entry *)img);
579}
580
581static void
582cache_clean(void)
583{
584 DBG("... cache clean!!! do");
585 LKL(cache_lock);
586 while ((cache_usage > ((cache_max_usage + cache_max_adjust) * 1024)) &&
587 (cache_images))
588 {
589 Img *img;
590 Eina_List *l;
591
592 DBG("... clean loop %i > %i", cache_usage, (cache_max_usage + cache_max_adjust) * 1024);
593 l = eina_list_last(cache_images); // THREAD: called from thread. happens to be safe as it uses no unlocked shared resources
594 if (!l) break;
595 img = l->data;
596 if (!img) break;
597 LKL(img->lock);
598 DBG("... REMOVE %p '%s'", img, img->file.file);
599#ifdef BUILD_PTHREAD
600 img->killme = 1;
601 img->useless = 1;
602 img->dead = 1;
603 cache_cleanme++;
604 LKU(img->lock);
605#else
606 cache_images = eina_list_remove_list(cache_images, l); // FIXME: called from thread
607 img->incache--;
608 cache_usage -= img->usage;
609 DBG("... IMG FREE %p", img);
610 img_free(img);
611#endif
612 }
613 LKU(cache_lock);
614}
615
616static void
617cache_timeout(time_t t)
618{
619 Eina_List *l, *l_next;
620 Img *img;
621
622 if (cache_item_timeout < 0) return;
623 LKL(cache_lock);
624 EINA_LIST_FOREACH_SAFE(cache_images, l, l_next, img)
625 {
626 LKL(img->lock);
627 if ((t - img->cached) > cache_item_timeout)
628 {
629 cache_images = eina_list_remove_list(cache_images, l);
630 img->incache--;
631 cache_usage -= img->usage;
632 img_free(img);
633 }
634 else
635 LKU(img->lock);
636 }
637 LKU(cache_lock);
638}
639
640static void
641mem_cache_adjust(void)
642{
643 int pval = cache_max_adjust;
644 int max = 0;
645 int mem_used;
646
647 if (mem_total <= 0) return;
648 mem_used = mem_total - mem_free - mem_cached - mem_buffers;
649#if 0 // this lets the image cache to grow to fill all real free ram, if
650 // there is any (ie ram unused by disk cache)
651 if (mem_free < mem_total)
652 {
653 cache_max_adjust = mem_free;
654 return;
655 }
656#endif
657
658 max = ((mem_free + mem_cached + mem_buffers) / 8) - cache_max_usage;
659 if (max < 0) max = 0;
660 if (max > cache_max_usage) max = cache_max_usage;
661 cache_max_adjust = max - cache_max_usage;
662
663 if (cache_max_adjust < -cache_max_usage)
664 cache_max_adjust = -cache_max_usage;
665 DBG("... cache_max_adjust = %i", cache_max_adjust);
666 if (pval != cache_max_adjust)
667 {
668 DBG("... cache clean");
669 // FIXME lock problem
670 cache_clean();
671 }
672}
673
674static void
675img_cache(Img *img)
676{
677 eina_hash_del(active_images, img->key, img);
678 if (img->dead)
679 {
680 DBG("... img %p '%s' dead", img , img->file.file);
681 img_free(img);
682 return;
683 }
684 if ((cache_usage + img->usage) > ((cache_max_usage + cache_max_adjust) * 1024))
685 {
686 DBG("... img %p '%s' too big for cache", img , img->file.file);
687 img_free(img);
688 return;
689 }
690 DBG("... img %p '%s' cached += %i", img , img->file.file, img->usage);
691 if (img->incache > 0)
692 {
693 ERR("EEEEEEEEEEEEEEEEK!");
694 ERR("EEEEEEEEEEEEEEEEK! %p '%s' already in cache",
695 img, img->file.file);
696 ERR("EEEEEEEEEEEEEEEEK!");
697 return;
698 }
699 LKL(cache_lock);
700 cache_images = eina_list_prepend(cache_images, img);
701 LKU(cache_lock);
702 img->incache++;
703 cache_usage += img->usage;
704 img->active = 0;
705 img->cached = t_now;
706 // FIXME: lock problem
707 if (cache_usage > ((cache_max_usage + cache_max_adjust) * 1024))
708 cache_clean();
709}
710
711static void
712img_dead(Img *img)
713{
714 if (img->active) return;
715 LKL(cache_lock);
716 cache_images = eina_list_remove(cache_images, img);
717 LKU(cache_lock);
718 img->incache--;
719 cache_usage -= img->usage;
720 img_free(img);
721}
722
723static Eina_Bool
724img_ok(Img *img)
725{
726 struct stat st;
727 int ret;
728
729 if (img->dead) return 0;
730 if ((t_now > img->file.last_stat) &&
731 ((t_now - img->file.last_stat) < stat_res_interval)) return 1;
732 img->file.last_stat = t_now;
733 ret = stat(img->file.file, &st);
734 img->file.last_stat = t_now;
735 if (ret < 0)
736 {
737 img->dead = 1;
738 img_dead(img);
739 return 0;
740 }
741 if (st.st_mtime != img->file.modtime)
742 {
743 img->dead = 1;
744 img_dead(img);
745 return 0;
746 }
747 return 1;
748}
749
750static Img *
751img_load(const char *file, const char *key, RGBA_Image_Loadopts *load_opts)
752{
753 Img *img;
754 char buf[8192];
755 Eina_List *l, *l_next;
756
757 if (!file) return NULL;
758 DBG("... img_load '%s'", file);
759 if (key) DBG("... ... key '%s'", key);
760 if (key)
761 snprintf(buf, sizeof(buf), "%s///::/%s/\001/%i/%1.8f/%ix%i",
762 file, key,
763 load_opts->scale_down_by,
764 load_opts->dpi,
765 load_opts->w, load_opts->h);
766 else
767 snprintf(buf, sizeof(buf), "%s///\001/%i/%1.8f/%ix%i",
768 file,
769 load_opts->scale_down_by,
770 load_opts->dpi,
771 load_opts->w, load_opts->h);
772 DBG("... find '%s'", buf);
773 img = eina_hash_find(active_images, buf);
774 if ((img) && (img_ok(img)))
775 {
776 DBG("... found!");
777 img->stats.load1saved++;
778 img->ref++;
779 DBG("... stats update");
780 stats_update();
781 DBG("... return %p", img);
782 return img;
783 }
784
785 // FIXME: keep hash of cached images too
786 LKL(cache_lock);
787 EINA_LIST_FOREACH_SAFE(cache_images, l, l_next, img)
788 {
789 if (!strcmp(img->key, buf))
790 {
791 LKL(img->lock);
792 if (img_ok(img))
793 {
794 DBG("... found cached");
795 cache_images = eina_list_remove_list(cache_images, l);
796 img->incache--;
797 cache_usage -= img->usage;
798 img->active = 1;
799 img->stats.load1saved++;
800 img->ref++;
801 eina_hash_direct_add(active_images, img->key, img);
802 DBG("... sats update");
803 stats_update();
804 DBG("... return %p", img);
805 LKU(img->lock);
806 LKU(cache_lock);
807 return img;
808 }
809 LKU(img->lock);
810 }
811 }
812 LKU(cache_lock);
813 DBG("... ned new img");
814 return img_new(file, key, load_opts, buf);
815}
816
817static void
818img_unload(Img *img)
819{
820 if (img->ref == 0)
821 {
822 ERR("EEEEEEEEEEEEEEEEK!");
823 ERR("EEEEEEEEEEEEEEEEK! %p '%s' already @ ref 0",
824 img, img->file.file);
825 ERR("EEEEEEEEEEEEEEEEK!");
826 return;
827 }
828 img->ref--;
829 DBG("... img ref-- = %i", img->ref);
830 if (img->ref == 0)
831 {
832 DBG("... img cache %p '%s'", img, img->file.file);
833 img_cache(img);
834 }
835}
836
837static void
838img_unloaddata(Img *img)
839{
840 DBG("img_unloaddata() %p '%s'", img, img->file.file);
841 if ((img->dref <= 0) && (img->useless) && (img->mem))
842 {
843 Image_Entry *ie = (Image_Entry *)img;
844
845 DBG("... really do forced unload");
846 if (!img->active) cache_usage -= img->usage;
847 img->usage -=
848 (4096 * (((img->image.w * img->image.h * sizeof(DATA32)) + 4095) / 4096)) +
849 sizeof(Mem);
850 if (!img->active) cache_usage += img->usage;
851 evas_cserve_mem_free(img->mem);
852 stat_mems = eina_list_remove(stat_mems, img->mem);
853 img->mem = NULL;
854 img->image.data = NULL;
855 img->dref = 0;
856 DBG("... done");
857
858 ie->flags.loaded = 0;
859 ie->allocated.w = 0;
860 ie->allocated.h = 0;
861 }
862}
863
864static void
865img_useless(Img *img)
866{
867 DBG("img_useless() %p", img);
868 img->useless = 1;
869 if (img->dref <= 0) img_unloaddata(img);
870}
871
872static void
873img_forcedunload(Img *img)
874{
875 DBG("img_forcedunload() %p", img);
876 img->dead = 1;
877 img_unload(img);
878}
879
880static void
881img_preload(Img *img)
882{
883 DBG("img_preload() %p", img);
884}
885
886static void
887client_del(void *data, Client *c)
888{
889 Eina_List *images;
890 Img *img;
891
892 images = data;
893 DBG("... CLIENT DEL %i", c->pid);
894 EINA_LIST_FREE(images, img)
895 {
896 DBG("... unloaddata img %p", img);
897 img_unloaddata(img);
898 DBG("... unload img %p", img);
899 img_unload(img);
900 }
901}
902
903static Eina_Bool
904getinfo_hash_image_cb(const Eina_Hash *hash __UNUSED__,
905 const void *key __UNUSED__,
906 void *data, void *fdata __UNUSED__)
907{
908 Img *img = data;
909 Eina_List **list = fdata;
910
911 *list = eina_list_append(*list, img);
912 return 1;
913}
914
915#ifdef BUILD_PTHREAD
916static void *
917load_data_thread(void *data)
918{
919 Load_Inf *li = data;
920 Img *img = li->img;
921 Client *c = li->c;
922 Op_Loaddata_Reply msg;
923
924 free(li);
925 LKL(img->lock);
926 if (img->mem)
927 {
928 memset(&msg, 0, sizeof(msg));
929 msg.mem.id = img->mem->id;
930 msg.mem.offset = img->mem->offset;
931 msg.mem.size = img->mem->size;
932 DBG("... reply");
933 evas_cserve_client_send(c, OP_LOADDATA, sizeof(msg), (unsigned char *)(&msg));
934 LKU(c->lock);
935 return NULL;
936 }
937 img_loaddata(img);
938 memset(&msg, 0, sizeof(msg));
939 if (img->mem)
940 {
941 msg.mem.id = img->mem->id;
942 msg.mem.offset = img->mem->offset;
943 msg.mem.size = img->mem->size;
944 }
945 else
946 msg.mem.id = msg.mem.offset = msg.mem.size = 0;
947 LKU(img->lock);
948 DBG("... reply");
949 evas_cserve_client_send(c, OP_LOADDATA, sizeof(msg), (unsigned char *)(&msg));
950 LKU(c->lock);
951 return NULL;
952}
953#endif
954
955static int
956message(void *fdata __UNUSED__, Server *s __UNUSED__, Client *c, int opcode, int size, unsigned char *data)
957{
958 // copy data into local aligned buffer... in case.
959 unsigned char *tdata = alloca(size + 16);
960 memcpy(tdata, data, size);
961
962 t_now = time(NULL);
963 DBG("message @ %i...", (int)t_now);
964 switch (opcode)
965 {
966 case OP_INIT:
967 {
968 Op_Init *rep;
969 Op_Init msg;
970
971 memset(&msg, 0, sizeof(msg));
972 msg.pid = getpid();
973 msg.server_id = server_id;
974 msg.handle = c;
975 rep = (Op_Init *)tdata;
976 c->pid = rep->pid;
977 if (rep->server_id == 1) // 2nd channel conn
978 {
979 c->client_main = rep->handle;
980 }
981 c->func = client_del;
982 c->data = NULL;
983 DBG("OP_INIT %i", c->pid);
984 DBG("... reply");
985 evas_cserve_client_send(c, OP_INIT, sizeof(msg), (unsigned char *)(&msg));
986 }
987 break;
988 case OP_LOAD:
989 {
990 Op_Load *rep;
991 Op_Load_Reply msg;
992 Img *img;
993 RGBA_Image_Loadopts lopt;
994 char *file = NULL, *key = NULL;
995
996 memset(&lopt, 0, sizeof lopt);
997 DBG("OP_LOAD %i", c->pid);
998 rep = (Op_Load *)tdata;
999 file = (char*) (data + sizeof(Op_Load));
1000 key = file + strlen(file) + 1;
1001 if (key[0] == 0) key = NULL;
1002 lopt.scale_down_by = rep->lopt.scale_down_by;
1003 lopt.dpi = rep->lopt.dpi;
1004 lopt.w = rep->lopt.w;
1005 lopt.h = rep->lopt.h;
1006 lopt.region.x = rep->lopt.region.x;
1007 lopt.region.y = rep->lopt.region.y;
1008 lopt.region.w = rep->lopt.region.w;
1009 lopt.region.h = rep->lopt.region.h;
1010 DBG("... img_load '%s'", file);
1011 if (key) DBG("'%s'", (char *)key);
1012 else DBG(" '%s'", "");
1013 DBG(" lopt { %i %1.1f %i %i { %i %i %i %i}}",
1014 lopt.scale_down_by, lopt.dpi, lopt.w, lopt.h,
1015 lopt.region.x, lopt.region.y, lopt.region.w, lopt.region.h);
1016 img = img_load(file, key, &lopt);
1017 DBG("... img_load = %p", img);
1018 if (img)
1019 {
1020 DBG("... add image to client list");
1021 if (c->client_main)
1022 c->client_main->data = eina_list_append(c->client_main->data, img);
1023 else
1024 c->data = eina_list_append(c->data, img);
1025 }
1026 memset(&msg, 0, sizeof(msg));
1027 msg.handle = img;
1028 if ((img) && (img->mem))
1029 {
1030 msg.mem.id = img->mem->id;
1031 msg.mem.offset = img->mem->offset;
1032 msg.mem.size = img->mem->size;
1033 img->stats.load2saved++;
1034 stats_update();
1035 }
1036 else
1037 msg.mem.id = msg.mem.offset = msg.mem.size = 0;
1038 if (img)
1039 {
1040 msg.image.w = img->image.w;
1041 msg.image.h = img->image.h;
1042 msg.image.alpha = img->image.alpha;
1043 }
1044 DBG("... reply");
1045 evas_cserve_client_send(c, OP_LOAD, sizeof(msg), (unsigned char *)(&msg));
1046 }
1047 break;
1048 case OP_UNLOAD:
1049 {
1050 Op_Unload *rep;
1051 Img *img;
1052
1053 DBG("OP_UNLOAD %i", c->pid);
1054 rep = (Op_Unload *)tdata;
1055 img = rep->handle;
1056 if ((img) && (rep->server_id == server_id))
1057 {
1058 Eina_Bool doflush = 0;
1059
1060 DBG("... remove %p from list", img);
1061 if (c->client_main)
1062 c->client_main->data = eina_list_remove(c->client_main->data, img);
1063 else
1064 c->data = eina_list_remove(c->data, img);
1065 DBG("... unload %p", img);
1066 LKL(img->lock);
1067 img->ref++;
1068 img_unload(img);
1069 img->ref--;
1070 if (img->ref == 0) doflush = 1;
1071 LKU(img->lock);
1072 if (doflush)
1073 img_cache(img);
1074 cache_clean();
1075 }
1076 }
1077 break;
1078 case OP_LOADDATA:
1079 {
1080 Op_Loaddata *rep;
1081 Op_Loaddata_Reply msg;
1082 Img *img;
1083
1084 DBG("OP_LOADDATA %i", c->pid);
1085 rep = (Op_Loaddata *)tdata;
1086 img = rep->handle;
1087 if ((img) && (rep->server_id == server_id))
1088 {
1089 if (img->mem)
1090 {
1091 DBG("... load saved - cached %p", img);
1092 img->stats.load2saved++;
1093 stats_update();
1094 memset(&msg, 0, sizeof(msg));
1095 if (img->mem)
1096 {
1097 msg.mem.id = img->mem->id;
1098 msg.mem.offset = img->mem->offset;
1099 msg.mem.size = img->mem->size;
1100 }
1101 else
1102 msg.mem.id = msg.mem.offset = msg.mem.size = 0;
1103 DBG("... reply");
1104 evas_cserve_client_send(c, OP_LOADDATA, sizeof(msg), (unsigned char *)(&msg));
1105 }
1106 else
1107 {
1108#ifdef BUILD_PTHREAD
1109 pthread_t tid;
1110 pthread_attr_t attr;
1111 Load_Inf *li;
1112
1113 DBG("... load data %p", img);
1114 pthread_attr_init(&attr);
1115 li = calloc(1, sizeof(Load_Inf));
1116 if (li)
1117 {
1118 li->img= img;
1119 li->c = c;
1120 LKL(c->lock);
1121 if (pthread_create(&tid, &attr, load_data_thread, li))
1122 {
1123 perror("pthread_create()");
1124 }
1125 else
1126 pthread_detach(tid);
1127 }
1128 pthread_attr_destroy(&attr);
1129#else
1130 img_loaddata(img);
1131 memset(&msg, 0, sizeof(msg));
1132 if (img->mem)
1133 {
1134 msg.mem.id = img->mem->id;
1135 msg.mem.offset = img->mem->offset;
1136 msg.mem.size = img->mem->size;
1137 }
1138 else
1139 msg.mem.id = msg.mem.offset = msg.mem.size = 0;
1140 DBG("... reply");
1141 evas_cserve_client_send(c, OP_LOADDATA, sizeof(msg), (unsigned char *)(&msg));
1142#endif
1143 }
1144 }
1145 else
1146 {
1147 msg.mem.id = msg.mem.offset = msg.mem.size = 0;
1148 evas_cserve_client_send(c, OP_LOADDATA, sizeof(msg), (unsigned char *)(&msg));
1149 }
1150 }
1151 break;
1152 case OP_UNLOADDATA:
1153 {
1154 Op_Unloaddata *rep;
1155 Img *img;
1156
1157 DBG("OP_UNLOADDATA %i", c->pid);
1158 rep = (Op_Unloaddata *)tdata;
1159 img = rep->handle;
1160 if ((img) && (rep->server_id == server_id))
1161 {
1162 DBG("... dref--");
1163 LKL(img->lock);
1164 img->dref--;
1165 if (img->dref < 0) img->dref = 0;
1166 DBG("... unload data %p '%s'", img, img->file.file);
1167 img_unloaddata(img);
1168 LKU(img->lock);
1169 }
1170 }
1171 break;
1172 case OP_USELESSDATA:
1173 {
1174 Op_Unloaddata *rep;
1175 Img *img;
1176
1177 DBG("OP_USELESSDATA %i", c->pid);
1178 rep = (Op_Unloaddata *)tdata;
1179 img = rep->handle;
1180 if ((img) && (rep->server_id == server_id))
1181 {
1182 DBG("... dref--");
1183 LKL(img->lock);
1184 img->dref--;
1185 if (img->dref < 0) img->dref = 0;
1186 DBG("... useless %p", img);
1187 img_useless(img);
1188 LKU(img->lock);
1189 }
1190 }
1191 break;
1192 case OP_PRELOAD:
1193 {
1194 Op_Preload *rep;
1195 Img *img;
1196
1197 DBG("OP_PRELOAD %i", c->pid);
1198 rep = (Op_Preload *)tdata;
1199 img = rep->handle;
1200 if ((img) && (rep->server_id == server_id))
1201 {
1202 LKL(img->lock);
1203 if (c->client_main)
1204 c->client_main->data = eina_list_remove(c->client_main->data, img);
1205 else
1206 c->data = eina_list_remove(c->data, img);
1207 // FIXME: preload doesn't work async
1208 img_preload(img);
1209 LKU(img->lock);
1210 }
1211 }
1212 case OP_FORCEDUNLOAD:
1213 {
1214 Op_Forcedunload *rep;
1215 Img *img;
1216
1217 DBG("OP_FORCEDUNLOAD %i", c->pid);
1218 rep = (Op_Forcedunload *)tdata;
1219 img = rep->handle;
1220 if ((img) && (rep->server_id == server_id))
1221 {
1222 Eina_Bool doflush = 0;
1223
1224 LKL(img->lock);
1225 DBG("remove %p from list", img);
1226 if (c->client_main)
1227 c->client_main->data = eina_list_remove(c->client_main->data, img);
1228 else
1229 c->data = eina_list_remove(c->data, img);
1230 DBG("... forced unload now");
1231 img->ref++;
1232 img_forcedunload(img);
1233 img->ref--;
1234 if (img->ref == 0) doflush = 1;
1235 LKU(img->lock);
1236 if (doflush)
1237 img_cache(img);
1238 cache_clean();
1239 }
1240 }
1241 break;
1242 case OP_GETCONFIG:
1243 {
1244 Op_Getconfig_Reply msg;
1245
1246 DBG("OP_GETCONFIG %i", c->pid);
1247 msg.cache_max_usage = cache_max_usage;
1248 msg.cache_item_timeout = cache_item_timeout;
1249 msg.cache_item_timeout_check = cache_item_timeout_check;
1250 DBG("... reply");
1251 evas_cserve_client_send(c, OP_GETCONFIG, sizeof(msg), (unsigned char *)(&msg));
1252 }
1253 break;
1254 case OP_SETCONFIG:
1255 {
1256 Op_Setconfig *rep;
1257
1258 DBG("OP_SETCONFIG %i", c->pid);
1259 rep = (Op_Setconfig *)tdata;
1260 cache_max_usage = rep->cache_max_usage;
1261 cache_item_timeout = rep->cache_item_timeout;
1262 cache_item_timeout_check = rep->cache_item_timeout_check;
1263 DBG("... cache timeout");
1264 cache_timeout(t_now);
1265 DBG("... cache clean");
1266 cache_clean();
1267 }
1268 break;
1269 case OP_GETSTATS:
1270 {
1271 Op_Getstats_Reply msg;
1272
1273 DBG("OP_GETSTATS %i", c->pid);
1274 stats_calc();
1275 msg.saved_memory = saved_memory;
1276 msg.wasted_memory = (real_memory - alloced_memory);
1277 msg.saved_memory_peak = saved_memory_peak;
1278 msg.wasted_memory_peak = (real_memory_peak - alloced_memory_peak);
1279 msg.saved_time_image_header_load = saved_load_lifetime + saved_load_time;
1280 msg.saved_time_image_data_load = saved_loaddata_lifetime + saved_loaddata_time;
1281 DBG("... reply");
1282 evas_cserve_client_send(c, OP_GETSTATS, sizeof(msg), (unsigned char *)(&msg));
1283 }
1284 break;
1285 case OP_GETINFO:
1286 {
1287 Op_Getinfo_Reply *msg;
1288 int len;
1289 Eina_List *imgs = NULL, *l;
1290 Img *img;
1291
1292 DBG("OP_GETINFO %i", c->pid);
1293 len = sizeof(Op_Getinfo_Reply);
1294 DBG("... foreach");
1295 if (active_images)
1296 eina_hash_foreach(active_images, getinfo_hash_image_cb, &imgs);
1297 DBG("... walk foreach list output");
1298 LKL(cache_lock);
1299 EINA_LIST_FOREACH(cache_images, l, img)
1300 {
1301 imgs = eina_list_append(imgs, img);
1302 }
1303 LKU(cache_lock);
1304 DBG("... walk image cache");
1305 EINA_LIST_FOREACH(imgs, l, img)
1306 {
1307 len += sizeof(Op_Getinfo_Item);
1308 if (img->file.file) len += strlen(img->file.file);
1309 len++;
1310 if (img->file.key) len += strlen(img->file.key);
1311 len++;
1312 }
1313 DBG("... malloc msg");
1314 msg = calloc(1, len);
1315 if (msg)
1316 {
1317 unsigned char *p;
1318
1319 DBG("... init msg");
1320 p = (unsigned char *)msg;
1321 msg->active.mem_total = 0;
1322 msg->active.count = 0;
1323 msg->cached.mem_total = 0;
1324 msg->cached.count = 0;
1325 p += sizeof(Op_Getinfo_Reply);
1326 DBG("... walk all imgs");
1327 EINA_LIST_FOREACH(imgs, l, img)
1328 {
1329 Op_Getinfo_Item it;
1330
1331 LKL(img->lock);
1332 DBG("... img %p", img);
1333 memset(&it, 0, sizeof(Op_Getinfo_Item));
1334 it.file_key_size = 0;
1335 if (img->file.file)
1336 {
1337 strcpy((char *)p + sizeof(Op_Getinfo_Item) + it.file_key_size, img->file.file);
1338 it.file_key_size += strlen(img->file.file);
1339 }
1340 p[sizeof(Op_Getinfo_Item) + it.file_key_size] = 0;
1341 it.file_key_size += 1;
1342 if (img->file.key)
1343 {
1344 strcpy((char *)p + sizeof(Op_Getinfo_Item) + it.file_key_size, img->file.key);
1345 it.file_key_size += strlen(img->file.key);
1346 }
1347 p[sizeof(Op_Getinfo_Item) + it.file_key_size] = 0;
1348 it.file_key_size += 1;
1349
1350 it.w = img->image.w;
1351 it.h = img->image.h;
1352 it.file_mod_time = img->file.modtime;
1353 it.file_checked_time = img->file.last_stat;
1354 if (!img->active)
1355 it.cached_time = img->cached;
1356 else
1357 it.cached_time = 0;
1358 it.refcount = img->ref;
1359 it.data_refcount = img->dref;
1360 it.memory_footprint = img->usage;
1361 it.head_load_time = img->stats.load1;
1362 it.data_load_time = img->stats.load2;
1363 it.alpha = img->image.alpha;
1364 if (img->image.data)
1365 it.data_loaded = 1;
1366 else
1367 it.data_loaded = 0;
1368 it.active = img->active;
1369 if (it.active)
1370 {
1371 msg->active.count++;
1372 msg->active.mem_total += img->usage;
1373 }
1374 else
1375 {
1376 msg->cached.count++;
1377 msg->cached.mem_total += img->usage;
1378 }
1379 it.dead = img->dead;
1380 it.useless = img->useless;
1381 DBG("... memcpy %p %p %zu ",
1382 p, &it, sizeof(Op_Getinfo_Item));
1383 memcpy(p, &it, sizeof(Op_Getinfo_Item));
1384 DBG("... memcpy done %p", img);
1385 p += sizeof(Op_Getinfo_Item) + it.file_key_size;
1386 LKU(img->lock);
1387 }
1388 DBG("... walk all imgs done");
1389 msg->active.mem_total =
1390 (msg->active.mem_total + 1023) / 1024;
1391 msg->cached.mem_total =
1392 (msg->cached.mem_total + 1023) / 1024;
1393 DBG("... reply");
1394 evas_cserve_client_send(c, OP_GETINFO, len, (unsigned char *)msg);
1395 free(msg);
1396 }
1397 else
1398 {
1399 DBG("... reply empty");
1400 evas_cserve_client_send(c, OP_GETINFO, 0, NULL);
1401 }
1402 DBG("... free imgs list");
1403 if (imgs) eina_list_free(imgs);
1404 }
1405 break;
1406 default:
1407 DBG("OP_... UNKNOWN??? %i opcode: %i", c->pid, opcode);
1408 break;
1409 }
1410 return 0;
1411}
1412
1413static void
1414parse_args(int argc, char **argv)
1415{
1416 int i;
1417
1418 for (i = 1; i < argc; i++)
1419 {
1420 if ((!strcmp(argv[i], "-h")) ||
1421 (!strcmp(argv[i], "-help")) ||
1422 (!strcmp(argv[i], "--help")))
1423 {
1424 printf("Options:\n"
1425 "\t-h This help\n"
1426 "\t-csize Size of speculative cache (Kb)\n"
1427 "\t-ctime Maximum life of a cached image (seconds)\n"
1428 "\t-ctimecheck Time between checking the cache for timeouts (seconds)\n"
1429 "\t-debug Enable debug logging\n"
1430 "\n");
1431 exit(0);
1432 }
1433 else if ((!strcmp(argv[i], "-csize")) && (i < (argc - 1)))
1434 {
1435 i++;
1436 cache_max_usage = atoi(argv[i]);
1437 }
1438 else if ((!strcmp(argv[i], "-ctime")) && (i < (argc - 1)))
1439 {
1440 i++;
1441 cache_item_timeout = atoi(argv[i]);
1442 }
1443 else if ((!strcmp(argv[i], "-ctimecheck")) && (i < (argc - 1)))
1444 {
1445 i++;
1446 cache_item_timeout_check = atoi(argv[i]);
1447 }
1448 else if (!strcmp(argv[i], "-debug"))
1449 {
1450 eina_log_level_set(EINA_LOG_LEVEL_DBG);
1451 }
1452 }
1453}
1454
1455static int exit_flag = 0;
1456
1457static void
1458exit_handler(int x __UNUSED__, siginfo_t *info __UNUSED__, void *data __UNUSED__)
1459{
1460 exit_flag = 1;
1461}
1462
1463static void
1464pipe_handler(int x __UNUSED__, siginfo_t *info __UNUSED__, void *data __UNUSED__)
1465{
1466}
1467
1468static void
1469signal_init(void)
1470{
1471 struct sigaction action, old_action;
1472
1473 action.sa_handler = NULL;
1474 action.sa_sigaction = exit_handler;
1475 action.sa_flags = SA_RESTART | SA_SIGINFO;
1476 sigemptyset(&action.sa_mask);
1477 sigaction(SIGINT, &action, &old_action);
1478
1479 action.sa_handler = NULL;
1480 action.sa_sigaction = exit_handler;
1481 action.sa_flags = SA_RESTART | SA_SIGINFO;
1482 sigemptyset(&action.sa_mask);
1483 sigaction(SIGTERM, &action, &old_action);
1484
1485 action.sa_handler = NULL;
1486 action.sa_sigaction = exit_handler;
1487 action.sa_flags = SA_RESTART | SA_SIGINFO;
1488 sigemptyset(&action.sa_mask);
1489 sigaction(SIGQUIT, &action, &old_action);
1490
1491 action.sa_handler = NULL;
1492 action.sa_sigaction = pipe_handler;
1493 action.sa_flags = SA_RESTART | SA_SIGINFO;
1494 sigemptyset(&action.sa_mask);
1495 sigaction(SIGPIPE, &action, &old_action);
1496
1497 // SIGUSR1
1498 // SIGUSR2
1499 // SIGHUP
1500
1501 // SIGCHLD
1502
1503 // SIGSEGV
1504 // SIGILL
1505 // SIGBUS
1506 // SIGFPE
1507 // SIGABRT
1508}
1509
1510static void
1511signal_shutdown(void)
1512{
1513}
1514
1515int
1516main(int argc, char **argv)
1517{
1518 Server *s;
1519 time_t last_check, t, t_next;
1520 pid_t pid;
1521
1522 t = time(NULL);
1523 pid = getpid();
1524 t ^= (pid << 24) | (pid << 16) | (pid << 8) | (pid);
1525 srand(t);
1526 server_id = rand();
1527
1528 parse_args(argc, argv);
1529
1530 unsetenv("EVAS_CSERVE");
1531
1532 eina_init();
1533 _evas_cserve_bin_log_dom = eina_log_domain_register
1534 ("evas_cserve_bin", CSERVE_BIN_DEFAULT_COLOR);
1535 if (_evas_cserve_bin_log_dom < 0)
1536 {
1537 EINA_LOG_ERR("impossible to create a log domain.");
1538 eina_shutdown();
1539 exit(1);
1540 }
1541
1542 DBG("evas init...");
1543 evas_init();
1544 DBG("img init...");
1545 img_init();
1546 DBG("signal init...");
1547 signal_init();
1548 DBG("cserve add...");
1549 s = evas_cserve_server_add();
1550 if (!s)
1551 {
1552 ERR("ERROR: server socket init fail. abort.");
1553 goto error;
1554 }
1555 DBG("mem open (status)...");
1556 stat_mem = evas_cserve_mem_open(0, 0, "status", sizeof(int), 0);
1557 if (stat_mem)
1558 {
1559 WRN("WARNING: previous evas_cserve left garbage. cleaning up.");
1560 stat_clean(stat_mem);
1561 evas_cserve_mem_close(stat_mem);
1562 stat_mem = NULL;
1563 }
1564 DBG("mem new (status)...");
1565 stat_mem = evas_cserve_mem_new(sizeof(int), "status");
1566 if (!stat_mem)
1567 {
1568 ERR("ERROR: cannot create status shmseg. abort.");
1569 goto error;
1570 }
1571 DBG("init status...");
1572 if (!stat_init(stat_mem))
1573 {
1574 ERR("cannot init status shmseg. abort.");
1575 evas_cserve_mem_free(stat_mem);
1576 stat_mem = NULL;
1577 goto error;
1578 }
1579
1580 DBG("cset server message handler...");
1581 evas_cserve_server_message_handler_set(s, message, NULL);
1582 last_check = time(NULL);
1583 t_next = 0;
1584 if (cache_item_timeout_check > 0) t_next = cache_item_timeout_check;
1585 DBG("LOOP!!! ...");
1586 for (;;)
1587 {
1588 /* fixme: timeout 0 only her - future use timeouts for timed
1589 * housekeping */
1590 if (exit_flag) break;
1591 DBG("wait for messages...");
1592 evas_cserve_server_wait(s, t_next * 1000000);
1593 if (exit_flag) break;
1594 t = time(NULL);
1595 t_next = t - last_check;
1596 if ((cache_item_timeout_check > 0) &&
1597 ((t_next) >= cache_item_timeout_check))
1598 {
1599 DBG("check timeout of items...");
1600 t_next = cache_item_timeout_check;
1601
1602 last_check = t;
1603 DBG("cache timeout...");
1604 cache_timeout(t);
1605 DBG("meminfo check...");
1606 meminfo_check();
1607 DBG("mem cache adjust...");
1608 mem_cache_adjust();
1609 }
1610 if ((t_next <= 0) && (cache_item_timeout_check > 0))
1611 t_next = 1;
1612 DBG("sleep for %isec...", (int)t_next);
1613
1614 LKL(strshr_freeme_lock);
1615 if (strshr_freeme_count > 0)
1616 {
1617 int i;
1618
1619 for (i = 0; i < strshr_freeme_count; i++)
1620 eina_stringshare_del(strshr_freeme[i]);
1621 strshr_freeme_count = 0;
1622 }
1623 LKU(strshr_freeme_lock);
1624
1625 LKL(cache_lock);
1626 if (cache_cleanme)
1627 {
1628 Eina_List *l;
1629 Img *img;
1630 Eina_List *kills = NULL;
1631
1632 EINA_LIST_FOREACH(cache_images, l, img)
1633 {
1634 LKL(img->lock);
1635 if (img->killme)
1636 kills = eina_list_append(kills, img);
1637 LKU(img->lock);
1638 }
1639 while (kills)
1640 {
1641 img = kills->data;
1642 kills = eina_list_remove_list(kills, kills);
1643 LKL(img->lock);
1644 cache_images = eina_list_remove(cache_images, img);
1645 img->incache--;
1646 cache_usage -= img->usage;
1647 DBG("... IMG FREE %p", img);
1648 img_free(img);
1649 }
1650 cache_cleanme = 0;
1651 }
1652 LKU(cache_lock);
1653 }
1654 DBG("end loop...");
1655 error:
1656 DBG("cleanup...");
1657 if (stat_mem)
1658 {
1659 DBG("clean mem stat...");
1660 stat_clean(stat_mem);
1661 }
1662 DBG("signal shutdown...");
1663 signal_shutdown();
1664 DBG("img shutdown...");
1665 img_shutdown();
1666 if (stat_mem)
1667 {
1668 DBG("free stat mem...");
1669 evas_cserve_mem_free(stat_mem);
1670 stat_mem = NULL;
1671 }
1672 if (s)
1673 {
1674 DBG("del server...");
1675 evas_cserve_server_del(s);
1676 }
1677 DBG("evas shutdown...");
1678 evas_shutdown();
1679 eina_log_domain_unregister(_evas_cserve_bin_log_dom);
1680 DBG("eina shutdown...");
1681 eina_shutdown();
1682 DBG("exit..");
1683 return 0;
1684}