/ Check-in [1944d92b]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Rollback any open write-transaction when a shared-cache connection is closed. (CVS 2947)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:1944d92b530d3bbcd31561063660de03d668af23
User & Date: danielk1977 2006-01-15 11:39:18
Context
2006-01-15
13:13
Fix a buffer-overrun that could occur after a malloc() failure. (CVS 2948) check-in: 66252221 user: danielk1977 tags: trunk
11:39
Rollback any open write-transaction when a shared-cache connection is closed. (CVS 2947) check-in: 1944d92b user: danielk1977 tags: trunk
02:43
Closing a file from the wrong thread is harmless on most systems. (See ticket #1611) But on systems like RedHat9 with broken fcntl() locks, it leaks file descriptors. That is better than the alternative of prematurely breaking locks and causing database corruption. Nevertheless, it would be good if we could figure out a way to report errors when closing a file from the wrong thread. (CVS 2946) check-in: ad8f12ca user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/btree.c.

     5      5   ** a legal notice, here is a blessing:
     6      6   **
     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12         -** $Id: btree.c,v 1.297 2006/01/13 11:22:07 danielk1977 Exp $
           12  +** $Id: btree.c,v 1.298 2006/01/15 11:39:18 danielk1977 Exp $
    13     13   **
    14     14   ** This file implements a external (disk-based) database using BTrees.
    15     15   ** For a detailed discussion of BTrees, refer to
    16     16   **
    17     17   **     Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3:
    18     18   **     "Sorting And Searching", pages 473-480. Addison-Wesley
    19     19   **     Publishing Company, Reading, Massachusetts.
................................................................................
  1693   1693       BtCursor *pTmp = pCur;
  1694   1694       pCur = pCur->pNext;
  1695   1695       if( pTmp->pBtree==p ){
  1696   1696         sqlite3BtreeCloseCursor(pTmp);
  1697   1697       }
  1698   1698     }
  1699   1699   
         1700  +  /* Rollback any active transaction and free the handle structure */
         1701  +  sqlite3BtreeRollback(p);
  1700   1702     sqliteFree(p);
  1701   1703   
  1702   1704   #ifndef SQLITE_OMIT_SHARED_CACHE
  1703   1705     /* If there are still other outstanding references to the shared-btree
  1704   1706     ** structure, return now. The remainder of this procedure cleans 
  1705   1707     ** up the shared-btree.
  1706   1708     */

Changes to src/util.c.

    10     10   **
    11     11   *************************************************************************
    12     12   ** Utility functions used throughout sqlite.
    13     13   **
    14     14   ** This file contains functions for allocating memory, comparing
    15     15   ** strings, and stuff like that.
    16     16   **
    17         -** $Id: util.c,v 1.170 2006/01/13 06:33:24 danielk1977 Exp $
           17  +** $Id: util.c,v 1.171 2006/01/15 11:39:18 danielk1977 Exp $
    18     18   */
    19     19   #include "sqliteInt.h"
    20     20   #include "os.h"
    21     21   #include <stdarg.h>
    22     22   #include <ctype.h>
    23     23   
    24     24   /*
................................................................................
  1351   1351   
  1352   1352   #ifndef NDEBUG
  1353   1353   /*
  1354   1354   ** This function sets a flag in the thread-specific-data structure that will
  1355   1355   ** cause an assert to fail if sqliteMalloc() or sqliteRealloc() is called.
  1356   1356   */
  1357   1357   void sqlite3MallocDisallow(){
  1358         -  assert(!sqlite3ThreadData()->mallocDisallowed);
  1359         -  sqlite3ThreadData()->mallocDisallowed = 1;
         1358  +  assert( sqlite3ThreadData()->mallocDisallowed>=0 );
         1359  +  sqlite3ThreadData()->mallocDisallowed++;
  1360   1360   }
  1361   1361   
  1362   1362   /*
  1363   1363   ** This function clears the flag set in the thread-specific-data structure set
  1364   1364   ** by sqlite3MallocDisallow().
  1365   1365   */
  1366   1366   void sqlite3MallocAllow(){
  1367         -  assert(sqlite3ThreadData()->mallocDisallowed);
  1368         -  sqlite3ThreadData()->mallocDisallowed = 0;
         1367  +  assert( sqlite3ThreadData()->mallocDisallowed>0 );
         1368  +  sqlite3ThreadData()->mallocDisallowed--;
  1369   1369   }
  1370   1370   #endif

Changes to test/shared.test.

     5      5   #
     6      6   #    May you do good and not evil.
     7      7   #    May you find forgiveness for yourself and forgive others.
     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   #
    12         -# $Id: shared.test,v 1.12 2006/01/14 08:02:29 danielk1977 Exp $
           12  +# $Id: shared.test,v 1.13 2006/01/15 11:39:18 danielk1977 Exp $
    13     13   
    14     14   set testdir [file dirname $argv0]
    15     15   source $testdir/tester.tcl
    16     16   db close
    17     17   
    18     18   ifcapable !shared_cache {
    19     19     finish_test
................................................................................
   636    636   } {1 2 3}
   637    637   do_test shared-9.3 {
   638    638     db close
   639    639     db2 close
   640    640   } {}
   641    641   
   642    642   } ; # End shared-9.*
          643  +
          644  +#---------------------------------------------------------------------------
          645  +# The following tests - shared-10.* - test that the library behaves 
          646  +# correctly when a connection to a shared-cache is closed. 
          647  +#
          648  +do_test shared-10.1 {
          649  +  # Create a small sample database with two connections to it (db and db2).
          650  +  file delete -force test.db
          651  +  sqlite3 db  test.db
          652  +  sqlite3 db2 test.db
          653  +  execsql {
          654  +    CREATE TABLE ab(a PRIMARY KEY, b);
          655  +    CREATE TABLE de(d PRIMARY KEY, e);
          656  +    INSERT INTO ab VALUES('Chiang Mai', 100000);
          657  +    INSERT INTO ab VALUES('Bangkok', 8000000);
          658  +    INSERT INTO de VALUES('Ubon', 120000);
          659  +    INSERT INTO de VALUES('Khon Kaen', 200000);
          660  +  }
          661  +} {}
          662  +do_test shared-10.2 {
          663  +  # Open a read-transaction with the first connection, a write-transaction
          664  +  # with the second.
          665  +  execsql {
          666  +    BEGIN;
          667  +    SELECT * FROM ab;
          668  +  }
          669  +  execsql {
          670  +    BEGIN;
          671  +    INSERT INTO de VALUES('Pataya', 30000);
          672  +  } db2
          673  +} {}
          674  +do_test shared-10.3 {
          675  +  # An external connection should be able to read the database, but not
          676  +  # prepare a write operation.
          677  +  sqlite3 db3 ./test.db
          678  +  execsql {
          679  +    SELECT * FROM ab;
          680  +  } db3
          681  +  catchsql {
          682  +    BEGIN;
          683  +    INSERT INTO de VALUES('Pataya', 30000);
          684  +  } db3
          685  +} {1 {database is locked}}
          686  +do_test shared-10.4 {
          687  +  # Close the connection with the write-transaction open
          688  +  db2 close
          689  +} {}
          690  +do_test shared-10.5 {
          691  +  # Test that the db2 transaction has been automatically rolled back.
          692  +  # If it has not the ('Pataya', 30000) entry will still be in the table.
          693  +  execsql {
          694  +    SELECT * FROM de;
          695  +  }
          696  +} {Ubon 120000 {Khon Kaen} 200000}
          697  +do_test shared-10.5 {
          698  +  # Closing db2 should have dropped the shared-cache back to a read-lock.
          699  +  # So db3 should be able to prepare a write...
          700  +  catchsql {INSERT INTO de VALUES('Pataya', 30000);} db3
          701  +} {0 {}}
          702  +do_test shared-10.6 {
          703  +  # ... but not commit it.
          704  +  catchsql {COMMIT} db3
          705  +} {1 {database is locked}}
          706  +do_test shared-10.7 {
          707  +  # Commit the (read-only) db transaction. Check via db3 to make sure the 
          708  +  # contents of table "de" are still as they should be.
          709  +  execsql {
          710  +    COMMIT;
          711  +  }
          712  +  execsql {
          713  +    SELECT * FROM de;
          714  +  } db3
          715  +} {Ubon 120000 {Khon Kaen} 200000 Pataya 30000}
          716  +do_test shared-10.9 {
          717  +  # Commit the external transaction.
          718  +  catchsql {COMMIT} db3
          719  +} {0 {}}
          720  +integrity_check shared-10.10
          721  +do_test shared-10.11 {
          722  +  db close
          723  +  db3 close
          724  +} {}
   643    725   
   644    726   finish_test
   645    727   sqlite3_enable_shared_cache $::enable_shared_cache