-C Add\ssupport\sfor\scrash\srecovery\sin\smulti-process\smode.\sAnd\sadd\stest\scases\sfor\nthe\ssame.
-D 2017-08-17T19:32:02.420
+C Do\snot\ssearch\sfor\slocks\sto\sclear\swhen\sconnecting\sto\sa\sdb\sin\smulti-process\smode\nunless\sit\slooks\slike\sthe\sprevious\suser\sof\sthe\sclient-id\scrashed.
+D 2017-08-18T16:04:40.867
F Makefile.in d9873c9925917cca9990ee24be17eb9613a668012c85a343aef7e5536ae266e8
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc 02b469e9dcd5b7ee63fc1fb05babc174260ee4cfa4e0ef2e48c3c6801567a016
F src/resolve.c 4324a94573b1e29286f8121e4881db59eaedc014afeb274c8d3e07ed282e0e20
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
F src/select.c c9b3d8444bbf6f167d84f41ca6f3672e2521cb163a8c706b19058dc82fffe9b8
-F src/server.c 481366fff6584dc6754b6e59d3340d379faf0c55fd7e012d46257139af282e1d
+F src/server.c 6ed43d130950389006399268ce3e9a8b1951eefc3709a5730e24b026712500b0
F src/server.h cf1ede28aaa07a30550228582f211327b5ebe5517d2334e35ec09d00fd6d230d
F src/shell.c bd6a37cbe8bf64ef6a6a74fdc50f067d3148149b4ce2b4d03154663e66ded55f
F src/shell.c.in b5725acacba95ccefa57b6d068f710e29ba8239c3aa704628a1902a1f729c175
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 380a7b7a458b212b0463c8e128c289cc70f2fdb9b9a63b91fc7542c120eb9c10
-R 70f8b6d0240578b43d191efd6f3e839e
+P a8115f95e80cc90c095fdd0a151da51f4d3ee427defdc34780e977585a68776d
+R 3a806093fb1d82eb28aea633865a3bda
U dan
-Z 25c9fec4aa243def4a00985f9de58c4b
+Z 66a9c79489e9385c1bc99754d5e08a1b
#define slotReaderMask(v) ((v) & HMA_SLOT_RL_MASK)
+#define fdOpen(pFd) ((pFd)->pMethods!=0)
/*
** Atomic CAS primitive used in multi-process mode. Equivalent to:
typedef struct ServerDb ServerDb;
typedef struct ServerJournal ServerJournal;
-struct ServerGlobal {
- ServerDb *pDb; /* Linked list of all ServerDb objects */
-};
-static struct ServerGlobal g_server;
-
struct ServerJournal {
char *zJournal;
sqlite3_file *jfd;
** database file opened in server mode by this process.
*/
struct ServerDb {
- sqlite3_mutex *mutex; /* Non-recursive mutex */
+ i64 aFileId[2]; /* Opaque VFS file-id */
+ ServerDb *pNext; /* Next db in this process */
int nClient; /* Current number of clients */
+ sqlite3_mutex *mutex; /* Non-recursive mutex */
+
+ /* Variables above this point are protected by the global mutex -
+ ** serverEnterMutex()/LeaveMutex(). Those below this point are
+ ** protected by the ServerDb.mutex mutex. */
+
int bInit; /* True once initialized */
u32 transmask; /* Bitmask of taken transaction ids */
u32 *aSlot; /* Array of page locking slots */
- i64 aFileId[2]; /* Opaque VFS file-id */
- ServerDb *pNext; /* Next db in this process */
sqlite3_vfs *pVfs;
ServerJournal aJrnl[HMA_MAX_TRANSACTIONID];
u8 *aJrnlFdSpace;
- void *pServerShm;
+ void *pServerShm; /* SHMOPEN handle (multi-process only) */
+ u32 *aClient; /* Client "transaction active" flags */
int iNextCommit; /* Commit id for next pre-commit call */
Server *pCommit; /* List of connections currently commiting */
Server *pNext; /* Next in pCommit or pReader list */
};
+struct ServerGlobal {
+ ServerDb *pDb; /* Linked list of all ServerDb objects */
+};
+static struct ServerGlobal g_server;
+
+
struct ServerFcntlArg {
void *h; /* Handle from SHMOPEN */
void *p; /* Mapping */
static void serverLeaveMutex(void){
sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_APP1));
}
+#if 0
static void serverAssertMutexHeld(void){
assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_APP1)) );
}
+#endif
/*
** Locate the ServerDb object shared by all connections to the db identified
int bExist = 1;
int rc = SQLITE_OK;
- if( pJ->jfd->pMethods==0 ){
+ if( fdOpen(pJ->jfd)==0 ){
bExist = 0;
rc = sqlite3OsAccess(pDb->pVfs, pJ->zJournal, SQLITE_ACCESS_EXISTS,&bExist);
if( bExist && rc==SQLITE_OK ){
ServerDb *pDb = p->pDb;
int i;
+ assert( pDb->pServerShm || bDelete );
for(i=0; i<HMA_MAX_TRANSACTIONID; i++){
ServerJournal *pJ = &pDb->aJrnl[i];
- if( pDb->pServerShm && bDelete ){
+ if( bDelete && (pDb->pServerShm || fdOpen(pJ->jfd)) ){
int rc = serverClientRollback(p, i);
if( rc!=SQLITE_OK ) bDelete = 0;
}
- if( pJ->jfd ){
+ if( fdOpen(pJ->jfd) ){
sqlite3OsClose(pJ->jfd);
if( bDelete ) sqlite3OsDelete(pDb->pVfs, pJ->zJournal, 0);
}
+
sqlite3_free(pJ->zJournal);
}
memset(pDb->aJrnl, 0, sizeof(ServerJournal)*HMA_MAX_TRANSACTIONID);
pDb->bInit = 0;
}
+/*
+** Clear all page locks held by client iClient. The handle passed as the
+** first argument may or may not correspond to client iClient.
+**
+** This function is called in multi-process mode as part of restoring the
+** system state after it has been detected that client iClient may have
+** failed mid transaction. It is never called for a single process system.
+*/
static void serverClientUnlock(Server *p, int iClient){
ServerDb *pDb = p->pDb;
int i;
ServerFcntlArg arg;
arg.h = 0;
arg.p = 0;
- arg.i1 = sizeof(u32)*HMA_PAGELOCK_SLOTS;
+ arg.i1 = sizeof(u32)*(HMA_PAGELOCK_SLOTS + HMA_MAX_TRANSACTIONID);
arg.i2 = 0;
rc = sqlite3OsFileControl(dbfd, SQLITE_FCNTL_SERVER_SHMOPEN, (void*)&arg);
if( rc==SQLITE_OK ){
pDb->aSlot = (u32*)arg.p;
+ pDb->aClient = &pDb->aSlot[HMA_PAGELOCK_SLOTS];
pDb->pServerShm = arg.h;
bRollback = arg.i2;
}
** back any hot journal file in the file-system and release
** page locks held by any crashed process. TODO: The call to
** serverClientUnlock() is expensive. */
- if( rc==SQLITE_OK && pDb->pServerShm ){
+ if( rc==SQLITE_OK && pDb->pServerShm && pDb->aClient[pNew->iTransId] ){
serverClientUnlock(pNew, pNew->iTransId);
rc = serverClientRollback(pNew, pNew->iTransId);
}
assert( p->pNext==0 );
if( pDb->pServerShm ){
p->eTrans = SERVER_TRANS_READWRITE;
+ pDb->aClient[p->iTransId] = 1;
}else{
assert( p->iTransId<0 );
sqlite3_mutex_enter(pDb->mutex);
sqlite3_mutex_leave(pDb->mutex);
p->pNext = 0;
- p->eTrans = SERVER_TRANS_NONE;
p->iTransId = -1;
p->iCommitId = 0;
}
if( p->eTrans!=SERVER_TRANS_NONE ){
if( p->pDb->pServerShm ){
serverReleaseLocks(p);
+ p->pDb->aClient[p->iTransId] = 0;
}else{
serverEndSingle(p);
}
+ p->eTrans = SERVER_TRANS_NONE;
}
return SQLITE_OK;
}