Re: [sqlite] SQLite BUSY error - single-threaded app

2010-02-23 Thread Alan Thomas
The application runs as a singleton; there are no other applications
accessing the data base.

I do not run the command-line tool while testing.

I've cut down the example code:

  SqlStatus = sqlite3_open16 ( db_loc_string
 , &SqlDB
 ) ;
  if ( SQLITE_OK != SqlStatus )
  {
. . .
return DATASTORE_UNAVAILABLE ;
  }

  SqlStatus = sqlite3_prepare16_v2 ( SqlDB
   , L"BEGIN TRANSACTION"
   , 36
   , &SqlStmt
   , NULL
   ) ;
  if ( SQLITE_OK != SqlStatus )
  {
. . .
return SQL_PREP_ERROR ;
  }

  SqlStatus = sqlite3_step ( SqlStmt ) ;
  if ( SQLITE_DONE != SqlStatus )
  {
. . .
return TXN_BEGIN_FAILED ;
  }

  SqlStatus = sqlite3_finalize ( SqlStmt ) ; SqlStmt = NULL ;
  if ( SQLITE_OK != SqlStatus )
  {
. . .
return SQL_FNLZ_ERROR ;
  }

  swprintf_s ( (PXID_CHAR)sql_statement
 , sizeof ( sql_statement ) / sizeof ( XID_CHAR )
 ,   L"DELETE"
  L" FROM RSPNS"
 L" WHERE . . .
 ) ;
  SqlStatus = sqlite3_prepare16_v2 ( SqlDB
   , sql_statement
   , ( lstrlen ( sql_statement ) + 1 ) *
sizeof ( XID_CHAR )
   , &SqlStmt
   , NULL
   ) ;
  if ( SQLITE_OK != SqlStatus )
  {
. . .
return SQL_PREP_ERROR ;
  }

  SqlStatus = sqlite3_step ( SqlStmt ) ;
  if ( SQLITE_DONE != SqlStatus )
  {
. . .
return SQL_DLET_ERROR ;
  }

  SqlStatus = sqlite3_finalize ( SqlStmt ) ; SqlStmt = NULL ;
  if ( SQLITE_OK != SqlStatus )
  {
. . .
return SQL_FNLZ_ERROR ;
  }

  SqlStatus = sqlite3_prepare16_v2 ( SqlDB
   , L"COMMIT TRANSACTION"
   , 38
   , &SqlStmt
   , NULL
   ) ;
  if ( SQLITE_OK != SqlStatus )
  {
. . .
return SQL_PREP_ERROR ;
  }

  SqlStatus = sqlite3_step ( SqlStmt ) ;
  if ( SQLITE_DONE != SqlStatus )
  {
. . .
return TXN_COMMIT_FAILED ;
  }

  SqlStatus = sqlite3_finalize ( SqlStmt ) ; SqlStmt = NULL ;
  if ( SQLITE_OK != SqlStatus )
  {
. . .
return SQL_FNLZ_ERROR ;
  }

  SqlStatus = sqlite3_prepare16_v2 ( SqlDB
   , L"BEGIN TRANSACTION"
   , 36
   , &SqlStmt
   , NULL
   ) ;
  if ( SQLITE_OK != SqlStatus )
  {
. . .
return SQL_PREP_ERROR ;
  }

  /*-*/

  SqlStatus = sqlite3_step ( SqlStmt ) ;
  if ( SQLITE_DONE != SqlStatus )
  {
. . .
return TXN_BEGIN_FAILED ;
  }

  SqlStatus = sqlite3_finalize ( SqlStmt ) ; SqlStmt = NULL ;
  if ( SQLITE_OK != SqlStatus )
  {
. . .
return SQL_FNLZ_ERROR ;
  }

  . . .

  swprintf_s ( (PXID_CHAR)sql_statement
 , sizeof ( sql_statement ) / sizeof ( XID_CHAR )
 ,   L"INSERT"
  L" INTO RSPNS"
 L" ( SERVER_NAME"
 . . .
 L" , RESPONSE_TEXT"
  L" )"
   L" VALUES ( '%s'"
 . , ,
  L" , '%s'"
  L" )"
 , ServerName
 . . .
 , &InputBuffer[m]
 ) ;

 SqlStatus = sqlite3_prepare16_v2 ( SqlDB
  , (const char *)sql_statement
  , ( lstrlen ( sql_statement ) + 1 ) *
sizeof ( XID_CHAR )
  , &SqlStmt
  , NULL
  ) ;
 if ( SQLITE_OK != SqlStatus )
 {
   SQLiteError ( sql_statement
   , L"sqlite3_prepare16_v2 ( )"
   ) ;
   sqlite3_close ( SqlDB ) ; SqlDB = NULL ;
   return SQL_PREP_ERROR ;
 }

 SqlStatus = sqlite3_step ( SqlStmt ) ;
 if ( SQLITE_DONE != SqlStatus )
 {
   . . . 
   return SQL_ISRT_ERROR ;
 }

 SqlStatus = sqlite3_finalize ( SqlStmt ) ;
 if ( SQLITE_OK != SqlStatus )
 {
   . . . 
   return XID_DBPA_SQL_FNLZ_ERROR ;
 }

  . . .

 SqlStatus = sqlite3_prepare16_v2 ( SqlDB
  , L"COMMIT TRANSACTION"
  , 38
  , &SqlStmt
  , NULL
  ) ;
 if ( SQLITE_OK != SqlStatus )
 {
   . . . 
   return XID_DBPA_SQL_PREP_ERROR ;
 }

 SqlStatus = sqlite3_step ( SqlStmt ) ;
 if ( SQLITE_DONE != SqlStatus )
 {
   . . . 
   return XID_DBPA

[sqlite] SQLite BUSY error - single-threaded app

2010-02-20 Thread Alan Thomas
I'm currently working with version 3.6.14 on Windows XP/SP4 (32-bit).  The
application is coded for Unicode.

I wrote all of the application (MS C++ native code) excluding SQLite, so I'm
confident that it is a single-threaded app.  Threads have never been part of
its design.

The failure occurs in a common service routine called perhaps 300 times
before this error is reported.

The failure occurs every time I run the program and always occurs in the
same place.

While executing the following set BEGIN/DELETE/COMMIT/BEGIN/INSERT/COMMIT
commands approximately once per second, SQLite is returning 0x05 (BUSY) on
the first COMMIT in the second iteration of the loop.  A journal file does
exist when the BUSY condition is returned. 

Because this is a single-threaded app, waiting for the lock to clear doesn't
work.

In the following source code, "SQLiteError ( )" is a common services routine
that provides a message box and logging in the event of an error.

Source code:

  SqlDB   = NULL ;

  SqlStmt = NULL ;

  SqlStatus = sqlite3_open16 ( db_loc_string

 , &SqlDB

 ) ;

  if ( SQLITE_OK != SqlStatus )

  {

SQLiteError ( NULL

, L"sqlite3_open16 ( )"

) ;

sqlite3_close ( SqlDB ) ; SqlDB = NULL ;

return DATASTORE_UNAVAILABLE ;

  }

 

 

  SqlStatus = sqlite3_open16 ( SqlDB

   , L"BEGIN TRANSACTION"

   , 36

   , &SqlStmt

   , NULL

   ) ;

  if ( SQLITE_OK != SqlStatus )

  {

SQLiteError ( L"BEGIN TRANSACTION 1"

, L"sqlite3_prepare16_V2 ( )"

) ;

sqlite3_close ( SqlDB ) ; SqlDB = NULL ;

return SQL_PREP_ERROR ;

  }

 

 

  SqlStatus = sqlite3_prepare16_v2 ( SqlDB

   , L"BEGIN TRANSACTION"

   , 36

   , &SqlStmt

   , NULL

   ) ;

  if ( SQLITE_OK != SqlStatus )

  {

SQLiteError ( L"BEGIN TRANSACTION 1"

, L"sqlite3_prepare16_V2 ( )"

) ;

sqlite3_close ( SqlDB ) ; SqlDB = NULL ;

return SQL_PREP_ERROR ;

  }

 

 

  SqlStatus = sqlite3_step ( SqlStmt ) ;

  if ( SQLITE_DONE != SqlStatus )

  {

SQLiteError ( L"BEGIN TRANSACTION 1"

, L"sqlite3_step ( )"

) ;

sqlite3_finalize ( SqlStmt ) ; SqlStmt = NULL ;

sqlite3_close( SqlDB   ) ; SqlDB   = NULL ;

return TXN_BEGIN_FAILED ;

  }

 

 

  SqlStatus = sqlite3_finalize ( SqlStmt ) ; SqlStmt = NULL ;

  if ( SQLITE_OK != SqlStatus )

  {

SQLiteError ( L"BEGIN TRANSACTION 1"

, L"sqlite3_finalize ( )"

) ;

sqlite3_close ( SqlDB ) ; SqlDB = NULL ;

return SQL_FNLZ_ERROR ;

  }

 

 

  swprintf_s ( (PXID_CHAR)sql_statement

 , sizeof ( sql_statement ) / sizeof ( XID_CHAR )

 ,   L"DELETE"

  L" FROM RSPNS"

 L" WHERE . . .

 ) ;

  SqlStatus = sqlite3_prepare16_v2 ( SqlDB

   , sql_statement

   , ( lstrlen ( sql_statement ) + 1 ) *
sizeof ( XID_CHAR )

   , &SqlStmt

   , NULL

   ) ;

  if ( SQLITE_OK != SqlStatus )

  {

SQLiteError ( sql_statement

, L"sqlite3_prepare16_v2 ( )"

) ;

sqlite3_close ( SqlDB ) ; SqlDB = NULL ;

return SQL_PREP_ERROR ;  //  IMPLICIT DATA BASE ROLLBACK

  }

 

 

  SqlStatus = sqlite3_step ( SqlStmt ) ;

  if ( SQLITE_DONE != SqlStatus )

  {

SQLiteError ( sql_statement

, L"sqlite3_step ( )"

) ;

sqlite3_finalize ( SqlStmt ) ; SqlStmt = NULL ;

sqlite3_close( SqlDB   ) ; SqlDB   = NULL ;

return SQL_DLET_ERROR ;

  }

 

 

  SqlStatus = sqlite3_finalize ( SqlStmt ) ; SqlStmt = NULL ;

  if ( SQLITE_OK != SqlStatus )

  {

SQLiteError ( sql_statement

, L"sqlite3_finalize ( )"

) ;

sqlite3_close ( SqlDB ) ; SqlDB = NULL ;

return SQL_FNLZ_ERROR ;

  }

 

 

  SqlStatus = sqlite3_prepare16_v2 ( SqlDB

   , L"COMMIT TRANSACTION"

   , 38

   , &SqlStmt

   , NULL

   ) ;

  if ( SQLITE_OK != SqlStatus )

  {

SQLiteError ( L"COMMIT TRANSACTION 1"

, L"sqlite3_prepare16_V2 ( )"

) ;

sqlite3_close ( SqlDB ) ; SqlDB = NULL ;

return SQL_PREP_ERROR ;

  }

 

 

  SqlStatus = sqlite3_step ( SqlStmt ) ;

  if ( SQLITE_DONE != SqlStatus )

  {

SQLiteError (