gboolean store_vcard;
GStaticRWLock rwlock;
+
+ GMutex *in_transaction_lock;
+ guint32 in_transaction;
};
G_DEFINE_TYPE (EBookBackendSqliteDB, e_book_backend_sqlitedb, G_TYPE_OBJECT)
g_free (priv->path);
priv->path = NULL;
+ g_mutex_free (priv->in_transaction_lock);
+ priv->in_transaction_lock = NULL;
+
g_free (priv);
priv = NULL;
ebsdb->priv->store_vcard = TRUE;
g_static_rw_lock_init (&ebsdb->priv->rwlock);
+
+ ebsdb->priv->in_transaction = 0;
+ ebsdb->priv->in_transaction_lock = g_mutex_new ();
}
static void
* Callers should hold the rw lock depending on read or write operation
* Returns:
**/
-static gint
+static gboolean
book_backend_sql_exec (sqlite3 *db,
const gchar *stmt,
gint (*callback)(gpointer ,gint,gchar **,gchar **),
0, "%s", errmsg);
sqlite3_free (errmsg);
errmsg = NULL;
- return -1;
+ return FALSE;
}
if (errmsg) {
errmsg = NULL;
}
- return 0;
+ return TRUE;
}
-static void
+/* the first caller holds the writer lock too */
+static gboolean
book_backend_sqlitedb_start_transaction (EBookBackendSqliteDB *ebsdb,
GError **error)
{
- book_backend_sql_exec (ebsdb->priv->db, "BEGIN", NULL, NULL, error);
+ gboolean res = TRUE;
+
+ g_return_val_if_fail (ebsdb != NULL, FALSE);
+ g_return_val_if_fail (ebsdb->priv != NULL, FALSE);
+ g_return_val_if_fail (ebsdb->priv->db != NULL, FALSE);
+
+ g_mutex_lock (ebsdb->priv->in_transaction_lock);
+
+ ebsdb->priv->in_transaction++;
+ if (ebsdb->priv->in_transaction == 0) {
+ g_mutex_unlock (ebsdb->priv->in_transaction_lock);
+
+ g_return_val_if_fail (ebsdb->priv->in_transaction != 0, FALSE);
+ return FALSE;
+ }
+
+ if (ebsdb->priv->in_transaction == 1) {
+ WRITER_LOCK (ebsdb);
+
+ res = book_backend_sql_exec (ebsdb->priv->db, "BEGIN", NULL, NULL, error);
+ }
+
+ g_mutex_unlock (ebsdb->priv->in_transaction_lock);
+
+ return res;
}
-static void
+/* the last caller releases the writer lock too */
+static gboolean
book_backend_sqlitedb_end_transaction (EBookBackendSqliteDB *ebsdb,
+ gboolean do_commit,
GError **error)
{
- if (!error || !*error)
- book_backend_sql_exec (ebsdb->priv->db, "COMMIT", NULL, NULL, error);
- else
- book_backend_sql_exec (ebsdb->priv->db, "ROLLBACK", NULL, NULL, NULL);
+ gboolean res = TRUE;
+
+ g_return_val_if_fail (ebsdb != NULL, FALSE);
+ g_return_val_if_fail (ebsdb->priv != NULL, FALSE);
+ g_return_val_if_fail (ebsdb->priv->db != NULL, FALSE);
+
+ g_mutex_lock (ebsdb->priv->in_transaction_lock);
+ if (ebsdb->priv->in_transaction == 0) {
+ g_mutex_unlock (ebsdb->priv->in_transaction_lock);
+
+ g_return_val_if_fail (ebsdb->priv->in_transaction > 0, FALSE);
+ return FALSE;
+ }
+
+ ebsdb->priv->in_transaction--;
+
+ if (ebsdb->priv->in_transaction == 0) {
+ res = book_backend_sql_exec (ebsdb->priv->db, do_commit ? "COMMIT" : "ROLLBACK", NULL, NULL, error);
+
+ WRITER_UNLOCK (ebsdb);
+ }
+
+ g_mutex_unlock (ebsdb->priv->in_transaction_lock);
+
+ return res;
}
static void
" partial_content INTEGER,"
" version INTEGER)";
- WRITER_LOCK (ebsdb);
book_backend_sqlitedb_start_transaction (ebsdb, &err);
if (!err)
book_backend_sql_exec (ebsdb->priv->db, stmt, NULL, NULL, &err);
}
- book_backend_sqlitedb_end_transaction (ebsdb, &err);
- WRITER_UNLOCK (ebsdb);
+ book_backend_sqlitedb_end_transaction (ebsdb, !err, err ? NULL : &err);
if (err)
g_propagate_error (error, err);
gchar *stmt;
GError *err = NULL;
- WRITER_LOCK (ebsdb);
book_backend_sqlitedb_start_transaction (ebsdb, &err);
if (!err) {
sqlite3_free (stmt);
}
- book_backend_sqlitedb_end_transaction (ebsdb, &err);
- WRITER_UNLOCK (ebsdb);
+ book_backend_sqlitedb_end_transaction (ebsdb, !err, err ? NULL : &err);
if (err)
g_propagate_error (error, err);
}
/* The column names match the fields used in book-backend-sexp */
-static gint
+static gboolean
create_contacts_table (EBookBackendSqliteDB *ebsdb,
const gchar *folderid,
GError **error)
{
- gint ret, i;
+ gint i;
+ gboolean ret;
gchar *stmt, *tmp;
GError *err = NULL;
GString *string;
return ebsdb;
}
+gboolean
+e_book_backend_sqlitedb_lock_updates (EBookBackendSqliteDB *ebsdb,
+ GError **error)
+{
+ g_return_val_if_fail (ebsdb != NULL, FALSE);
+ g_return_val_if_fail (ebsdb->priv != NULL, FALSE);
+
+ return book_backend_sqlitedb_start_transaction (ebsdb, error);
+}
+
+gboolean
+e_book_backend_sqlitedb_unlock_updates (EBookBackendSqliteDB *ebsdb,
+ gboolean do_commit,
+ GError **error)
+{
+ g_return_val_if_fail (ebsdb != NULL, FALSE);
+ g_return_val_if_fail (ebsdb->priv != NULL, FALSE);
+
+ return book_backend_sqlitedb_end_transaction (ebsdb, do_commit, error);
+}
+
/* Add Contact (free the result with g_free() ) */
static gchar *
insert_stmt_from_contact (EContact *contact,
priv = ebsdb->priv;
- WRITER_LOCK (ebsdb);
book_backend_sqlitedb_start_transaction (ebsdb, &err);
for (l = contacts; !err && l != NULL; l = g_slist_next (l)) {
g_free (stmt);
}
- book_backend_sqlitedb_end_transaction (ebsdb, &err);
-
- WRITER_UNLOCK (ebsdb);
+ book_backend_sqlitedb_end_transaction (ebsdb, !err, err ? NULL : &err);
if (err)
g_propagate_error (error, err);
g_string_truncate (str, str->len - 1);
g_string_append (str, ")");
- WRITER_LOCK (ebsdb);
-
- if (!err)
- book_backend_sqlitedb_start_transaction (ebsdb, &err);
+ book_backend_sqlitedb_start_transaction (ebsdb, &err);
if (!err)
book_backend_sql_exec (priv->db, str->str, NULL, NULL, &err);
- book_backend_sqlitedb_end_transaction (ebsdb, &err);
- WRITER_UNLOCK (ebsdb);
+ book_backend_sqlitedb_end_transaction (ebsdb, !err, err ? NULL : &err);
g_string_free (str, TRUE);
gchar *stmt = NULL;
GError *err = NULL;
- WRITER_LOCK (ebsdb);
book_backend_sqlitedb_start_transaction (ebsdb, &err);
if (!err) {
sqlite3_free (stmt);
}
- book_backend_sqlitedb_end_transaction (ebsdb, &err);
- WRITER_UNLOCK (ebsdb);
+ book_backend_sqlitedb_end_transaction (ebsdb, !err, err ? NULL : &err);
if (err)
g_propagate_error (error, err);
gchar *stmt = NULL;
GError *err = NULL;
- WRITER_LOCK (ebsdb);
book_backend_sqlitedb_start_transaction (ebsdb, &err);
if (!err) {
sqlite3_free (stmt);
}
- book_backend_sqlitedb_end_transaction (ebsdb, &err);
- WRITER_UNLOCK (ebsdb);
+ book_backend_sqlitedb_end_transaction (ebsdb, !err, err ? NULL : &err);
if (err)
g_propagate_error (error, err);
gchar *stmt = NULL;
GError *err = NULL;
- WRITER_LOCK (ebsdb);
book_backend_sqlitedb_start_transaction (ebsdb, &err);
if (!err) {
sqlite3_free (stmt);
}
- book_backend_sqlitedb_end_transaction (ebsdb, &err);
- WRITER_UNLOCK (ebsdb);
+ book_backend_sqlitedb_end_transaction (ebsdb, !err, err ? NULL : &err);
if (err)
g_propagate_error (error, err);
gchar *stmt = NULL;
GError *err = NULL;
- WRITER_LOCK (ebsdb);
book_backend_sqlitedb_start_transaction (ebsdb, &err);
if (!err) {
sqlite3_free (stmt);
}
- book_backend_sqlitedb_end_transaction (ebsdb, &err);
- WRITER_UNLOCK (ebsdb);
+ book_backend_sqlitedb_end_transaction (ebsdb, !err, err ? NULL : &err);
if (err)
g_propagate_error (error, err);
gchar *stmt = NULL;
GError *err = NULL;
- WRITER_LOCK (ebsdb);
book_backend_sqlitedb_start_transaction (ebsdb, &err);
if (!err) {
sqlite3_free (stmt);
}
- book_backend_sqlitedb_end_transaction (ebsdb, &err);
- WRITER_UNLOCK (ebsdb);
+ book_backend_sqlitedb_end_transaction (ebsdb, !err, err ? NULL : &err);
if (err)
g_propagate_error (error, err);
gchar *stmt;
GError *err = NULL;
- WRITER_LOCK (ebsdb);
book_backend_sqlitedb_start_transaction (ebsdb, &err);
/* delete the contacts table */
sqlite3_free (stmt);
}
- book_backend_sqlitedb_end_transaction (ebsdb, &err);
- WRITER_UNLOCK (ebsdb);
+ book_backend_sqlitedb_end_transaction (ebsdb, !err, err ? NULL : &err);
if (err)
g_propagate_error (error, err);