Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Support per-thread and system-wide lock modes

A THREAD lock mode is used when another thread cannot access some shared state,
for instance when populating an in-memory cache.

A PROCESS lock mode is used when the package manager is doing something to the
system, which should be locked even for other processes.

This breaks API and ABI, again.
  • Loading branch information...
commit 1c082edd1ccf9fdd3552cb39726df2bc38716ad5 1 parent 819dc43
@hughsie authored
View
6 libzif/zif-config.c
@@ -60,6 +60,7 @@ struct _ZifConfigPrivate
GHashTable *hash_override;
GHashTable *hash_default;
gchar **basearch_list;
+ GMutex mutex;
};
G_DEFINE_TYPE (ZifConfig, zif_config, G_TYPE_OBJECT)
@@ -105,6 +106,9 @@ zif_config_load (ZifConfig *config,
GError *error_local = NULL;
guint config_schema_version;
+ /* lock other threads */
+ g_mutex_lock (&config->priv->mutex);
+
/* already loaded */
if (config->priv->loaded)
goto out;
@@ -170,6 +174,8 @@ zif_config_load (ZifConfig *config,
/* done */
config->priv->loaded = TRUE;
out:
+ /* unlock other threads */
+ g_mutex_unlock (&config->priv->mutex);
return ret;
}
View
51 libzif/zif-groups.c
@@ -138,16 +138,17 @@ zif_groups_set_mapping_file (ZifGroups *groups, const gchar *mapping_file, GErro
/**
* zif_groups_load:
* @groups: A #ZifGroups
+ * @state: A #ZifState to use for progress reporting
* @error: A #GError, or %NULL
*
* Loads the mapping file from disk into memory.
*
* Return value: %TRUE for success, %FALSE otherwise
*
- * Since: 0.1.0
+ * Since: 0.3.1
**/
gboolean
-zif_groups_load (ZifGroups *groups, GError **error)
+zif_groups_load (ZifGroups *groups, ZifState *state, GError **error)
{
gboolean ret = TRUE;
gchar *data = NULL;
@@ -165,6 +166,14 @@ zif_groups_load (ZifGroups *groups, GError **error)
if (groups->priv->loaded)
goto out;
+ /* take lock */
+ ret = zif_state_take_lock (state,
+ ZIF_LOCK_TYPE_GROUPS,
+ ZIF_LOCK_MODE_THREAD,
+ error);
+ if (!ret)
+ goto out;
+
/* no mapping file */
if (groups->priv->mapping_file == NULL) {
ret = FALSE;
@@ -216,6 +225,7 @@ zif_groups_load (ZifGroups *groups, GError **error)
/**
* zif_groups_get_groups:
* @groups: A #ZifGroups
+ * @state: A #ZifState to use for progress reporting
* @error: A #GError, or %NULL
*
* Gets the groups supported by the packaging system.
@@ -223,10 +233,12 @@ zif_groups_load (ZifGroups *groups, GError **error)
* Return value: (transfer full): An array of the string groups that are supported, free
* with g_ptr_array_unref() when done.
*
- * Since: 0.1.0
+ * Since: 0.3.1
**/
GPtrArray *
-zif_groups_get_groups (ZifGroups *groups, GError **error)
+zif_groups_get_groups (ZifGroups *groups,
+ ZifState *state,
+ GError **error)
{
GError *error_local = NULL;
gboolean ret;
@@ -236,7 +248,7 @@ zif_groups_get_groups (ZifGroups *groups, GError **error)
/* if not already loaded, load */
if (!groups->priv->loaded) {
- ret = zif_groups_load (groups, &error_local);
+ ret = zif_groups_load (groups, state, &error_local);
if (!ret) {
g_set_error (error, ZIF_GROUPS_ERROR, ZIF_GROUPS_ERROR_FAILED,
"failed to load config file: %s", error_local->message);
@@ -251,6 +263,7 @@ zif_groups_get_groups (ZifGroups *groups, GError **error)
/**
* zif_groups_get_categories:
* @groups: A #ZifGroups
+ * @state: A #ZifState to use for progress reporting
* @error: A #GError, or %NULL
*
* Gets the categories supported by the packaging system.
@@ -258,10 +271,12 @@ zif_groups_get_groups (ZifGroups *groups, GError **error)
* Return value: (transfer full): An array of category list as strings, free
* with g_ptr_array_unref() when done.
*
- * Since: 0.1.0
+ * Since: 0.3.1
**/
GPtrArray *
-zif_groups_get_categories (ZifGroups *groups, GError **error)
+zif_groups_get_categories (ZifGroups *groups,
+ ZifState *state,
+ GError **error)
{
guint i;
GPtrArray *array = NULL;
@@ -273,7 +288,7 @@ zif_groups_get_categories (ZifGroups *groups, GError **error)
/* if not already loaded, load */
if (!groups->priv->loaded) {
- ret = zif_groups_load (groups, &error_local);
+ ret = zif_groups_load (groups, state, &error_local);
if (!ret) {
g_set_error (error, ZIF_GROUPS_ERROR, ZIF_GROUPS_ERROR_FAILED,
"failed to load config file: %s", error_local->message);
@@ -294,6 +309,7 @@ zif_groups_get_categories (ZifGroups *groups, GError **error)
* zif_groups_get_cats_for_group:
* @groups: A #ZifGroups
* @group_enum: A group enumeration, e.g. "education"
+ * @state: A #ZifState to use for progress reporting
* @error: A #GError, or %NULL
*
* Gets all the categories that map to to this group enumeration.
@@ -301,10 +317,13 @@ zif_groups_get_categories (ZifGroups *groups, GError **error)
* Return value: (transfer full): An array of category list as strings, free
* with g_ptr_array_unref() when done.
*
- * Since: 0.1.1
+ * Since: 0.3.1
**/
GPtrArray *
-zif_groups_get_cats_for_group (ZifGroups *groups, const gchar *group_enum, GError **error)
+zif_groups_get_cats_for_group (ZifGroups *groups,
+ const gchar *group_enum,
+ ZifState *state,
+ GError **error)
{
guint i;
GPtrArray *array = NULL;
@@ -322,7 +341,7 @@ zif_groups_get_cats_for_group (ZifGroups *groups, const gchar *group_enum, GErro
/* if not already loaded, load */
if (!priv->loaded) {
- ret = zif_groups_load (groups, &error_local);
+ ret = zif_groups_load (groups, state, &error_local);
if (!ret) {
g_set_error (error, ZIF_GROUPS_ERROR, ZIF_GROUPS_ERROR_FAILED,
"failed to load config file: %s", error_local->message);
@@ -353,16 +372,20 @@ zif_groups_get_cats_for_group (ZifGroups *groups, const gchar *group_enum, GErro
* zif_groups_get_group_for_cat:
* @groups: A #ZifGroups
* @cat: Category name, e.g. "games/action"
+ * @state: A #ZifState to use for progress reporting
* @error: A #GError, or %NULL
*
* Returns the group enumerated type for the category.
*
* Return value: A specific group name or %NULL
*
- * Since: 0.1.0
+ * Since: 0.3.1
**/
const gchar *
-zif_groups_get_group_for_cat (ZifGroups *groups, const gchar *cat, GError **error)
+zif_groups_get_group_for_cat (ZifGroups *groups,
+ const gchar *cat,
+ ZifState *state,
+ GError **error)
{
const gchar *group = NULL;
GError *error_local = NULL;
@@ -374,7 +397,7 @@ zif_groups_get_group_for_cat (ZifGroups *groups, const gchar *cat, GError **erro
/* if not already loaded, load */
if (!groups->priv->loaded) {
- ret = zif_groups_load (groups, &error_local);
+ ret = zif_groups_load (groups, state, &error_local);
if (!ret) {
g_set_error (error, ZIF_GROUPS_ERROR, ZIF_GROUPS_ERROR_FAILED,
"failed to load config file: %s", error_local->message);
View
7 libzif/zif-groups.h
@@ -28,6 +28,8 @@
#include <glib-object.h>
+#include "zif-state.h"
+
G_BEGIN_DECLS
#define ZIF_TYPE_GROUPS (zif_groups_get_type ())
@@ -70,16 +72,21 @@ gboolean zif_groups_set_mapping_file (ZifGroups *groups,
const gchar *mapping_file,
GError **error);
gboolean zif_groups_load (ZifGroups *groups,
+ ZifState *state,
GError **error);
GPtrArray *zif_groups_get_groups (ZifGroups *groups,
+ ZifState *state,
GError **error);
GPtrArray *zif_groups_get_categories (ZifGroups *groups,
+ ZifState *state,
GError **error);
GPtrArray *zif_groups_get_cats_for_group (ZifGroups *groups,
const gchar *group_enum,
+ ZifState *state,
GError **error);
const gchar *zif_groups_get_group_for_cat (ZifGroups *groups,
const gchar *cat,
+ ZifState *state,
GError **error);
G_END_DECLS
View
28 libzif/zif-history.c
@@ -80,11 +80,24 @@ zif_history_load (ZifHistory *history, GError **error)
gboolean ret = TRUE;
gchar *error_msg = NULL;
gint rc;
+ guint lock_id;
+ ZifLock *lock = NULL;
/* already loaded */
if (history->priv->loaded)
goto out;
+ /* take lock */
+ lock = zif_lock_new ();
+ lock_id = zif_lock_take (lock,
+ ZIF_LOCK_TYPE_HISTORY,
+ ZIF_LOCK_MODE_THREAD,
+ error);
+ if (lock_id == 0) {
+ ret = FALSE;
+ goto out;
+ }
+
/* nothing set */
if (history->priv->filename == NULL) {
history->priv->filename = zif_config_get_string (history->priv->config,
@@ -92,6 +105,7 @@ zif_history_load (ZifHistory *history, GError **error)
error);
if (history->priv->filename == NULL) {
ret = FALSE;
+ zif_lock_release_noerror (lock, lock_id);
goto out;
}
}
@@ -100,8 +114,10 @@ zif_history_load (ZifHistory *history, GError **error)
ret = zif_ensure_parent_dir_exists (history->priv->filename,
NULL,
error);
- if (!ret)
+ if (!ret) {
+ zif_lock_release_noerror (lock, lock_id);
goto out;
+ }
/* open db */
g_debug ("trying to open database '%s'", history->priv->filename);
@@ -116,6 +132,7 @@ zif_history_load (ZifHistory *history, GError **error)
sqlite3_errmsg (history->priv->db));
sqlite3_close (history->priv->db);
history->priv->db = NULL;
+ zif_lock_release_noerror (lock, lock_id);
goto out;
}
@@ -155,7 +172,16 @@ zif_history_load (ZifHistory *history, GError **error)
/* yippee */
history->priv->loaded = TRUE;
+
+ /* unlock */
+ ret = zif_lock_release (lock,
+ lock_id,
+ error);
+ if (!ret)
+ goto out;
out:
+ if (lock != NULL)
+ g_object_unref (lock);
return ret;
}
View
238 libzif/zif-lock.c
@@ -50,10 +50,17 @@ struct _ZifLockPrivate
{
GMutex mutex;
ZifConfig *config;
- guint refcount[ZIF_LOCK_TYPE_LAST];
- gpointer owner[ZIF_LOCK_TYPE_LAST];
+ GPtrArray *item_array;
};
+typedef struct {
+ gpointer owner;
+ guint id;
+ guint refcount;
+ ZifLockMode mode;
+ ZifLockType type;
+} ZifLockItem;
+
enum {
SIGNAL_STATE_CHANGED,
SIGNAL_LAST
@@ -104,16 +111,81 @@ zif_lock_is_instance_valid (void)
const gchar *
zif_lock_type_to_string (ZifLockType lock_type)
{
- if (lock_type == ZIF_LOCK_TYPE_RPMDB_WRITE)
- return "rpmdb-write";
- if (lock_type == ZIF_LOCK_TYPE_REPO_WRITE)
- return "repo-write";
- if (lock_type == ZIF_LOCK_TYPE_METADATA_WRITE)
- return "metadata-write";
+ if (lock_type == ZIF_LOCK_TYPE_RPMDB)
+ return "rpmdb";
+ if (lock_type == ZIF_LOCK_TYPE_REPO)
+ return "repo";
+ if (lock_type == ZIF_LOCK_TYPE_METADATA)
+ return "metadata";
+ if (lock_type == ZIF_LOCK_TYPE_GROUPS)
+ return "groups";
+ if (lock_type == ZIF_LOCK_TYPE_RELEASE)
+ return "release";
+ if (lock_type == ZIF_LOCK_TYPE_CONFIG)
+ return "config";
+ if (lock_type == ZIF_LOCK_TYPE_HISTORY)
+ return "history";
return "unknown";
}
/**
+ * zif_lock_get_item_by_type_mode:
+ **/
+static ZifLockItem *
+zif_lock_get_item_by_type_mode (ZifLock *lock,
+ ZifLockType type,
+ ZifLockMode mode)
+{
+ ZifLockItem *item;
+ guint i;
+
+ /* search for the item that matches type */
+ for (i = 0; i < lock->priv->item_array->len; i++) {
+ item = g_ptr_array_index (lock->priv->item_array, i);
+ if (item->type == type && item->mode == mode)
+ return item;
+ }
+ return NULL;
+}
+
+/**
+ * zif_lock_get_item_by_id:
+ **/
+static ZifLockItem *
+zif_lock_get_item_by_id (ZifLock *lock, guint id)
+{
+ ZifLockItem *item;
+ guint i;
+
+ /* search for the item that matches the ID */
+ for (i = 0; i < lock->priv->item_array->len; i++) {
+ item = g_ptr_array_index (lock->priv->item_array, i);
+ if (item->id == id)
+ return item;
+ }
+ return NULL;
+}
+
+/**
+ * zif_lock_create_item:
+ **/
+static ZifLockItem *
+zif_lock_create_item (ZifLock *lock, ZifLockType type, ZifLockMode mode)
+{
+ static guint id = 1;
+ ZifLockItem *item;
+
+ item = g_new0 (ZifLockItem, 1);
+ item->id = id++;
+ item->type = type;
+ item->owner = g_thread_self ();
+ item->refcount = 1;
+ item->mode = mode;
+ g_ptr_array_add (lock->priv->item_array, item);
+ return item;
+}
+
+/**
* zif_lock_get_pid:
**/
static guint
@@ -245,13 +317,13 @@ zif_lock_get_state (ZifLock *lock)
{
guint bitfield = 0;
guint i;
+ ZifLockItem *item;
g_return_val_if_fail (ZIF_IS_LOCK (lock), FALSE);
- for (i = 0; i < ZIF_LOCK_TYPE_LAST; i++) {
- if (lock->priv->refcount[i] == 0)
- continue;
- bitfield += 1 << i;
+ for (i = 0; i < lock->priv->item_array->len; i++) {
+ item = g_ptr_array_index (lock->priv->item_array, i);
+ bitfield += 1 << item->type;
}
return bitfield;
}
@@ -270,25 +342,31 @@ zif_lock_emit_state (ZifLock *lock)
/**
* zif_lock_take:
* @lock: A #ZifLock
- * @type: A ZifLockType, e.g. %ZIF_LOCK_TYPE_RPMDB_WRITE
+ * @type: A #ZifLockType, e.g. %ZIF_LOCK_TYPE_RPMDB
+ * @mode: A #ZifLockMode, e.g. %ZIF_LOCK_MODE_PROCESS
* @error: A #GError, or %NULL
*
* Tries to take a lock for the packaging system.
*
- * Return value: %TRUE if we locked, else %FALSE and the error is set
+ * Return value: A lock ID greater than 0, or 0 for an error.
*
- * Since: 0.1.6
+ * Since: 0.3.1
**/
-gboolean
-zif_lock_take (ZifLock *lock, ZifLockType type, GError **error)
+guint
+zif_lock_take (ZifLock *lock,
+ ZifLockType type,
+ ZifLockMode mode,
+ GError **error)
{
- gboolean ret = FALSE;
+ gboolean ret;
gchar *cmdline = NULL;
gchar *filename = NULL;
gchar *pid_filename = NULL;
gchar *pid_text = NULL;
GError *error_local = NULL;
+ guint id = 0;
guint pid;
+ ZifLockItem *item;
g_return_val_if_fail (ZIF_IS_LOCK (lock), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
@@ -296,7 +374,17 @@ zif_lock_take (ZifLock *lock, ZifLockType type, GError **error)
/* lock other threads */
g_mutex_lock (&lock->priv->mutex);
- if (lock->priv->refcount[type] == 0) {
+ /* find the lock type, and ensure we find a process lock for
+ * a thread lock */
+ item = zif_lock_get_item_by_type_mode (lock, type, mode);
+ if (item == NULL && mode == ZIF_LOCK_MODE_THREAD) {
+ item = zif_lock_get_item_by_type_mode (lock,
+ type,
+ ZIF_LOCK_MODE_PROCESS);
+ }
+
+ /* create a lock file for process locks */
+ if (item == NULL && mode == ZIF_LOCK_MODE_PROCESS) {
/* get the lock filename */
filename = zif_lock_get_filename_for_type (lock,
@@ -345,29 +433,36 @@ zif_lock_take (ZifLock *lock, ZifLockType type, GError **error)
g_error_free (error_local);
goto out;
}
- } else {
- /* we're trying to lock something that's already locked
- * in another thread */
- if (lock->priv->owner[type] != g_thread_self ()) {
- g_set_error (error,
- ZIF_LOCK_ERROR,
- ZIF_LOCK_ERROR_FAILED,
- "failed to obtain lock '%s' already taken by thread %p",
- zif_lock_type_to_string (type),
- lock->priv->owner[type]);
- goto out;
- }
}
- /* emit the new locking bitfield */
- zif_lock_emit_state (lock);
+ /* create new lock */
+ if (item == NULL) {
+ item = zif_lock_create_item (lock, type, mode);
+ id = item->id;
+ zif_lock_emit_state (lock);
+ goto out;
+ }
+
+ /* we're trying to lock something that's already locked
+ * in another thread */
+ if (item->owner != g_thread_self ()) {
+ g_set_error (error,
+ ZIF_LOCK_ERROR,
+ ZIF_LOCK_ERROR_FAILED,
+ "failed to obtain lock '%s' already taken by thread %p",
+ zif_lock_type_to_string (type),
+ item->owner);
+ goto out;
+ }
/* increment ref count */
- lock->priv->refcount[type]++;
- lock->priv->owner[type] = g_thread_self ();
+ item->refcount++;
+
+ /* emit the new locking bitfield */
+ zif_lock_emit_state (lock);
/* success */
- ret = TRUE;
+ id = item->id;
out:
/* unlock other threads */
g_mutex_unlock (&lock->priv->mutex);
@@ -376,63 +471,67 @@ zif_lock_take (ZifLock *lock, ZifLockType type, GError **error)
g_free (pid_filename);
g_free (filename);
g_free (cmdline);
- return ret;
+ return id;
}
/**
* zif_lock_release:
* @lock: A #ZifLock
- * @type: A ZifLockType, e.g. %ZIF_LOCK_TYPE_RPMDB_WRITE
+ * @id: A lock ID, as given by zif_lock_take()
* @error: A #GError, or %NULL
*
* Tries to release a lock for the packaging system.
*
* Return value: %TRUE if we locked, else %FALSE and the error is set
*
- * Since: 0.1.6
+ * Since: 0.3.1
**/
gboolean
-zif_lock_release (ZifLock *lock, ZifLockType type, GError **error)
+zif_lock_release (ZifLock *lock, guint id, GError **error)
{
gboolean ret = FALSE;
gchar *filename = NULL;
GError *error_local = NULL;
GFile *file = NULL;
+ ZifLockItem *item;
g_return_val_if_fail (ZIF_IS_LOCK (lock), FALSE);
+ g_return_val_if_fail (id != 0, FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
/* lock other threads */
g_mutex_lock (&lock->priv->mutex);
/* never took */
- if (lock->priv->refcount[type] == 0) {
+ item = zif_lock_get_item_by_id (lock, id);
+ if (item == NULL) {
g_set_error (error,
ZIF_LOCK_ERROR,
ZIF_LOCK_ERROR_NOT_LOCKED,
- "Lock %s was never taken",
- zif_lock_type_to_string (type));
+ "Lock was never taken with id %i", id);
goto out;
}
/* not the same thread */
- if (lock->priv->owner[type] != g_thread_self ()) {
+ if (item->owner != g_thread_self ()) {
g_set_error (error,
ZIF_LOCK_ERROR,
ZIF_LOCK_ERROR_NOT_LOCKED,
"Lock %s was not taken by this thread",
- zif_lock_type_to_string (type));
+ zif_lock_type_to_string (item->type));
goto out;
}
/* idecrement ref count */
- lock->priv->refcount[type]--;
+ item->refcount--;
+
+ /* delete file for process locks */
+ if (item->refcount == 0 &&
+ item->mode == ZIF_LOCK_MODE_PROCESS) {
- /* delete file? */
- if (lock->priv->refcount[type] == 0) {
/* get the lock filename */
filename = zif_lock_get_filename_for_type (lock,
- type,
+ item->type,
error);
if (filename == NULL)
goto out;
@@ -449,11 +548,12 @@ zif_lock_release (ZifLock *lock, ZifLockType type, GError **error)
g_error_free (error_local);
goto out;
}
-
- /* no thread now owns this lock */
- lock->priv->owner[type] = NULL;
}
+ /* no thread now owns this lock */
+ if (item->refcount == 0)
+ g_ptr_array_remove (lock->priv->item_array, item);
+
/* emit the new locking bitfield */
zif_lock_emit_state (lock);
@@ -469,6 +569,28 @@ zif_lock_release (ZifLock *lock, ZifLockType type, GError **error)
}
/**
+ * zif_lock_release_noerror:
+ * @lock: A #ZifLock
+ * @id: A lock ID, as given by zif_lock_take()
+ *
+ * Tries to release a lock for the packaging system. This method
+ * should not be used lightly as no error will be returned.
+ *
+ * Since: 0.3.1
+ **/
+void
+zif_lock_release_noerror (ZifLock *lock, guint id)
+{
+ gboolean ret;
+ GError *error = NULL;
+ ret = zif_lock_release (lock, id, &error);
+ if (!ret) {
+ g_warning ("Handled locally: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+/**
* zif_lock_finalize:
**/
static void
@@ -476,21 +598,24 @@ zif_lock_finalize (GObject *object)
{
guint i;
ZifLock *lock;
+ ZifLockItem *item;
g_return_if_fail (object != NULL);
g_return_if_fail (ZIF_IS_LOCK (object));
lock = ZIF_LOCK (object);
/* unlock if we hold the lock */
- for (i=0; i<ZIF_LOCK_TYPE_LAST; i++) {
- if (lock->priv->refcount[i] > 0) {
+ for (i = 0; i < lock->priv->item_array->len; i++) {
+ item = g_ptr_array_index (lock->priv->item_array, i);
+ if (item->refcount > 0) {
g_warning ("held lock %s at shutdown",
- zif_lock_type_to_string (i));
- zif_lock_release (lock, i, NULL);
+ zif_lock_type_to_string (item->type));
+ zif_lock_release (lock, item->type, NULL);
}
}
g_object_unref (lock->priv->config);
+ g_ptr_array_unref (lock->priv->item_array);
G_OBJECT_CLASS (zif_lock_parent_class)->finalize (object);
}
@@ -522,6 +647,7 @@ zif_lock_init (ZifLock *lock)
{
lock->priv = ZIF_LOCK_GET_PRIVATE (lock);
lock->priv->config = zif_config_new ();
+ lock->priv->item_array = g_ptr_array_new_with_free_func (g_free);
}
/**
View
23 libzif/zif-lock.h
@@ -70,23 +70,36 @@ typedef enum {
} ZifLockError;
typedef enum {
- ZIF_LOCK_TYPE_RPMDB_WRITE,
- ZIF_LOCK_TYPE_REPO_WRITE,
- ZIF_LOCK_TYPE_METADATA_WRITE,
+ ZIF_LOCK_TYPE_RPMDB,
+ ZIF_LOCK_TYPE_REPO,
+ ZIF_LOCK_TYPE_METADATA,
+ ZIF_LOCK_TYPE_GROUPS,
+ ZIF_LOCK_TYPE_RELEASE,
+ ZIF_LOCK_TYPE_CONFIG,
+ ZIF_LOCK_TYPE_HISTORY,
ZIF_LOCK_TYPE_LAST
} ZifLockType;
+typedef enum {
+ ZIF_LOCK_MODE_THREAD,
+ ZIF_LOCK_MODE_PROCESS,
+ ZIF_LOCK_MODE_LAST
+} ZifLockMode;
+
GType zif_lock_get_type (void);
GQuark zif_lock_error_quark (void);
ZifLock *zif_lock_new (void);
gboolean zif_lock_is_instance_valid (void);
-gboolean zif_lock_take (ZifLock *lock,
+guint zif_lock_take (ZifLock *lock,
ZifLockType type,
+ ZifLockMode mode,
GError **error);
gboolean zif_lock_release (ZifLock *lock,
- ZifLockType type,
+ guint id,
GError **error);
+void zif_lock_release_noerror (ZifLock *lock,
+ guint id);
const gchar *zif_lock_type_to_string (ZifLockType lock_type);
guint zif_lock_get_state (ZifLock *lock);
View
5 libzif/zif-package-local.c
@@ -393,7 +393,10 @@ zif_package_local_ensure_data (ZifPackage *pkg,
text = zif_package_get_category (pkg, state, error);
if (text == NULL)
goto out;
- group = zif_groups_get_group_for_cat (ZIF_PACKAGE_LOCAL(pkg)->priv->groups, text, error);
+ group = zif_groups_get_group_for_cat (ZIF_PACKAGE_LOCAL(pkg)->priv->groups,
+ text,
+ state,
+ error);
if (group == NULL)
goto out;
View
1  libzif/zif-package-remote.c
@@ -847,6 +847,7 @@ zif_package_remote_ensure_data (ZifPackage *pkg,
goto out;
group = zif_groups_get_group_for_cat (pkg_remote->priv->groups,
text,
+ state,
error);
if (group == NULL)
goto out;
View
8 libzif/zif-release.c
@@ -142,6 +142,14 @@ zif_release_load (ZifRelease *release, ZifState *state, GError **error)
ZifReleasePrivate *priv = release->priv;
ZifUpgrade *upgrade;
+ /* take lock */
+ ret = zif_state_take_lock (state,
+ ZIF_LOCK_TYPE_RELEASE,
+ ZIF_LOCK_MODE_THREAD,
+ error);
+ if (!ret)
+ goto out;
+
/* nothing set */
cache_dir = zif_config_get_string (priv->config,
"upgrade_cache_dir",
View
8 libzif/zif-repos.c
@@ -274,6 +274,14 @@ zif_repos_load (ZifRepos *repos, ZifState *state, GError **error)
if (repos->priv->loaded)
goto out;
+ /* take lock */
+ ret = zif_state_take_lock (state,
+ ZIF_LOCK_TYPE_REPO,
+ ZIF_LOCK_MODE_THREAD,
+ error);
+ if (!ret)
+ goto out;
+
/* set action */
zif_state_action_start (state, ZIF_STATE_ACTION_LOADING_REPOS, NULL);
View
82 libzif/zif-self-test.c
@@ -1230,6 +1230,7 @@ zif_groups_func (void)
const gchar *group;
const gchar *category;
gchar *filename;
+ ZifState *state;
groups = zif_groups_new ();
g_assert (groups != NULL);
@@ -1240,27 +1241,32 @@ zif_groups_func (void)
g_assert_no_error (error);
g_assert (ret);
- ret = zif_groups_load (groups, &error);
+ state = zif_state_new ();
+ ret = zif_groups_load (groups, state, &error);
g_assert_no_error (error);
g_assert (ret);
- array = zif_groups_get_groups (groups, &error);
+ zif_state_reset (state);
+ array = zif_groups_get_groups (groups, state, &error);
g_assert_no_error (error);
g_assert (array != NULL);
group = g_ptr_array_index (array, 0);
g_assert_cmpstr (group, ==, "admin-tools");
- array = zif_groups_get_categories (groups, &error);
+ zif_state_reset (state);
+ array = zif_groups_get_categories (groups, state, &error);
g_assert_no_error (error);
g_assert (array != NULL);
g_assert_cmpint (array->len, >, 100);
g_ptr_array_unref (array);
- group = zif_groups_get_group_for_cat (groups, "language-support;kashubian-support", &error);
+ zif_state_reset (state);
+ group = zif_groups_get_group_for_cat (groups, "language-support;kashubian-support", state, &error);
g_assert_no_error (error);
g_assert_cmpstr (group, ==, "localization");
- array = zif_groups_get_cats_for_group (groups, "localization", &error);
+ zif_state_reset (state);
+ array = zif_groups_get_cats_for_group (groups, "localization", state, &error);
g_assert_no_error (error);
g_assert (array != NULL);
g_assert_cmpint (array->len, >, 50);
@@ -1269,6 +1275,7 @@ zif_groups_func (void)
g_ptr_array_unref (array);
g_object_unref (groups);
+ g_object_unref (state);
zif_check_singletons ();
}
@@ -1325,6 +1332,8 @@ zif_lock_func (void)
ZifLock *lock;
ZifConfig *config;
gboolean ret;
+ guint lock_id1;
+ guint lock_id2;
GError *error = NULL;
gchar *pidfile;
gchar *filename;
@@ -1349,48 +1358,58 @@ zif_lock_func (void)
/* nothing yet! */
g_assert_cmpint (zif_lock_get_state (lock), ==, 0);
- ret = zif_lock_release (lock, ZIF_LOCK_TYPE_RPMDB_WRITE, &error);
+ ret = zif_lock_release (lock, 999, &error);
g_assert_error (error, ZIF_LOCK_ERROR, ZIF_LOCK_ERROR_NOT_LOCKED);
g_assert (!ret);
g_clear_error (&error);
/* take one */
- ret = zif_lock_take (lock, ZIF_LOCK_TYPE_RPMDB_WRITE, &error);
+ lock_id1 = zif_lock_take (lock,
+ ZIF_LOCK_TYPE_RPMDB,
+ ZIF_LOCK_MODE_PROCESS,
+ &error);
g_assert_no_error (error);
- g_assert (ret);
- g_assert_cmpint (zif_lock_get_state (lock), ==, 1 << ZIF_LOCK_TYPE_RPMDB_WRITE);
+ g_assert (lock_id1 != 0);
+ g_assert_cmpint (zif_lock_get_state (lock), ==, 1 << ZIF_LOCK_TYPE_RPMDB);
g_assert_cmpint (_zif_lock_state_changed, ==, 1);
/* take a different one */
- ret = zif_lock_take (lock, ZIF_LOCK_TYPE_REPO_WRITE, &error);
+ lock_id2 = zif_lock_take (lock,
+ ZIF_LOCK_TYPE_REPO,
+ ZIF_LOCK_MODE_PROCESS,
+ &error);
g_assert_no_error (error);
- g_assert (ret);
- g_assert_cmpint (zif_lock_get_state (lock), ==, 1 << ZIF_LOCK_TYPE_RPMDB_WRITE | 1 << ZIF_LOCK_TYPE_REPO_WRITE);
+ g_assert (lock_id2 != 0);
+ g_assert (lock_id2 != lock_id1);
+ g_assert_cmpint (zif_lock_get_state (lock), ==, 1 << ZIF_LOCK_TYPE_RPMDB | 1 << ZIF_LOCK_TYPE_REPO);
g_assert_cmpint (_zif_lock_state_changed, ==, 2);
/* take two */
- ret = zif_lock_take (lock, ZIF_LOCK_TYPE_RPMDB_WRITE, &error);
+ lock_id1 = zif_lock_take (lock,
+ ZIF_LOCK_TYPE_RPMDB,
+ ZIF_LOCK_MODE_PROCESS,
+ &error);
g_assert_no_error (error);
- g_assert (ret);
- g_assert_cmpint (zif_lock_get_state (lock), ==, 1 << ZIF_LOCK_TYPE_RPMDB_WRITE | 1 << ZIF_LOCK_TYPE_REPO_WRITE);
+ g_assert (lock_id1 != 0);
+ g_assert_cmpint (zif_lock_get_state (lock), ==, 1 << ZIF_LOCK_TYPE_RPMDB | 1 << ZIF_LOCK_TYPE_REPO);
/* release one */
- ret = zif_lock_release (lock, ZIF_LOCK_TYPE_RPMDB_WRITE, &error);
+ ret = zif_lock_release (lock, lock_id1, &error);
g_assert_no_error (error);
g_assert (ret);
/* release different one */
- ret = zif_lock_release (lock, ZIF_LOCK_TYPE_REPO_WRITE, &error);
+ ret = zif_lock_release (lock, lock_id2, &error);
g_assert_no_error (error);
g_assert (ret);
/* release two */
- ret = zif_lock_release (lock, ZIF_LOCK_TYPE_RPMDB_WRITE, &error);
+ ret = zif_lock_release (lock, lock_id1, &error);
g_assert_no_error (error);
g_assert (ret);
/* no more! */
- ret = zif_lock_release (lock, ZIF_LOCK_TYPE_RPMDB_WRITE, &error);
+ ret = zif_lock_release (lock, lock_id1, &error);
g_assert_error (error, ZIF_LOCK_ERROR, ZIF_LOCK_ERROR_NOT_LOCKED);
g_assert (!ret);
g_clear_error (&error);
@@ -1408,13 +1427,16 @@ static gpointer
zif_self_test_lock_thread_one (gpointer data)
{
GError *error = NULL;
- gboolean ret;
+ guint lock_id;
ZifLock *lock = ZIF_LOCK (data);
g_usleep (G_USEC_PER_SEC / 100);
- ret = zif_lock_take (lock, ZIF_LOCK_TYPE_REPO_WRITE, &error);
+ lock_id = zif_lock_take (lock,
+ ZIF_LOCK_TYPE_REPO,
+ ZIF_LOCK_MODE_PROCESS,
+ &error);
g_assert_error (error, ZIF_LOCK_ERROR, ZIF_LOCK_ERROR_FAILED);
- g_assert (!ret);
+ g_assert_cmpint (lock_id, ==, 0);
g_error_free (error);
return NULL;
}
@@ -1427,6 +1449,7 @@ zif_lock_threads_func (void)
gchar *pidfile;
GError *error = NULL;
GThread *one;
+ guint lock_id;
ZifConfig *config;
ZifLock *lock;
@@ -1446,9 +1469,12 @@ zif_lock_threads_func (void)
/* take in master thread */
lock = zif_lock_new ();
- ret = zif_lock_take (lock, ZIF_LOCK_TYPE_REPO_WRITE, &error);
+ lock_id = zif_lock_take (lock,
+ ZIF_LOCK_TYPE_REPO,
+ ZIF_LOCK_MODE_PROCESS,
+ &error);
g_assert_no_error (error);
- g_assert (ret);
+ g_assert_cmpint (lock_id, >, 0);
/* attempt to take in slave thread (should fail) */
one = g_thread_new ("zif-lock-one",
@@ -1459,7 +1485,7 @@ zif_lock_threads_func (void)
g_usleep (G_USEC_PER_SEC);
/* release lock */
- ret = zif_lock_release (lock, ZIF_LOCK_TYPE_REPO_WRITE, &error);
+ ret = zif_lock_release (lock, lock_id, &error);
g_assert_no_error (error);
g_assert (ret);
@@ -3221,14 +3247,16 @@ zif_state_locking_func (void)
/* lock once */
ret = zif_state_take_lock (state,
- ZIF_LOCK_TYPE_RPMDB_WRITE,
+ ZIF_LOCK_TYPE_RPMDB,
+ ZIF_LOCK_MODE_PROCESS,
&error);
g_assert_no_error (error);
g_assert (ret);
/* succeeded, even again */
ret = zif_state_take_lock (state,
- ZIF_LOCK_TYPE_RPMDB_WRITE,
+ ZIF_LOCK_TYPE_RPMDB,
+ ZIF_LOCK_MODE_PROCESS,
&error);
g_assert_no_error (error);
g_assert (ret);
View
45 libzif/zif-state.c
@@ -125,7 +125,7 @@ struct _ZifStatePrivate
ZifStateErrorHandlerCb error_handler_cb;
ZifStateLockHandlerCb lock_handler_cb;
ZifState *parent;
- GPtrArray *locks;
+ GPtrArray *lock_ids;
ZifLock *lock;
};
@@ -282,7 +282,8 @@ zif_state_set_lock_handler (ZifState *state,
/**
* zif_state_take_lock:
* @state: A #ZifState
- * @lock_type: A #ZifLockType, e.g. %ZIF_LOCK_TYPE_RPMDB_WRITE
+ * @lock_type: A #ZifLockType, e.g. %ZIF_LOCK_TYPE_RPMDB
+ * @lock_mode: A #ZifLockMode, e.g. %ZIF_LOCK_MODE_PROCESS
* @error: A #GError
*
* Takes a lock of a specified type.
@@ -293,21 +294,27 @@ zif_state_set_lock_handler (ZifState *state,
*
* Return value: %FALSE if the lock is fatal, %TRUE otherwise
*
- * Since: 0.1.6
+ * Since: 0.3.0
**/
gboolean
zif_state_take_lock (ZifState *state,
ZifLockType lock_type,
+ ZifLockMode lock_mode,
GError **error)
{
- gboolean ret = FALSE;
+ gboolean ret = TRUE;
+ guint lock_id = 0;
/* no custom handler */
if (state->priv->lock_handler_cb == NULL) {
- ret = zif_lock_take (state->priv->lock,
- lock_type,
- error);
+ lock_id = zif_lock_take (state->priv->lock,
+ lock_type,
+ lock_mode,
+ error);
+ if (lock_id == 0)
+ ret = FALSE;
} else {
+ lock_id = G_MAXUINT;
ret = state->priv->lock_handler_cb (state,
state->priv->lock,
lock_type,
@@ -318,10 +325,9 @@ zif_state_take_lock (ZifState *state,
goto out;
/* add the lock to an array so we can release on completion */
- g_debug ("adding lock %s",
- zif_lock_type_to_string (lock_type));
- g_ptr_array_add (state->priv->locks,
- GUINT_TO_POINTER (lock_type));
+ g_debug ("adding lock %i", lock_id);
+ g_ptr_array_add (state->priv->lock_ids,
+ GUINT_TO_POINTER (lock_id));
out:
return ret;
}
@@ -504,20 +510,19 @@ zif_state_release_locks (ZifState *state)
{
gboolean ret = TRUE;
guint i;
- ZifLockType lock_type;
+ guint lock_id;
/* release each one */
- for (i=0; i<state->priv->locks->len; i++) {
- lock_type = GPOINTER_TO_UINT (g_ptr_array_index (state->priv->locks, i));
- g_debug ("releasing lock %s",
- zif_lock_type_to_string (lock_type));
+ for (i = 0; i < state->priv->lock_ids->len; i++) {
+ lock_id = GPOINTER_TO_UINT (g_ptr_array_index (state->priv->lock_ids, i));
+ g_debug ("releasing lock %i", lock_id);
ret = zif_lock_release (state->priv->lock,
- lock_type,
+ lock_id,
NULL);
if (!ret)
goto out;
}
- g_ptr_array_set_size (state->priv->locks, 0);
+ g_ptr_array_set_size (state->priv->lock_ids, 0);
out:
return ret;
}
@@ -1600,7 +1605,7 @@ zif_state_finalize (GObject *object)
g_object_unref (state->priv->cancellable);
g_timer_destroy (state->priv->timer);
g_free (state->priv->speed_data);
- g_ptr_array_unref (state->priv->locks);
+ g_ptr_array_unref (state->priv->lock_ids);
g_object_unref (state->priv->lock);
G_OBJECT_CLASS (zif_state_parent_class)->finalize (object);
@@ -1717,7 +1722,7 @@ zif_state_init (ZifState *state)
state->priv->action = ZIF_STATE_ACTION_UNKNOWN;
state->priv->last_action = ZIF_STATE_ACTION_UNKNOWN;
state->priv->timer = g_timer_new ();
- state->priv->locks = g_ptr_array_new ();
+ state->priv->lock_ids = g_ptr_array_new ();
state->priv->report_progress = TRUE;
state->priv->lock = zif_lock_new ();
state->priv->speed_data = g_new0 (guint64, ZIF_STATE_SPEED_SMOOTHING_ITEMS);
View
1  libzif/zif-state.h
@@ -172,6 +172,7 @@ void zif_state_set_lock_handler (ZifState *state,
gpointer user_data);
gboolean zif_state_take_lock (ZifState *state,
ZifLockType lock_type,
+ ZifLockMode lock_mode,
GError **error);
G_END_DECLS
View
8 libzif/zif-store-local.c
@@ -289,6 +289,14 @@ zif_store_local_load (ZifStore *store, ZifState *state, GError **error)
g_return_val_if_fail (ZIF_IS_STORE_LOCAL (store), FALSE);
g_return_val_if_fail (zif_state_valid (state), FALSE);
+ /* take lock */
+ ret = zif_state_take_lock (state,
+ ZIF_LOCK_TYPE_RPMDB,
+ ZIF_LOCK_MODE_THREAD,
+ error);
+ if (!ret)
+ goto out;
+
/* setup steps */
if (local->priv->prefix == NULL) {
ret = zif_state_set_steps (state,
View
22 libzif/zif-store-remote.c
@@ -1862,7 +1862,8 @@ zif_store_remote_refresh (ZifStore *store, gboolean force, ZifState *state, GErr
/* take lock */
ret = zif_state_take_lock (state,
- ZIF_LOCK_TYPE_METADATA_WRITE,
+ ZIF_LOCK_TYPE_METADATA,
+ ZIF_LOCK_MODE_PROCESS,
error);
if (!ret)
goto out;
@@ -2635,7 +2636,8 @@ zif_store_remote_set_enabled (ZifStoreRemote *store,
/* take lock */
ret = zif_state_take_lock (state,
- ZIF_LOCK_TYPE_REPO_WRITE,
+ ZIF_LOCK_TYPE_REPO,
+ ZIF_LOCK_MODE_PROCESS,
error);
if (!ret)
goto out;
@@ -3171,8 +3173,9 @@ zif_store_remote_search_group (ZifStore *store, gchar **search, ZifState *state,
} else {
ret = zif_state_set_steps (state,
error,
- 80, /* load */
- 20, /* search */
+ 80, /* load metadata */
+ 1, /* load groups */
+ 19, /* search */
-1);
if (!ret)
goto out;
@@ -3202,10 +3205,19 @@ zif_store_remote_search_group (ZifStore *store, gchar **search, ZifState *state,
/* we can't just use zif_md_primary_*_search_group() as this searches
* by *rpm* group, which isn't what we want -- instead we need to get
* the list of categories for each group, and then return results. */
- array_tmp = zif_groups_get_cats_for_group (remote->priv->groups, search[0], error);
+ state_local = zif_state_get_child (state);
+ array_tmp = zif_groups_get_cats_for_group (remote->priv->groups,
+ search[0],
+ state_local,
+ error);
if (array_tmp == NULL)
goto out;
+ /* this section done */
+ ret = zif_state_done (state, error);
+ if (!ret)
+ goto out;
+
/* no results for this group enum is not fatal */
if (array_tmp->len == 0) {
ret = zif_state_finished (state, error);
View
15 libzif/zif-transaction.c
@@ -4571,7 +4571,9 @@ zif_transaction_prepare_ensure_trusted (ZifTransaction *transaction,
* Since: 0.1.3
**/
gboolean
-zif_transaction_prepare (ZifTransaction *transaction, ZifState *state, GError **error)
+zif_transaction_prepare (ZifTransaction *transaction,
+ ZifState *state,
+ GError **error)
{
const gchar *cache_filename;
gboolean ret = FALSE;
@@ -4590,6 +4592,14 @@ zif_transaction_prepare (ZifTransaction *transaction, ZifState *state, GError **
g_return_val_if_fail (zif_state_valid (state), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ /* take lock */
+ ret = zif_state_take_lock (state,
+ ZIF_LOCK_TYPE_RPMDB,
+ ZIF_LOCK_MODE_THREAD,
+ error);
+ if (!ret)
+ goto out;
+
/* get private */
priv = transaction->priv;
@@ -5840,7 +5850,8 @@ zif_transaction_commit_full (ZifTransaction *transaction,
/* take lock */
ret = zif_state_take_lock (state,
- ZIF_LOCK_TYPE_RPMDB_WRITE,
+ ZIF_LOCK_TYPE_RPMDB,
+ ZIF_LOCK_MODE_PROCESS,
error);
if (!ret)
goto out;
View
22 tools/zif-main.c
@@ -1759,7 +1759,7 @@ zif_cmd_get_groups (ZifCmdPrivate *priv, gchar **values, GError **error)
goto out;
/* get bitfield */
- array = zif_groups_get_groups (groups, error);
+ array = zif_groups_get_groups (groups, priv->state, error);
if (array == NULL) {
ret = FALSE;
goto out;
@@ -6347,7 +6347,10 @@ zif_take_lock_cb (ZifState *state,
for (i=0; i<lock_retries; i++) {
/* try to take */
- ret = zif_lock_take (lock, lock_type, &error_local);
+ ret = zif_lock_take (lock,
+ lock_type,
+ ZIF_LOCK_MODE_PROCESS,
+ &error_local);
if (ret)
break;
@@ -6488,13 +6491,14 @@ main (int argc, char *argv[])
gboolean assume_no = FALSE;
gboolean assume_yes = FALSE;
gboolean background = FALSE;
+ gboolean distro_sync = FALSE;
+ gboolean exact_arch = FALSE;
+ gboolean lock_all = FALSE;
gboolean offline = FALSE;
gboolean profile = FALSE;
gboolean ret;
gboolean skip_broken = FALSE;
- gboolean exact_arch = FALSE;
gboolean verbose = FALSE;
- gboolean distro_sync = FALSE;
gchar *cmd_descriptions = NULL;
gchar *config_file = NULL;
gchar *excludes = NULL;
@@ -6545,6 +6549,8 @@ main (int argc, char *argv[])
_("Disable one or more repositories"), NULL },
{ "package-dump", '\0', 0, G_OPTION_ARG_FILENAME, &package_dump,
_("Specify a directory of packages as a remote store"), NULL },
+ { "lock-all", '\0', 0, G_OPTION_ARG_FILENAME, &lock_all,
+ _("Take all locks at startup rather than as required"), NULL },
{ NULL}
};
@@ -6746,9 +6752,11 @@ main (int argc, char *argv[])
g_signal_connect (priv->state, "notify::speed",
G_CALLBACK (zif_state_speed_changed_cb),
priv->progressbar);
- zif_state_set_lock_handler (priv->state,
- zif_take_lock_cb,
- priv);
+ if (lock_all) {
+ zif_state_set_lock_handler (priv->state,
+ zif_take_lock_cb,
+ priv);
+ }
/* always set this, even if --skip-broken isn't set so we can
* override the config file at runtime */
Please sign in to comment.
Something went wrong with that request. Please try again.