diff options
author | Yorhel <git@yorhel.nl> | 2013-04-07 15:48:16 +0200 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2013-04-08 12:37:32 +0200 |
commit | 4ff495284cd696c754fc4d5185722cd5d89465be (patch) | |
tree | b2b78816772c1118668354f8cce4ec9f94785d19 | |
parent | abec3322245407dda77542b9bfaef5108506e4d1 (diff) |
sqlasync update
-rw-r--r-- | ylib/sqlasync.c | 28 | ||||
-rw-r--r-- | ylib/sqlasync.h | 44 |
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 |