Patch sqlite_retry for SQLite related Bug #51680
Patch version 2010-04-28 08:50 UTC
Return to Bug #51680 |
Download this patch
Patch Revisions:
Developer: ncoesel@dealogic.nl
--- php-5.2.6/ext/pdo_sqlite/sqlite_driver.c.orig 2007-12-31 08:20:10.000000000 +0100
+++ php-5.2.6/ext/pdo_sqlite/sqlite_driver.c 2010-04-28 10:15:29.000000000 +0200
@@ -31,6 +31,8 @@
#include "php_pdo_sqlite_int.h"
#include "zend_exceptions.h"
+
+
int _pdo_sqlite_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *file, int line TSRMLS_DC) /* {{{ */
{
pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
@@ -182,22 +184,69 @@
return 0;
}
+#define SQLITE_NUM_RETRIES 30
+
+
static long sqlite_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC)
{
+ /*
+ 28-4-2010: This function has been changed because sqlite3_busy_timeout doesn't always wait.
+ When one process fires two queries from different threads Sqlite will not wait in order
+ to prevent potential deadlock situations. The calling process must handle this situation!
+ The solution below waits for an increasing time period until the database becomes available.
+ The (u)sleep doesn't consume any CPU cycles.
+ */
+ long retval;
+ int res;
+ int retries=0;
pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
char *errmsg = NULL;
- if (sqlite3_exec(H->db, sql, NULL, NULL, &errmsg) != SQLITE_OK) {
- pdo_sqlite_error(dbh);
- if (errmsg)
- sqlite3_free(errmsg);
- return -1;
- } else {
- return sqlite3_changes(H->db);
- }
+ while(retries<SQLITE_NUM_RETRIES)
+ {
+ res=sqlite3_exec(H->db, sql, NULL, NULL, &errmsg);
+ if (res!=SQLITE_OK)
+ {
+ if (errmsg)
+ {
+ sqlite3_free(errmsg);
+ }
+
+ if ((res==SQLITE_BUSY) || (res==SQLITE_LOCKED))
+ {
+ //the database is locked/busy. Wait for a short while
+ retval=-1;
+#if defined(HAVE_USLEEP) && HAVE_USLEEP
+ usleep(20000 * retries); //do a taskswitch
+#else
+ sleep(retries);
+#endif
+ retries++;
+ }
+ else
+ {
+ //an error occured. Exit
+ retval=sqlite3_changes(H->db);
+ retries=SQLITE_NUM_RETRIES; //success!
+ }
+ }
+ else
+ {
+ retval=sqlite3_changes(H->db);
+ retries=SQLITE_NUM_RETRIES; //success!
+ }
+ }
+
+ if (retval<0)
+ {
+ pdo_sqlite_error(dbh);
+ }
+
+ return retval;
}
+
static char *pdo_sqlite_last_insert_id(pdo_dbh_t *dbh, const char *name, unsigned int *len TSRMLS_DC)
{
pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
|