Remove infinite loop from SqlConnection
authorZofia Abramowska <z.abramowska@samsung.com>
Tue, 22 Jul 2014 15:03:30 +0000 (17:03 +0200)
committerBartlomiej Grzelewski <b.grzelewski@samsung.com>
Fri, 12 Sep 2014 12:59:17 +0000 (14:59 +0200)
Change-Id: I9437401d609e9e2ec57fbb10416b440f0039afba

src/manager/dpl/db/src/sql_connection.cpp
src/manager/service/db-crypto.cpp
src/manager/service/db-crypto.h

index d9bf3a4..a5478fc 100644 (file)
 #include <cstdarg>
 #include <memory>
 
+
+namespace {
+const int MAX_RETRY = 10;
+}
+
 namespace CKM {
 namespace DB {
 namespace // anonymous
@@ -73,14 +78,17 @@ SqlConnection::DataCommand::DataCommand(SqlConnection *connection,
     // Notify all after potentially synchronized database connection access
     ScopedNotifyAll notifyAll(connection->m_synchronizationObject.get());
 
-    for (;;) {
+    for (int i = 0; i < MAX_RETRY; i++) {
         int ret = sqlcipher3_prepare_v2(connection->m_connection,
                                      buffer, strlen(buffer),
                                      &m_stmt, NULL);
 
         if (ret == SQLCIPHER_OK) {
-            LogPedantic("Data command prepared successfuly");
-            break;
+            LogPedantic("Prepared data command: " << buffer);
+
+            // Increment stored data command count
+            ++m_masterConnection->m_dataCommandsCount;
+            return;
         } else if (ret == SQLCIPHER_BUSY) {
             LogPedantic("Collision occurred while preparing SQL command");
 
@@ -104,10 +112,8 @@ SqlConnection::DataCommand::DataCommand(SqlConnection *connection,
         ThrowMsg(Exception::SyntaxError, error);
     }
 
-    LogPedantic("Prepared data command: " << buffer);
-
-    // Increment stored data command count
-    ++m_masterConnection->m_dataCommandsCount;
+    LogError("sqlite in the state of possible infinite loop");
+    ThrowMsg(Exception::InternalError, "sqlite permanently busy");
 }
 
 SqlConnection::DataCommand::~DataCommand()
@@ -358,7 +364,7 @@ bool SqlConnection::DataCommand::Step()
     ScopedNotifyAll notifyAll(
         m_masterConnection->m_synchronizationObject.get());
 
-    for (;;) {
+    for (int i = 0; i < MAX_RETRY; i++) {
         int ret = sqlcipher3_step(m_stmt);
 
         if (ret == SQLCIPHER_ROW) {
@@ -379,7 +385,6 @@ bool SqlConnection::DataCommand::Step()
 
                 continue;
             }
-
             // No synchronization object defined. Fail.
         }
 
@@ -391,6 +396,9 @@ bool SqlConnection::DataCommand::Step()
 
         ThrowMsg(Exception::InternalError, error);
     }
+
+    LogError("sqlite in the state of possible infinite loop");
+    ThrowMsg(Exception::InternalError, "sqlite permanently busy");
 }
 
 void SqlConnection::DataCommand::Reset()
@@ -886,7 +894,7 @@ void SqlConnection::ExecCommand(const char *format, ...)
     // Notify all after potentially synchronized database connection access
     ScopedNotifyAll notifyAll(m_synchronizationObject.get());
 
-    for (;;) {
+    for (int i = 0; i < MAX_RETRY; i++) {
         char *errorBuffer;
 
         int ret = sqlcipher3_exec(m_connection,
@@ -924,6 +932,9 @@ void SqlConnection::ExecCommand(const char *format, ...)
         LogError("Failed to execute SQL command. Error: " << errorMsg);
         ThrowMsg(Exception::SyntaxError, errorMsg);
     }
+
+    LogError("sqlite in the state of possible infinite loop");
+    ThrowMsg(Exception::InternalError, "sqlite permanently busy");
 }
 
 SqlConnection::DataCommandUniquePtr SqlConnection::PrepareDataCommand(
index b151c02..0fc0cb1 100644 (file)
@@ -185,6 +185,9 @@ using namespace DB;
         } Catch(SqlConnection::Exception::SyntaxError) {
             LogError("Couldn't create table : " << table_name << "!");
             throw;
+        } Catch(SqlConnection::Exception::InternalError) {
+            LogError("Sqlite got into infinite busy state");
+            throw;
         }
     }
 
index 05e360d..7abb79a 100644 (file)
@@ -100,6 +100,9 @@ namespace CKM {
                             m_db->m_connection->ExecCommand("BEGIN EXCLUSIVE");
                             m_db->m_inUserTransaction = true;
                             m_inTransaction = true;
+                        } Catch (DB::SqlConnection::Exception::InternalError) {
+                            LogError("sqlite got into infinite busy state");
+                            ReThrow(DBCrypto::Exception::TransactionError);
                         } Catch (DB::SqlConnection::Exception::Base) {
                             LogError("Couldn't begin transaction");
                             ReThrow(DBCrypto::Exception::TransactionError);
@@ -112,6 +115,9 @@ namespace CKM {
                             m_db->m_connection->CommitTransaction();
                             m_db->m_inUserTransaction = false;
                             m_inTransaction = false;
+                        } Catch (DB::SqlConnection::Exception::InternalError) {
+                            LogError("sqlite got into infinite busy state");
+                            ReThrow(DBCrypto::Exception::TransactionError);
                         } Catch (DB::SqlConnection::Exception::Base) {
                             LogError("Couldn't commit transaction");
                             ReThrow(DBCrypto::Exception::TransactionError);
@@ -124,6 +130,9 @@ namespace CKM {
                             m_db->m_connection->RollbackTransaction();
                             m_db->m_inUserTransaction = false;
                             m_inTransaction = false;
+                        } Catch (DB::SqlConnection::Exception::InternalError) {
+                            LogError("sqlite got into infinite busy state");
+                            ReThrow(DBCrypto::Exception::TransactionError);
                         } Catch (DB::SqlConnection::Exception::Base) {
                             LogError("Couldn't rollback transaction");
                             ReThrow(DBCrypto::Exception::TransactionError);
@@ -136,6 +145,9 @@ namespace CKM {
                             m_db->m_inUserTransaction = false;
                             m_db->m_connection->RollbackTransaction();
                         }
+                    } Catch (DB::SqlConnection::Exception::InternalError) {
+                        LogError("sqlite got into infinite busy state");
+                        ReThrow(DBCrypto::Exception::TransactionError);
                     } Catch (DB::SqlConnection::Exception::Base) {
                         LogError("Transaction rollback failed!");
                     }