Commit 6facb344 authored by Matthias Klumpp's avatar Matthias Klumpp
Browse files

Add asynchronous method for loading the metadata pool

parent 86b4a519
......@@ -25,6 +25,7 @@
* Caches are used by #AsPool to quickly search for components while not keeping all
* component data in memory.
* Internally, a cache is backed by an LMDB database.
* This class is threadsafe.
*
* See also: #AsPool
*/
......@@ -90,6 +91,8 @@ typedef struct
GFunc cpt_refine_func;
gpointer cpt_refine_func_udata;
GMutex mutex;
} AsCachePrivate;
G_DEFINE_TYPE_WITH_PRIVATE (AsCache, as_cache, G_TYPE_OBJECT)
......@@ -136,6 +139,8 @@ as_cache_init (AsCache *cache)
{
AsCachePrivate *priv = GET_PRIVATE (cache);
g_mutex_init (&priv->mutex);
priv->opened = FALSE;
priv->max_keysize = 511;
priv->cpt_refine_func = NULL;
......@@ -177,16 +182,19 @@ as_cache_finalize (GObject *object)
AsCache *cache = AS_CACHE (object);
AsCachePrivate *priv = GET_PRIVATE (cache);
g_object_unref (priv->context);
as_cache_close (cache);
g_mutex_lock (&priv->mutex);
g_object_unref (priv->context);
g_free (priv->locale);
g_free (priv->fname);
g_hash_table_unref (priv->cpt_map);
g_hash_table_unref (priv->cid_set);
g_hash_table_unref (priv->ro_removed_set);
g_mutex_unlock (&priv->mutex);
g_mutex_clear (&priv->mutex);
G_OBJECT_CLASS (as_cache_parent_class)->finalize (object);
}
......@@ -638,6 +646,7 @@ inline static gboolean
as_cache_check_opened (AsCache *cache, gboolean allow_floating, GError **error)
{
AsCachePrivate *priv = GET_PRIVATE (cache);
g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&priv->mutex);
if (!allow_floating && priv->floating) {
g_set_error (error,
......@@ -713,10 +722,13 @@ as_cache_open (AsCache *cache, const gchar *fname, const gchar *locale, GError *
mdb_mode_t db_mode;
gboolean nosync;
gboolean readonly;
g_autoptr(GMutexLocker) locker = NULL;
/* close cache in case it was open */
as_cache_close (cache);
locker = g_mutex_locker_new (&priv->mutex);
rc = mdb_env_create (&priv->db_env);
if (rc != MDB_SUCCESS) {
g_set_error (error,
......@@ -1005,6 +1017,7 @@ gboolean
as_cache_close (AsCache *cache)
{
AsCachePrivate *priv = GET_PRIVATE (cache);
g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&priv->mutex);
if (!priv->opened)
return FALSE;
......@@ -1109,11 +1122,11 @@ as_cache_insert (AsCache *cache, AsComponent *cpt, GError **error)
GPtrArray *provides;
GPtrArray *extends;
static GMutex mutex;
g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&mutex);
g_autoptr(GMutexLocker) locker = NULL;
if (!as_cache_check_opened (cache, TRUE, error))
return FALSE;
locker = g_mutex_locker_new (&priv->mutex);
if (priv->floating) {
/* floating cache, don't really add this component yet but stage it in the internal map */
......@@ -1440,9 +1453,11 @@ as_cache_remove_by_data_id (AsCache *cache, const gchar *cdid, GError **error)
g_autofree guint8 *cpt_checksum = NULL;
GError *tmp_error = NULL;
gboolean ret;
g_autoptr(GMutexLocker) locker = NULL;
if (!as_cache_check_opened (cache, TRUE, error))
return FALSE;
locker = g_mutex_locker_new (&priv->mutex);
if (priv->floating) {
/* floating cache, remove only from the internal map */
......@@ -1666,9 +1681,11 @@ as_cache_get_components_all (AsCache *cache, GError **error)
MDB_val dval;
MDB_val dkey;
g_autoptr(GPtrArray) results = NULL;
g_autoptr(GMutexLocker) locker = NULL;
if (!as_cache_check_opened (cache, FALSE, error))
return NULL;
locker = g_mutex_locker_new (&priv->mutex);
txn = as_cache_transaction_new (cache, MDB_RDONLY, error);
if (txn == NULL)
......@@ -1715,7 +1732,7 @@ as_cache_get_components_all (AsCache *cache, GError **error)
}
/**
* as_cache_get_component_by_cid:
* as_cache_get_components_by_id:
* @cache: An instance of #AsCache.
* @id: The component ID to search for.
* @error: A #GError or %NULL.
......@@ -1732,9 +1749,11 @@ as_cache_get_components_by_id (AsCache *cache, const gchar *id, GError **error)
GError *tmp_error = NULL;
MDB_val dval;
GPtrArray *result = NULL;
g_autoptr(GMutexLocker) locker = NULL;
if (!as_cache_check_opened (cache, TRUE, error))
return NULL;
locker = g_mutex_locker_new (&priv->mutex);
if (priv->floating) {
/* floating cache, check only the internal map */
......@@ -1795,9 +1814,11 @@ as_cache_get_component_by_data_id (AsCache *cache, const gchar *cdid, GError **e
GError *tmp_error = NULL;
g_autofree guint8 *cpt_hash = NULL;
AsComponent *cpt;
g_autoptr(GMutexLocker) locker = NULL;
if (!as_cache_check_opened (cache, TRUE, error))
return NULL;
locker = g_mutex_locker_new (&priv->mutex);
if (priv->floating) {
/* floating cache, check only the internal map */
......@@ -1847,9 +1868,11 @@ as_cache_get_components_by_kind (AsCache *cache, AsComponentKind kind, GError **
MDB_val dval;
GPtrArray *result = NULL;
const gchar *kind_str = as_component_kind_to_string (kind);
g_autoptr(GMutexLocker) locker = NULL;
if (!as_cache_check_opened (cache, FALSE, error))
return NULL;
locker = g_mutex_locker_new (&priv->mutex);
txn = as_cache_transaction_new (cache, MDB_RDONLY, error);
if (txn == NULL)
......@@ -1892,9 +1915,11 @@ as_cache_get_components_by_provided_item (AsCache *cache, AsProvidedKind kind, c
MDB_val dval;
g_autofree gchar *item_key = NULL;
GPtrArray *result = NULL;
g_autoptr(GMutexLocker) locker = NULL;
if (!as_cache_check_opened (cache, FALSE, error))
return NULL;
locker = g_mutex_locker_new (&priv->mutex);
item_key = g_strconcat (as_provided_kind_to_string (kind), item, NULL);
txn = as_cache_transaction_new (cache, MDB_RDONLY, error);
......@@ -1935,9 +1960,11 @@ as_cache_get_components_by_categories (AsCache *cache, gchar **categories, GErro
MDB_txn *txn;
GError *tmp_error = NULL;
g_autoptr(GPtrArray) result = NULL;
g_autoptr(GMutexLocker) locker = NULL;
if (!as_cache_check_opened (cache, FALSE, error))
return NULL;
locker = g_mutex_locker_new (&priv->mutex);
txn = as_cache_transaction_new (cache, MDB_RDONLY, error);
if (txn == NULL)
......@@ -1995,9 +2022,11 @@ as_cache_get_components_by_launchable (AsCache *cache, AsLaunchableKind kind, co
g_autofree gchar *entry_key = NULL;
MDB_val dval;
GPtrArray *result = NULL;
g_autoptr(GMutexLocker) locker = NULL;
if (!as_cache_check_opened (cache, FALSE, error))
return NULL;
locker = g_mutex_locker_new (&priv->mutex);
entry_key = g_strconcat (as_launchable_kind_to_string (kind), id, NULL);
txn = as_cache_transaction_new (cache, MDB_RDONLY, error);
......@@ -2116,6 +2145,7 @@ as_cache_search (AsCache *cache, gchar **terms, gboolean sort, GError **error)
g_autoptr(GHashTable) results_ht = NULL;
GHashTableIter ht_iter;
gpointer ht_value;
g_autoptr(GMutexLocker) locker = NULL;
if (!as_cache_check_opened (cache, FALSE, error))
return NULL;
......@@ -2125,6 +2155,8 @@ as_cache_search (AsCache *cache, gchar **terms, gboolean sort, GError **error)
return as_cache_get_components_all (cache, error);
}
locker = g_mutex_locker_new (&priv->mutex);
txn = as_cache_transaction_new (cache, MDB_RDONLY, error);
if (txn == NULL)
return NULL;
......@@ -2207,6 +2239,9 @@ as_cache_search (AsCache *cache, gchar **terms, gboolean sort, GError **error)
mdb_cursor_close (cur);
}
/* we don't need the mutex anymore, no class struct access here */
g_clear_pointer (&locker, g_mutex_locker_free);
/* compile our result */
g_hash_table_iter_init (&ht_iter, results_ht);
while (g_hash_table_iter_next (&ht_iter, NULL, &ht_value))
......@@ -2238,9 +2273,11 @@ as_cache_has_component_id (AsCache *cache, const gchar *id, GError **error)
GError *tmp_error = NULL;
MDB_val dval;
gboolean found;
g_autoptr(GMutexLocker) locker = NULL;
if (!as_cache_check_opened (cache, TRUE, error))
return FALSE;
locker = g_mutex_locker_new (&priv->mutex);
if (priv->floating) {
/* floating cache, check only the internal map */
......@@ -2281,9 +2318,11 @@ as_cache_count_components (AsCache *cache, GError **error)
MDB_stat stats;
gint rc;
gssize count = -1;
g_autoptr(GMutexLocker) locker = NULL;
if (!as_cache_check_opened (cache, FALSE, error))
return 0;
locker = g_mutex_locker_new (&priv->mutex);
txn = as_cache_transaction_new (cache, MDB_RDONLY, error);
if (txn == NULL)
......@@ -2316,6 +2355,7 @@ as_cache_get_ctime (AsCache *cache)
{
AsCachePrivate *priv = GET_PRIVATE (cache);
struct stat cache_sbuf;
g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&priv->mutex);
if (priv->fname == NULL)
return 0;
......@@ -2336,6 +2376,7 @@ gboolean
as_cache_is_open (AsCache *cache)
{
AsCachePrivate *priv = GET_PRIVATE (cache);
g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&priv->mutex);
return priv->opened;
}
......@@ -2350,6 +2391,7 @@ void
as_cache_make_floating (AsCache *cache)
{
AsCachePrivate *priv = GET_PRIVATE (cache);
g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&priv->mutex);
if (priv->floating)
return;
......@@ -2375,6 +2417,8 @@ as_cache_unfloat (AsCache *cache, GError **error)
gpointer ht_value;
guint invalid_cpts = 0;
g_mutex_lock (&priv->mutex);
priv->floating = FALSE;
g_hash_table_iter_init (&iter, priv->cpt_map);
......@@ -2395,13 +2439,16 @@ as_cache_unfloat (AsCache *cache, GError **error)
continue;
}
g_mutex_unlock (&priv->mutex);
if (!as_cache_insert (cache, cpt, error))
return 0;
g_mutex_lock (&priv->mutex);
}
g_hash_table_remove_all (priv->cid_set);
g_hash_table_remove_all (priv->cpt_map);
g_mutex_unlock (&priv->mutex);
g_debug ("Cache returned from floating mode (all changes are now persistent)");
return invalid_cpts;
......@@ -2417,6 +2464,7 @@ const gchar*
as_cache_get_location (AsCache *cache)
{
AsCachePrivate *priv = GET_PRIVATE (cache);
g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&priv->mutex);
return priv->fname;
}
......@@ -2430,6 +2478,8 @@ void
as_cache_set_location (AsCache *cache, const gchar *location)
{
AsCachePrivate *priv = GET_PRIVATE (cache);
g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&priv->mutex);
g_free (priv->fname);
priv->fname = g_strdup (location);
}
......@@ -2444,6 +2494,7 @@ gboolean
as_cache_get_nosync (AsCache *cache)
{
AsCachePrivate *priv = GET_PRIVATE (cache);
g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&priv->mutex);
return priv->nosync;
}
......@@ -2459,6 +2510,7 @@ void
as_cache_set_nosync (AsCache *cache, gboolean nosync)
{
AsCachePrivate *priv = GET_PRIVATE (cache);
g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&priv->mutex);
priv->nosync = nosync;
}
......@@ -2472,6 +2524,7 @@ gboolean
as_cache_get_readonly (AsCache *cache)
{
AsCachePrivate *priv = GET_PRIVATE (cache);
g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&priv->mutex);
return priv->readonly;
}
......@@ -2485,6 +2538,7 @@ void
as_cache_set_readonly (AsCache *cache, gboolean ro)
{
AsCachePrivate *priv = GET_PRIVATE (cache);
g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&priv->mutex);
priv->readonly = ro;
}
......@@ -2498,6 +2552,8 @@ void
as_cache_set_refine_func (AsCache *cache, GFunc func, gpointer user_data)
{
AsCachePrivate *priv = GET_PRIVATE (cache);
g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&priv->mutex);
priv->cpt_refine_func = func;
priv->cpt_refine_func_udata = user_data;
}
......
......@@ -23,16 +23,18 @@
* @short_description: Access the AppStream metadata pool.
*
* This class loads AppStream metadata from various sources and refines it with existing
* knowledge about the system (e.g. by setting absolute pazhs for cached icons).
* knowledge about the system (e.g. by setting absolute paths for cached icons).
* An #AsPool will use an on-disk cache to store metadata is has read and refined to
* speed up the loading time when the same data is requested a second time.
*
* You can find AppStream metadata matching farious criteria, and also add new metadata to
* the pool.
* The caching behavior can be controlled by the application using #AsPool.
* You can find AppStream metadata matching various user-defined criteria, and also add new
* metadata to the pool.
* The caching behavior can be controlled by the application using #AsCacheFlags.
*
* An AppStream cache object can also be created and read using the appstreamcli(1) utility.
*
* This class is threadsafe.
*
* See also: #AsComponent
*/
......@@ -72,7 +74,7 @@ typedef struct
AsCache *system_cache;
AsCache *cache;
gchar *cache_fname;
gchar *system_cache_fname;
gchar *sys_cache_dir;
gchar **term_greylist;
......@@ -80,8 +82,7 @@ typedef struct
AsCacheFlags cache_flags;
gboolean prefer_local_metainfo;
gchar *sys_cache_path;
gchar *user_cache_path;
GMutex mutex;
} AsPoolPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (AsPool, as_pool, G_TYPE_OBJECT)
......@@ -125,6 +126,8 @@ as_pool_init (AsPool *pool)
guint i;
g_autoptr(AsDistroDetails) distro = NULL;
g_mutex_init (&priv->mutex);
/* set active locale */
priv->locale = as_get_current_locale ();
......@@ -139,7 +142,7 @@ as_pool_init (AsPool *pool)
priv->term_greylist = g_strsplit (AS_SEARCH_GREYLIST_STR, ";", -1);
/* system-wide cache locations */
priv->sys_cache_path = g_strdup (AS_APPSTREAM_CACHE_PATH);
priv->sys_cache_dir = g_strdup (AS_APPSTREAM_CACHE_PATH);
if (as_utils_is_root ()) {
/* users umask shouldn't interfere with us creating new files when we are root */
......@@ -194,6 +197,7 @@ as_pool_finalize (GObject *object)
AsPool *pool = AS_POOL (object);
AsPoolPrivate *priv = GET_PRIVATE (pool);
g_mutex_lock (&priv->mutex);
g_free (priv->screenshot_service_url);
g_ptr_array_unref (priv->xml_dirs);
......@@ -203,14 +207,14 @@ as_pool_finalize (GObject *object)
g_object_unref (priv->cache);
g_object_unref (priv->system_cache);
g_free (priv->cache_fname);
g_free (priv->sys_cache_dir);
g_free (priv->locale);
g_free (priv->current_arch);
g_strfreev (priv->term_greylist);
g_free (priv->sys_cache_path);
g_free (priv->user_cache_path);
g_mutex_unlock (&priv->mutex);
g_mutex_clear (&priv->mutex);
G_OBJECT_CLASS (as_pool_parent_class)->finalize (object);
}
......@@ -234,6 +238,7 @@ static inline gboolean
as_pool_can_query_system_cache (AsPool *pool)
{
AsPoolPrivate *priv = GET_PRIVATE (pool);
g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&priv->mutex);
if (as_flags_contains (priv->cache_flags, AS_CACHE_FLAG_USE_SYSTEM))
return as_cache_is_open (priv->system_cache);
return FALSE;
......@@ -572,6 +577,7 @@ gboolean
as_pool_clear2 (AsPool *pool, GError **error)
{
AsPoolPrivate *priv = GET_PRIVATE (pool);
g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&priv->mutex);
/* close & delete session cache */
as_cache_close (priv->cache);
......@@ -652,6 +658,7 @@ as_pool_has_system_metadata_paths (AsPool *pool)
{
AsPoolPrivate *priv = GET_PRIVATE (pool);
guint i;
g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&priv->mutex);
for (i = 0; i < priv->xml_dirs->len; i++) {
const gchar *dir = (const gchar*) g_ptr_array_index (priv->xml_dirs, i);
......@@ -675,6 +682,7 @@ as_pool_metadata_changed (AsPool *pool, AsCache *cache, gboolean system_only)
{
AsPoolPrivate *priv = GET_PRIVATE (pool);
guint i;
g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&priv->mutex);
for (i = 0; i < priv->xml_dirs->len; i++) {
const gchar *dir = (const gchar*) g_ptr_array_index (priv->xml_dirs, i);
......@@ -702,6 +710,7 @@ as_pool_metadata_changed (AsPool *pool, AsCache *cache, gboolean system_only)
static gboolean
as_pool_load_collection_data (AsPool *pool, gboolean refresh, GError **error)
{
AsPoolPrivate *priv = GET_PRIVATE (pool);
GPtrArray *cpts;
g_autoptr(GPtrArray) merge_cpts = NULL;
guint i;
......@@ -709,23 +718,29 @@ as_pool_load_collection_data (AsPool *pool, gboolean refresh, GError **error)
g_autoptr(AsMetadata) metad = NULL;
g_autoptr(GPtrArray) mdata_files = NULL;
GError *tmp_error = NULL;
AsPoolPrivate *priv = GET_PRIVATE (pool);
g_autoptr(GMutexLocker) locker = NULL;
/* see if we can use the system caches */
if (!refresh && as_pool_has_system_metadata_paths (pool)) {
g_autofree gchar *fname = NULL;
fname = g_strdup_printf ("%s/%s.cache", priv->sys_cache_path, priv->locale);
g_mutex_lock (&priv->mutex);
fname = g_strdup_printf ("%s/%s.cache", priv->sys_cache_dir, priv->locale);
as_cache_set_location (priv->system_cache, fname);
g_mutex_unlock (&priv->mutex);
if (!as_pool_metadata_changed (pool, priv->system_cache, TRUE)) {
g_debug ("System metadata cache seems up to date.");
g_mutex_lock (&priv->mutex);
if (as_flags_contains (priv->cache_flags, AS_CACHE_FLAG_USE_SYSTEM)) {
g_mutex_unlock (&priv->mutex);
g_debug ("Using system cache data.");
if (g_file_test (fname, G_FILE_TEST_EXISTS)) {
as_cache_close (priv->system_cache);
g_mutex_lock (&priv->mutex);
if (as_cache_open2 (priv->system_cache, priv->locale, &tmp_error)) {
g_mutex_unlock (&priv->mutex);
return TRUE;
} else {
/* if we can't open the system cache for whatever reason, we complain but
......@@ -734,10 +749,12 @@ as_pool_load_collection_data (AsPool *pool, gboolean refresh, GError **error)
g_error_free (tmp_error);
tmp_error = NULL;
}
g_mutex_unlock (&priv->mutex);
} else {
g_debug ("Missing cache for language '%s', attempting to load fresh data.", priv->locale);
}
} else {
g_mutex_unlock (&priv->mutex);
g_debug ("Not using system cache.");
as_cache_close (priv->system_cache);
}
......@@ -752,12 +769,17 @@ as_pool_load_collection_data (AsPool *pool, gboolean refresh, GError **error)
/* prepare metadata parser */
metad = as_metadata_new ();
as_metadata_set_format_style (metad, AS_FORMAT_STYLE_COLLECTION);
g_mutex_lock (&priv->mutex);
as_metadata_set_locale (metad, priv->locale);
g_mutex_unlock (&priv->mutex);
/* find AppStream metadata */
ret = TRUE;
mdata_files = g_ptr_array_new_with_free_func (g_free);
/* protect access to directory lists */
locker = g_mutex_locker_new (&priv->mutex);
/* find XML data */
for (i = 0; i < priv->xml_dirs->len; i++) {
const gchar *xml_path = (const gchar *) g_ptr_array_index (priv->xml_dirs, i);
......@@ -800,6 +822,9 @@ as_pool_load_collection_data (AsPool *pool, gboolean refresh, GError **error)
}
}
/* no need for further locking after this point, AsCache is threadsafe */
g_clear_pointer (&locker, g_mutex_locker_free);
/* parse the found data */
for (i = 0; i < mdata_files->len; i++) {
g_autoptr(GFile) infile = NULL;
......@@ -855,7 +880,7 @@ as_pool_load_collection_data (AsPool *pool, gboolean refresh, GError **error)
continue;
}
as_pool_add_component (pool, cpt, &tmp_error);
as_pool_add_component_internal (pool, cpt, TRUE, &tmp_error);
if (tmp_error != NULL) {
g_debug ("Metadata ignored: %s", tmp_error->message);
g_error_free (tmp_error);
......@@ -868,7 +893,7 @@ as_pool_load_collection_data (AsPool *pool, gboolean refresh, GError **error)
for (i = 0; i < merge_cpts->len; i++) {
AsComponent *mcpt = AS_COMPONENT (g_ptr_array_index (merge_cpts, i));
as_pool_add_component (pool, mcpt, &tmp_error);
as_pool_add_component_internal (pool, mcpt, TRUE, &tmp_error);
if (tmp_error != NULL) {
g_debug ("Merge component ignored: %s", tmp_error->message);
g_error_free (tmp_error);
......@@ -898,7 +923,9 @@ as_pool_get_desktop_entries_table (AsPool *pool)
/* prepare metadata parser */
metad = as_metadata_new ();
g_mutex_lock (&priv->mutex);
as_metadata_set_locale (metad, priv->locale);
g_mutex_unlock (&priv->mutex);
de_cpt_table = g_hash_table_new_full (g_str_hash,
g_str_equal,
......@@ -968,7 +995,9 @@ as_pool_load_metainfo_data (AsPool *pool, GHashTable *desktop_entry_cpts)
/* prepare metadata parser */
metad = as_metadata_new ();
g_mutex_lock (&priv->mutex);
as_metadata_set_locale (metad, priv->locale);
g_mutex_unlock (&priv->mutex);
/* find metainfo files */
g_debug ("Searching for data in: %s", METAINFO_DIR);
......@@ -1082,23 +1111,34 @@ as_pool_load_metainfo_desktop_data (AsPool *pool)
g_autoptr(GHashTable) de_cpts = NULL;
/* check if we actually need to load anything */
if (!as_flags_contains (priv->flags, AS_POOL_FLAG_READ_DESKTOP_FILES) && !as_flags_contains (priv->flags, AS_POOL_FLAG_READ_METAINFO))
g_mutex_lock (&priv->mutex);
if (!as_flags_contains (priv->flags, AS_POOL_FLAG_READ_DESKTOP_FILES) && !as_flags_contains (priv->flags, AS_POOL_FLAG_READ_METAINFO)) {
g_mutex_unlock (&priv->mutex);
return;
}
g_mutex_unlock (&priv->mutex);
/* get a hashmap of desktop-entry components */
de_cpts = as_pool_get_desktop_entries_table (pool);
g_mutex_lock (&priv->mutex);
if (as_flags_contains (priv->flags, AS_POOL_FLAG_READ_METAINFO)) {
g_mutex_unlock (&priv->mutex);
/* load metainfo components, absorb desktop-entry components into them */
as_pool_load_metainfo_data (pool, de_cpts);
} else {
g_mutex_unlock (&priv->mutex);
}
/* read all remaining .desktop file components, if needed */
g_mutex_lock (&priv->mutex);
if (as_flags_contains (priv->flags, AS_POOL_FLAG_READ_DESKTOP_FILES)) {
GHashTableIter iter;
gpointer value;
GError *error = NULL;
g_mutex_unlock (&priv->mutex);
g_debug ("Including components from .desktop files in the pool.");
g_hash_table_iter_init (&iter, de_cpts);
while (g_hash_table_iter_next (&iter, NULL, &value)) {
......@@ -1111,6 +1151,8 @@ as_pool_load_metainfo_desktop_data (AsPool *pool)
error = NULL;
}
}
} else {
g_mutex_unlock (&priv->mutex);
}
}
......@@ -1126,6 +1168,7 @@ as_pool_cache_refine_component_cb (gpointer data, gpointer user_data)
AsPool *pool = AS_POOL (user_data);
AsPoolPrivate *priv = GET_PRIVATE (pool);
AsComponent *cpt = AS_COMPONENT (data);
g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&priv->mutex);
/* add additional data to the component, e.g. external screenshots. Also refines
* the component's icon paths */
......@@ -1137,6 +1180,7 @@ as_pool_cache_refine_component_cb (gpointer data, gpointer user_data)
/**
* as_pool_load:
* @pool: An instance of #AsPool.
* @cancellable: a #GCancellable.
* @error: A #GError or %NULL.
*
* Builds an index of all found components in the watched locations.
......@@ -1158,12 +1202,19 @@ as_pool_load (AsPool *pool, GCancellable *cancellable, GError **error)
gdouble valid_percentage;
GError *tmp_error = NULL;
g_mutex_lock (&priv->mutex);
if (as_flags_contains (priv->cache_flags, AS_CACHE_FLAG_NO_CLEAR)) {
g_autoptr(GMutexLocker) inner_locker = NULL;
g_mutex_unlock (&priv->mutex);
inner_locker = g_mutex_locker_new (&priv->mutex);
/* we are supposed not to clear the cache before laoding its data */
if (!as_cache_open (priv->cache, priv->cache_fname, priv->locale, error))
return FALSE;
} else {
/* load (usually) means to reload, so we clear potential old data */
g_mutex_unlock (&priv->mutex);