}
path = _ethumb_build_absolute_path(path, buf);
+ eina_stringshare_replace(&e->src_hash, NULL);
eina_stringshare_replace(&e->src_path, path);
eina_stringshare_replace(&e->src_key, key);
_ethumb_file_generate_path(Ethumb *e)
{
char buf[PATH_MAX];
- char *fullname;
- const char *hash;
const char *thumb_dir, *category;
const char *ext;
int fdo_format;
else
ext = "eet";
- fullname = ecore_file_realpath(e->src_path);
- hash = _ethumb_generate_hash(fullname);
- snprintf(buf, sizeof(buf), "%s/%s/%s.%s", thumb_dir, category, hash, ext);
- free(fullname);
+ if (!e->src_hash)
+ {
+ char *fullname;
+
+ fullname = ecore_file_realpath(e->src_path);
+ e->src_hash = _ethumb_generate_hash(fullname);
+ free(fullname);
+ }
+ snprintf(buf, sizeof(buf), "%s/%s/%s.%s", thumb_dir, category, e->src_hash, ext);
DBG("ethumb=%p, path=%s", e, buf);
eina_stringshare_replace(&e->thumb_path, buf);
if (e->format == ETHUMB_THUMB_EET)
eina_stringshare_del(thumb_dir);
eina_stringshare_del(category);
- eina_stringshare_del(hash);
}
EAPI void
EINA_SAFETY_ON_NULL_RETURN(e);
DBG("ethumb=%p", e);
+ eina_stringshare_replace(&e->src_hash, NULL);
eina_stringshare_replace(&e->src_path, NULL);
eina_stringshare_replace(&e->src_key, NULL);
eina_stringshare_replace(&e->thumb_path, NULL);
if (key) *key = e->thumb_key;
}
+EAPI void
+ethumb_thumb_hash(Ethumb *e)
+{
+ EINA_SAFETY_ON_NULL_RETURN(e);
+ if (!e->src_hash)
+ {
+ char *fullname;
+
+ fullname = ecore_file_realpath(e->src_path);
+ e->src_hash = _ethumb_generate_hash(fullname);
+ free(fullname);
+ }
+}
+
+EAPI void
+ethumb_thumb_hash_copy(Ethumb *dst, const Ethumb *src)
+{
+ EINA_SAFETY_ON_NULL_RETURN(dst);
+ EINA_SAFETY_ON_NULL_RETURN(src);
+
+ if (src == dst) return ;
+
+ eina_stringshare_del(dst->src_hash);
+ dst->src_hash = eina_stringshare_ref(src->src_hash);
+}
+
void
ethumb_calculate_aspect_from_ratio(Ethumb *e, float ia, int *w, int *h)
{
r->thumb_dir = eina_stringshare_ref(e->thumb_dir);
r->category = eina_stringshare_ref(e->category);
+ r->src_hash = eina_stringshare_ref(e->src_hash);
r->src_path = eina_stringshare_ref(e->src_path);
r->src_key = eina_stringshare_ref(e->src_key);
r->thumb_path = eina_stringshare_ref(e->thumb_path);
CMP_PARAM(thumb_dir);
CMP_PARAM(category);
- CMP_PARAM(thumb_dir);
- CMP_PARAM(category);
CMP_PARAM(tw);
CMP_PARAM(th);
CMP_PARAM(format);
};
typedef struct _Ethumb_Async_Exists Ethumb_Async_Exists;
-typedef struct _Ethumb_Async_Exists_Cb Ethumb_Async_Exists_Cb;
struct _Ethumb_Async_Exists
{
- Ethumb *dup;
- Ethumb_Client *source;
+ const char *path;
- Eina_List *callbacks;
+ Ethumb *dup; /* We will work on that one to prevent race and lock */
+ Eina_List *callbacks;
Ecore_Thread *thread;
- EINA_REFCOUNT;
-
- Eina_Bool exists : 1;
- Eina_Bool cancel : 1;
};
-struct _Ethumb_Async_Exists_Cb
+struct _Ethumb_Exists
{
+ Ethumb_Async_Exists *parent;
+ Ethumb_Client *client;
+ Ethumb *dup; /* We don't want to loose parameters so keep them around */
+
Ethumb_Client_Thumb_Exists_Cb exists_cb;
const void *data;
};
{
Ethumb_Async_Exists *async = data;
- ethumb_free(async->dup);
+ assert(async->callbacks == NULL);
+ assert(async->thread == NULL);
- EINA_REFCOUNT_UNREF(async->source)
- _ethumb_client_free(async->source);
+ ethumb_free(async->dup);
+ eina_stringshare_del(async->path);
free(async);
}
static void
-_ethumb_async_cancel(Ethumb_Async_Exists *async)
-{
- async->cancel = EINA_TRUE;
- ecore_thread_cancel(async->thread);
-}
-
-static void
_ethumb_client_name_owner_changed(void *data, DBusMessage *msg)
{
DBusError err;
{
Ethumb_Async_Exists *async = data;
- async->exists = ethumb_exists(async->dup);
+ ethumb_thumb_hash(async->dup);
}
static void
_ethumb_client_exists_end(void *data, Ecore_Thread *thread __UNUSED__)
{
Ethumb_Async_Exists *async = data;
- Ethumb_Async_Exists_Cb *cb;
- Ethumb *tmp = async->source->ethumb;
-
- async->source->ethumb = async->dup;
+ Ethumb_Exists *cb;
EINA_LIST_FREE(async->callbacks, cb)
{
- cb->exists_cb(async->source, (Ethumb_Exists*) async, async->exists, (void*) cb->data);
- free(cb);
+ Ethumb *tmp;
+
+ ethumb_thumb_hash_copy(cb->dup, async->dup);
+ tmp = cb->client->ethumb;
+ cb->client->ethumb = cb->dup;
+
+ cb->exists_cb(cb->client, cb,
+ ethumb_exists(cb->client->ethumb),
+ (void*) cb->data);
+
+ cb->client->ethumb = tmp;
+ EINA_REFCOUNT_UNREF(cb->client)
+ _ethumb_client_free(cb->client);
+ ethumb_free(cb->dup);
+ free(cb);
}
- async->source->ethumb = tmp;
async->thread = NULL;
- eina_hash_del(_exists_request, async->dup, async);
+ eina_hash_del(_exists_request, async->path, async);
}
/**
ethumb_init();
e_dbus_init();
- _exists_request = eina_hash_new(ethumb_length,
- ethumb_key_cmp,
- ethumb_hash,
- _ethumb_async_delete,
- 3);
+ _exists_request = eina_hash_stringshared_new(_ethumb_async_delete);
return ++_initcount;
}
return _initcount;
/* should find a non racy solution to closing all pending exists request */
+ eina_hash_free(_exists_request);
+ _exists_request = NULL;
e_dbus_shutdown();
ethumb_shutdown();
EAPI Ethumb_Exists *
ethumb_client_thumb_exists(Ethumb_Client *client, Ethumb_Client_Thumb_Exists_Cb exists_cb, const void *data)
{
- Ethumb_Async_Exists_Cb *cb;
- Ethumb_Async_Exists *async;
+ const char *path = NULL;
+ Ethumb_Async_Exists *async = NULL;
+ Ethumb_Exists *cb = NULL;
Ecore_Thread *t;
EINA_SAFETY_ON_NULL_RETURN_VAL(client, NULL);
- cb = malloc(sizeof (Ethumb_Async_Exists_Cb));
- if (!cb)
+ ethumb_file_get(client->ethumb, &path, NULL);
+ if (!path) goto on_error;
+
+ async = eina_hash_find(_exists_request, path);
+ if (!async)
{
- exists_cb(client, NULL, EINA_FALSE, (void*) data);
- return NULL;
- }
+ async = malloc(sizeof (Ethumb_Async_Exists));
+ if (!async) goto on_error;
- cb->exists_cb = exists_cb;
- cb->data = data;
+ async->path = eina_stringshare_ref(path);
+ async->callbacks = NULL;
+ async->dup = ethumb_dup(client->ethumb);
+
+ if (!async->dup) goto on_error;
+
+ cb = malloc(sizeof (Ethumb_Exists));
+ if (!cb) goto on_error;
+
+ EINA_REFCOUNT_REF(client);
+ cb->client = client;
+ cb->dup = ethumb_dup(client->ethumb);
+ cb->exists_cb = exists_cb;
+ cb->data = data;
+ cb->parent = async;
- async = eina_hash_find(_exists_request, client->ethumb);
- if (async)
- {
- EINA_REFCOUNT_REF(async);
async->callbacks = eina_list_append(async->callbacks, cb);
- return (Ethumb_Exists*) async;
+
+ /* spawn a thread here */
+ t = ecore_thread_run(_ethumb_client_exists_heavy,
+ _ethumb_client_exists_end,
+ _ethumb_client_exists_end,
+ async);
+ if (!t) return NULL;
+ async->thread = t;
+
+ eina_hash_direct_add(_exists_request, async->path, async);
+
+ return cb;
}
- async = malloc(sizeof (Ethumb_Async_Exists));
- if (!async)
+ cb = malloc(sizeof (Ethumb_Exists));
+ if (!cb)
{
- free(cb);
- exists_cb(client, NULL, EINA_FALSE, (void*) data);
- return NULL;
+ async = NULL;
+ goto on_error;
}
- async->dup = ethumb_dup(client->ethumb);
- async->source = client;
- EINA_REFCOUNT_REF(async->source);
- async->exists = EINA_FALSE;
- async->cancel = EINA_FALSE;
+ EINA_REFCOUNT_REF(client);
+ cb->client = client;
+ cb->dup = ethumb_dup(client->ethumb);
+ cb->exists_cb = exists_cb;
+ cb->data = data;
+ cb->parent = async;
- async->callbacks = eina_list_append(NULL, cb);
+ async->callbacks = eina_list_append(async->callbacks, cb);
- EINA_REFCOUNT_INIT(async);
- t = ecore_thread_run(_ethumb_client_exists_heavy,
- _ethumb_client_exists_end,
- _ethumb_client_exists_end,
- async);
- if (!t) return NULL;
+ return cb;
- async->thread = t;
- eina_hash_direct_add(_exists_request, async->dup, async);
+ on_error:
+ exists_cb(client, NULL, EINA_FALSE, (void*) data);
- return (Ethumb_Exists*) async;
+ if (async)
+ {
+ eina_stringshare_del(async->path);
+ if (async->dup) ethumb_free(async->dup);
+ free(async);
+ }
+ return NULL;
}
/**
* @param exists the request to cancel.
*/
EAPI void
-ethumb_client_thumb_exists_cancel(Ethumb_Exists *exists, Ethumb_Client_Thumb_Exists_Cb exists_cb, const void *data)
+ethumb_client_thumb_exists_cancel(Ethumb_Exists *exists)
{
- Ethumb_Async_Exists_Cb *cb;
- Ethumb_Async_Exists *async = (Ethumb_Async_Exists*) exists;
- Eina_List *l;
+ Ethumb_Async_Exists *async = exists->parent;
- EINA_LIST_FOREACH(async->callbacks, l, cb)
- if (cb->exists_cb == exists_cb && cb->data == data)
- {
- async->callbacks = eina_list_remove_list(async->callbacks, l);
- free(cb);
- break;
- }
+ async->callbacks = eina_list_remove(async->callbacks, exists);
+ if (eina_list_count(async->callbacks) <= 0)
+ ecore_thread_cancel(async->thread);
- EINA_REFCOUNT_UNREF(async)
- _ethumb_async_cancel(async);
+ ethumb_free(exists->dup);
+ EINA_REFCOUNT_UNREF(exists->client)
+ _ethumb_client_free(exists->client);
+ free(exists);
}
/**
EAPI Eina_Bool
ethumb_client_thumb_exists_check(Ethumb_Exists *exists)
{
- Ethumb_Async_Exists *async = (Ethumb_Async_Exists*) exists;
+ Ethumb_Async_Exists *async = exists->parent;
if (!async) return EINA_TRUE;
- if (async->callbacks || async->cancel) return EINA_FALSE;
+ if (async->callbacks) return EINA_FALSE;
return ecore_thread_check(async->thread);
}