summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2013-04-07 15:48:16 +0200
committerYorhel <git@yorhel.nl>2013-04-08 12:37:32 +0200
commit4ff495284cd696c754fc4d5185722cd5d89465be (patch)
treeb2b78816772c1118668354f8cce4ec9f94785d19
parentabec3322245407dda77542b9bfaef5108506e4d1 (diff)
sqlasync update
-rw-r--r--ylib/sqlasync.c28
-rw-r--r--ylib/sqlasync.h44
2 files changed, 46 insertions, 26 deletions
diff --git a/ylib/sqlasync.c b/ylib/sqlasync.c
index 67e2bf4..f50badb 100644
--- a/ylib/sqlasync.c
+++ b/ylib/sqlasync.c
@@ -528,8 +528,9 @@ static int sqlasync_thread_commit(sqlasync_t *s) {
while((r = sqlite3_step(s->commit)) == SQLITE_BUSY)
;
sqlite3_reset(s->commit);
- if(r != SQLITE_OK)
+ if(r != SQLITE_DONE)
sqlasync_thread_rollback(s);
+ s->intrans = 0;
return r;
}
@@ -667,13 +668,18 @@ static void sqlasync_thread_open(sqlasync_t *s, sqlasync_op_t *op) {
sqlite3_close(s->db);
s->db = NULL;
} else {
- res = sqlasync_result_create(r, 0, 0);
- s->dbqueue = op->q;
+ res = sqlasync_result_create(r, 1, 0);
+ s->dbqueue = op->args[1].val.ptr;
/* TODO: Make the busy handling configurable? */
sqlite3_busy_timeout(s->db, 10);
}
-
sqlasync_queue_result(op->q, res);
+
+ /* XXX: Don't merge into the above if/else. This result has to be sent
+ * after the normal result, in order to handle the case where the same
+ * queue is used for both purposes. */
+ if(r)
+ sqlasync_queue_result(op->args[1].val.ptr, sqlasync_result_create(SQLITE_OK, 1, 0));
}
@@ -732,8 +738,11 @@ static void *sqlasync_thread(void *dat) {
flags == SQLASYNC_QUIT || (flags & SQLASYNC_SINGLE) == SQLASYNC_SINGLE))) {
assert("Can't close a transaction when we still have a SQLASYNC_NEXT to process" && !s->donext);
int r = sqlasync_thread_commit(s);
- if(r != SQLITE_OK)
- sqlasync_queue_result(s->dbqueue, sqlasync_result_create(r, 0, 0));
+ if(r != SQLITE_DONE) {
+ sqlasync_result_t *res = sqlasync_result_create(r, 0, 1);
+ res->col[0] = sqlasync_text(SQLASYNC_COPY, sqlite3_errmsg(s->db));
+ sqlasync_queue_result(s->dbqueue, res);
+ }
}
if(!op)
@@ -761,10 +770,13 @@ static void *sqlasync_thread(void *dat) {
-sqlasync_queue_t *sqlasync_open(sqlasync_t *s, sqlasync_queue_t *q, const char *filename, int flags) {
- sqlasync_op_t *op = sqlasync_op_create(q, filename, SQLASYNC_OPEN, 1);
+sqlasync_queue_t *sqlasync_open(sqlasync_t *s, sqlasync_queue_t *q, sqlasync_queue_t *errq, const char *filename, int flags) {
+ sqlasync_op_t *op = sqlasync_op_create(q, filename, SQLASYNC_OPEN, 2);
op->args[0] = sqlasync_int(flags);
+ op->args[1].freeptr = 0;
+ op->args[1].val.ptr = errq; /* Abuse the sqlasync_value_t to pass a queue pointer */
sqlasync_queue_schedule(q);
+ sqlasync_queue_schedule(errq);
pthread_mutex_lock(&s->lock);
queue_push(s, op, op);
diff --git a/ylib/sqlasync.h b/ylib/sqlasync.h
index 5b137d0..00836c5 100644
--- a/ylib/sqlasync.h
+++ b/ylib/sqlasync.h
@@ -319,30 +319,38 @@ sqlasync_t *sqlasync_create(const struct timespec *transtimeout);
* The `open_flags' argument is passed as-is to sqlite3_open_v2(). If its value
* is 0, sqlite3_open() will be used instead.
*
- * If the open failed, a result will be passed back on the queue with the
- * return code in `result' and an error message in the first result column as
- * SQLITE3_TEXT.
- *
- * If the open was successful, a non-last result with `result' set to SQLITE_OK
- * is passed to the queue. The queue will be re-used later on for reporting an
- * error when a COMMIT has failed that has been initiated as part of a
- * transaction timeout (see sqlasync_create()) or as part of an SQLASYNC_SINGLE
- * query or sqlasync_close() or sqlasync_destroy(). Such an error is not fatal
- * for the database connection, but may indicate the modifications of earlier
- * queries to have been rolled back. The `last' result sent to the queue will
- * be available after sqlasync_close() has been processed.
+ * The result of the sqlite3_open() or sqlite3_open_v2() call is passed back on
+ * the first queue. If the open failed, the `result' will indicate the error
+ * code, and the error message is passed in the first column as SQLITE3_TEXT.
+ *
+ * The second queue is used for reporting asynchronous errors that are not
+ * directly linked to a certain action. This only happens when a COMMIT has
+ * failed that has been initiated as part of a transaction timeout (see
+ * sqlasync_create()) or as part of an SQLASYNC_SINGLE query or
+ * sqlasync_close() or sqlasync_destroy(). Such an error is not fatal for the
+ * database connection, but may indicate the modifications of earlier queries
+ * to have been rolled back. If the transtimeout given to sqlasync_create() is
+ * NULL, then no such errors are possible.
+ *
+ * An SQLITE_OK result with the `last' flag set will be passed to the second
+ * queue when the database connection has been closed, either because the open
+ * failed or after sqlasync_close() has been processed.
*
* You should not use a queue created with sqlasync_queue_async() with `each'
- * set to 0, otherwise you will not get any results before sqlasync_close() has
- * finished. Similarly, you can't re-use the queue given to this function for
- * other operations until the database has been closed. A NULL queue is allowed
- * if you don't care about any results.
+ * set to 0 for the second queue, otherwise you will not receive any errors
+ * before the database has been closed. Similarly, you can't re-use this queue
+ * for other operations until the database has been closed.
+ *
+ * Either or both of the queues can be NULL if you're not interested in the
+ * messages. You can also pass the same queue twice, in which case the result
+ * of the open will be passed first (with the `last' flag set), followed by
+ * whatever the second queue would receive.
*/
-sqlasync_queue_t *sqlasync_open(sqlasync_t *sql, sqlasync_queue_t *q, const char *filename, int open_flags);
+sqlasync_queue_t *sqlasync_open(sqlasync_t *sql, sqlasync_queue_t *q, sqlasync_queue_t *errq, const char *filename, int open_flags);
/* Closes the database. This is a no-op is no database is currently open. If a
* database has been closed successfully, a SQLITE_OK result with `last' set is
- * passed to the queue given to sqlasync_open(). */
+ * passed to the second queue given to sqlasync_open(). */
void sqlasync_close(sqlasync_t *sql);
/* Stops the database thread and frees any resources. This function blocks