/* db-database.c generated by valac 0.56.3, the Vala compiler
 * generated from db-database.vala, do not modify */

/*
 * Copyright 2016 Software Freedom Conservancy Inc.
 * Copyright 2018 Michael Gratton <mike@vee.net>
 *
 * This software is licensed under the GNU Lesser General Public License
 * (version 2.1 or later).  See the COPYING file in this distribution.
 */

#include "geary-engine.h"
#include <gio/gio.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <glib-object.h>
#include <sqlite3.h>

#define GEARY_DB_TYPE_TRANSACTION_ASYNC_JOB (geary_db_transaction_async_job_get_type ())
#define GEARY_DB_TRANSACTION_ASYNC_JOB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEARY_DB_TYPE_TRANSACTION_ASYNC_JOB, GearyDbTransactionAsyncJob))
#define GEARY_DB_TRANSACTION_ASYNC_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEARY_DB_TYPE_TRANSACTION_ASYNC_JOB, GearyDbTransactionAsyncJobClass))
#define GEARY_DB_IS_TRANSACTION_ASYNC_JOB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEARY_DB_TYPE_TRANSACTION_ASYNC_JOB))
#define GEARY_DB_IS_TRANSACTION_ASYNC_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEARY_DB_TYPE_TRANSACTION_ASYNC_JOB))
#define GEARY_DB_TRANSACTION_ASYNC_JOB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEARY_DB_TYPE_TRANSACTION_ASYNC_JOB, GearyDbTransactionAsyncJobClass))

typedef struct _GearyDbTransactionAsyncJob GearyDbTransactionAsyncJob;
typedef struct _GearyDbTransactionAsyncJobClass GearyDbTransactionAsyncJobClass;
enum  {
	GEARY_DB_DATABASE_0_PROPERTY,
	GEARY_DB_DATABASE_FILE_PROPERTY,
	GEARY_DB_DATABASE_PATH_PROPERTY,
	GEARY_DB_DATABASE_FLAGS_PROPERTY,
	GEARY_DB_DATABASE_IS_OPEN_PROPERTY,
	GEARY_DB_DATABASE_LOGGING_PARENT_PROPERTY,
	GEARY_DB_DATABASE_NUM_PROPERTIES
};
static GParamSpec* geary_db_database_properties[GEARY_DB_DATABASE_NUM_PROPERTIES];
#define _g_thread_pool_free0(var) ((var == NULL) ? NULL : (var = (g_thread_pool_free (var, FALSE, TRUE), NULL)))
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
#define _g_free0(var) (var = (g_free (var), NULL))
typedef struct _Block22Data Block22Data;
typedef struct _GearyDbDatabaseOpenData GearyDbDatabaseOpenData;
#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL)))
typedef struct _Block23Data Block23Data;
typedef struct _GearyDbDatabaseOpenConnectionData GearyDbDatabaseOpenConnectionData;
typedef struct _GearyDbDatabaseExecTransactionAsyncData GearyDbDatabaseExecTransactionAsyncData;
#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }
#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return val; }
#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);

struct _GearyDbDatabasePrivate {
	GFile* _file;
	gchar* _path;
	GearyDbDatabaseFlags _flags;
	gboolean _is_open;
	GRecMutex __lock__is_open;
	GearyLoggingSource* _logging_parent;
	GearyDbDatabaseConnection* primary;
	gint outstanding_async_jobs;
	GRecMutex __lock_outstanding_async_jobs;
	GThreadPool* thread_pool;
};

struct _Block22Data {
	int _ref_count_;
	GearyDbDatabase* self;
	GearyDbDatabaseFlags flags;
	GCancellable* cancellable;
	gpointer _async_data_;
};

struct _GearyDbDatabaseOpenData {
	int _state_;
	GObject* _source_object_;
	GAsyncResult* _res_;
	GTask* _async_result;
	GearyDbDatabase* self;
	GearyDbDatabaseFlags flags;
	GCancellable* cancellable;
	Block22Data* _data22_;
	gboolean _tmp0_;
	gboolean _tmp1_;
	gboolean _tmp2_;
	GFile* _tmp3_;
	GFile* _tmp4_;
	GFile* _tmp5_;
	GFile* _tmp6_;
	GThreadPool* _tmp7_;
	GThreadPool* _tmp8_;
	GThreadPool* _tmp9_;
	GThreadPool* _tmp10_;
	gboolean _tmp11_;
	gboolean _tmp12_;
	GFile* _tmp13_;
	gboolean _tmp14_;
	GFile* _tmp15_;
	GearyNonblockingConcurrent* _tmp16_;
	GearyNonblockingConcurrent* _tmp17_;
	GError* _inner_error0_;
};

struct _Block23Data {
	int _ref_count_;
	GearyDbDatabase* self;
	GearyDbDatabaseConnection* cx;
	GCancellable* cancellable;
	gpointer _async_data_;
};

struct _GearyDbDatabaseOpenConnectionData {
	int _state_;
	GObject* _source_object_;
	GAsyncResult* _res_;
	GTask* _async_result;
	GearyDbDatabase* self;
	GCancellable* cancellable;
	GearyDbDatabaseConnection* result;
	Block23Data* _data23_;
	GearyNonblockingConcurrent* _tmp0_;
	GearyNonblockingConcurrent* _tmp1_;
	GearyDbDatabaseConnection* _tmp2_;
	GError* _inner_error0_;
};

struct _GearyDbDatabaseExecTransactionAsyncData {
	int _state_;
	GObject* _source_object_;
	GAsyncResult* _res_;
	GTask* _async_result;
	GearyDbDatabase* self;
	GearyDbTransactionType type;
	GearyDbTransactionMethod cb;
	gpointer cb_target;
	GCancellable* cancellable;
	GearyDbTransactionOutcome result;
	GearyDbTransactionAsyncJob* job;
	GearyDbTransactionAsyncJob* _tmp0_;
	GearyDbTransactionAsyncJob* _tmp1_;
	GearyDbTransactionOutcome _tmp2_;
	GearyDbTransactionAsyncJob* _tmp3_;
	GError* _inner_error0_;
};

static gint GearyDbDatabase_private_offset;
static gpointer geary_db_database_parent_class = NULL;

VALA_EXTERN GType geary_db_transaction_async_job_get_type (void) G_GNUC_CONST ;
VALA_EXTERN GearyDbDatabase* geary_db_context_get_database (GearyDbContext* self);
static void geary_db_database_set_file (GearyDbDatabase* self,
                                 GFile* value);
static void geary_db_database_set_path (GearyDbDatabase* self,
                                 const gchar* value);
static void geary_db_database_set_flags (GearyDbDatabase* self,
                                  GearyDbDatabaseFlags value);
static void geary_db_database_set_is_open (GearyDbDatabase* self,
                                    gboolean value);
static void geary_db_database_real_open_data_free (gpointer _data);
static void geary_db_database_real_open (GearyDbDatabase* self,
                                  GearyDbDatabaseFlags flags,
                                  GCancellable* cancellable,
                                  GAsyncReadyCallback _callback_,
                                  gpointer _user_data_);
static gboolean geary_db_database_real_open_co (GearyDbDatabaseOpenData* _data_);
static Block22Data* block22_data_ref (Block22Data* _data22_);
static void block22_data_unref (void * _userdata_);
static void geary_db_database_open_ready (GObject* source_object,
                                   GAsyncResult* _res_,
                                   gpointer _user_data_);
static void geary_db_database_on_async_job (GearyDbDatabase* self,
                                     GearyDbTransactionAsyncJob* job);
static void _geary_db_database_on_async_job_gfunc (gpointer data,
                                            gpointer self);
static void ___lambda22_ (Block22Data* _data22_,
                   GError** error);
static void geary_db_database_check_for_corruption (GearyDbDatabase* self,
                                             GearyDbDatabaseFlags flags,
                                             GCancellable* cancellable,
                                             GError** error);
static void ____lambda22__geary_nonblocking_concurrent_concurrent_callback (GCancellable* cancellable,
                                                                     gpointer self,
                                                                     GError** error);
VALA_EXTERN GearyDbDatabaseConnection* geary_db_database_connection_new (GearyDbDatabase* database,
                                                             gint sqlite_flags,
                                                             GCancellable* cancellable,
                                                             GError** error);
VALA_EXTERN GearyDbDatabaseConnection* geary_db_database_connection_construct (GType object_type,
                                                                   GearyDbDatabase* database,
                                                                   gint sqlite_flags,
                                                                   GCancellable* cancellable,
                                                                   GError** error);
static void geary_db_database_real_close (GearyDbDatabase* self,
                                   GCancellable* cancellable,
                                   GError** error);
static void geary_db_database_check_open (GearyDbDatabase* self,
                                   GError** error);
static void geary_db_database_open_connection_data_free (gpointer _data);
static gboolean geary_db_database_open_connection_co (GearyDbDatabaseOpenConnectionData* _data_);
static Block23Data* block23_data_ref (Block23Data* _data23_);
static void block23_data_unref (void * _userdata_);
static void __lambda23_ (Block23Data* _data23_,
                  GError** error);
static GearyDbDatabaseConnection* geary_db_database_internal_open_connection (GearyDbDatabase* self,
                                                                       gboolean is_primary,
                                                                       GCancellable* cancellable,
                                                                       GError** error);
static void ___lambda23__geary_nonblocking_concurrent_concurrent_callback (GCancellable* cancellable,
                                                                    gpointer self,
                                                                    GError** error);
static void geary_db_database_open_connection_ready (GObject* source_object,
                                              GAsyncResult* _res_,
                                              gpointer _user_data_);
static void geary_db_database_exec_transaction_async_data_free (gpointer _data);
static gboolean geary_db_database_exec_transaction_async_co (GearyDbDatabaseExecTransactionAsyncData* _data_);
VALA_EXTERN GearyDbTransactionAsyncJob* geary_db_transaction_async_job_new (GearyDbDatabaseConnection* default_cx,
                                                                GearyDbTransactionType type,
                                                                GearyDbTransactionMethod cb,
                                                                gpointer cb_target,
                                                                GCancellable* cancellable);
VALA_EXTERN GearyDbTransactionAsyncJob* geary_db_transaction_async_job_construct (GType object_type,
                                                                      GearyDbDatabaseConnection* default_cx,
                                                                      GearyDbTransactionType type,
                                                                      GearyDbTransactionMethod cb,
                                                                      gpointer cb_target,
                                                                      GCancellable* cancellable);
VALA_EXTERN void geary_db_database_add_async_job (GearyDbDatabase* self,
                                      GearyDbTransactionAsyncJob* new_job,
                                      GError** error);
VALA_EXTERN void geary_db_transaction_async_job_wait_for_completion_async (GearyDbTransactionAsyncJob* self,
                                                               GAsyncReadyCallback _callback_,
                                                               gpointer _user_data_);
VALA_EXTERN GearyDbTransactionOutcome geary_db_transaction_async_job_wait_for_completion_finish (GearyDbTransactionAsyncJob* self,
                                                                                     GAsyncResult* _res_,
                                                                                     GError** error);
static void geary_db_database_exec_transaction_async_ready (GObject* source_object,
                                                     GAsyncResult* _res_,
                                                     gpointer _user_data_);
static GearyLoggingState* geary_db_database_real_to_logging_state (GearyDbContext* base);
static GearyDbDatabase* geary_db_database_real_get_database (GearyDbContext* base);
static void geary_db_database_real_prepare_connection (GearyDbDatabase* self,
                                                GearyDbDatabaseConnection* cx,
                                                GError** error);
VALA_EXTERN GearyDbDatabaseConnection* geary_db_transaction_async_job_get_default_cx (GearyDbTransactionAsyncJob* self);
VALA_EXTERN GCancellable* geary_db_transaction_async_job_get_cancellable (GearyDbTransactionAsyncJob* self);
VALA_EXTERN void geary_db_transaction_async_job_execute (GearyDbTransactionAsyncJob* self,
                                             GearyDbDatabaseConnection* cx);
VALA_EXTERN void geary_db_transaction_async_job_failed (GearyDbTransactionAsyncJob* self,
                                            GError* err);
static void geary_db_database_finalize (GObject * obj);
static GType geary_db_database_get_type_once (void);
static void _vala_geary_db_database_get_property (GObject * object,
                                           guint property_id,
                                           GValue * value,
                                           GParamSpec * pspec);
static void _vala_geary_db_database_set_property (GObject * object,
                                           guint property_id,
                                           const GValue * value,
                                           GParamSpec * pspec);

static inline gpointer
geary_db_database_get_instance_private (GearyDbDatabase* self)
{
	return G_STRUCT_MEMBER_P (self, GearyDbDatabase_private_offset);
}

static void
vala__g_thread_pool_free_wrapper (GThreadPool* pool,
                                  gboolean immediate,
                                  gboolean wait)
{
	GThreadPool* ptr = NULL;
	GThreadPool* _tmp0_;
	GThreadPool* _tmp1_;
	_tmp0_ = pool;
	pool = NULL;
	ptr = _tmp0_;
	_tmp1_ = ptr;
	if (_tmp1_ != NULL) {
		GThreadPool* _tmp2_;
		_tmp2_ = ptr;
		g_thread_pool_free ((GThreadPool*) _tmp2_, immediate, wait);
	}
	_g_thread_pool_free0 (pool);
}

GFile*
geary_db_database_get_file (GearyDbDatabase* self)
{
	GFile* result;
	GFile* _tmp0_;
	g_return_val_if_fail (GEARY_DB_IS_DATABASE (self), NULL);
	_tmp0_ = self->priv->_file;
	result = _tmp0_;
	return result;
}

static gpointer
_g_object_ref0 (gpointer self)
{
	return self ? g_object_ref (self) : NULL;
}

static void
geary_db_database_set_file (GearyDbDatabase* self,
                            GFile* value)
{
	GFile* old_value;
	g_return_if_fail (GEARY_DB_IS_DATABASE (self));
	old_value = geary_db_database_get_file (self);
	if (old_value != value) {
		GFile* _tmp0_;
		_tmp0_ = _g_object_ref0 (value);
		_g_object_unref0 (self->priv->_file);
		self->priv->_file = _tmp0_;
		g_object_notify_by_pspec ((GObject *) self, geary_db_database_properties[GEARY_DB_DATABASE_FILE_PROPERTY]);
	}
}

const gchar*
geary_db_database_get_path (GearyDbDatabase* self)
{
	const gchar* result;
	const gchar* _tmp0_;
	g_return_val_if_fail (GEARY_DB_IS_DATABASE (self), NULL);
	_tmp0_ = self->priv->_path;
	result = _tmp0_;
	return result;
}

static void
geary_db_database_set_path (GearyDbDatabase* self,
                            const gchar* value)
{
	gchar* old_value;
	g_return_if_fail (GEARY_DB_IS_DATABASE (self));
	old_value = geary_db_database_get_path (self);
	if (g_strcmp0 (value, old_value) != 0) {
		gchar* _tmp0_;
		_tmp0_ = g_strdup (value);
		_g_free0 (self->priv->_path);
		self->priv->_path = _tmp0_;
		g_object_notify_by_pspec ((GObject *) self, geary_db_database_properties[GEARY_DB_DATABASE_PATH_PROPERTY]);
	}
}

GearyDbDatabaseFlags
geary_db_database_get_flags (GearyDbDatabase* self)
{
	GearyDbDatabaseFlags result;
	g_return_val_if_fail (GEARY_DB_IS_DATABASE (self), 0U);
	result = self->priv->_flags;
	return result;
}

static void
geary_db_database_set_flags (GearyDbDatabase* self,
                             GearyDbDatabaseFlags value)
{
	GearyDbDatabaseFlags old_value;
	g_return_if_fail (GEARY_DB_IS_DATABASE (self));
	old_value = geary_db_database_get_flags (self);
	if (old_value != value) {
		self->priv->_flags = value;
		g_object_notify_by_pspec ((GObject *) self, geary_db_database_properties[GEARY_DB_DATABASE_FLAGS_PROPERTY]);
	}
}

gboolean
geary_db_database_get_is_open (GearyDbDatabase* self)
{
	gboolean result;
	GError* _inner_error0_ = NULL;
	g_return_val_if_fail (GEARY_DB_IS_DATABASE (self), FALSE);
	{
		gboolean _tmp0_ = FALSE;
		g_rec_mutex_lock (&self->priv->__lock__is_open);
		{
			result = self->priv->_is_open;
			{
				g_rec_mutex_unlock (&self->priv->__lock__is_open);
			}
			return result;
		}
		__finally0:
		{
			g_rec_mutex_unlock (&self->priv->__lock__is_open);
		}
		g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
		g_clear_error (&_inner_error0_);
		return _tmp0_;
	}
}

static void
geary_db_database_set_is_open (GearyDbDatabase* self,
                               gboolean value)
{
	GError* _inner_error0_ = NULL;
	g_return_if_fail (GEARY_DB_IS_DATABASE (self));
	{
		g_rec_mutex_lock (&self->priv->__lock__is_open);
		{
			self->priv->_is_open = value;
		}
		__finally0:
		{
			g_rec_mutex_unlock (&self->priv->__lock__is_open);
		}
		if (G_UNLIKELY (_inner_error0_ != NULL)) {
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return;
		}
	}
	g_object_notify_by_pspec ((GObject *) self, geary_db_database_properties[GEARY_DB_DATABASE_IS_OPEN_PROPERTY]);
}

static GearyLoggingSource*
geary_db_database_real_get_logging_parent (GearyDbContext* base)
{
	GearyLoggingSource* result;
	GearyDbDatabase* self;
	GearyLoggingSource* _tmp0_;
	self = G_TYPE_CHECK_INSTANCE_CAST (base, GEARY_DB_TYPE_DATABASE, GearyDbDatabase);
	_tmp0_ = self->priv->_logging_parent;
	result = _tmp0_;
	return result;
}

/**
     * Constructs a new database that is persisted on disk.
     */
GearyDbDatabase*
geary_db_database_construct_persistent (GType object_type,
                                        GFile* db_file)
{
	GearyDbDatabase * self = NULL;
	gchar* _tmp0_;
	gchar* _tmp1_;
	g_return_val_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (db_file, g_file_get_type ()), NULL);
	self = (GearyDbDatabase*) geary_db_context_construct (object_type);
	geary_db_database_set_file (self, db_file);
	_tmp0_ = g_file_get_path (db_file);
	_tmp1_ = _tmp0_;
	geary_db_database_set_path (self, _tmp1_);
	_g_free0 (_tmp1_);
	return self;
}

GearyDbDatabase*
geary_db_database_new_persistent (GFile* db_file)
{
	return geary_db_database_construct_persistent (GEARY_DB_TYPE_DATABASE, db_file);
}

/**
     * Constructs a new database that is stored in memory only.
     */
GearyDbDatabase*
geary_db_database_construct_transient (GType object_type)
{
	GearyDbDatabase * self = NULL;
	self = (GearyDbDatabase*) geary_db_context_construct (object_type);
	geary_db_database_set_file (self, NULL);
	geary_db_database_set_path (self, GEARY_DB_DATABASE_MEMORY_PATH);
	return self;
}

GearyDbDatabase*
geary_db_database_new_transient (void)
{
	return geary_db_database_construct_transient (GEARY_DB_TYPE_DATABASE);
}

static void
geary_db_database_real_open_data_free (gpointer _data)
{
	GearyDbDatabaseOpenData* _data_;
	_data_ = _data;
	_g_object_unref0 (_data_->self);
	g_slice_free (GearyDbDatabaseOpenData, _data_);
}

static void
geary_db_database_real_open (GearyDbDatabase* self,
                             GearyDbDatabaseFlags flags,
                             GCancellable* cancellable,
                             GAsyncReadyCallback _callback_,
                             gpointer _user_data_)
{
	GearyDbDatabaseOpenData* _data_;
	GearyDbDatabase* _tmp0_;
	GCancellable* _tmp1_;
	g_return_if_fail ((cancellable == NULL) || G_TYPE_CHECK_INSTANCE_TYPE (cancellable, g_cancellable_get_type ()));
	_data_ = g_slice_new0 (GearyDbDatabaseOpenData);
	_data_->_async_result = g_task_new (G_OBJECT (self), cancellable, _callback_, _user_data_);
	g_task_set_task_data (_data_->_async_result, _data_, geary_db_database_real_open_data_free);
	_tmp0_ = _g_object_ref0 (self);
	_data_->self = _tmp0_;
	_data_->flags = flags;
	_tmp1_ = _g_object_ref0 (cancellable);
	_g_object_unref0 (_data_->cancellable);
	_data_->cancellable = _tmp1_;
	geary_db_database_real_open_co (_data_);
}

static void
geary_db_database_real_open_finish (GearyDbDatabase* self,
                                    GAsyncResult* _res_,
                                    GError** error)
{
	GearyDbDatabaseOpenData* _data_;
	_data_ = g_task_propagate_pointer (G_TASK (_res_), error);
	if (NULL == _data_) {
		return;
	}
}

/**
     * Prepares the database for use.
     *
     * This will create any needed files and directories, check the
     * database's integrity, and so on, depending on the flags passed
     * to this method.
     *
     * NOTE: A Database may be closed, but the Connections it creates
     * will always be valid as they hold a reference to their source
     * Database. To release a Database's resources, drop all
     * references to it and its associated Connections, Statements,
     * and Results.
     */
static Block22Data*
block22_data_ref (Block22Data* _data22_)
{
	g_atomic_int_inc (&_data22_->_ref_count_);
	return _data22_;
}

static void
block22_data_unref (void * _userdata_)
{
	Block22Data* _data22_;
	_data22_ = (Block22Data*) _userdata_;
	if (g_atomic_int_dec_and_test (&_data22_->_ref_count_)) {
		GearyDbDatabase* self;
		self = _data22_->self;
		_g_object_unref0 (_data22_->cancellable);
		_g_object_unref0 (self);
		g_slice_free (Block22Data, _data22_);
	}
}

static void
geary_db_database_open_ready (GObject* source_object,
                              GAsyncResult* _res_,
                              gpointer _user_data_)
{
	GearyDbDatabaseOpenData* _data_;
	_data_ = _user_data_;
	_data_->_source_object_ = source_object;
	_data_->_res_ = _res_;
	geary_db_database_real_open_co (_data_);
}

static void
_geary_db_database_on_async_job_gfunc (gpointer data,
                                       gpointer self)
{
	geary_db_database_on_async_job ((GearyDbDatabase*) self, (GearyDbTransactionAsyncJob*) data);
}

static void
___lambda22_ (Block22Data* _data22_,
              GError** error)
{
	GearyDbDatabase* self;
	GError* _inner_error0_ = NULL;
	self = _data22_->self;
	geary_db_database_check_for_corruption (self, _data22_->flags, _data22_->cancellable, &_inner_error0_);
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		g_propagate_error (error, _inner_error0_);
		return;
	}
}

static void
____lambda22__geary_nonblocking_concurrent_concurrent_callback (GCancellable* cancellable,
                                                                gpointer self,
                                                                GError** error)
{
	___lambda22_ (self, error);
}

static gboolean
geary_db_database_real_open_co (GearyDbDatabaseOpenData* _data_)
{
	switch (_data_->_state_) {
		case 0:
		goto _state_0;
		case 1:
		goto _state_1;
		case 2:
		goto _state_2;
		case 3:
		goto _state_3;
		default:
		g_assert_not_reached ();
	}
	_state_0:
	_data_->_data22_ = g_slice_new0 (Block22Data);
	_data_->_data22_->_ref_count_ = 1;
	_data_->_data22_->self = g_object_ref (_data_->self);
	_data_->_data22_->flags = _data_->flags;
	_g_object_unref0 (_data_->_data22_->cancellable);
	_data_->_data22_->cancellable = _data_->cancellable;
	_data_->_data22_->_async_data_ = _data_;
	_data_->_tmp0_ = geary_db_database_get_is_open (_data_->self);
	_data_->_tmp1_ = _data_->_tmp0_;
	if (_data_->_tmp1_) {
		block22_data_unref (_data_->_data22_);
		_data_->_data22_ = NULL;
		g_task_return_pointer (_data_->_async_result, _data_, NULL);
		if (_data_->_state_ != 0) {
			while (!g_task_get_completed (_data_->_async_result)) {
				g_main_context_iteration (g_task_get_context (_data_->_async_result), TRUE);
			}
		}
		g_object_unref (_data_->_async_result);
		return FALSE;
	}
	geary_db_database_set_flags (_data_->self, _data_->_data22_->flags);
	_data_->_tmp3_ = _data_->self->priv->_file;
	if (_data_->_tmp3_ != NULL) {
		_data_->_tmp2_ = (_data_->_data22_->flags & GEARY_DB_DATABASE_FLAGS_CREATE_DIRECTORY) != 0;
	} else {
		_data_->_tmp2_ = FALSE;
	}
	if (_data_->_tmp2_) {
		_data_->_tmp4_ = _data_->self->priv->_file;
		_data_->_tmp5_ = g_file_get_parent (_data_->_tmp4_);
		_data_->_tmp6_ = _data_->_tmp5_;
		_data_->_state_ = 1;
		geary_files_make_directory_with_parents (_data_->_tmp6_, NULL, geary_db_database_open_ready, _data_);
		return FALSE;
		_state_1:
		geary_files_make_directory_with_parents_finish (_data_->_res_, &_data_->_inner_error0_);
		_g_object_unref0 (_data_->_tmp6_);
		if (G_UNLIKELY (_data_->_inner_error0_ != NULL)) {
			g_task_return_error (_data_->_async_result, _data_->_inner_error0_);
			block22_data_unref (_data_->_data22_);
			_data_->_data22_ = NULL;
			g_object_unref (_data_->_async_result);
			return FALSE;
		}
	}
	if (geary_db_threadsafe ()) {
		_data_->_tmp7_ = _data_->self->priv->thread_pool;
		if (_data_->_tmp7_ == NULL) {
			_data_->_tmp9_ = g_thread_pool_new (_geary_db_database_on_async_job_gfunc, _data_->self, GEARY_DB_DATABASE_DEFAULT_MAX_CONCURRENCY, TRUE, &_data_->_inner_error0_);
			_data_->_tmp8_ = _data_->_tmp9_;
			if (G_UNLIKELY (_data_->_inner_error0_ != NULL)) {
				g_task_return_error (_data_->_async_result, _data_->_inner_error0_);
				block22_data_unref (_data_->_data22_);
				_data_->_data22_ = NULL;
				g_object_unref (_data_->_async_result);
				return FALSE;
			}
			_data_->_tmp10_ = _data_->_tmp8_;
			_data_->_tmp8_ = NULL;
			_g_thread_pool_free0 (_data_->self->priv->thread_pool);
			_data_->self->priv->thread_pool = _data_->_tmp10_;
			_g_thread_pool_free0 (_data_->_tmp8_);
		}
	} else {
		geary_logging_source_warning (G_TYPE_CHECK_INSTANCE_CAST (_data_->self, GEARY_LOGGING_TYPE_SOURCE, GearyLoggingSource), "SQLite not thread-safe: asynchronous queries will not be available");
	}
	if ((_data_->_data22_->flags & GEARY_DB_DATABASE_FLAGS_CHECK_CORRUPTION) != 0) {
		_data_->_tmp13_ = _data_->self->priv->_file;
		_data_->_tmp12_ = _data_->_tmp13_ != NULL;
	} else {
		_data_->_tmp12_ = FALSE;
	}
	if (_data_->_tmp12_) {
		_data_->_tmp15_ = _data_->self->priv->_file;
		_data_->_state_ = 2;
		geary_files_query_exists_async (_data_->_tmp15_, _data_->_data22_->cancellable, geary_db_database_open_ready, _data_);
		return FALSE;
		_state_2:
		_data_->_tmp14_ = geary_files_query_exists_finish (_data_->_res_, &_data_->_inner_error0_);
		if (G_UNLIKELY (_data_->_inner_error0_ != NULL)) {
			g_task_return_error (_data_->_async_result, _data_->_inner_error0_);
			block22_data_unref (_data_->_data22_);
			_data_->_data22_ = NULL;
			g_object_unref (_data_->_async_result);
			return FALSE;
		}
		_data_->_tmp11_ = _data_->_tmp14_;
	} else {
		_data_->_tmp11_ = FALSE;
	}
	if (_data_->_tmp11_) {
		_data_->_tmp16_ = geary_nonblocking_concurrent_get_global ();
		_data_->_tmp17_ = _data_->_tmp16_;
		_data_->_state_ = 3;
		geary_nonblocking_concurrent_schedule_async (_data_->_tmp17_, ____lambda22__geary_nonblocking_concurrent_concurrent_callback, _data_->_data22_, _data_->_data22_->cancellable, geary_db_database_open_ready, _data_);
		return FALSE;
		_state_3:
		geary_nonblocking_concurrent_schedule_finish (_data_->_tmp17_, _data_->_res_, &_data_->_inner_error0_);
		if (G_UNLIKELY (_data_->_inner_error0_ != NULL)) {
			g_task_return_error (_data_->_async_result, _data_->_inner_error0_);
			block22_data_unref (_data_->_data22_);
			_data_->_data22_ = NULL;
			g_object_unref (_data_->_async_result);
			return FALSE;
		}
	}
	geary_db_database_set_is_open (_data_->self, TRUE);
	block22_data_unref (_data_->_data22_);
	_data_->_data22_ = NULL;
	g_task_return_pointer (_data_->_async_result, _data_, NULL);
	if (_data_->_state_ != 0) {
		while (!g_task_get_completed (_data_->_async_result)) {
			g_main_context_iteration (g_task_get_context (_data_->_async_result), TRUE);
		}
	}
	g_object_unref (_data_->_async_result);
	return FALSE;
}

void
geary_db_database_open (GearyDbDatabase* self,
                        GearyDbDatabaseFlags flags,
                        GCancellable* cancellable,
                        GAsyncReadyCallback _callback_,
                        gpointer _user_data_)
{
	GearyDbDatabaseClass* _klass_;
	_klass_ = GEARY_DB_DATABASE_GET_CLASS (self);
	if (_klass_->open) {
		_klass_->open (self, flags, cancellable, _callback_, _user_data_);
	}
}

void
geary_db_database_open_finish (GearyDbDatabase* self,
                               GAsyncResult* _res_,
                               GError** error)
{
	GearyDbDatabaseClass* _klass_;
	_klass_ = GEARY_DB_DATABASE_GET_CLASS (self);
	if (_klass_->open_finish) {
		_klass_->open_finish (self, _res_, error);
	}
}

static void
geary_db_database_check_for_corruption (GearyDbDatabase* self,
                                        GearyDbDatabaseFlags flags,
                                        GCancellable* cancellable,
                                        GError** error)
{
	GError* _inner_error0_ = NULL;
	g_return_if_fail (GEARY_DB_IS_DATABASE (self));
	g_return_if_fail ((cancellable == NULL) || G_TYPE_CHECK_INSTANCE_TYPE (cancellable, g_cancellable_get_type ()));
	if ((flags & GEARY_DB_DATABASE_FLAGS_READ_ONLY) == 0) {
		GearyDbDatabaseConnection* cx = NULL;
		GearyDbDatabaseConnection* _tmp0_;
		_tmp0_ = geary_db_database_connection_new (self, SQLITE_OPEN_READWRITE, cancellable, &_inner_error0_);
		cx = _tmp0_;
		if (G_UNLIKELY (_inner_error0_ != NULL)) {
			g_propagate_error (error, _inner_error0_);
			return;
		}
		{
			GearyDbDatabaseConnection* _tmp1_;
			GearyDbDatabaseConnection* _tmp2_;
			GearyDbDatabaseConnection* _tmp3_;
			GearyDbDatabaseConnection* _tmp4_;
			GearyDbDatabaseConnection* _tmp5_;
			_tmp1_ = cx;
			geary_db_connection_exec (G_TYPE_CHECK_INSTANCE_CAST (_tmp1_, GEARY_DB_TYPE_CONNECTION, GearyDbConnection), "DROP TABLE IF EXISTS CorruptionCheckTable", NULL, &_inner_error0_);
			if (G_UNLIKELY (_inner_error0_ != NULL)) {
				goto __catch0_g_error;
			}
			_tmp2_ = cx;
			geary_db_connection_exec (G_TYPE_CHECK_INSTANCE_CAST (_tmp2_, GEARY_DB_TYPE_CONNECTION, GearyDbConnection), "CREATE TABLE CorruptionCheckTable (text_col TEXT)", NULL, &_inner_error0_);
			if (G_UNLIKELY (_inner_error0_ != NULL)) {
				goto __catch0_g_error;
			}
			_tmp3_ = cx;
			geary_db_connection_exec (G_TYPE_CHECK_INSTANCE_CAST (_tmp3_, GEARY_DB_TYPE_CONNECTION, GearyDbConnection), "INSERT INTO CorruptionCheckTable (text_col) VALUES ('xyzzy')", NULL, &_inner_error0_);
			if (G_UNLIKELY (_inner_error0_ != NULL)) {
				goto __catch0_g_error;
			}
			_tmp4_ = cx;
			geary_db_connection_exec (G_TYPE_CHECK_INSTANCE_CAST (_tmp4_, GEARY_DB_TYPE_CONNECTION, GearyDbConnection), "SELECT * FROM CorruptionCheckTable", NULL, &_inner_error0_);
			if (G_UNLIKELY (_inner_error0_ != NULL)) {
				goto __catch0_g_error;
			}
			_tmp5_ = cx;
			geary_db_connection_exec (G_TYPE_CHECK_INSTANCE_CAST (_tmp5_, GEARY_DB_TYPE_CONNECTION, GearyDbConnection), "DROP TABLE CorruptionCheckTable", NULL, &_inner_error0_);
			if (G_UNLIKELY (_inner_error0_ != NULL)) {
				goto __catch0_g_error;
			}
		}
		goto __finally0;
		__catch0_g_error:
		{
			GError* err = NULL;
			const gchar* _tmp6_;
			GError* _tmp7_;
			const gchar* _tmp8_;
			GError* _tmp9_;
			err = _inner_error0_;
			_inner_error0_ = NULL;
			_tmp6_ = self->priv->_path;
			_tmp7_ = err;
			_tmp8_ = _tmp7_->message;
			_tmp9_ = g_error_new (GEARY_DATABASE_ERROR, GEARY_DATABASE_ERROR_CORRUPT, "Possible integrity problem discovered in %s: %s", _tmp6_, _tmp8_);
			_inner_error0_ = _tmp9_;
			_g_error_free0 (err);
			goto __finally0;
		}
		__finally0:
		if (G_UNLIKELY (_inner_error0_ != NULL)) {
			g_propagate_error (error, _inner_error0_);
			_g_object_unref0 (cx);
			return;
		}
		_g_object_unref0 (cx);
	}
}

/**
     * Closes the database, releasing any resources it may hold.
     *
     * Note that closing a Database does not close or invalidate
     * Connections it has spawned nor does it cancel any scheduled
     * asynchronous jobs pending or in execution.  All Connections,
     * Statements, and Results will be able to communicate with the
     * database.  Only when they are destroyed is the Database object
     * finally destroyed.
     */
static void
geary_db_database_real_close (GearyDbDatabase* self,
                              GCancellable* cancellable,
                              GError** error)
{
	gboolean _tmp0_;
	gboolean _tmp1_;
	g_return_if_fail ((cancellable == NULL) || G_TYPE_CHECK_INSTANCE_TYPE (cancellable, g_cancellable_get_type ()));
	_tmp0_ = geary_db_database_get_is_open (self);
	_tmp1_ = _tmp0_;
	if (!_tmp1_) {
		return;
	}
	_g_object_unref0 (self->priv->primary);
	self->priv->primary = NULL;
	geary_db_database_set_is_open (self, FALSE);
}

void
geary_db_database_close (GearyDbDatabase* self,
                         GCancellable* cancellable,
                         GError** error)
{
	GearyDbDatabaseClass* _klass_;
	g_return_if_fail (GEARY_DB_IS_DATABASE (self));
	_klass_ = GEARY_DB_DATABASE_GET_CLASS (self);
	if (_klass_->close) {
		_klass_->close (self, cancellable, error);
	}
}

static void
geary_db_database_check_open (GearyDbDatabase* self,
                              GError** error)
{
	gboolean _tmp0_;
	gboolean _tmp1_;
	GError* _inner_error0_ = NULL;
	g_return_if_fail (GEARY_DB_IS_DATABASE (self));
	_tmp0_ = geary_db_database_get_is_open (self);
	_tmp1_ = _tmp0_;
	if (!_tmp1_) {
		const gchar* _tmp2_;
		GError* _tmp3_;
		_tmp2_ = self->priv->_path;
		_tmp3_ = g_error_new (GEARY_DATABASE_ERROR, GEARY_DATABASE_ERROR_OPEN_REQUIRED, "Database %s not open", _tmp2_);
		_inner_error0_ = _tmp3_;
		g_propagate_error (error, _inner_error0_);
		return;
	}
}

static void
geary_db_database_open_connection_data_free (gpointer _data)
{
	GearyDbDatabaseOpenConnectionData* _data_;
	_data_ = _data;
	_g_object_unref0 (_data_->result);
	_g_object_unref0 (_data_->self);
	g_slice_free (GearyDbDatabaseOpenConnectionData, _data_);
}

void
geary_db_database_open_connection (GearyDbDatabase* self,
                                   GCancellable* cancellable,
                                   GAsyncReadyCallback _callback_,
                                   gpointer _user_data_)
{
	GearyDbDatabaseOpenConnectionData* _data_;
	GearyDbDatabase* _tmp0_;
	GCancellable* _tmp1_;
	g_return_if_fail (GEARY_DB_IS_DATABASE (self));
	g_return_if_fail ((cancellable == NULL) || G_TYPE_CHECK_INSTANCE_TYPE (cancellable, g_cancellable_get_type ()));
	_data_ = g_slice_new0 (GearyDbDatabaseOpenConnectionData);
	_data_->_async_result = g_task_new (G_OBJECT (self), cancellable, _callback_, _user_data_);
	g_task_set_task_data (_data_->_async_result, _data_, geary_db_database_open_connection_data_free);
	_tmp0_ = _g_object_ref0 (self);
	_data_->self = _tmp0_;
	_tmp1_ = _g_object_ref0 (cancellable);
	_g_object_unref0 (_data_->cancellable);
	_data_->cancellable = _tmp1_;
	geary_db_database_open_connection_co (_data_);
}

GearyDbDatabaseConnection*
geary_db_database_open_connection_finish (GearyDbDatabase* self,
                                          GAsyncResult* _res_,
                                          GError** error)
{
	GearyDbDatabaseConnection* result;
	GearyDbDatabaseOpenConnectionData* _data_;
	_data_ = g_task_propagate_pointer (G_TASK (_res_), error);
	if (NULL == _data_) {
		return NULL;
	}
	result = _data_->result;
	_data_->result = NULL;
	return result;
}

/**
     * Throws DatabaseError.OPEN_REQUIRED if not open.
     */
static Block23Data*
block23_data_ref (Block23Data* _data23_)
{
	g_atomic_int_inc (&_data23_->_ref_count_);
	return _data23_;
}

static void
block23_data_unref (void * _userdata_)
{
	Block23Data* _data23_;
	_data23_ = (Block23Data*) _userdata_;
	if (g_atomic_int_dec_and_test (&_data23_->_ref_count_)) {
		GearyDbDatabase* self;
		self = _data23_->self;
		_g_object_unref0 (_data23_->cx);
		_g_object_unref0 (_data23_->cancellable);
		_g_object_unref0 (self);
		g_slice_free (Block23Data, _data23_);
	}
}

static void
__lambda23_ (Block23Data* _data23_,
             GError** error)
{
	GearyDbDatabase* self;
	GearyDbDatabaseConnection* _tmp0_ = NULL;
	GearyDbDatabaseConnection* _tmp1_;
	GearyDbDatabaseConnection* _tmp2_;
	GError* _inner_error0_ = NULL;
	self = _data23_->self;
	_tmp1_ = geary_db_database_internal_open_connection (self, FALSE, _data23_->cancellable, &_inner_error0_);
	_tmp0_ = _tmp1_;
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		g_propagate_error (error, _inner_error0_);
		return;
	}
	_tmp2_ = _tmp0_;
	_tmp0_ = NULL;
	_g_object_unref0 (_data23_->cx);
	_data23_->cx = _tmp2_;
	_g_object_unref0 (_tmp0_);
}

static void
___lambda23__geary_nonblocking_concurrent_concurrent_callback (GCancellable* cancellable,
                                                               gpointer self,
                                                               GError** error)
{
	__lambda23_ (self, error);
}

static void
geary_db_database_open_connection_ready (GObject* source_object,
                                         GAsyncResult* _res_,
                                         gpointer _user_data_)
{
	GearyDbDatabaseOpenConnectionData* _data_;
	_data_ = _user_data_;
	_data_->_source_object_ = source_object;
	_data_->_res_ = _res_;
	geary_db_database_open_connection_co (_data_);
}

static gboolean
geary_db_database_open_connection_co (GearyDbDatabaseOpenConnectionData* _data_)
{
	switch (_data_->_state_) {
		case 0:
		goto _state_0;
		case 1:
		goto _state_1;
		default:
		g_assert_not_reached ();
	}
	_state_0:
	_data_->_data23_ = g_slice_new0 (Block23Data);
	_data_->_data23_->_ref_count_ = 1;
	_data_->_data23_->self = g_object_ref (_data_->self);
	_g_object_unref0 (_data_->_data23_->cancellable);
	_data_->_data23_->cancellable = _data_->cancellable;
	_data_->_data23_->_async_data_ = _data_;
	_data_->_data23_->cx = NULL;
	_data_->_tmp0_ = geary_nonblocking_concurrent_get_global ();
	_data_->_tmp1_ = _data_->_tmp0_;
	_data_->_state_ = 1;
	geary_nonblocking_concurrent_schedule_async (_data_->_tmp1_, ___lambda23__geary_nonblocking_concurrent_concurrent_callback, _data_->_data23_, _data_->_data23_->cancellable, geary_db_database_open_connection_ready, _data_);
	return FALSE;
	_state_1:
	geary_nonblocking_concurrent_schedule_finish (_data_->_tmp1_, _data_->_res_, &_data_->_inner_error0_);
	if (G_UNLIKELY (_data_->_inner_error0_ != NULL)) {
		g_task_return_error (_data_->_async_result, _data_->_inner_error0_);
		block23_data_unref (_data_->_data23_);
		_data_->_data23_ = NULL;
		g_object_unref (_data_->_async_result);
		return FALSE;
	}
	_data_->_tmp2_ = _g_object_ref0 (_data_->_data23_->cx);
	_data_->result = _data_->_tmp2_;
	block23_data_unref (_data_->_data23_);
	_data_->_data23_ = NULL;
	g_task_return_pointer (_data_->_async_result, _data_, NULL);
	if (_data_->_state_ != 0) {
		while (!g_task_get_completed (_data_->_async_result)) {
			g_main_context_iteration (g_task_get_context (_data_->_async_result), TRUE);
		}
	}
	g_object_unref (_data_->_async_result);
	return FALSE;
}

static GearyDbDatabaseConnection*
geary_db_database_internal_open_connection (GearyDbDatabase* self,
                                            gboolean is_primary,
                                            GCancellable* cancellable,
                                            GError** error)
{
	gint _tmp0_ = 0;
	GearyDbDatabaseFlags _tmp1_;
	gint sqlite_flags = 0;
	GearyDbDatabaseFlags _tmp2_;
	GFile* _tmp3_;
	GearyDbDatabaseConnection* cx = NULL;
	GearyDbDatabaseConnection* _tmp4_;
	GearyDbDatabaseConnection* _tmp5_;
	GError* _inner_error0_ = NULL;
	GearyDbDatabaseConnection* result;
	g_return_val_if_fail (GEARY_DB_IS_DATABASE (self), NULL);
	g_return_val_if_fail ((cancellable == NULL) || G_TYPE_CHECK_INSTANCE_TYPE (cancellable, g_cancellable_get_type ()), NULL);
	geary_db_database_check_open (self, &_inner_error0_);
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		g_propagate_error (error, _inner_error0_);
		return NULL;
	}
	_tmp1_ = self->priv->_flags;
	if ((_tmp1_ & GEARY_DB_DATABASE_FLAGS_READ_ONLY) != 0) {
		_tmp0_ = SQLITE_OPEN_READONLY;
	} else {
		_tmp0_ = SQLITE_OPEN_READWRITE;
	}
	sqlite_flags = _tmp0_;
	_tmp2_ = self->priv->_flags;
	if ((_tmp2_ & GEARY_DB_DATABASE_FLAGS_CREATE_FILE) != 0) {
		sqlite_flags |= SQLITE_OPEN_CREATE;
	}
	_tmp3_ = self->priv->_file;
	if (_tmp3_ == NULL) {
		sqlite_flags |= SQLITE_OPEN_URI;
	}
	_tmp4_ = geary_db_database_connection_new (self, sqlite_flags, cancellable, &_inner_error0_);
	cx = _tmp4_;
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		g_propagate_error (error, _inner_error0_);
		return NULL;
	}
	_tmp5_ = cx;
	geary_db_database_prepare_connection (self, _tmp5_, &_inner_error0_);
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		g_propagate_error (error, _inner_error0_);
		_g_object_unref0 (cx);
		return NULL;
	}
	result = cx;
	return result;
}

/**
     * Returns the primary connection for the database.
     *
     * The primary connection is a general-use connection many of the
     * calls in Database (including exec(), exec_file(), query(),
     * prepare(), and exec_transaction()) use to perform their work.
     * It can also be used by the caller if a dedicated Connection is
     * not required.
     *
     * Throws {@link DatabaseError.OPEN_REQUIRED} if not open.
     */
GearyDbDatabaseConnection*
geary_db_database_get_primary_connection (GearyDbDatabase* self,
                                          GError** error)
{
	GearyDbDatabaseConnection* _tmp0_;
	GearyDbDatabaseConnection* _tmp4_;
	GearyDbDatabaseConnection* _tmp5_;
	GError* _inner_error0_ = NULL;
	GearyDbDatabaseConnection* result;
	g_return_val_if_fail (GEARY_DB_IS_DATABASE (self), NULL);
	_tmp0_ = self->priv->primary;
	if (_tmp0_ == NULL) {
		GearyDbDatabaseConnection* _tmp1_ = NULL;
		GearyDbDatabaseConnection* _tmp2_;
		GearyDbDatabaseConnection* _tmp3_;
		_tmp2_ = geary_db_database_internal_open_connection (self, TRUE, NULL, &_inner_error0_);
		_tmp1_ = _tmp2_;
		if (G_UNLIKELY (_inner_error0_ != NULL)) {
			g_propagate_error (error, _inner_error0_);
			return NULL;
		}
		_tmp3_ = _tmp1_;
		_tmp1_ = NULL;
		_g_object_unref0 (self->priv->primary);
		self->priv->primary = _tmp3_;
		_g_object_unref0 (_tmp1_);
	}
	_tmp4_ = self->priv->primary;
	_tmp5_ = _g_object_ref0 (_tmp4_);
	result = _tmp5_;
	return result;
}

/**
     * Executes a statement from a string using the primary connection.
     *
     * This is a convenience method for calling {@link
     * Connection.exec} on the connection returned by {@link
     * get_primary_connection}. Throws {@link
     * DatabaseError.OPEN_REQUIRED} if not open.
     *
     * @see Connection.exec
     */
void
geary_db_database_exec (GearyDbDatabase* self,
                        const gchar* sql,
                        GCancellable* cancellable,
                        GError** error)
{
	GearyDbDatabaseConnection* _tmp0_ = NULL;
	GearyDbDatabaseConnection* _tmp1_;
	GError* _inner_error0_ = NULL;
	g_return_if_fail (GEARY_DB_IS_DATABASE (self));
	g_return_if_fail (sql != NULL);
	g_return_if_fail ((cancellable == NULL) || G_TYPE_CHECK_INSTANCE_TYPE (cancellable, g_cancellable_get_type ()));
	_tmp1_ = geary_db_database_get_primary_connection (self, &_inner_error0_);
	_tmp0_ = _tmp1_;
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		g_propagate_error (error, _inner_error0_);
		return;
	}
	geary_db_connection_exec (G_TYPE_CHECK_INSTANCE_CAST (_tmp0_, GEARY_DB_TYPE_CONNECTION, GearyDbConnection), sql, cancellable, &_inner_error0_);
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		g_propagate_error (error, _inner_error0_);
		_g_object_unref0 (_tmp0_);
		return;
	}
	_g_object_unref0 (_tmp0_);
}

/**
     * Executes a statement from a file using the primary connection.
     *
     * This is a convenience method for calling {@link
     * Connection.exec_file} on the connection returned by {@link
     * get_primary_connection}. Throws {@link
     * DatabaseError.OPEN_REQUIRED} if not open.
     *
     * @see Connection.exec_file
     */
void
geary_db_database_exec_file (GearyDbDatabase* self,
                             GFile* file,
                             GCancellable* cancellable,
                             GError** error)
{
	GearyDbDatabaseConnection* _tmp0_ = NULL;
	GearyDbDatabaseConnection* _tmp1_;
	GError* _inner_error0_ = NULL;
	g_return_if_fail (GEARY_DB_IS_DATABASE (self));
	g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (file, g_file_get_type ()));
	g_return_if_fail ((cancellable == NULL) || G_TYPE_CHECK_INSTANCE_TYPE (cancellable, g_cancellable_get_type ()));
	_tmp1_ = geary_db_database_get_primary_connection (self, &_inner_error0_);
	_tmp0_ = _tmp1_;
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		g_propagate_error (error, _inner_error0_);
		return;
	}
	geary_db_connection_exec_file (G_TYPE_CHECK_INSTANCE_CAST (_tmp0_, GEARY_DB_TYPE_CONNECTION, GearyDbConnection), file, cancellable, &_inner_error0_);
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		g_propagate_error (error, _inner_error0_);
		_g_object_unref0 (_tmp0_);
		return;
	}
	_g_object_unref0 (_tmp0_);
}

/**
     * Prepares a statement from a string using the primary connection.
     *
     * This is a convenience method for calling {@link
     * Connection.prepare} on the connection returned by {@link
     * get_primary_connection}. Throws {@link
     * DatabaseError.OPEN_REQUIRED} if not open.
     *
     * @see Connection.prepare
     */
GearyDbStatement*
geary_db_database_prepare (GearyDbDatabase* self,
                           const gchar* sql,
                           GError** error)
{
	GearyDbDatabaseConnection* _tmp0_ = NULL;
	GearyDbDatabaseConnection* _tmp1_;
	GearyDbStatement* _tmp2_ = NULL;
	GearyDbStatement* _tmp3_;
	GearyDbStatement* _tmp4_;
	GError* _inner_error0_ = NULL;
	GearyDbStatement* result;
	g_return_val_if_fail (GEARY_DB_IS_DATABASE (self), NULL);
	g_return_val_if_fail (sql != NULL, NULL);
	_tmp1_ = geary_db_database_get_primary_connection (self, &_inner_error0_);
	_tmp0_ = _tmp1_;
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		g_propagate_error (error, _inner_error0_);
		return NULL;
	}
	_tmp3_ = geary_db_connection_prepare (G_TYPE_CHECK_INSTANCE_CAST (_tmp0_, GEARY_DB_TYPE_CONNECTION, GearyDbConnection), sql, &_inner_error0_);
	_tmp2_ = _tmp3_;
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		g_propagate_error (error, _inner_error0_);
		_g_object_unref0 (_tmp0_);
		return NULL;
	}
	_tmp4_ = _tmp2_;
	_tmp2_ = NULL;
	result = _tmp4_;
	_g_object_unref0 (_tmp2_);
	_g_object_unref0 (_tmp0_);
	return result;
}

/**
     * Executes a query using the primary connection.
     *
     * This is a convenience method for calling {@link
     * Connection.query} on the connection returned by {@link
     * get_primary_connection}. Throws {@link
     * DatabaseError.OPEN_REQUIRED} if not open.
     *
     * @see Connection.query
     */
GearyDbResult*
geary_db_database_query (GearyDbDatabase* self,
                         const gchar* sql,
                         GCancellable* cancellable,
                         GError** error)
{
	GearyDbDatabaseConnection* _tmp0_ = NULL;
	GearyDbDatabaseConnection* _tmp1_;
	GearyDbResult* _tmp2_ = NULL;
	GearyDbResult* _tmp3_;
	GearyDbResult* _tmp4_;
	GError* _inner_error0_ = NULL;
	GearyDbResult* result;
	g_return_val_if_fail (GEARY_DB_IS_DATABASE (self), NULL);
	g_return_val_if_fail (sql != NULL, NULL);
	g_return_val_if_fail ((cancellable == NULL) || G_TYPE_CHECK_INSTANCE_TYPE (cancellable, g_cancellable_get_type ()), NULL);
	_tmp1_ = geary_db_database_get_primary_connection (self, &_inner_error0_);
	_tmp0_ = _tmp1_;
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		g_propagate_error (error, _inner_error0_);
		return NULL;
	}
	_tmp3_ = geary_db_connection_query (G_TYPE_CHECK_INSTANCE_CAST (_tmp0_, GEARY_DB_TYPE_CONNECTION, GearyDbConnection), sql, cancellable, &_inner_error0_);
	_tmp2_ = _tmp3_;
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		g_propagate_error (error, _inner_error0_);
		_g_object_unref0 (_tmp0_);
		return NULL;
	}
	_tmp4_ = _tmp2_;
	_tmp2_ = NULL;
	result = _tmp4_;
	_g_object_unref0 (_tmp2_);
	_g_object_unref0 (_tmp0_);
	return result;
}

/**
     * Executes a transaction using the primary connection.
     *
     * This is a convenience method for calling {@link
     * DatabaseConnection.exec_transaction} on the connection returned
     * by {@link get_primary_connection}. Throws {@link
     * DatabaseError.OPEN_REQUIRED} if not open.
     *
     * @see DatabaseConnection.exec_transaction
     */
GearyDbTransactionOutcome
geary_db_database_exec_transaction (GearyDbDatabase* self,
                                    GearyDbTransactionType type,
                                    GearyDbTransactionMethod cb,
                                    gpointer cb_target,
                                    GCancellable* cancellable,
                                    GError** error)
{
	GearyDbDatabaseConnection* _tmp0_ = NULL;
	GearyDbDatabaseConnection* _tmp1_;
	GearyDbTransactionOutcome _tmp2_ = 0;
	GError* _inner_error0_ = NULL;
	GearyDbTransactionOutcome result;
	g_return_val_if_fail (GEARY_DB_IS_DATABASE (self), 0);
	g_return_val_if_fail ((cancellable == NULL) || G_TYPE_CHECK_INSTANCE_TYPE (cancellable, g_cancellable_get_type ()), 0);
	_tmp1_ = geary_db_database_get_primary_connection (self, &_inner_error0_);
	_tmp0_ = _tmp1_;
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		g_propagate_error (error, _inner_error0_);
		return 0;
	}
	_tmp2_ = geary_db_database_connection_exec_transaction (_tmp0_, type, cb, cb_target, cancellable, &_inner_error0_);
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		g_propagate_error (error, _inner_error0_);
		_g_object_unref0 (_tmp0_);
		return 0;
	}
	result = _tmp2_;
	_g_object_unref0 (_tmp0_);
	return result;
}

static void
geary_db_database_exec_transaction_async_data_free (gpointer _data)
{
	GearyDbDatabaseExecTransactionAsyncData* _data_;
	_data_ = _data;
	_g_object_unref0 (_data_->cancellable);
	_g_object_unref0 (_data_->self);
	g_slice_free (GearyDbDatabaseExecTransactionAsyncData, _data_);
}

void
geary_db_database_exec_transaction_async (GearyDbDatabase* self,
                                          GearyDbTransactionType type,
                                          GearyDbTransactionMethod cb,
                                          gpointer cb_target,
                                          GCancellable* cancellable,
                                          GAsyncReadyCallback _callback_,
                                          gpointer _user_data_)
{
	GearyDbDatabaseExecTransactionAsyncData* _data_;
	GearyDbDatabase* _tmp0_;
	GCancellable* _tmp1_;
	g_return_if_fail (GEARY_DB_IS_DATABASE (self));
	g_return_if_fail ((cancellable == NULL) || G_TYPE_CHECK_INSTANCE_TYPE (cancellable, g_cancellable_get_type ()));
	_data_ = g_slice_new0 (GearyDbDatabaseExecTransactionAsyncData);
	_data_->_async_result = g_task_new (G_OBJECT (self), cancellable, _callback_, _user_data_);
	g_task_set_task_data (_data_->_async_result, _data_, geary_db_database_exec_transaction_async_data_free);
	_tmp0_ = _g_object_ref0 (self);
	_data_->self = _tmp0_;
	_data_->type = type;
	_data_->cb = cb;
	_data_->cb_target = cb_target;
	_tmp1_ = _g_object_ref0 (cancellable);
	_g_object_unref0 (_data_->cancellable);
	_data_->cancellable = _tmp1_;
	geary_db_database_exec_transaction_async_co (_data_);
}

GearyDbTransactionOutcome
geary_db_database_exec_transaction_finish (GearyDbDatabase* self,
                                           GAsyncResult* _res_,
                                           GError** error)
{
	GearyDbTransactionOutcome result;
	GearyDbDatabaseExecTransactionAsyncData* _data_;
	_data_ = g_task_propagate_pointer (G_TASK (_res_), error);
	if (NULL == _data_) {
		return 0;
	}
	result = _data_->result;
	return result;
}

/**
     * Starts a new asynchronous transaction using a new connection.
     *
     * Asynchronous transactions are handled via background
     * threads. The background thread opens a new connection, and
     * calls {@link DatabaseConnection.exec_transaction}; see that
     * method for more information about coding a transaction. The
     * only caveat is that the {@link TransactionMethod} passed to it
     * must be thread-safe.
     *
     * Throws {@link DatabaseError.OPEN_REQUIRED} if not open.
     *
     * @see DatabaseConnection.exec_transaction
     */
static void
geary_db_database_exec_transaction_async_ready (GObject* source_object,
                                                GAsyncResult* _res_,
                                                gpointer _user_data_)
{
	GearyDbDatabaseExecTransactionAsyncData* _data_;
	_data_ = _user_data_;
	_data_->_source_object_ = source_object;
	_data_->_res_ = _res_;
	geary_db_database_exec_transaction_async_co (_data_);
}

static gboolean
geary_db_database_exec_transaction_async_co (GearyDbDatabaseExecTransactionAsyncData* _data_)
{
	switch (_data_->_state_) {
		case 0:
		goto _state_0;
		case 1:
		goto _state_1;
		default:
		g_assert_not_reached ();
	}
	_state_0:
	_data_->_tmp0_ = geary_db_transaction_async_job_new (NULL, _data_->type, _data_->cb, _data_->cb_target, _data_->cancellable);
	_data_->job = _data_->_tmp0_;
	_data_->_tmp1_ = _data_->job;
	geary_db_database_add_async_job (_data_->self, _data_->_tmp1_, &_data_->_inner_error0_);
	if (G_UNLIKELY (_data_->_inner_error0_ != NULL)) {
		g_task_return_error (_data_->_async_result, _data_->_inner_error0_);
		_g_object_unref0 (_data_->job);
		g_object_unref (_data_->_async_result);
		return FALSE;
	}
	_data_->_tmp3_ = _data_->job;
	_data_->_state_ = 1;
	geary_db_transaction_async_job_wait_for_completion_async (_data_->_tmp3_, geary_db_database_exec_transaction_async_ready, _data_);
	return FALSE;
	_state_1:
	_data_->_tmp2_ = geary_db_transaction_async_job_wait_for_completion_finish (_data_->_tmp3_, _data_->_res_, &_data_->_inner_error0_);
	if (G_UNLIKELY (_data_->_inner_error0_ != NULL)) {
		g_task_return_error (_data_->_async_result, _data_->_inner_error0_);
		_g_object_unref0 (_data_->job);
		g_object_unref (_data_->_async_result);
		return FALSE;
	}
	_data_->result = _data_->_tmp2_;
	_g_object_unref0 (_data_->job);
	g_task_return_pointer (_data_->_async_result, _data_, NULL);
	if (_data_->_state_ != 0) {
		while (!g_task_get_completed (_data_->_async_result)) {
			g_main_context_iteration (g_task_get_context (_data_->_async_result), TRUE);
		}
	}
	g_object_unref (_data_->_async_result);
	return FALSE;
}

/** Sets the logging parent context object for this database. */
void
geary_db_database_set_logging_parent (GearyDbDatabase* self,
                                      GearyLoggingSource* parent)
{
	g_return_if_fail (GEARY_DB_IS_DATABASE (self));
	g_return_if_fail (GEARY_LOGGING_IS_SOURCE (parent));
	self->priv->_logging_parent = parent;
}

/** {@inheritDoc} */
static gchar*
bool_to_string (gboolean self)
{
	gchar* result;
	if (self) {
		gchar* _tmp0_;
		_tmp0_ = g_strdup ("true");
		result = _tmp0_;
		return result;
	} else {
		gchar* _tmp1_;
		_tmp1_ = g_strdup ("false");
		result = _tmp1_;
		return result;
	}
}

static GearyLoggingState*
geary_db_database_real_to_logging_state (GearyDbContext* base)
{
	GearyDbDatabase * self;
	const gchar* _tmp0_;
	gboolean _tmp1_;
	gboolean _tmp2_;
	gchar* _tmp3_;
	gchar* _tmp4_;
	GearyLoggingState* _tmp5_;
	GearyLoggingState* _tmp6_;
	GearyLoggingState* result;
	self = G_TYPE_CHECK_INSTANCE_CAST (base, GEARY_DB_TYPE_DATABASE, GearyDbDatabase);
	_tmp0_ = self->priv->_path;
	_tmp1_ = geary_db_database_get_is_open (self);
	_tmp2_ = _tmp1_;
	_tmp3_ = bool_to_string (_tmp2_);
	_tmp4_ = _tmp3_;
	_tmp5_ = geary_logging_state_new (G_TYPE_CHECK_INSTANCE_CAST (self, GEARY_LOGGING_TYPE_SOURCE, GearyLoggingSource), "%s, is_open: %s", _tmp0_, _tmp4_);
	_tmp6_ = _tmp5_;
	_g_free0 (_tmp4_);
	result = _tmp6_;
	return result;
}

/** Adds the given job to the thread pool. */
void
geary_db_database_add_async_job (GearyDbDatabase* self,
                                 GearyDbTransactionAsyncJob* new_job,
                                 GError** error)
{
	GThreadPool* _tmp0_;
	GThreadPool* _tmp3_;
	GearyDbTransactionAsyncJob* _tmp4_;
	GError* _inner_error0_ = NULL;
	g_return_if_fail (GEARY_DB_IS_DATABASE (self));
	g_return_if_fail (GEARY_DB_IS_TRANSACTION_ASYNC_JOB (new_job));
	geary_db_database_check_open (self, &_inner_error0_);
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		g_propagate_error (error, _inner_error0_);
		return;
	}
	_tmp0_ = self->priv->thread_pool;
	if (_tmp0_ == NULL) {
		GError* _tmp1_;
		_tmp1_ = g_error_new_literal (GEARY_DATABASE_ERROR, GEARY_DATABASE_ERROR_GENERAL, "SQLite thread safety disabled, async operations unallowed");
		_inner_error0_ = _tmp1_;
		g_propagate_error (error, _inner_error0_);
		return;
	}
	{
		g_rec_mutex_lock (&self->priv->__lock_outstanding_async_jobs);
		{
			gint _tmp2_;
			_tmp2_ = self->priv->outstanding_async_jobs;
			self->priv->outstanding_async_jobs = _tmp2_ + 1;
		}
		__finally0:
		{
			g_rec_mutex_unlock (&self->priv->__lock_outstanding_async_jobs);
		}
		if (G_UNLIKELY (_inner_error0_ != NULL)) {
			g_propagate_error (error, _inner_error0_);
			return;
		}
	}
	_tmp3_ = self->priv->thread_pool;
	_tmp4_ = _g_object_ref0 (new_job);
	g_thread_pool_push (_tmp3_, _tmp4_, &_inner_error0_);
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		g_propagate_error (error, _inner_error0_);
		return;
	}
}

static GearyDbDatabase*
geary_db_database_real_get_database (GearyDbContext* base)
{
	GearyDbDatabase * self;
	GearyDbDatabase* _tmp0_;
	GearyDbDatabase* result;
	self = G_TYPE_CHECK_INSTANCE_CAST (base, GEARY_DB_TYPE_DATABASE, GearyDbDatabase);
	_tmp0_ = _g_object_ref0 (self);
	result = _tmp0_;
	return result;
}

/**
     * Hook for subclasses to modify a new SQLite connection before use.
     *
     * This allows sub-classes to configure SQLite on a newly
     * established connections before being used, such as setting
     * pragmas, custom collation functions, and so on,
     */
static void
geary_db_database_real_prepare_connection (GearyDbDatabase* self,
                                           GearyDbDatabaseConnection* cx,
                                           GError** error)
{
	g_return_if_fail (GEARY_DB_IS_DATABASE_CONNECTION (cx));
}

void
geary_db_database_prepare_connection (GearyDbDatabase* self,
                                      GearyDbDatabaseConnection* cx,
                                      GError** error)
{
	GearyDbDatabaseClass* _klass_;
	g_return_if_fail (GEARY_DB_IS_DATABASE (self));
	_klass_ = GEARY_DB_DATABASE_GET_CLASS (self);
	if (_klass_->prepare_connection) {
		_klass_->prepare_connection (self, cx, error);
	}
}

static gpointer
_g_error_copy0 (gpointer self)
{
	return self ? g_error_copy (self) : NULL;
}

static void
geary_db_database_on_async_job (GearyDbDatabase* self,
                                GearyDbTransactionAsyncJob* job)
{
	GearyDbDatabaseConnection* cx = NULL;
	GearyDbDatabaseConnection* _tmp0_;
	GearyDbDatabaseConnection* _tmp1_;
	GearyDbDatabaseConnection* _tmp2_;
	GError* open_err = NULL;
	GearyDbDatabaseConnection* _tmp3_;
	GearyDbDatabaseConnection* _tmp14_;
	GError* _inner_error0_ = NULL;
	g_return_if_fail (GEARY_DB_IS_DATABASE (self));
	g_return_if_fail (GEARY_DB_IS_TRANSACTION_ASYNC_JOB (job));
	_tmp0_ = geary_db_transaction_async_job_get_default_cx (job);
	_tmp1_ = _tmp0_;
	_tmp2_ = _g_object_ref0 (_tmp1_);
	cx = _tmp2_;
	open_err = NULL;
	_tmp3_ = cx;
	if (_tmp3_ == NULL) {
		{
			GearyDbDatabaseConnection* _tmp4_ = NULL;
			GCancellable* _tmp5_;
			GCancellable* _tmp6_;
			GearyDbDatabaseConnection* _tmp7_;
			GearyDbDatabaseConnection* _tmp8_;
			_tmp5_ = geary_db_transaction_async_job_get_cancellable (job);
			_tmp6_ = _tmp5_;
			_tmp7_ = geary_db_database_internal_open_connection (self, FALSE, _tmp6_, &_inner_error0_);
			_tmp4_ = _tmp7_;
			if (G_UNLIKELY (_inner_error0_ != NULL)) {
				goto __catch0_g_error;
			}
			_tmp8_ = _tmp4_;
			_tmp4_ = NULL;
			_g_object_unref0 (cx);
			cx = _tmp8_;
			_g_object_unref0 (_tmp4_);
		}
		goto __finally0;
		__catch0_g_error:
		{
			GError* err = NULL;
			GError* _tmp9_;
			GError* _tmp10_;
			const gchar* _tmp11_;
			GError* _tmp12_;
			const gchar* _tmp13_;
			err = _inner_error0_;
			_inner_error0_ = NULL;
			_tmp9_ = err;
			_tmp10_ = _g_error_copy0 (_tmp9_);
			_g_error_free0 (open_err);
			open_err = _tmp10_;
			_tmp11_ = self->priv->_path;
			_tmp12_ = err;
			_tmp13_ = _tmp12_->message;
			geary_logging_source_debug (G_TYPE_CHECK_INSTANCE_CAST (self, GEARY_LOGGING_TYPE_SOURCE, GearyLoggingSource), "Warning: unable to open database connection to %s, cancelling AsyncJob" \
": %s", _tmp11_, _tmp13_);
			_g_error_free0 (err);
		}
		__finally0:
		if (G_UNLIKELY (_inner_error0_ != NULL)) {
			_g_error_free0 (open_err);
			_g_object_unref0 (cx);
			_g_object_unref0 (job);
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return;
		}
	}
	_tmp14_ = cx;
	if (_tmp14_ != NULL) {
		GearyDbDatabaseConnection* _tmp15_;
		_tmp15_ = cx;
		geary_db_transaction_async_job_execute (job, _tmp15_);
	} else {
		GError* _tmp16_;
		_tmp16_ = open_err;
		geary_db_transaction_async_job_failed (job, _tmp16_);
	}
	{
		g_rec_mutex_lock (&self->priv->__lock_outstanding_async_jobs);
		{
			gint _tmp17_;
			_vala_assert (self->priv->outstanding_async_jobs > 0, "outstanding_async_jobs > 0");
			self->priv->outstanding_async_jobs = self->priv->outstanding_async_jobs - 1;
			_tmp17_ = self->priv->outstanding_async_jobs;
		}
		__finally1:
		{
			g_rec_mutex_unlock (&self->priv->__lock_outstanding_async_jobs);
		}
		if (G_UNLIKELY (_inner_error0_ != NULL)) {
			_g_error_free0 (open_err);
			_g_object_unref0 (cx);
			_g_object_unref0 (job);
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return;
		}
	}
	_g_error_free0 (open_err);
	_g_object_unref0 (cx);
	_g_object_unref0 (job);
}

GearyDbDatabase*
geary_db_database_construct (GType object_type)
{
	GearyDbDatabase * self = NULL;
	self = (GearyDbDatabase*) geary_db_context_construct (object_type);
	return self;
}

GearyDbDatabase*
geary_db_database_new (void)
{
	return geary_db_database_construct (GEARY_DB_TYPE_DATABASE);
}

static void
geary_db_database_class_init (GearyDbDatabaseClass * klass,
                              gpointer klass_data)
{
	geary_db_database_parent_class = g_type_class_peek_parent (klass);
	g_type_class_adjust_private_offset (klass, &GearyDbDatabase_private_offset);
	((GearyDbDatabaseClass *) klass)->open = (void (*) (GearyDbDatabase*, GearyDbDatabaseFlags, GCancellable*, GAsyncReadyCallback, gpointer)) geary_db_database_real_open;
	((GearyDbDatabaseClass *) klass)->open_finish = (void (*) (GearyDbDatabase*, GAsyncResult*, GError**)) geary_db_database_real_open_finish;
	((GearyDbDatabaseClass *) klass)->close = (void (*) (GearyDbDatabase*, GCancellable*, GError**)) geary_db_database_real_close;
	((GearyDbContextClass *) klass)->to_logging_state = (GearyLoggingState* (*) (GearyDbContext*)) geary_db_database_real_to_logging_state;
	((GearyDbContextClass *) klass)->get_database = (GearyDbDatabase* (*) (GearyDbContext*)) geary_db_database_real_get_database;
	((GearyDbDatabaseClass *) klass)->prepare_connection = (void (*) (GearyDbDatabase*, GearyDbDatabaseConnection*, GError**)) geary_db_database_real_prepare_connection;
	GEARY_DB_CONTEXT_CLASS (klass)->get_logging_parent = geary_db_database_real_get_logging_parent;
	G_OBJECT_CLASS (klass)->get_property = _vala_geary_db_database_get_property;
	G_OBJECT_CLASS (klass)->set_property = _vala_geary_db_database_set_property;
	G_OBJECT_CLASS (klass)->finalize = geary_db_database_finalize;
	/**
	     * The database's location on the filesystem.
	     *
	     * If null, this is a transient, in-memory database.
	     */
	g_object_class_install_property (G_OBJECT_CLASS (klass), GEARY_DB_DATABASE_FILE_PROPERTY, geary_db_database_properties[GEARY_DB_DATABASE_FILE_PROPERTY] = g_param_spec_object ("file", "file", "file", g_file_get_type (), G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
	/**
	     * The path passed to Sqlite when opening the database.
	     *
	     * This will be the path to the database file on disk for
	     * persistent databases, else {@link MEMORY_PATH} for transient
	     * databases.
	     */
	g_object_class_install_property (G_OBJECT_CLASS (klass), GEARY_DB_DATABASE_PATH_PROPERTY, geary_db_database_properties[GEARY_DB_DATABASE_PATH_PROPERTY] = g_param_spec_string ("path", "path", "path", NULL, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
	g_object_class_install_property (G_OBJECT_CLASS (klass), GEARY_DB_DATABASE_FLAGS_PROPERTY, geary_db_database_properties[GEARY_DB_DATABASE_FLAGS_PROPERTY] = g_param_spec_flags ("flags", "flags", "flags", GEARY_DB_TYPE_DATABASE_FLAGS, 0U, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
	g_object_class_install_property (G_OBJECT_CLASS (klass), GEARY_DB_DATABASE_IS_OPEN_PROPERTY, geary_db_database_properties[GEARY_DB_DATABASE_IS_OPEN_PROPERTY] = g_param_spec_boolean ("is-open", "is-open", "is-open", FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
	/** {@inheritDoc} */
	g_object_class_install_property (G_OBJECT_CLASS (klass), GEARY_DB_DATABASE_LOGGING_PARENT_PROPERTY, geary_db_database_properties[GEARY_DB_DATABASE_LOGGING_PARENT_PROPERTY] = g_param_spec_object ("logging-parent", "logging-parent", "logging-parent", GEARY_LOGGING_TYPE_SOURCE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
}

static void
geary_db_database_instance_init (GearyDbDatabase * self,
                                 gpointer klass)
{
	self->priv = geary_db_database_get_instance_private (self);
	g_rec_mutex_init (&self->priv->__lock__is_open);
	self->priv->_is_open = FALSE;
	self->priv->_logging_parent = NULL;
	self->priv->primary = NULL;
	g_rec_mutex_init (&self->priv->__lock_outstanding_async_jobs);
	self->priv->outstanding_async_jobs = 0;
	self->priv->thread_pool = NULL;
}

static void
geary_db_database_finalize (GObject * obj)
{
	GearyDbDatabase * self;
	GThreadPool* _tmp0_;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, GEARY_DB_TYPE_DATABASE, GearyDbDatabase);
	_tmp0_ = self->priv->thread_pool;
	if (_tmp0_ != NULL) {
		GThreadPool* _tmp1_;
		_tmp1_ = self->priv->thread_pool;
		self->priv->thread_pool = NULL;
		vala__g_thread_pool_free_wrapper (_tmp1_, TRUE, TRUE);
	}
	_g_object_unref0 (self->priv->_file);
	_g_free0 (self->priv->_path);
	g_rec_mutex_clear (&self->priv->__lock__is_open);
	_g_object_unref0 (self->priv->primary);
	g_rec_mutex_clear (&self->priv->__lock_outstanding_async_jobs);
	_g_thread_pool_free0 (self->priv->thread_pool);
	G_OBJECT_CLASS (geary_db_database_parent_class)->finalize (obj);
}

/**
 * Represents a single SQLite database.
 *
 * This class provides convenience methods to execute queries for
 * applications that do not require concurrent access to the database,
 * and it supports executing and asynchronous transaction using a
 * thread pool, as well as allowing multiple connections to be opened
 * for fully concurrent access.
 */
 G_GNUC_NO_INLINE static GType
geary_db_database_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (GearyDbDatabaseClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) geary_db_database_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (GearyDbDatabase), 0, (GInstanceInitFunc) geary_db_database_instance_init, NULL };
	GType geary_db_database_type_id;
	geary_db_database_type_id = g_type_register_static (GEARY_DB_TYPE_CONTEXT, "GearyDbDatabase", &g_define_type_info, 0);
	GearyDbDatabase_private_offset = g_type_add_instance_private (geary_db_database_type_id, sizeof (GearyDbDatabasePrivate));
	return geary_db_database_type_id;
}

GType
geary_db_database_get_type (void)
{
	static gsize geary_db_database_type_id__once = 0;
	if (g_once_init_enter (&geary_db_database_type_id__once)) {
		GType geary_db_database_type_id;
		geary_db_database_type_id = geary_db_database_get_type_once ();
		g_once_init_leave (&geary_db_database_type_id__once, geary_db_database_type_id);
	}
	return geary_db_database_type_id__once;
}

static void
_vala_geary_db_database_get_property (GObject * object,
                                      guint property_id,
                                      GValue * value,
                                      GParamSpec * pspec)
{
	GearyDbDatabase * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, GEARY_DB_TYPE_DATABASE, GearyDbDatabase);
	switch (property_id) {
		case GEARY_DB_DATABASE_FILE_PROPERTY:
		g_value_set_object (value, geary_db_database_get_file (self));
		break;
		case GEARY_DB_DATABASE_PATH_PROPERTY:
		g_value_set_string (value, geary_db_database_get_path (self));
		break;
		case GEARY_DB_DATABASE_FLAGS_PROPERTY:
		g_value_set_flags (value, geary_db_database_get_flags (self));
		break;
		case GEARY_DB_DATABASE_IS_OPEN_PROPERTY:
		g_value_set_boolean (value, geary_db_database_get_is_open (self));
		break;
		case GEARY_DB_DATABASE_LOGGING_PARENT_PROPERTY:
		g_value_set_object (value, geary_db_context_get_logging_parent (G_TYPE_CHECK_INSTANCE_CAST (self, GEARY_DB_TYPE_CONTEXT, GearyDbContext)));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static void
_vala_geary_db_database_set_property (GObject * object,
                                      guint property_id,
                                      const GValue * value,
                                      GParamSpec * pspec)
{
	GearyDbDatabase * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, GEARY_DB_TYPE_DATABASE, GearyDbDatabase);
	switch (property_id) {
		case GEARY_DB_DATABASE_FILE_PROPERTY:
		geary_db_database_set_file (self, g_value_get_object (value));
		break;
		case GEARY_DB_DATABASE_PATH_PROPERTY:
		geary_db_database_set_path (self, g_value_get_string (value));
		break;
		case GEARY_DB_DATABASE_FLAGS_PROPERTY:
		geary_db_database_set_flags (self, g_value_get_flags (value));
		break;
		case GEARY_DB_DATABASE_IS_OPEN_PROPERTY:
		geary_db_database_set_is_open (self, g_value_get_boolean (value));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

