php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Return to Bug #51680
Patch sqlite_retry revision 2010-04-28 08:50 UTC by ncoesel at dealogic dot nl

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;
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Apr 26 00:01:30 2024 UTC