more todo items knocked off for cserve
authorraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Tue, 5 May 2009 14:37:18 +0000 (14:37 +0000)
committerraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Tue, 5 May 2009 14:37:18 +0000 (14:37 +0000)
git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/evas@40509 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/bin/Makefile.am
src/bin/evas_cserve_main.c
src/bin/evas_cserve_test_main.c [deleted file]
src/bin/evas_cserve_tool.c [new file with mode: 0644]
src/lib/cserve/evas_cs.h
src/lib/cserve/evas_cs_client.c

index 76c7aa8..84dedfa 100644 (file)
@@ -19,7 +19,7 @@ AM_CPPFLAGS = \
 
 AM_CFLAGS = @WIN32_CFLAGS@
 
-bin_PROGRAMS = evas_cserve evas_cserve_test
+bin_PROGRAMS = evas_cserve evas_cserve_tool
 
 evas_cserve_SOURCES = \
 evas_cserve_main.c
@@ -27,14 +27,14 @@ evas_cserve_main.c
 evas_cserve_LDADD = \
 $(top_builddir)/src/lib/libevas.la
 
-evas_cserve_test_LDFLAGS =
+evas_cserve_tool_LDFLAGS =
 
-evas_cserve_test_SOURCES = \
-evas_cserve_test_main.c
+evas_cserve_tool_SOURCES = \
+evas_cserve_tool.c
 
-evas_cserve_test_LDADD = \
+evas_cserve_tool_LDADD = \
 $(top_builddir)/src/lib/libevas.la
 
-evas_cserve_test_LDFLAGS =
+evas_cserve_tool_LDFLAGS =
 
 endif
index db10194..2500b8d 100644 (file)
@@ -1,11 +1,15 @@
 #include "Evas.h"
 #include "evas_cs.h"
 #include <signal.h>
+#include <sys/time.h>
+#include <time.h>
+#ifdef _WIN32
+# include <windows.h>
+#endif
 
 // fixme:'s
 // 
-// add ops to get/set cache size, check time and cache time (both)
-// add ops to get internal state (both)
+// add ops to get internal cache state (both)
 // preload - make it work (both)
 // monitor /proc/meminfo and if mem low - free items until cache empty (server)
 // 
@@ -35,6 +39,10 @@ struct _Img
       time_t modtime;
       time_t last_stat;
    } file;
+   struct {
+      int load1saved, load2saved;
+      double load1, load2;
+   } stats;
    Lopt load_opts;
    struct {
       int w, h;
@@ -57,12 +65,116 @@ static Eina_List *cache_images = NULL;
 static int cache_usage = 0;
 static int cache_max_usage = 1 * 1024 * 1024;
 static int cache_item_timeout = -1;
-static int cache_item_timeout_check = 10;
+static int cache_item_timeout_check = -1;
 static Mem *stat_mem = NULL;
 
 static int stat_mem_num = 0;
 static Eina_List *stat_mems = NULL;
 
+#ifndef _WIN32
+static double
+get_time(void)
+{
+   struct timeval      timev;
+   
+   gettimeofday(&timev, NULL);
+   return (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000);
+}
+#else
+static double
+get_time(void)
+{
+   return (double)GetTickCount()/1000.0;
+}
+#endif
+
+
+static int stats_dirty = 0;
+static int saved_loads = 0;
+static double saved_load_time = 0;
+static double saved_load_lifetime = 0;
+
+static int saved_loaddatas = 0;
+static double saved_loaddata_time = 0;
+static double saved_loaddata_lifetime = 0;
+
+static int saved_memory = 0;
+static int saved_memory_peak = 0;
+static int alloced_memory = 0;
+static int alloced_memory_peak = 0;
+static int real_memory = 0;
+static int real_memory_peak = 0;
+
+static Eina_Bool
+stats_hash_image_cb(const Eina_Hash *hash __UNUSED__, 
+                   const void *key __UNUSED__,
+                   void *data, void *fdata __UNUSED__)
+{
+   Img *img = data;
+   
+   saved_load_time += img->stats.load1 * img->stats.load1saved;
+   saved_loaddata_time += img->stats.load2 * img->stats.load2saved;
+   if (img->ref > 1)
+     saved_memory += img->image.w * img->image.h * sizeof(DATA32) * (img->ref - 1);
+   if (img->mem)
+     {
+        alloced_memory += img->image.w * img->image.h * sizeof(DATA32);
+        real_memory += (((img->image.w * img->image.h * sizeof(DATA32)) + 4095) >> 12) << 12;
+     }
+   return 1;
+}
+
+static void
+stats_calc(void)
+{
+   Img *img;
+   Eina_List *l;
+   
+   if (!stats_dirty) return;
+   stats_dirty = 0;
+   saved_loads = 0;
+   saved_load_time = 0;
+   saved_loaddatas = 0;
+   saved_loaddata_time = 0;
+   saved_memory = 0;
+   alloced_memory = 0;
+   real_memory = 0;
+   
+   if (active_images)
+     eina_hash_foreach(active_images, stats_hash_image_cb, NULL);
+   EINA_LIST_FOREACH(cache_images, l, img)
+     {
+        saved_loads += img->stats.load1saved;
+        saved_load_time += img->stats.load1 * img->stats.load1saved;
+        saved_loaddatas += img->stats.load2saved;
+        saved_loaddata_time += img->stats.load2 * img->stats.load2saved;
+        if (img->mem)
+          {
+             alloced_memory += img->image.w * img->image.h * sizeof(DATA32);
+             real_memory += (((img->image.w * img->image.h * sizeof(DATA32)) + 4095) >> 12) << 12;
+          }
+     }
+   if (saved_memory > saved_memory_peak)
+     saved_memory_peak = saved_memory;
+   if (real_memory > real_memory_peak)
+     real_memory_peak = real_memory;
+   if (alloced_memory > alloced_memory_peak)
+     alloced_memory_peak = alloced_memory;
+}
+
+static void
+stats_update(void)
+{
+   stats_dirty = 1;
+}
+
+static void
+stats_lifetime_update(Img *img)
+{
+   saved_load_lifetime += img->stats.load1 * img->stats.load1saved;
+   saved_loaddata_lifetime += img->stats.load2 * img->stats.load2saved;
+}
+
 static void
 stat_clean(Mem *m)
 {
@@ -279,12 +391,16 @@ img_new(const char *file, const char *key, RGBA_Image_Loadopts *load_opts, const
    int ret;
    Image_Entry *ie;
    int err = 0;
+   double t;
    
    ret = stat(file, &st);
    if (ret < 0) return NULL;
+   t = get_time();
    ie = evas_cache_image_request(cache, file, key, load_opts, &err);
+   t = get_time() - t;
    if (!ie) return NULL;
    img = (Img *)ie;
+   img->stats.load1 = t;
    img->key = eina_stringshare_add(bufkey);
    img->file.modtime = st.st_mtime;
    img->file.file = eina_stringshare_add(file);
@@ -309,8 +425,13 @@ img_new(const char *file, const char *key, RGBA_Image_Loadopts *load_opts, const
 static void
 img_loaddata(Img *img)
 {
+   double t;
+   
    // fixme: load img data
+   t = get_time();
    evas_cache_image_load_data((Image_Entry *)img);
+   t = get_time() - t;
+   img->stats.load2 = t;
    if (img->image.data)
      msync(img->image.data, img->image.w * img->image.h * sizeof(DATA32), MS_SYNC | MS_INVALIDATE);
    img->usage += 
@@ -321,6 +442,8 @@ img_loaddata(Img *img)
 static void
 img_free(Img *img)
 {
+   stats_lifetime_update(img);
+   stats_update();
    eina_stringshare_del(img->key);
    eina_stringshare_del(img->file.file);
    eina_stringshare_del(img->file.key);
@@ -437,7 +560,9 @@ img_load(const char *file, const char *key, RGBA_Image_Loadopts *load_opts)
    img = eina_hash_find(active_images, buf);
    if ((img) && (img_ok(img)))
      {
+        img->stats.load1saved++;
         img->ref++;
+        stats_update();
         return img;
      }
    
@@ -448,9 +573,11 @@ img_load(const char *file, const char *key, RGBA_Image_Loadopts *load_opts)
           {
              if (img_ok(img))
                {
+                  img->stats.load1saved++;
                   img->ref++;
                   cache_images = eina_list_remove_list(cache_images, l);
                   eina_hash_direct_add(active_images, img->key, img);
+                  stats_update();
                   return img;
                }
           }
@@ -546,6 +673,8 @@ message(void *fdata, Server *s, Client *c, int opcode, int size, unsigned char *
                   msg.mem.id = img->mem->id;
                   msg.mem.offset = img->mem->offset;
                   msg.mem.size = img->mem->size;
+                  img->stats.load2saved++;
+                  stats_update();
                }
              else
                msg.mem.id = msg.mem.offset = msg.mem.size = 0;
@@ -574,12 +703,16 @@ message(void *fdata, Server *s, Client *c, int opcode, int size, unsigned char *
              Op_Loaddata *rep;
              Op_Loaddata_Reply msg;
              Img *img;
-// fixme: handle loadopts on loaddata             
-//             RGBA_Image_Loadopts lopt = {0, 0.0, 0, 0};
              
              rep = (Op_Loaddata *)data;
              img = rep->handle;
-             img_loaddata(img);
+             if (img->mem)
+               {
+                  img->stats.load2saved++;
+                  stats_update();
+               }
+             else
+               img_loaddata(img);
              memset(&msg, 0, sizeof(msg));
              if (img->mem)
                {
@@ -614,6 +747,57 @@ message(void *fdata, Server *s, Client *c, int opcode, int size, unsigned char *
              img_forcedunload(img);
           } 
         break;
+     case OP_GETCONFIG:
+          {
+             Op_Getconfig_Reply msg;
+             
+             msg.cache_max_usage = cache_max_usage;
+             msg.cache_item_timeout = cache_item_timeout;
+             msg.cache_item_timeout_check = cache_item_timeout_check;
+             evas_cserve_client_send(c, OP_GETCONFIG, sizeof(msg), (unsigned char *)(&msg));
+          } 
+        break;
+     case OP_SETCONFIG:
+          {
+             Op_Setconfig *rep;
+             
+             rep = (Op_Setconfig *)data;
+             cache_max_usage = rep->cache_max_usage;
+             cache_item_timeout = rep->cache_item_timeout;
+             cache_item_timeout_check = rep->cache_item_timeout_check;
+             cache_clean();
+          } 
+        break;
+     case OP_GETSTATS:
+          {
+             Op_Getstats_Reply msg;
+
+             stats_calc();
+             msg.saved_memory = saved_memory;
+             msg.wasted_memory = (real_memory - alloced_memory);
+             msg.saved_memory_peak = saved_memory_peak;
+             msg.wasted_memory_peak = (real_memory_peak - alloced_memory_peak);
+             msg.saved_time_image_header_load = saved_load_lifetime + saved_load_time;
+             msg.saved_time_image_data_load = saved_loaddata_lifetime + saved_loaddata_time;
+             evas_cserve_client_send(c, OP_GETSTATS, sizeof(msg), (unsigned char *)(&msg));
+          } 
+        break;
+     case OP_GETINFO:
+          {
+// get a list of all images in active hash and cache list, and their info like
+//  file + key
+//  width, height and alpha flag
+//  refcount
+//  data loaded flag
+//  active ot cached
+//  last active timestamp
+//  dead
+//  mod time
+//  last checked mod time time
+//  memory footprint
+//             Op_Getstats_Reply msg;
+          } 
+        break;
      default:
         break;
      }
diff --git a/src/bin/evas_cserve_test_main.c b/src/bin/evas_cserve_test_main.c
deleted file mode 100644 (file)
index 8a72705..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-#include "evas_cs.h"
-
-int
-main(int argc, char **argv)
-{
-   evas_init();
-   
-   printf("evas_cserve_init = %i\n", evas_cserve_init());
-   
-     {
-        Image_Entry *ie;
-        RGBA_Image_Loadopts lopt = { 0, 0.0, 0, 0};
-        
-        ie = malloc(sizeof(Image_Entry));
-        if (evas_cserve_image_load(ie, argv[1], NULL, &lopt))
-          {
-             printf("load ok\n");
-             if (evas_cserve_image_data_load(ie))
-               {
-                  Mem *m;
-                  
-                  m = ie->data2;
-                  printf("first pixel: %08x\n", *((int *)m->data));
-                  printf("load data ok\n");
-//                  evas_cserve_image_free(ie);
-               }
-          }
-     }
-   
-   evas_cserve_shutdown();
-   evas_shutdown();
-   return 0;
-}
diff --git a/src/bin/evas_cserve_tool.c b/src/bin/evas_cserve_tool.c
new file mode 100644 (file)
index 0000000..7d10865
--- /dev/null
@@ -0,0 +1,101 @@
+#include "evas_cs.h"
+
+int
+main(int argc, char **argv)
+{
+   int i;
+   
+   evas_init();
+   if (!evas_cserve_init())
+     {
+        printf("ERROR: Cannot connect to cserve. abort\n");
+        exit(-1);
+     }
+
+   for (i = 1; i < argc; i++)
+     {
+        if ((!strcmp(argv[i], "-h")) ||
+            (!strcmp(argv[i], "-help")) ||
+            (!strcmp(argv[i], "--help")))
+          {
+             printf("Options:\n"
+                    "\t-h                                  This help\n"
+                    "\tgetconfig                           Get configuration values\n"
+                    "\tsetconfig csize ctimeout ctimecheck Set the config values\n"
+                    "\tgetstats                            Get current cache statistics\n"
+                    );
+             exit(0);
+          }
+        else if ((!strcmp(argv[i], "getconfig")))
+          {
+             Op_Getconfig_Reply config;
+             
+             if (!evas_cserve_config_get(&config))
+               {
+                  printf("ERROR: cannot fetch config.\n");
+                  exit(-1);
+               }
+             printf("csize: %i\n", config.cache_max_usage / 1024);
+             printf("ctime: %i\n", config.cache_item_timeout);
+             printf("ctimecheck: %i\n", config.cache_item_timeout_check);
+             printf("-OK-\n");
+          }
+        else if ((!strcmp(argv[i], "setconfig")) && (i < (argc - 3)))
+          {
+             Op_Setconfig config;
+             
+             i++;
+             config.cache_max_usage = atoi(argv[i]) * 1024;
+             i++;
+             config.cache_item_timeout = atoi(argv[i]);
+             i++;
+             config.cache_item_timeout_check = atoi(argv[i]);
+             if (!evas_cserve_config_set(&config))
+               {
+                  printf("ERROR: cannot set config.\n");
+                  exit(-1);
+               }
+          }
+        else if ((!strcmp(argv[i], "getstats")))
+          {
+             Op_Getstats_Reply stats;
+             
+             if (!evas_cserve_stats_get(&stats))
+               {
+                  printf("ERROR: cannot fetch stats.\n");
+                  exit(-1);
+               }
+             printf("saved_memory: %i Kb\n", stats.saved_memory / 1024);
+             printf("wasted_memory: %i Kb\n", stats.wasted_memory / 1024);
+             printf("saved_memory_peak: %i Kb\n", stats.saved_memory_peak / 1024);
+             printf("wasted_memory_peak: %i Kb\n", stats.wasted_memory_peak / 1024);
+             printf("saved_time_image_header_load: %1.3f sec\n", stats.saved_time_image_header_load);
+             printf("saved_time_image_data_load: %1.3f sec\n", stats.saved_time_image_data_load);
+             printf("-OK-\n");
+          }
+     }
+/*   
+     {
+        Image_Entry *ie;
+        RGBA_Image_Loadopts lopt = { 0, 0.0, 0, 0};
+        
+        ie = malloc(sizeof(Image_Entry));
+        if (evas_cserve_image_load(ie, argv[1], NULL, &lopt))
+          {
+             printf("load ok\n");
+             if (evas_cserve_image_data_load(ie))
+               {
+                  Mem *m;
+                  
+                  m = ie->data2;
+                  printf("first pixel: %08x\n", *((int *)m->data));
+                  printf("load data ok\n");
+//                  evas_cserve_image_free(ie);
+               }
+          }
+     }
+ */
+   evas_cserve_shutdown();
+   evas_shutdown();
+   return 0;
+}
index bc9ab39..a613190 100644 (file)
@@ -92,35 +92,6 @@ struct _Mem
 };
 
 //// for comms
-// for clients to connect to cserve
-EAPI Eina_Bool evas_cserve_init(void);
-EAPI int       evas_cserve_use_get(void);
-EAPI void      evas_cserve_shutdown(void);
-EAPI Eina_Bool evas_cserve_image_load(Image_Entry *ie, const char *file, const char *key, RGBA_Image_Loadopts *lopt);
-EAPI Eina_Bool evas_cserve_image_data_load(Image_Entry *ie);
-EAPI void      evas_cserve_image_free(Image_Entry *ie);
-    
-// for the server
-EAPI Server *evas_cserve_server_add(void);
-EAPI void evas_cserve_server_del(Server *s);
-EAPI void evas_cserve_client_send(Client *c, int opcode, int size, unsigned char *data);
-EAPI void evas_cserve_server_message_handler_set(Server *s, int (*func) (void *fdata, Server *s, Client *c, int opcode, int size, unsigned char *data), void *data);
-EAPI void evas_cserve_server_wait(Server *s, int timeout);
-    
-//// for memory
-// for server
-EAPI Mem *evas_cserve_mem_new(int size, const char *name);
-EAPI void evas_cserve_mem_free(Mem *m);
-    
-// for client
-EAPI Mem *evas_cserve_mem_open(int pid, int id, const char *name, int size, int write);
-EAPI void evas_cserve_mem_close(Mem *m);
-
-// for both
-EAPI Eina_Bool evas_cserve_mem_resize(Mem *m, int size);
-EAPI void      evas_cserve_mem_del(int pid, int id);
-    
-
 enum
 {
    OP_NOP, // 0
@@ -132,6 +103,11 @@ enum
      OP_PRELOAD, // 5
      OP_FORCEDUNLOAD, // 6
      
+     OP_GETCONFIG, // 7
+     OP_SETCONFIG, // 8
+     OP_GETSTATS, // 9
+     OP_GETINFO, // 10
+     
    OP_INVALID // 6
 };
 
@@ -193,6 +169,59 @@ typedef struct
 {
    void *handle;
 } Op_Forcedunload;
+typedef struct
+{
+   int cache_max_usage;
+   int cache_item_timeout;
+   int cache_item_timeout_check;
+} Op_Getconfig_Reply;
+typedef struct
+{
+   int cache_max_usage;
+   int cache_item_timeout;
+   int cache_item_timeout_check;
+} Op_Setconfig;
+typedef struct
+{
+   int saved_memory;
+   int wasted_memory;
+   int saved_memory_peak;
+   int wasted_memory_peak;
+   double saved_time_image_header_load;
+   double saved_time_image_data_load;
+} Op_Getstats_Reply;
+
+
+// for clients to connect to cserve
+EAPI Eina_Bool evas_cserve_init(void);
+EAPI int       evas_cserve_use_get(void);
+EAPI void      evas_cserve_shutdown(void);
+EAPI Eina_Bool evas_cserve_image_load(Image_Entry *ie, const char *file, const char *key, RGBA_Image_Loadopts *lopt);
+EAPI Eina_Bool evas_cserve_image_data_load(Image_Entry *ie);
+EAPI void      evas_cserve_image_free(Image_Entry *ie);
+EAPI Eina_Bool evas_cserve_config_get(Op_Getconfig_Reply *config);
+EAPI Eina_Bool evas_cserve_config_set(Op_Setconfig *config);
+EAPI Eina_Bool evas_cserve_stats_get(Op_Getstats_Reply *stats);
+    
+// for the server
+EAPI Server *evas_cserve_server_add(void);
+EAPI void evas_cserve_server_del(Server *s);
+EAPI void evas_cserve_client_send(Client *c, int opcode, int size, unsigned char *data);
+EAPI void evas_cserve_server_message_handler_set(Server *s, int (*func) (void *fdata, Server *s, Client *c, int opcode, int size, unsigned char *data), void *data);
+EAPI void evas_cserve_server_wait(Server *s, int timeout);
+    
+//// for memory
+// for server
+EAPI Mem *evas_cserve_mem_new(int size, const char *name);
+EAPI void evas_cserve_mem_free(Mem *m);
+    
+// for client
+EAPI Mem *evas_cserve_mem_open(int pid, int id, const char *name, int size, int write);
+EAPI void evas_cserve_mem_close(Mem *m);
+
+// for both
+EAPI Eina_Bool evas_cserve_mem_resize(Mem *m, int size);
+EAPI void      evas_cserve_mem_del(int pid, int id);
 
 #endif
 
index d029eca..6a3ab43 100644 (file)
@@ -194,7 +194,7 @@ evas_cserve_image_load(Image_Entry *ie, const char *file, const char *key, RGBA_
    Op_Load msg;
    Op_Load_Reply *rep;
    unsigned char *buf;
-   char fbuf[PATH_MAX], wd[PATH_MAX];
+   char fbuf[PATH_MAX], wdb[PATH_MAX];
    int flen, klen;
    int opcode;
    int size;
@@ -210,13 +210,13 @@ evas_cserve_image_load(Image_Entry *ie, const char *file, const char *key, RGBA_
    msg.lopt.h = lopt->h;
    if (file[0] != '/')
      {
-        if (getcwd(wd, sizeof(wd)))
+        if (getcwd(wdb, sizeof(wdb)))
           {
-             snprintf(fbuf, "%s/%s", wd, file);
+             snprintf(fbuf, sizeof(buf), "%s/%s", wdb, file);
              file = fbuf;
           }
      }
-   if (!realpath(file, wd)) file = wd;
+   if (!realpath(file, wdb)) file = wdb;
    flen = strlen(file) + 1;
    klen = strlen(key) + 1;
    buf = malloc(sizeof(msg) + flen + klen);
@@ -288,4 +288,52 @@ evas_cserve_image_free(Image_Entry *ie)
    ie->data1 = NULL;
 }
 
+EAPI Eina_Bool
+evas_cserve_config_get(Op_Getconfig_Reply *config)
+{
+   Op_Getconfig_Reply *rep;
+   int opcode;
+   int size;
+   if (csrve_init > 0) server_reinit();
+   else return 0;
+   if (!cserve) return 0;
+   if (!server_send(cserve, OP_GETCONFIG, 0, NULL)) return 0;
+   rep = (Op_Getconfig_Reply *)server_read(cserve, &opcode, &size);
+   if ((rep) && (opcode == OP_GETCONFIG) && (size == sizeof(Op_Getconfig_Reply)))
+     {
+        memcpy(config, rep, sizeof(Op_Getconfig_Reply));
+        return 1;
+     }
+   return 0;
+}
+
+EAPI Eina_Bool
+evas_cserve_config_set(Op_Setconfig *config)
+{
+   if (csrve_init > 0) server_reinit();
+   else return 0;
+   if (!cserve) return 0;
+   if (!server_send(cserve, OP_SETCONFIG, sizeof(Op_Setconfig), (unsigned char *)config)) return 0;
+   return 1;
+}
+
+EAPI Eina_Bool
+evas_cserve_stats_get(Op_Getstats_Reply *stats)
+{
+   Op_Getstats_Reply *rep;
+   int opcode;
+   int size;
+   if (csrve_init > 0) server_reinit();
+   else return 0;
+   if (!cserve) return 0;
+   if (!server_send(cserve, OP_GETSTATS, 0, NULL)) return 0;
+   rep = (Op_Getstats_Reply *)server_read(cserve, &opcode, &size);
+   if ((rep) && (opcode == OP_GETSTATS) && (size == sizeof(Op_Getstats_Reply)))
+     {
+        memcpy(stats, rep, sizeof(Op_Getstats_Reply));
+        return 1;
+     }
+   return 0;
+}
+
 #endif