-C Add\stests\sto\sthis\sbranch.
-D 2017-08-18T18:55:22.047
+C Ensure\sthat\swrite-locks\son\spages\sare\sdropped\sat\sthe\send\sof\seach\nwrite\stransaction,\seven\sif\sthere\sis\sstill\sa\sread\stransaction\sopen.
+D 2017-08-19T15:50:45.975
F Makefile.in d9873c9925917cca9990ee24be17eb9613a668012c85a343aef7e5536ae266e8
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc 02b469e9dcd5b7ee63fc1fb05babc174260ee4cfa4e0ef2e48c3c6801567a016
F src/os_unix.c 6947c0fccc1b68404def7161553881b2efab6fcac4a58bf9f4ce36a4ad27d325
F src/os_win.c 964165b66cde03abc72fe948198b01be608436894732eadb94c8720d2467f223
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
-F src/pager.c e53f35d61f266c47cc3883e34c7d01eaca38a71451dd72efb3cf21e043b471a7
+F src/pager.c 4e8dc5bf9011a2a26e3ab18838f3c07d82e5d56c5bf177c5c11bfd63cdc2f429
F src/pager.h 316dac0671fd7555af9e73d4357febd5f2d3ce6a185ffd8d77b7fc0423ac8b1a
F src/parse.y 58a2de13e855aece3d7709440e6e86849f4cde97f5227c6a25e6bba2fc5e2976
F src/pcache.c 62835bed959e2914edd26afadfecce29ece0e870
F src/resolve.c 4324a94573b1e29286f8121e4881db59eaedc014afeb274c8d3e07ed282e0e20
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
F src/select.c c9b3d8444bbf6f167d84f41ca6f3672e2521cb163a8c706b19058dc82fffe9b8
-F src/server.c 6ed43d130950389006399268ce3e9a8b1951eefc3709a5730e24b026712500b0
-F src/server.h cf1ede28aaa07a30550228582f211327b5ebe5517d2334e35ec09d00fd6d230d
+F src/server.c 4215bc2287c28f37e2bc79521eb8163e1340be2ca45f0fe4b2566f5faec9300c
+F src/server.h f46be129ffe407cac9b7018e6d4851b04e685d59b6837c73a1fb69e6aab52e3a
F src/shell.c bd6a37cbe8bf64ef6a6a74fdc50f067d3148149b4ce2b4d03154663e66ded55f
F src/shell.c.in b5725acacba95ccefa57b6d068f710e29ba8239c3aa704628a1902a1f729c175
F src/sqlite.h.in 29317515594eb3db2800a21fe8b568e502d76899fc64cc3b685f90c4a1ebe214
F test/selectF.test 21c94e6438f76537b72532fa9fd4710cdd455fc3
F test/selectG.test e8600e379589e85e9fefd2fe4d44a4cdd63f6982
F test/server1.test 46803bd3fe8b99b30dbc5ff38ffc756f5c13a118
-F test/server2.test e7890fb1eb9a11a0f94cd0892279e0f3cd1ba8c3006fa343637ee9ff3c4689f6
+F test/server2.test 787ba6044b5e9b2c3d60588bc5596054e6a5c3a7dc64bc2fb0e62f6616c142a9
F test/server3.test c3ae4ca7a6e7df870bfcd2450a9815507eaa80b9cdc44ee6c7975d48311505d4
F test/server_common.tcl c491d0f509b94a5cca845d45ca3bb47e464ad3a4bc89641982269112d0f1f3f4
F test/servercrash.test 1cbd2f98cadee2d8d42ed85ad76fbcf48958fedd537c82221838cd9bc6899dae
-F test/serverfreelist.test 2e554001145170094a19731a8ce2981d040cf44c947542b35d130e6e31256fca w test/server5.test
+F test/serverfreelist.test 2e554001145170094a19731a8ce2981d040cf44c947542b35d130e6e31256fca
F test/serverlimit.test 4bc013c0b991956486ddbff6ea3bee78a0d14a3d8091f5ec00e2bd34a7fa9aa7
-F test/serverreadonly.test 97040670597948a695b1973537d770417589f1998bcbb3959302aaee3c211250 w test/server4.test
+F test/serverreadonly.test 97040670597948a695b1973537d770417589f1998bcbb3959302aaee3c211250
F test/session.test 78fa2365e93d3663a6e933f86e7afc395adf18be
F test/shared.test 1da9dbad400cee0d93f252ccf76e1ae007a63746
F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 66fb9e1cb479f1e764f1606f041bd97fd3bd428093832c000ee36b643377e9e2
-R 6a3c43c16b1d75fce7516d061ebaa6d6
+P abb6e076c851c0b10f62c02d0d7e54f24d86c75f01036dddbc0a8a7dfc627a0d
+R aa6e06e084e3c3d3595864687ba9477a
U dan
-Z f1a62abc260e8d42c995536e20991d87
+Z 571fa6db3e131de25960c3e8f380a0b4
-abb6e076c851c0b10f62c02d0d7e54f24d86c75f01036dddbc0a8a7dfc627a0d
\ No newline at end of file
+2dd36ade9ea948de27b217b83cbf704e071e6ea5dddb8566165a645143b0f846
\ No newline at end of file
#ifdef SQLITE_SERVER_EDITION
if( pagerIsServer(pPager) ){
- rc2 = sqlite3ServerReleaseWriteLocks(pPager->pServer);
+ rc2 = sqlite3ServerEndWrite(pPager->pServer);
}else
#endif
if( !pPager->exclusiveMode
p->nLock = 0;
}
-/*
-** End a transaction (and release all locks). This version runs in
-** single process mode only.
-*/
-static void serverEndSingle(Server *p){
- Server **pp;
- ServerDb *pDb = p->pDb;
- ServerPage *pPg = 0;
-
- assert( p->eTrans!=SERVER_TRANS_NONE );
+static void serverRecycleBuffers(ServerDb *pDb){
assert( pDb->pServerShm==0 );
-
- sqlite3_mutex_enter(pDb->mutex);
-
- if( p->eTrans==SERVER_TRANS_READONLY ){
- /* Remove the connection from the readers list */
- for(pp=&pDb->pReader; *pp!=p; pp = &((*pp)->pNext));
- *pp = p->pNext;
- }else{
- serverReleaseLocks(p);
-
- /* Clear the bit in the transaction mask. */
- pDb->transmask &= ~((u32)1 << p->iTransId);
-
- /* If this connection is in the committers list, remove it. */
- for(pp=&pDb->pCommit; *pp; pp = &((*pp)->pNext)){
- if( *pp==p ){
- *pp = p->pNext;
- break;
- }
- }
- }
+ assert( sqlite3_mutex_held(pDb->mutex) );
/* See if it is possible to free any ServerPage records. If so, remove
- ** them from the linked list and hash table, but do not call sqlite3_free()
- ** on them until the mutex has been released. */
+ ** them from the linked list and hash table, and add them to the pFree
+ ** list. */
if( pDb->pPgFirst ){
- ServerPage *pLast = 0;
+ ServerPage *pPg;
Server *pIter;
+ ServerPage *pLast = 0;
int iOldest = 0x7FFFFFFF;
for(pIter=pDb->pReader; pIter; pIter=pIter->pNext){
iOldest = MIN(iOldest, pIter->iCommitId);
pDb->pPgFirst = pPg;
}
}
+}
+
+/*
+** End a transaction (and release all locks). This version runs in
+** single process mode only.
+*/
+static void serverEndSingle(Server *p){
+ Server **pp;
+ ServerDb *pDb = p->pDb;
+
+ assert( p->eTrans!=SERVER_TRANS_NONE );
+ assert( pDb->pServerShm==0 );
+ sqlite3_mutex_enter(pDb->mutex);
+
+ if( p->eTrans==SERVER_TRANS_READONLY ){
+ /* Remove the connection from the readers list */
+ for(pp=&pDb->pReader; *pp!=p; pp = &((*pp)->pNext));
+ *pp = p->pNext;
+ }else{
+ serverReleaseLocks(p);
+
+ /* Clear the bit in the transaction mask. */
+ pDb->transmask &= ~((u32)1 << p->iTransId);
+ }
+
+ serverRecycleBuffers(pDb);
sqlite3_mutex_leave(pDb->mutex);
p->pNext = 0;
p->iTransId = -1;
- p->iCommitId = 0;
}
/*
/*
** Release all write-locks.
*/
-int sqlite3ServerReleaseWriteLocks(Server *p){
- int rc = SQLITE_OK;
- return rc;
+int sqlite3ServerEndWrite(Server *p){
+ ServerDb *pDb = p->pDb;
+ int i;
+
+ if( pDb->pServerShm==0 ) sqlite3_mutex_enter(pDb->mutex);
+ for(i=0; i<p->nLock; i++){
+ while( 1 ){
+ u32 *pSlot = serverLockingSlot(pDb, p->aLock[i]);
+ u32 o = *pSlot;
+ u32 n = o & ~((u32)1 << p->iTransId);
+ if( slotGetWriter(n)==p->iTransId ){
+ n -= ((p->iTransId + 1) << HMA_MAX_TRANSACTIONID);
+ n |= ((u32)1 << p->iTransId);
+ }
+ if( o==n || serverCompareAndSwap(pSlot, o, n) ) break;
+ }
+ }
+ if( pDb->pServerShm==0 ){
+ ServerDb **pp;
+ /* If this connection is in the committers list, remove it. */
+ for(pp=&pDb->pCommit; *pp; pp = &((*pp)->pNext)){
+ if( *pp==p ){
+ *pp = p->pNext;
+ break;
+ }
+ }
+ p->iCommitId = 0;
+ sqlite3_mutex_leave(pDb->mutex);
+ }
+
+ return SQLITE_OK;
}
static int serverCheckClient(Server *p, int iClient){
return rc;
}
-int sqlite3ServerHasLock(Server *p, Pgno pgno, int bWrite){
- assert( 0 );
- return 0;
-}
-
static void serverIncrSlowReader(u32 *pSlot, int n){
assert( n==1 || n==-1 );
*pSlot += (n * (1 << HMA_SLOT_RLWL_BITS));
int sqlite3ServerPreCommit(Server*, ServerPage*);
int sqlite3ServerEnd(Server *p);
-int sqlite3ServerReleaseWriteLocks(Server *p);
+int sqlite3ServerEndWrite(Server *p);
int sqlite3ServerLock(Server *p, Pgno pgno, int bWrite, int bBlock);
-int sqlite3ServerHasLock(Server *p, Pgno pgno, int bWrite);
-
ServerPage *sqlite3ServerBuffer(Server*);
int sqlite3ServerIsSingleProcess(Server*);
db close
lsort [glob -nocomplain test.db-journal/*-journal]
} {}
+
+ #-----------------------------------------------------------------------
+ # Test that write-locks are downgraded when a transaction is ended,
+ # even if the connection holds an open read statement.
+ #
+ do_test $tn.4.1 {
+ server_sqlite3 db test.db
+ server_sqlite3 db2 test.db
+ db eval {
+ CREATE TABLE t2(a);
+ INSERT INTO t2 VALUES('one');
+ INSERT INTO t2 VALUES('two');
+ INSERT INTO t2 VALUES('three');
+ CREATE TABLE t3(k INTEGER PRIMARY KEY, val);
+ }
+
+ set res [list]
+ db eval { SELECT a FROM t2 ORDER BY rowid } {
+ db eval { REPLACE INTO t3 VALUES(1, $a) }
+ lappend res [db2 one { SELECT val FROM t3 }]
+ }
+
+ set res
+ } {one two three}
+
+ catch { db close }
+ catch { db2 close }
}
finish_test