Fixed by ac260575195900a532c3e3102e03a025d3a7cd98, 9a637112b42b91f6b739ab1addce6902b123921a, and 32fa4583704b3875eefcac85e75c7579a2ca5496. I enjoyed build break during the successive commits :)
Thanks. Daniel Juyung Seo (SeoZ) On Sun, Aug 11, 2013 at 8:10 PM, Daniel Juyung Seo <[email protected]>wrote: > Dear Cedric, you broke edje reload gracefully. > > Test) > 1. clone themes/dark. > 2. go to dark/edje directory. > 3. ./build.sh > 4. ELM_THEME=./dark.edj terminology > 5. ./build.sh > 6. resize terminology window > 7. yay > > Can you check this? > > Daniel Juyung SeoZ (SeoZ) > > > On Fri, Aug 9, 2013 at 8:59 PM, Cedric Bail - Enlightenment Git < > [email protected]> wrote: > >> cedric pushed a commit to branch master. >> >> commit 7506faaca2f5f7500426d4edaf3aaaef0e0ed707 >> Author: Cedric Bail <[email protected]> >> Date: Fri Aug 9 20:49:52 2013 +0900 >> >> edje: add edje_file_mmap_set. >> >> This reduce the number of system call to stat especially when using >> GROUP >> and reduce the risk of a race condition when using GROUP. >> --- >> ChangeLog | 4 +++ >> NEWS | 1 + >> src/lib/edje/Edje_Eo.h | 14 ++++++++ >> src/lib/edje/Edje_Legacy.h | 36 +++++++++++++++++++++ >> src/lib/edje/edje_cache.c | 30 ++++------------- >> src/lib/edje/edje_load.c | 79 >> ++++++++++++++++++++++++++++++--------------- >> src/lib/edje/edje_private.h | 5 ++- >> src/lib/edje/edje_smart.c | 29 ++++++++++++++++- >> 8 files changed, 145 insertions(+), 53 deletions(-) >> >> diff --git a/ChangeLog b/ChangeLog >> index 4d4b518..4be775c 100644 >> --- a/ChangeLog >> +++ b/ChangeLog >> @@ -1,3 +1,7 @@ >> +2013-08-09 Cedric Bail >> + >> + * Edje: add edje_object_mmap_set(). >> + >> 2013-08-08 Tom Hacohen >> >> * Evas textblock: Make the ellipsis format the same as the >> surrounding. >> diff --git a/NEWS b/NEWS >> index c717434..0790089 100644 >> --- a/NEWS >> +++ b/NEWS >> @@ -128,6 +128,7 @@ Additions: >> - support edc map color set >> - Add threshold support to Edje draggable part. >> - Reduce load time of Edje_Object using Evas_Object_Textblock and >> many styles. >> + - Add edje_object_mmap_set. >> * Eeze: >> - Add a dummy libmount replacement for when libmount is not there. >> * Ecore_Con: >> diff --git a/src/lib/edje/Edje_Eo.h b/src/lib/edje/Edje_Eo.h >> index 941aee4..6678a96 100644 >> --- a/src/lib/edje/Edje_Eo.h >> +++ b/src/lib/edje/Edje_Eo.h >> @@ -132,6 +132,7 @@ enum >> EDJE_OBJ_SUB_ID_PART_EXTERNAL_PARAM_TYPE_GET, >> >> EDJE_OBJ_SUB_ID_FILE_SET, >> + EDJE_OBJ_SUB_ID_MMAP_SET, >> EDJE_OBJ_SUB_ID_FILE_GET, >> EDJE_OBJ_SUB_ID_LOAD_ERROR_GET, >> >> @@ -612,6 +613,19 @@ enum >> #define edje_obj_file_set(file, group, ret) >> EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_FILE_SET), EO_TYPECHECK(const char*, file), >> EO_TYPECHECK(const char *, group), EO_TYPECHECK(Eina_Bool *, ret) >> >> /** >> + * @def edje_obj_mmap_set >> + * @since 1.8 >> + * >> + * @param[in] file in >> + * @param[in] group in >> + * @param[in] nested in >> + * @param[out] ret out >> + * >> + * @see edje_object_file_set >> + */ >> +#define edje_obj_mmap_set(file, group, ret) >> EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_MMAP_SET), EO_TYPECHECK(Eina_File*, file), >> EO_TYPECHECK(const char *, group), EO_TYPECHECK(Eina_Bool *, ret) >> + >> +/** >> * @def edje_obj_file_get >> * @since 1.8 >> * >> diff --git a/src/lib/edje/Edje_Legacy.h b/src/lib/edje/Edje_Legacy.h >> index 3b0ccab..196e498 100644 >> --- a/src/lib/edje/Edje_Legacy.h >> +++ b/src/lib/edje/Edje_Legacy.h >> @@ -1770,10 +1770,46 @@ EAPI const char *edje_object_data_get >> (const Evas_Object *obj, const >> * >> * @see edje_object_add() >> * @see edje_object_file_get() >> + * @see edje_object_mmap_set() >> */ >> EAPI Eina_Bool edje_object_file_set (Evas_Object *obj, >> const char *file, const char *group); >> >> /** >> + * @brief Sets the @b EDJ file (and group within it) to load an Edje >> + * object's contents from >> + * >> + * @param obj A handle to an Edje object >> + * @param file The Eina_File pointing to the EDJ file to load @p from >> + * @param group The name of the group, in @p file, which implements an >> + * Edje object >> + * @return @c EINA_TRUE, on success or @c EINA_FALSE, on errors (check >> + * edje_object_load_error_get() after this call to get errors causes) >> + * >> + * Edje expects EDJ files, which are theming objects' descriptions and >> + * resources packed together in an EET file, to read Edje object >> + * definitions from. They usually are created with the @c .edj >> + * extension. EDJ files, in turn, are assembled from @b textual object >> + * description files, where one describes Edje objects declaratively >> + * -- the EDC files (see @ref edcref "the syntax" for those files). >> + * >> + * Those description files were designed so that many Edje object >> + * definitions -- also called @b groups (or collections) -- could be >> + * packed together <b>in the same EDJ file</b>, so that a whole >> + * application's theme could be packed in one file only. This is the >> + * reason for the @p group argument. >> + * >> + * Use this function after you instantiate a new Edje object, so that >> + * you can "give him life", telling where to get its contents from. >> + * >> + * @see edje_object_add() >> + * @see edje_object_file_get() >> + * @see edje_object_mmap_set() >> + * @since 1.8 >> + */ >> +EAPI Eina_Bool edje_object_mmap_set(Evas_Object *obj, Eina_File *file, >> const char *group); >> + >> + >> +/** >> * @brief Get the file and group name that a given Edje object is bound >> to >> * >> * @param obj A handle to an Edje object >> diff --git a/src/lib/edje/edje_cache.c b/src/lib/edje/edje_cache.c >> index aa7e075..100ca55 100644 >> --- a/src/lib/edje/edje_cache.c >> +++ b/src/lib/edje/edje_cache.c >> @@ -399,32 +399,22 @@ _edje_file_dangling(Edje_File *edf) >> #endif >> >> Edje_File * >> -_edje_cache_file_coll_open(const char *file, const char *coll, int >> *error_ret, Edje_Part_Collection **edc_ret, Edje *ed) >> +_edje_cache_file_coll_open(Eina_File *file, const char *coll, int >> *error_ret, Edje_Part_Collection **edc_ret, Edje *ed) >> { >> - Eina_File *f; >> Edje_File *edf; >> Eina_List *l, *hist; >> Edje_Part_Collection *edc; >> Edje_Part *ep; >> >> - f = eina_file_open(file, EINA_FALSE); >> - if (!f) >> - { >> - *error_ret = EDJE_LOAD_ERROR_DOES_NOT_EXIST; >> - return NULL; >> - } >> - >> if (!_edje_file_hash) >> { >> _edje_file_hash = eina_hash_pointer_new(NULL); >> goto find_list; >> } >> >> - edf = eina_hash_find(_edje_file_hash, f); >> + edf = eina_hash_find(_edje_file_hash, file); >> if (edf) >> { >> - eina_file_close(f); >> - >> edf->references++; >> goto open; >> } >> @@ -432,23 +422,17 @@ _edje_cache_file_coll_open(const char *file, const >> char *coll, int *error_ret, E >> find_list: >> EINA_LIST_FOREACH(_edje_file_cache, l, edf) >> { >> - if (edf->f == f) >> + if (edf->f == file) >> { >> - eina_file_close(f); >> - >> edf->references = 1; >> _edje_file_cache = eina_list_remove_list(_edje_file_cache, >> l); >> - eina_hash_direct_add(_edje_file_hash, f, edf); >> + eina_hash_direct_add(_edje_file_hash, file, edf); >> goto open; >> } >> } >> >> - edf = _edje_file_open(f, coll, error_ret, edc_ret, >> eina_file_mtime_get(f)); >> - if (!edf) >> - { >> - eina_file_close(f); >> - return NULL; >> - } >> + edf = _edje_file_open(file, coll, error_ret, edc_ret, >> eina_file_mtime_get(file)); >> + if (!edf) return NULL; >> >> #ifdef HAVE_EIO >> if (ed) edf->edjes = eina_list_append(edf->edjes, ed); >> @@ -456,7 +440,7 @@ find_list: >> (void) ed; >> #endif >> >> - eina_hash_direct_add(_edje_file_hash, f, edf); >> + eina_hash_direct_add(_edje_file_hash, file, edf); >> /* return edf; */ >> >> open: >> diff --git a/src/lib/edje/edje_load.c b/src/lib/edje/edje_load.c >> index 331dab5..a65dbd5 100644 >> --- a/src/lib/edje/edje_load.c >> +++ b/src/lib/edje/edje_load.c >> @@ -24,6 +24,8 @@ struct _Edje_Drag_Items >> } page; >> }; >> >> +void _edje_file_add(Edje *ed, Eina_File *f); >> + >> /* START - Nested part support */ >> #define _edje_smart_nested_type "Evas_Smart_Nested" >> typedef struct _Edje_Nested_Support Edje_Nested_Support; >> @@ -80,6 +82,16 @@ edje_object_file_set(Evas_Object *obj, const char >> *file, const char *group) >> return ret; >> } >> >> +EAPI Eina_Bool >> +edje_object_mmap_set(Evas_Object *obj, Eina_File *file, const char >> *group) >> +{ >> + if (!obj) return EINA_FALSE; >> + Eina_Bool ret = EINA_FALSE; >> + >> + eo_do(obj, edje_obj_mmap_set(file, group, &ret)); >> + return ret; >> +} >> + >> EAPI void >> edje_object_file_get(const Evas_Object *obj, const char **file, const >> char **group) >> { >> @@ -149,11 +161,14 @@ EAPI Eina_List * >> edje_file_collection_list(const char *file) >> { >> Eina_List *lst = NULL; >> + Eina_File *f; >> Edje_File *edf; >> int error_ret = 0; >> >> if ((!file) || (!*file)) return NULL; >> - edf = _edje_cache_file_coll_open(file, NULL, &error_ret, NULL, NULL); >> + f = eina_file_open(file, EINA_FALSE); >> + if (!f) return NULL; >> + edf = _edje_cache_file_coll_open(f, NULL, &error_ret, NULL, NULL); >> if (edf) >> { >> Eina_Iterator *i; >> @@ -168,6 +183,7 @@ edje_file_collection_list(const char *file) >> >> _edje_cache_file_unref(edf); >> } >> + eina_file_close(f); >> return lst; >> } >> >> @@ -185,6 +201,7 @@ EAPI Eina_Bool >> edje_file_group_exists(const char *file, const char *glob) >> { >> Edje_File *edf; >> + Eina_File *f; >> int error_ret = 0; >> Eina_Bool succeed = EINA_FALSE; >> Eina_Bool is_glob = EINA_FALSE; >> @@ -193,9 +210,11 @@ edje_file_group_exists(const char *file, const char >> *glob) >> if ((!file) || (!*file) || (!glob)) >> return EINA_FALSE; >> >> - edf = _edje_cache_file_coll_open(file, NULL, &error_ret, NULL, NULL); >> - if (!edf) >> - return EINA_FALSE; >> + f = eina_file_open(file, EINA_FALSE); >> + if (!f) return EINA_FALSE; >> + >> + edf = _edje_cache_file_coll_open(f, NULL, &error_ret, NULL, NULL); >> + if (!edf) goto on_error; >> >> for (p = glob; *p; p++) >> { >> @@ -240,6 +259,8 @@ edje_file_group_exists(const char *file, const char >> *glob) >> >> DBG("edje_file_group_exists: '%s', '%s': %i.", file, glob, succeed); >> >> + on_error: >> + eina_file_close(f); >> return succeed; >> } >> >> @@ -248,12 +269,16 @@ EAPI char * >> edje_file_data_get(const char *file, const char *key) >> { >> Edje_File *edf; >> + Eina_File *f; >> char *str = NULL; >> int error_ret = 0; >> >> if (key) >> { >> - edf = _edje_cache_file_coll_open(file, NULL, &error_ret, NULL, >> NULL); >> + f = eina_file_open(file, EINA_FALSE); >> + if (!f) return NULL; >> + >> + edf = _edje_cache_file_coll_open(f, NULL, &error_ret, NULL, >> NULL); >> if (edf) >> { >> str = (char*) edje_string_get(eina_hash_find(edf->data, >> key)); >> @@ -262,6 +287,8 @@ edje_file_data_get(const char *file, const char *key) >> >> _edje_cache_file_unref(edf); >> } >> + >> + eina_file_close(f); >> } >> return str; >> } >> @@ -290,7 +317,7 @@ _edje_physics_world_update_cb(void *data, >> EPhysics_World *world EINA_UNUSED, voi >> #endif >> >> int >> -_edje_object_file_set_internal(Evas_Object *obj, const char *file, const >> char *group, const char *parent, Eina_List *group_path, Eina_Array *nested) >> +_edje_object_file_set_internal(Evas_Object *obj, Eina_File *file, const >> char *group, const char *parent, Eina_List *group_path, Eina_Array *nested) >> { >> Edje *ed; >> Evas *tev; >> @@ -310,18 +337,11 @@ _edje_object_file_set_internal(Evas_Object *obj, >> const char *file, const char *g >> >> ed = _edje_fetch(obj); >> if (!ed) return 0; >> - if (!file) file = ""; >> if (!group) group = ""; >> - if (((ed->path) && (!strcmp(file, ed->path))) && >> - (ed->group) && (!strcmp(group, ed->group)) && >> - ed->file) >> + if ((ed->file) && (ed->file->f == file) && >> + (ed->group) && (!strcmp(group, ed->group))) >> { >> - struct stat st; >> - >> - if (stat(file, &st) != 0) >> - return 1; >> - if (st.st_mtime == ed->file->mtime) >> - return 1; >> + return 1; >> } >> >> tev = evas_object_evas_get(obj); >> @@ -343,13 +363,13 @@ _edje_object_file_set_internal(Evas_Object *obj, >> const char *file, const char *g >> >> _edje_file_del(ed); >> >> - eina_stringshare_replace(&ed->path, file); >> + eina_stringshare_replace(&ed->path, file ? >> eina_file_filename_get(file) : NULL); >> eina_stringshare_replace(&ed->group, group); >> >> ed->parent = eina_stringshare_add(parent); >> >> ed->load_error = EDJE_LOAD_ERROR_NONE; >> - _edje_file_add(ed); >> + _edje_file_add(ed, file); >> ed->block_break = EINA_FALSE; >> >> if (ed->file && ed->file->external_dir) >> @@ -567,7 +587,7 @@ _edje_object_file_set_internal(Evas_Object *obj, >> const char *file, const char *g >> break; >> case EDJE_PART_TYPE_GRADIENT: >> ERR("SPANK ! SPANK ! SPANK ! YOU ARE USING >> GRADIENT IN PART %s FROM GROUP %s INSIDE FILE %s !! THEY ARE NOW REMOVED !", >> - ep->name, group, file); >> + ep->name, group, >> eina_file_filename_get(file)); >> break; >> case EDJE_PART_TYPE_SPACER: >> rp->object = NULL; >> @@ -834,7 +854,7 @@ _edje_object_file_set_internal(Evas_Object *obj, >> const char *file, const char *g >> if (data == group_path_entry) >> { >> ERR("recursive loop group '%s' >> already included inside part '%s' of group '%s' from file '%s'", >> - group_path_entry, rp->part->name, >> group, file); >> + group_path_entry, rp->part->name, >> group, eina_file_filename_get(file)); >> ed->load_error = >> EDJE_LOAD_ERROR_RECURSIVE_REFERENCE; >> >> eina_stringshare_del(group_path_entry); >> goto on_error; >> @@ -862,7 +882,7 @@ _edje_object_file_set_internal(Evas_Object *obj, >> const char *file, const char *g >> if >> (!_edje_object_file_set_internal(child_obj, file, source, rp->part->name, >> group_path, nested)) >> { >> ERR("impossible to set part '%s' of >> group '%s' from file '%s' to '%s'", >> - rp->part->name, group_path_entry, >> file, source); >> + rp->part->name, group_path_entry, >> eina_file_filename_get(file), source); >> ed->load_error = >> edje_object_load_error_get(child_obj); >> evas_object_del(child_obj); >> >> eina_stringshare_del(group_path_entry); >> @@ -1106,13 +1126,20 @@ on_error: >> } >> >> void >> -_edje_file_add(Edje *ed) >> +_edje_file_add(Edje *ed, Eina_File *f) >> { >> if (!_edje_edd_edje_file) return; >> - ed->file = _edje_cache_file_coll_open(ed->path, ed->group, >> - &(ed->load_error), >> - &(ed->collection), >> - ed); >> + if (!f) >> + { >> + ed->load_error = EDJE_LOAD_ERROR_DOES_NOT_EXIST; >> + } >> + else >> + { >> + ed->file = _edje_cache_file_coll_open(f, ed->group, >> + &(ed->load_error), >> + &(ed->collection), >> + ed); >> + } >> >> if (!ed->collection) >> { >> diff --git a/src/lib/edje/edje_private.h b/src/lib/edje/edje_private.h >> index b29b469..608aa01 100644 >> --- a/src/lib/edje/edje_private.h >> +++ b/src/lib/edje/edje_private.h >> @@ -1967,9 +1967,8 @@ void *_edje_signal_callback_disable(const >> Edje_Signal_Callback_Group *cgp, >> EAPI void _edje_edd_init(void); >> EAPI void _edje_edd_shutdown(void); >> >> -int _edje_object_file_set_internal(Evas_Object *obj, const char *file, >> const char *group, const char *parent, Eina_List *group_path, Eina_Array >> *nested); >> +int _edje_object_file_set_internal(Evas_Object *obj, Eina_File *file, >> const char *group, const char *parent, Eina_List *group_path, Eina_Array >> *nested); >> >> -void _edje_file_add(Edje *ed); >> void _edje_file_del(Edje *ed); >> void _edje_file_free(Edje_File *edf); >> void _edje_file_cache_shutdown(void); >> @@ -2150,7 +2149,7 @@ void _edje_textblock_styles_del(Edje *ed); >> void _edje_textblock_style_all_update(Edje *ed); >> void _edje_textblock_style_parse_and_fix(Edje_File *edf); >> void _edje_textblock_style_cleanup(Edje_File *edf); >> -Edje_File *_edje_cache_file_coll_open(const char *file, const char >> *coll, int *error_ret, Edje_Part_Collection **edc_ret, Edje *ed); >> +Edje_File *_edje_cache_file_coll_open(Eina_File *file, const char *coll, >> int *error_ret, Edje_Part_Collection **edc_ret, Edje *ed); >> void _edje_cache_coll_clean(Edje_File *edf); >> void _edje_cache_coll_flush(Edje_File *edf); >> void _edje_cache_coll_unref(Edje_File *edf, Edje_Part_Collection *edc); >> diff --git a/src/lib/edje/edje_smart.c b/src/lib/edje/edje_smart.c >> index e4590fb..b692a5a 100644 >> --- a/src/lib/edje/edje_smart.c >> +++ b/src/lib/edje/edje_smart.c >> @@ -333,12 +333,37 @@ _edje_smart_file_set(Eo *obj, void *_pd >> EINA_UNUSED, va_list *list) >> const char *file = va_arg(*list, const char *); >> const char *group = va_arg(*list, const char *); >> Eina_Bool *ret = va_arg(*list, Eina_Bool *); >> + Eina_File *f; >> Eina_Array *nested; >> + >> if (ret) *ret = EINA_FALSE; >> >> + f = eina_file_open(file, EINA_FALSE); >> nested = eina_array_new(8); >> - if (_edje_object_file_set_internal(obj, file, group, NULL, NULL, >> nested)) >> + >> + if (_edje_object_file_set_internal(obj, f, group, NULL, NULL, nested)) >> if (ret) *ret = EINA_TRUE; >> + >> + eina_array_free(nested); >> + eina_file_close(f); >> + _edje_object_orientation_inform(obj); >> +} >> + >> +static void >> +_edje_smart_mmap_set(Eo *obj, void *_pd EINA_UNUSED, va_list *list) >> +{ >> + Eina_File *f = va_arg(*list, Eina_File *); >> + const char *group = va_arg(*list, const char *); >> + Eina_Bool *ret = va_arg(*list, Eina_Bool *); >> + Eina_Array *nested; >> + >> + if (ret) *ret = EINA_FALSE; >> + >> + nested = eina_array_new(8); >> + >> + if (_edje_object_file_set_internal(obj, f, group, NULL, NULL, nested)) >> + if (ret) *ret = EINA_TRUE; >> + >> eina_array_free(nested); >> _edje_object_orientation_inform(obj); >> } >> @@ -481,6 +506,7 @@ _edje_smart_class_constructor(Eo_Class *klass) >> >> EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_PART_EXTERNAL_CONTENT_GET), >> _part_external_content_get), >> >> EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_PART_EXTERNAL_PARAM_TYPE_GET), >> _part_external_param_type_get), >> EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_FILE_SET), >> _edje_smart_file_set), >> + EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_MMAP_SET), >> _edje_smart_mmap_set), >> EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_FILE_GET), _file_get), >> EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_LOAD_ERROR_GET), >> _load_error_get), >> EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_MESSAGE_SEND), >> _message_send), >> @@ -626,6 +652,7 @@ static const Eo_Op_Description op_desc[] = { >> EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_PART_EXTERNAL_CONTENT_GET, "Get >> an object contained in an part of type EXTERNAL"), >> EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_PART_EXTERNAL_PARAM_TYPE_GET, >> "Facility to query the type of the given parameter of the given part."), >> EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_FILE_SET, "Sets the @b EDJ file >> (and group within it) to load an Edje"), >> + EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_MMAP_SET, "Sets the @b EDJ file >> (and group within it) to load an Edje"), >> EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_FILE_GET, "Get the file and group >> name that a given Edje object is bound to"), >> EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_LOAD_ERROR_GET, "Gets the (last) >> file loading error for a given Edje object"), >> EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_MESSAGE_SEND, "Send an (Edje) >> message to a given Edje object"), >> >> -- >> >> >> ------------------------------------------------------------------------------ >> Get 100% visibility into Java/.NET code with AppDynamics Lite! >> It's a free troubleshooting tool designed for production. >> Get down to code-level detail for bottlenecks, with <2% overhead. >> Download for free and get started troubleshooting in minutes. >> >> http://pubads.g.doubleclick.net/gampad/clk?id=48897031&iu=/4140/ostg.clktrk >> > >
------------------------------------------------------------------------------ Get 100% visibility into Java/.NET code with AppDynamics Lite! It's a free troubleshooting tool designed for production. Get down to code-level detail for bottlenecks, with <2% overhead. Download for free and get started troubleshooting in minutes. http://pubads.g.doubleclick.net/gampad/clk?id=48897031&iu=/4140/ostg.clktrk
