void gom_repository_find_async (GomRepository *repository, GType resource_type, GomFilter *filter, GAsyncReadyCallback callback, gpointer user_data) { GomRepositoryPrivate *priv; GSimpleAsyncResult *simple; g_return_if_fail(GOM_IS_REPOSITORY(repository)); g_return_if_fail(g_type_is_a(resource_type, GOM_TYPE_RESOURCE)); g_return_if_fail(resource_type != GOM_TYPE_RESOURCE); g_return_if_fail(!filter || GOM_IS_FILTER(filter)); g_return_if_fail(callback != NULL); priv = repository->priv; simple = g_simple_async_result_new(G_OBJECT(repository), callback, user_data, gom_repository_find_async); g_object_set_data(G_OBJECT(simple), "resource-type", GSIZE_TO_POINTER(resource_type)); g_object_set_data_full(G_OBJECT(simple), "filter", filter ? g_object_ref(filter) : NULL, filter ? g_object_unref : NULL); gom_adapter_queue_read(priv->adapter, gom_repository_find_cb, simple); }
/** * gom_repository_migrate_async: * @repository: (in): A #GomRepository. * @version: (in): The version to migrate to. * @migrator: (in) (scope async): A function to perform the migrations. * @migrator_data: (in): User data for @migrator * @callback: (in): A callback to execute upon completion. * @user_data: (in): User data for @callback. * * Asynchronously performs a migration on the underlying database. This will * call @migrator from the SQLite thread for each migration to perform. * * Upon completion, @callback will be executed and it must call * gom_repository_migrate_finish(). */ void gom_repository_migrate_async (GomRepository *repository, guint version, GomRepositoryMigrator migrator, gpointer migrator_data, GAsyncReadyCallback callback, gpointer user_data) { GomRepositoryPrivate *priv; GSimpleAsyncResult *simple; g_return_if_fail(GOM_IS_REPOSITORY(repository)); g_return_if_fail(migrator != NULL); g_return_if_fail(callback != NULL); g_return_if_fail(version >= 1); priv = repository->priv; simple = g_simple_async_result_new(G_OBJECT(repository), callback, user_data, gom_repository_migrate_async); g_object_set_data(G_OBJECT(simple), "version", GINT_TO_POINTER(version)); g_object_set_data(G_OBJECT(simple), "migrator", migrator); g_object_set_data(G_OBJECT(simple), "migrator_data", migrator_data); gom_adapter_queue_write(priv->adapter, gom_repository_migrate_cb, simple); }
static void gom_repository_find_one_cb (GObject *object, GAsyncResult *result, gpointer user_data) { GSimpleAsyncResult *simple = user_data; GomResourceGroup *group; GomRepository *repository = (GomRepository *)object; GError *error = NULL; g_return_if_fail(GOM_IS_REPOSITORY(repository)); g_return_if_fail(G_IS_SIMPLE_ASYNC_RESULT(simple)); if (!(group = gom_repository_find_finish(repository, result, &error))) { g_simple_async_result_take_error(simple, error); g_simple_async_result_complete_in_idle(simple); g_object_unref(simple); return; } if (!gom_resource_group_get_count(group)) { g_simple_async_result_set_error(simple, GOM_ERROR, GOM_ERROR_REPOSITORY_EMPTY_RESULT, _("No resources were found.")); g_simple_async_result_complete_in_idle(simple); g_object_unref(simple); g_object_unref(group); return; } gom_resource_group_fetch_async(group, 0, 1, gom_repository_find_one_fetch_cb, simple); g_object_unref(group); }
static void gom_resource_set_repository (GomResource *resource, GomRepository *repository) { GomResourcePrivate *priv; GomRepository *old; g_return_if_fail(GOM_IS_RESOURCE(resource)); g_return_if_fail(!repository || GOM_IS_REPOSITORY(repository)); priv = resource->priv; old = priv->repository; if (old) { g_object_remove_weak_pointer(G_OBJECT(priv->repository), (gpointer *)&priv->repository); priv->repository = NULL; } if (repository) { priv->repository = repository; g_object_add_weak_pointer(G_OBJECT(priv->repository), (gpointer *)&priv->repository); g_object_notify_by_pspec(G_OBJECT(resource), gParamSpecs[PROP_REPOSITORY]); } }
gboolean gom_repository_automatic_migrate_finish (GomRepository *repository, GAsyncResult *result, GError **error) { g_return_val_if_fail(GOM_IS_REPOSITORY(repository), FALSE); g_return_val_if_fail(G_IS_SIMPLE_ASYNC_RESULT(result), FALSE); g_object_set_data(G_OBJECT(repository), "object-types", NULL); return gom_repository_migrate_finish(repository, result, error); }
static void gom_repository_set_adapter (GomRepository *repository, GomAdapter *adapter) { GomRepositoryPrivate *priv; g_return_if_fail(GOM_IS_REPOSITORY(repository)); g_return_if_fail(GOM_IS_ADAPTER(adapter)); priv = repository->priv; g_clear_object(&priv->adapter); priv->adapter = g_object_ref(adapter); g_object_notify_by_pspec(G_OBJECT(repository), gParamSpecs[PROP_ADAPTER]); }
/** * gom_repository_automatic_migrate_async: * @repository: (in): A #GomRepository. * @version: (in): The version to migrate to. * @object_types: (element-type GType) (transfer container): a #GList of #GType * @callback: (in): A callback to execute upon completion. * @user_data: (in): User data for @callback. * * Performs an automatic migration on the underlying database. See * gom_repository_automatic_migrate_sync() for details. * * Upon completion, @callback will be executed and it must call * gom_repository_automatic_migrate_finish(). */ void gom_repository_automatic_migrate_async (GomRepository *repository, guint version, GList *object_types, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(GOM_IS_REPOSITORY(repository)); g_return_if_fail(callback != NULL); g_return_if_fail(version >= 1); g_return_if_fail(object_types != NULL); g_object_set_data_full (G_OBJECT (repository), "object-types", object_types, (GDestroyNotify) g_list_free); gom_repository_migrate_async (repository, version, gom_repository_automatic_migrator, object_types, callback, user_data); }
/** * gom_repository_find_one_finish: * @repository: (in): A #GomRepository. * @result: (in): A #GAsyncResult. * @error: (out): A location for a #GError, or %NULL. * * Completes an asynchronous request to find a single resource in the * repository. See gom_repository_find_one_async() for more info. * * Returns: (transfer full): A #GomResource if successful, otherwise %NULL. */ GomResource * gom_repository_find_one_finish (GomRepository *repository, GAsyncResult *result, GError **error) { GSimpleAsyncResult *simple = (GSimpleAsyncResult *)result; GomResource *ret; g_return_val_if_fail(GOM_IS_REPOSITORY(repository), NULL); g_return_val_if_fail(G_IS_SIMPLE_ASYNC_RESULT(simple), NULL); if (!(ret = g_simple_async_result_get_op_res_gpointer(simple))) { g_simple_async_result_propagate_error(simple, error); } return ret ? g_object_ref(ret) : NULL; }
gboolean gom_repository_migrate_finish (GomRepository *repository, GAsyncResult *result, GError **error) { GSimpleAsyncResult *simple = (GSimpleAsyncResult *)result; gboolean ret; g_return_val_if_fail(GOM_IS_REPOSITORY(repository), FALSE); g_return_val_if_fail(G_IS_SIMPLE_ASYNC_RESULT(result), FALSE); if (!(ret = g_simple_async_result_get_op_res_gboolean(simple))) { g_simple_async_result_propagate_error(simple, error); } g_object_unref(simple); return ret; }
static gint gom_repository_query_version (GomRepository *repository, GError **error) { GomRepositoryPrivate *priv; GomCommand *command; GomCursor *cursor; gint version; g_return_val_if_fail(GOM_IS_REPOSITORY(repository), -1); priv = repository->priv; command = g_object_new(GOM_TYPE_COMMAND, "adapter", priv->adapter, "sql", "CREATE TABLE IF NOT EXISTS _gom_version (version INTEGER);", NULL); if (!gom_command_execute(command, NULL, error)) { g_object_unref(command); return -1; } g_object_unref(command); command = g_object_new(GOM_TYPE_COMMAND, "adapter", priv->adapter, "sql", "SELECT MAX(version) FROM _gom_version;", NULL); if (!gom_command_execute(command, &cursor, error)) { g_object_unref(command); return -1; } if (!gom_cursor_next(cursor)) { g_object_unref(cursor); g_object_unref(command); return 0; } version = gom_cursor_get_column_uint(cursor, 0); g_object_unref(cursor); g_object_unref(command); return version; }
/** * gom_repository_find_sync: * @repository: (in): A #GomRepository. * @resource_type: (in): The #GType of the resources to query. * @filter: (in) (allow-none): An optional filter for the query. * @error: (out): A location for a #GError, or %NULL. * * Synchronously queries the #GomRepository for objects matching the * requested query. This must only be run from a callback provided to * gom_adapter_queue_read(). * * Returns: (transfer full): A #GomResourceGroup or %NULL. */ GomResourceGroup * gom_repository_find_sync (GomRepository *repository, GType resource_type, GomFilter *filter, GError **error) { GomRepositoryPrivate *priv; GSimpleAsyncResult *simple; GomResourceGroup *ret; GAsyncQueue *queue; g_return_val_if_fail(GOM_IS_REPOSITORY(repository), NULL); g_return_val_if_fail(g_type_is_a(resource_type, GOM_TYPE_RESOURCE), NULL); g_return_val_if_fail(resource_type != GOM_TYPE_RESOURCE, NULL); g_return_val_if_fail(!filter || GOM_IS_FILTER(filter), NULL); priv = repository->priv; queue = g_async_queue_new(); simple = g_simple_async_result_new(G_OBJECT(repository), NULL, NULL, gom_repository_find_sync); g_object_set_data(G_OBJECT(simple), "resource-type", GSIZE_TO_POINTER(resource_type)); g_object_set_data_full(G_OBJECT(simple), "filter", filter ? g_object_ref(filter) : NULL, filter ? g_object_unref : NULL); g_object_set_data(G_OBJECT(simple), "queue", queue); gom_adapter_queue_read(priv->adapter, gom_repository_find_cb, simple); g_async_queue_pop(queue); g_async_queue_unref(queue); if (!(ret = g_simple_async_result_get_op_res_gpointer(simple))) { g_simple_async_result_propagate_error(simple, error); } else { ret = g_object_ref(ret); } g_object_unref(simple); return ret; }
void gom_repository_find_one_async (GomRepository *repository, GType resource_type, GomFilter *filter, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *simple; g_return_if_fail(GOM_IS_REPOSITORY(repository)); g_return_if_fail(g_type_is_a(resource_type, GOM_TYPE_RESOURCE)); g_return_if_fail(!filter || GOM_IS_FILTER(filter)); g_return_if_fail(callback != NULL); simple = g_simple_async_result_new(G_OBJECT(repository), callback, user_data, gom_repository_find_one_async); gom_repository_find_async(repository, resource_type, filter, gom_repository_find_one_cb, simple); }
/** * gom_repository_automatic_migrate_sync: * @repository: (in): A #GomRepository. * @version: (in): The version to migrate to. * @object_types: (element-type GType) (transfer container): a #GList of #GType * @error: a #GError * * Performs an automatic migration on the underlying database. For * each of the #GType passed in @object_types, the table will be * created if necessary, and each of the columns corresponding to * properties will be added if needed. * * Returns: #TRUE in case of success. */ gboolean gom_repository_automatic_migrate_sync (GomRepository *repository, guint version, GList *object_types, GError **error) { gboolean ret; g_return_val_if_fail(GOM_IS_REPOSITORY(repository), FALSE); g_return_val_if_fail(version >= 1, FALSE); g_return_val_if_fail(object_types != NULL, FALSE); ret = gom_repository_migrate_sync(repository, version, gom_repository_automatic_migrator, object_types, error); g_list_free(object_types); return ret; }
/** * gom_repository_migrate_sync: * @repository: (in): A #GomRepository. * @version: (in): The version to migrate to. * @migrator: (in) (scope call): A function to perform the migrations. * @migrator_data: (in): User data for @migrator. * @error: a #GError * * Performs a migration on the underlying database. This will * call @migrator from the SQLite thread for each migration to perform. * * Returns: #TRUE in case of success. */ gboolean gom_repository_migrate_sync (GomRepository *repository, guint version, GomRepositoryMigrator migrator, gpointer migrator_data, GError **error) { GomRepositoryPrivate *priv; GSimpleAsyncResult *simple; GAsyncQueue *queue; gboolean ret; g_return_val_if_fail(GOM_IS_REPOSITORY(repository), FALSE); g_return_val_if_fail(migrator != NULL, FALSE); g_return_val_if_fail(version >= 1, FALSE); priv = repository->priv; queue = g_async_queue_new(); simple = g_simple_async_result_new(G_OBJECT(repository), NULL, NULL, gom_repository_migrate_sync); g_object_set_data(G_OBJECT(simple), "version", GINT_TO_POINTER(version)); g_object_set_data(G_OBJECT(simple), "migrator", migrator); g_object_set_data(G_OBJECT(simple), "migrator_data", migrator_data); g_object_set_data(G_OBJECT(simple), "queue", queue); gom_adapter_queue_write(priv->adapter, gom_repository_migrate_cb, simple); g_async_queue_pop(queue); g_async_queue_unref(queue); if (!(ret = g_simple_async_result_get_op_res_gboolean(simple))) { g_simple_async_result_propagate_error(simple, error); } g_object_unref(simple); return ret; }
void gom_resource_fetch_m2m_async (GomResource *resource, GType resource_type, const gchar *m2m_table, GomFilter *filter, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *simple; GomRepository *repository; GomAdapter *adapter; g_return_if_fail(GOM_IS_RESOURCE(resource)); g_return_if_fail(g_type_is_a(resource_type, GOM_TYPE_RESOURCE)); g_return_if_fail(m2m_table != NULL); g_return_if_fail(callback != NULL); repository = gom_resource_get_repository(resource); g_assert(GOM_IS_REPOSITORY(repository)); adapter = gom_repository_get_adapter(repository); g_assert(GOM_IS_ADAPTER(adapter)); simple = g_simple_async_result_new(G_OBJECT(resource), callback, user_data, gom_resource_fetch_m2m_async); g_object_set_data(G_OBJECT(simple), "resource-type", GINT_TO_POINTER(resource_type)); g_object_set_data_full(G_OBJECT(simple), "m2m-table", g_strdup(m2m_table), g_free); if (filter) { g_object_set_data_full(G_OBJECT(simple), "filter", g_object_ref(filter), g_object_unref); } gom_adapter_queue_read(adapter, gom_resource_fetch_m2m_cb, simple); }
/** * gom_repository_find_one_sync: * @repository: (in): A #GomRepository. * @resource_type: (in): A #GType of the resource to lookup. * @filter: (in): A #GomFilter to apply to your search. * @error: (out): A location for a #GError, or %NULL. * * Synchronous version of gom_repository_find_async(). * * Returns: (transfer full): A #GomResource or %NULL. */ GomResource * gom_repository_find_one_sync (GomRepository *repository, GType resource_type, GomFilter *filter, GError **error) { GomResourceGroup *group; GomResource *ret; g_return_val_if_fail(GOM_IS_REPOSITORY(repository), NULL); g_return_val_if_fail(g_type_is_a(resource_type, GOM_TYPE_RESOURCE), NULL); g_return_val_if_fail(resource_type != GOM_TYPE_RESOURCE, NULL); g_return_val_if_fail(!filter || GOM_IS_FILTER(filter), NULL); if (!(group = gom_repository_find_sync(repository, resource_type, filter, error))) { return NULL; } if (!gom_resource_group_get_count(group)) { g_set_error(error, GOM_ERROR, GOM_ERROR_REPOSITORY_EMPTY_RESULT, _("No resources were found.")); g_object_unref(group); return NULL; } if (!gom_resource_group_fetch_sync(group, 0, 1, error)) { g_object_unref(group); return NULL; } ret = g_object_ref(gom_resource_group_get_index(group, 0)); g_object_unref(group); return ret; }
static void gom_repository_find_cb (GomAdapter *adapter, gpointer user_data) { GSimpleAsyncResult *simple = user_data; GomCommandBuilder *builder = NULL; GomResourceGroup *ret; GomRepository *repository = NULL; GomCommand *command; GomCursor *cursor; GomFilter *filter; GError *error = NULL; GType resource_type; GAsyncQueue *queue; guint count; g_return_if_fail(GOM_IS_ADAPTER(adapter)); g_return_if_fail(G_IS_SIMPLE_ASYNC_RESULT(simple)); repository = GOM_REPOSITORY(g_async_result_get_source_object(G_ASYNC_RESULT(simple))); g_assert(GOM_IS_REPOSITORY(repository)); resource_type = GPOINTER_TO_SIZE(g_object_get_data(G_OBJECT(simple), "resource-type")); g_assert(g_type_is_a(resource_type, GOM_TYPE_RESOURCE)); filter = g_object_get_data(G_OBJECT(simple), "filter"); g_assert(!filter || GOM_IS_FILTER(filter)); queue = g_object_get_data(G_OBJECT(simple), "queue"); builder = g_object_new(GOM_TYPE_COMMAND_BUILDER, "adapter", adapter, "resource-type", resource_type, "filter", filter, NULL); command = gom_command_builder_build_count(builder); g_assert(GOM_IS_COMMAND(command)); if (!gom_command_execute(command, &cursor, &error)) { g_simple_async_result_take_error(simple, error); goto out; } g_assert(GOM_IS_CURSOR(cursor)); if (!gom_cursor_next(cursor)) { g_assert_not_reached(); goto out; } count = gom_cursor_get_column_uint(cursor, 0); ret = g_object_new(GOM_TYPE_RESOURCE_GROUP, "adapter", adapter, "count", count, "filter", filter, "repository", repository, "resource-type", resource_type, NULL); g_simple_async_result_set_op_res_gpointer(simple, ret, g_object_unref); out: if (!queue) g_simple_async_result_complete_in_idle(simple); else g_async_queue_push(queue, GINT_TO_POINTER(TRUE)); g_object_unref(repository); g_clear_object(&cursor); g_clear_object(&command); g_clear_object(&builder); }
static void gom_repository_migrate_cb (GomAdapter *adapter, gpointer user_data) { GomRepositoryMigrator migrator; GSimpleAsyncResult *simple = user_data; GomRepository *repository; GomCommand *command = NULL; gpointer migrate_data; GError *error = NULL; guint current; guint i; guint version; GAsyncQueue *queue; g_return_if_fail(GOM_IS_ADAPTER(adapter)); g_return_if_fail(G_IS_SIMPLE_ASYNC_RESULT(simple)); repository = GOM_REPOSITORY(g_async_result_get_source_object(G_ASYNC_RESULT(simple))); version = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(simple), "version")); migrator = g_object_get_data(G_OBJECT(simple), "migrator"); migrate_data = g_object_get_data(G_OBJECT(simple), "migrator_data"); queue = g_object_get_data(G_OBJECT(simple), "queue"); g_assert(GOM_IS_REPOSITORY(repository)); g_assert_cmpint(version, >, 0); g_assert(migrator != NULL); if (-1 == (current = gom_repository_query_version(repository, &error))) { g_warning("Failed to determine schema version: %s", error->message); goto error; } if (version == current) { g_simple_async_result_set_op_res_gboolean(simple, TRUE); goto out; } EXECUTE_OR_GOTO(adapter, "PRAGMA synchronous = NORMAL;", &error, rollback); EXECUTE_OR_GOTO(adapter, "PRAGMA journal_mode = PERSIST;", &error, rollback); EXECUTE_OR_GOTO(adapter, "BEGIN;", &error, rollback); for (i = MAX(current, 1); i <= version; i++) { if (!migrator(repository, adapter, i, migrate_data, &error)) { if (!error) g_warning ("Migration function failed without returning a error"); goto rollback; } command = g_object_new(GOM_TYPE_COMMAND, "adapter", adapter, "sql", "INSERT INTO _gom_version (" " version" ") VALUES (?);", NULL); gom_command_set_param_uint(command, 0, i); if (!gom_command_execute(command, NULL, &error)) { g_object_unref(command); goto rollback; } g_object_unref(command); } EXECUTE_OR_GOTO(adapter, "COMMIT;", &error, rollback); g_simple_async_result_set_op_res_gboolean(simple, TRUE); goto out; rollback: EXECUTE_OR_GOTO(adapter, "ROLLBACK;", NULL, error); error: g_assert(error); g_simple_async_result_take_error(simple, error); out: g_object_unref(repository); if (!queue) g_simple_async_result_complete_in_idle(simple); else g_async_queue_push(queue, GINT_TO_POINTER(TRUE)); }
/** * gom_repository_get_adapter: * @repository: (in): A #GomRepository. * * Fetches the underlying adapter. * * Returns: (transfer none): A #GomAdapter. */ GomAdapter * gom_repository_get_adapter (GomRepository *repository) { g_return_val_if_fail(GOM_IS_REPOSITORY(repository), NULL); return repository->priv->adapter; }
static void gom_resource_fetch_m2m_cb (GomAdapter *adapter, gpointer user_data) { GSimpleAsyncResult *simple = user_data; GomCommandBuilder *builder = NULL; GomResourceGroup *group; GomRepository *repository; const gchar *m2m_table; GomResource *resource; GomCommand *command = NULL; GomCursor *cursor = NULL; GomFilter *filter = NULL; GError *error = NULL; guint count = 0; GType resource_type; g_return_if_fail(GOM_IS_ADAPTER(adapter)); g_return_if_fail(G_IS_SIMPLE_ASYNC_RESULT(simple)); m2m_table = g_object_get_data(G_OBJECT(simple), "m2m-table"); resource_type = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(simple), "resource-type")); filter = g_object_get_data(G_OBJECT(simple), "filter"); resource = GOM_RESOURCE(g_async_result_get_source_object(G_ASYNC_RESULT(simple))); repository = gom_resource_get_repository(resource); g_assert(GOM_IS_RESOURCE(resource)); g_assert(m2m_table); g_assert(g_type_is_a(resource_type, GOM_TYPE_RESOURCE)); g_assert(!filter || GOM_IS_FILTER(filter)); g_assert(GOM_IS_REPOSITORY(repository)); builder = g_object_new(GOM_TYPE_COMMAND_BUILDER, "adapter", adapter, "filter", filter, "resource-type", resource_type, "m2m-table", m2m_table, "m2m-type", G_TYPE_FROM_INSTANCE(resource), NULL); command = gom_command_builder_build_count(builder); if (!gom_command_execute(command, &cursor, &error)) { g_simple_async_result_take_error(simple, error); goto out; } if (!gom_cursor_next(cursor)) { g_simple_async_result_set_error(simple, GOM_ERROR, GOM_ERROR_RESOURCE_CURSOR, _("No result was returned from the cursor.")); goto out; } count = gom_cursor_get_column_int64(cursor, 0); group = g_object_new(GOM_TYPE_RESOURCE_GROUP, "count", count, "filter", filter, "m2m-table", m2m_table, "m2m-type", G_TYPE_FROM_INSTANCE(resource), "repository", repository, "resource-type", resource_type, NULL); g_simple_async_result_set_op_res_gpointer(simple, group, g_object_unref); out: g_object_unref(resource); g_clear_object(&command); g_clear_object(&cursor); g_clear_object(&builder); g_simple_async_result_complete_in_idle(simple); g_object_unref(simple); }