From: Kim Yunhan <spbear@gmail.com>
authorraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 3 Nov 2011 11:07:03 +0000 (11:07 +0000)
committerraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 3 Nov 2011 11:07:03 +0000 (11:07 +0000)
Subject: [E-devel] [elm_map] Fix up too many connections at the same
time.

Currently, elm_map requests all visible map image tile to map server
at the
same time.
If the scene is turned off while panning or zooming, it will be
aborted on
HTTP requests.
But it already sent to map server, and it already made useless HTTP
connections.
So if you pan scrolling quickly, elm_map try to download and abort too
many
HTTP
connections repeatedly.

If you have stable and high-throughput data connection, it doesn't
matter
on your side.
However map server will get high load, It is sufficient reason to block
you.
In another case, if you have poor data connection such as 3G
connection, it
has less
throughput and it causes delay of downloading. And finally, the device
is
as full as
HTTP connections even you already aborted. It makes low-performance
issue on
your device.

I wrote a patch for solving this situation.
The idea is simple.

1. I limited number of maximum HTTP request on elm_map side.
2. If maximum HTTP request is exceed, keep requests on Eina_List.
3. If each image downloading is completed, try to download recent
request.
   (Because it has strong possibility for your screen)
   4. At the same time, invisible request will be removed.
      (It doesn't make HTTP connection yet)

      I tested many times on my desktop and device.
      It works for me. And elm_map's performance is improved
appreciably on 3G
connections.

git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/elementary@64685 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/lib/elm_map.c

index c9001dd..460298c 100644 (file)
@@ -45,6 +45,7 @@ typedef struct _Track_Dump Track_Dump;
 
 #define PINCH_ZOOM_MIN 0.25
 #define PINCH_ZOOM_MAX 4.0
+#define MAX_CONCURRENT_DOWNLOAD 10
 
 #define GPX_NAME "name>"
 #define GPX_COORDINATES "trkpt "
@@ -241,9 +242,11 @@ struct _Elm_Map_Name
 struct _Grid_Item
 {
    Widget_Data *wd;
+   Grid *g;
    Evas_Object *img;
    //Evas_Object *txt;
    const char *file;
+   const char *source;
    struct {
         int x, y, w, h;
    } src, out;
@@ -298,7 +301,6 @@ struct _Widget_Data
    } show;
    int tsize;
    int nosmooth;
-   int preload_num;
    Eina_List *grids;
    Eina_Bool resized : 1;
    Eina_Bool on_hold : 1;
@@ -362,6 +364,8 @@ struct _Widget_Data
    Map_Sources_Tab *src;
    const char *gpx_file;
    int zoom_min, zoom_max;
+   Eina_List *download_list;
+   int download_num;
 };
 
 struct _Pan
@@ -501,6 +505,8 @@ static void grid_clear(Evas_Object *obj, Grid *g);
 static Grid *grid_create(Evas_Object *obj);
 static void grid_load(Evas_Object *obj, Grid *g);
 
+static void _process_download_list(Evas_Object *obj);
+static void _add_download_list(Evas_Object *obj, Grid_Item *gi);
 
 static void _group_object_create(Marker_Group *group);
 static void _group_object_free(Marker_Group *group);
@@ -1147,17 +1153,8 @@ grid_clear(Evas_Object *obj, Grid *g)
         evas_object_del(gi->img);
         //evas_object_del(gi->txt);
 
-        if (gi->want)
-          {
-             gi->want = EINA_FALSE;
-             wd->preload_num--;
-             if (!wd->preload_num)
-               {
-                  edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
-                                          "elm,state,busy,stop", "elm");
-                  evas_object_smart_callback_call(obj, SIG_LOADED_DETAIL, NULL);
-               }
-          }
+        wd->download_list = eina_list_remove(wd->download_list, gi);
+        gi->want = EINA_FALSE;
 
         if (gi->job)
           {
@@ -1170,6 +1167,8 @@ grid_clear(Evas_Object *obj, Grid *g)
           }
         if (gi->file)
           eina_stringshare_del(gi->file);
+        if (gi->source)
+          eina_stringshare_del(gi->source);
 
         free(gi);
      }
@@ -1201,13 +1200,6 @@ _tile_update(Grid_Item *gi)
    //evas_object_show(gi->txt);
 
    gi->have = EINA_TRUE;
-   gi->wd->preload_num--;
-   if (!gi->wd->preload_num)
-     {
-        edje_object_signal_emit(elm_smart_scroller_edje_object_get(gi->wd->scr),
-                                "elm,state,busy,stop", "elm");
-        evas_object_smart_callback_call(gi->wd->obj, SIG_LOADED_DETAIL, NULL);
-     }
 }
 
 static void
@@ -1215,10 +1207,15 @@ _tile_downloaded(void *data, const char *file __UNUSED__, int status)
 {
    Grid_Item *gi = data;
 
+   gi->wd->download_num--;
    gi->download = EINA_FALSE;
    gi->job = NULL;
 
-   if ((gi->want) && (status == 200)) _tile_update(gi);
+   if ((gi->want) && (status == 200))
+     {
+        _tile_update(gi);
+        DBG("DOWNLOAD done %s", gi->file);
+     }
 
    if (status != 200)
      {
@@ -1230,7 +1227,86 @@ _tile_downloaded(void *data, const char *file __UNUSED__, int status)
      gi->wd->finish_num++;
 
    evas_object_smart_callback_call(gi->wd->obj, SIG_DOWNLOADED, NULL);
-   DBG("DOWNLOAD done %s", gi->file);
+   if (!gi->wd->download_num)
+     {
+        edje_object_signal_emit(elm_smart_scroller_edje_object_get(gi->wd->scr), "elm,state,busy,stop", "elm");
+        evas_object_smart_callback_call(gi->wd->obj, SIG_LOADED_DETAIL, NULL);
+     }
+   _process_download_list(gi->wd->obj);
+}
+
+static void
+_process_download_list(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Eina_List *l;
+   Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh, tx, ty, gw, gh, xx, yy, ww, hh;
+   Grid_Item *gi;
+
+   evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
+   evas_output_viewport_get(evas_object_evas_get(wd->obj), &cvx, &cvy, &cvw, &cvh);
+
+   gw = wd->size.w;
+   gh = wd->size.h;
+
+   EINA_LIST_FOREACH(wd->download_list, l, gi)
+     {
+        xx = gi->out.x;
+        yy = gi->out.y;
+        ww = gi->out.w;
+        hh = gi->out.h;
+
+        if ((gw != gi->g->w) && (gi->g->w > 0))
+          {
+             tx = xx;
+             xx = ((long long )gw * xx) / gi->g->w;
+             ww = (((long long)gw * (tx + ww)) / gi->g->w) - xx;
+          }
+        if ((gh != gi->g->h) && (gi->g->h > 0))
+          {
+             ty = yy;
+             yy = ((long long)gh * yy) / gi->g->h;
+             hh = (((long long)gh * (ty + hh)) / gi->g->h) - yy;
+          }
+        if (!ELM_RECTS_INTERSECT(xx - wd->pan_x + ox,
+                                 yy  - wd->pan_y + oy,
+                                 ww, hh,
+                                 cvx, cvy, cvw, cvh))
+          {
+             gi->download = EINA_FALSE;
+             wd->download_list = eina_list_remove(wd->download_list, gi);
+          }
+     }
+
+   EINA_LIST_REVERSE_FOREACH(wd->download_list, l, gi)
+     {
+        if (gi->wd->download_num >= MAX_CONCURRENT_DOWNLOAD)
+          break;
+
+        ecore_file_download_full(gi->source, gi->file, _tile_downloaded, NULL, gi, &(gi->job), wd->ua);
+        if (!gi->job)
+          DBG("Can't start to download %s to %s", gi->source, gi->file);
+        else
+          {
+             gi->wd->download_num++;
+             wd->try_num++;
+             wd->download_list = eina_list_remove(wd->download_list, gi);
+             if (wd->download_num == 1)
+               edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), "elm,state,busy,start", "elm");
+          }
+     }
+}
+
+static void
+_add_download_list(Evas_Object *obj, Grid_Item *gi)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   wd->download_list = eina_list_remove(wd->download_list, gi);
+   wd->download_list = eina_list_append(wd->download_list, gi);
+   _process_download_list(obj);
 }
 
 static Grid *
@@ -1334,15 +1410,6 @@ grid_load(Evas_Object *obj, Grid *g)
                        wd->try_num--;
                     }
                   gi->download = EINA_FALSE;
-                  wd->preload_num--;
-                  if (!wd->preload_num)
-                    {
-                       edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
-                                               "elm,state,busy,stop", "elm");
-                       evas_object_smart_callback_call(obj, SIG_LOADED_DETAIL,
-                                                       NULL);
-                    }
-
                }
              else if (gi->have)
                {
@@ -1392,6 +1459,7 @@ grid_load(Evas_Object *obj, Grid *g)
                   gi->out.h = gi->src.h;
 
                   gi->wd = wd;
+                  gi->g = g;
 
                   gi->img = evas_object_image_add(evas_object_evas_get(obj));
                   evas_object_image_scale_hint_set
@@ -1431,31 +1499,15 @@ grid_load(Evas_Object *obj, Grid *g)
                   if ((!source) || (strlen(source)==0)) continue;
 
                   eina_stringshare_replace(&gi->file, buf2);
+                  eina_stringshare_replace(&gi->source, source);
 
                   if ((ecore_file_exists(buf2)) || (g == eina_list_data_get(wd->grids)))
                     {
                        gi->download = EINA_TRUE;
-                       wd->preload_num++;
-                       if (wd->preload_num == 1)
-                         {
-                            edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
-                                                    "elm,state,busy,start", "elm");
-                            evas_object_smart_callback_call(obj,
-                                                            SIG_LOAD_DETAIL,
-                                                            NULL);
-                         }
-
                        if (ecore_file_exists(buf2))
                          _tile_update(gi);
                        else
-                         {
-                            DBG("DOWNLOAD %s \t in %s", source, buf2);
-                            ecore_file_download_full(source, buf2, _tile_downloaded, NULL, gi, &(gi->job), wd->ua);
-                            if (!gi->job)
-                              DBG("Can't start to download %s", buf);
-                            else
-                              wd->try_num++;
-                         }
+                         _add_download_list(obj, gi);
                     }
                   if (source) free(source);
                }
@@ -1481,6 +1533,7 @@ grid_clearall(Evas_Object *obj)
         grid_clear(obj, g);
         free(g);
      }
+   wd->download_list = eina_list_free(wd->download_list);
 }
 
 static void