Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Use a blocking call to obtain the wal-mode WRITER lock in some cases. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | server-edition |
Files: | files | file ages | folders |
SHA3-256: |
4464ca1d686b5c457995cc885d4a8704 |
User & Date: | dan 2017-05-10 13:46:29.059 |
Context
2017-05-10
| ||
16:18 | Fix a problem causing a lock to be held past the end of a transaction. Use a blocking lock to take the read-lock on page 1 taken by all transactions. (check-in: 2584df3d42 user: dan tags: server-edition) | |
13:46 | Use a blocking call to obtain the wal-mode WRITER lock in some cases. (check-in: 4464ca1d68 user: dan tags: server-edition) | |
2017-05-09
| ||
16:32 | Fix a problem with wrapping the log file in server mode. (check-in: 270b7d1eac user: dan tags: server-edition) | |
Changes
Changes to src/pager.c.
︙ | ︙ | |||
5684 5685 5686 5687 5688 5689 5690 | Pager *pPager, /* The pager open on the database file */ Pgno pgno, /* Page number to fetch */ DbPage **ppPage, /* Write a pointer to the page here */ int flags /* PAGER_GET_XXX flags */ ){ #ifdef SQLITE_SERVER_EDITION if( pagerIsServer(pPager) ){ | | | 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 | Pager *pPager, /* The pager open on the database file */ Pgno pgno, /* Page number to fetch */ DbPage **ppPage, /* Write a pointer to the page here */ int flags /* PAGER_GET_XXX flags */ ){ #ifdef SQLITE_SERVER_EDITION if( pagerIsServer(pPager) ){ int rc = sqlite3ServerLock(pPager->pServer, pgno, 0, 0); if( rc!=SQLITE_OK ) return rc; } #endif return pPager->xGet(pPager, pgno, ppPage, flags); } /* |
︙ | ︙ | |||
5992 5993 5994 5995 5996 5997 5998 | assert( assert_pager_state(pPager) ); assert( pPager->errCode==0 ); assert( pPager->readOnly==0 ); CHECK_PAGE(pPg); #ifdef SQLITE_SERVER_EDITION if( pagerIsServer(pPager) ){ | | | 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 | assert( assert_pager_state(pPager) ); assert( pPager->errCode==0 ); assert( pPager->readOnly==0 ); CHECK_PAGE(pPg); #ifdef SQLITE_SERVER_EDITION if( pagerIsServer(pPager) ){ rc = sqlite3ServerLock(pPager->pServer, pPg->pgno, 1, 0); if( rc!=SQLITE_OK ) return rc; } #endif /* The journal file needs to be opened. Higher level routines have already ** obtained the necessary locks to begin the write-transaction, but the ** rollback journal might not yet be open. Open it now if this is the case. |
︙ | ︙ | |||
7665 7666 7667 7668 7669 7670 7671 | #endif #ifdef SQLITE_SERVER_EDITION int sqlite3PagerIsServer(Pager *pPager){ return pagerIsServer(pPager); } int sqlite3PagerPagelock(Pager *pPager, Pgno pgno, int bWrite){ | | | 7665 7666 7667 7668 7669 7670 7671 7672 7673 7674 7675 7676 | #endif #ifdef SQLITE_SERVER_EDITION int sqlite3PagerIsServer(Pager *pPager){ return pagerIsServer(pPager); } int sqlite3PagerPagelock(Pager *pPager, Pgno pgno, int bWrite){ return sqlite3ServerLock(pPager->pServer, pgno, bWrite, 0); } #endif #endif /* SQLITE_OMIT_DISKIO */ |
Changes to src/server.c.
︙ | ︙ | |||
352 353 354 355 356 357 358 | sqlite3ServerDisconnect(p, 0); p = 0; } *ppOut = p; return rc; } | | > > > > > > < > | < < < < | | | | | | | > > > > > > > > | | | | > > > | | > | | > > > | | 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 | sqlite3ServerDisconnect(p, 0); p = 0; } *ppOut = p; return rc; } static int serverOvercomeLock( Server *p, /* Server connection */ int bWrite, /* True for a write-lock */ int bBlock, /* If true, block for this lock */ u32 v, /* Value of blocking page locking slot */ int *pbRetry /* OUT: True if caller should retry lock */ ){ int rc = SQLITE_OK; int iBlock = ((int)(v>>HMA_CLIENT_SLOTS))-1; if( iBlock<0 ){ for(iBlock=0; iBlock<HMA_CLIENT_SLOTS; iBlock++){ if( iBlock!=p->iClient && (v & (1<<iBlock)) ) break; } } assert( iBlock<HMA_CLIENT_SLOTS ); serverEnterMutex(); if( 0==p->pHma->aClient[iBlock] ){ rc = posixLock(p->pHma->fd, iBlock+1, SERVER_WRITE_LOCK, 0); if( rc==SQLITE_OK ){ rc = serverRollbackClient(p, iBlock); /* Release the lock on slot iBlock */ posixLock(p->pHma->fd, iBlock+1, SERVER_NO_LOCK, 0); if( rc==SQLITE_OK ){ *pbRetry = 1; } }else if( rc==SQLITE_BUSY ){ if( bBlock ){ rc = posixLock(p->pHma->fd, iBlock+1, SERVER_READ_LOCK, 1); if( rc==SQLITE_OK ){ posixLock(p->pHma->fd, iBlock+1, SERVER_NO_LOCK, 0); *pbRetry = 1; } } if( rc==SQLITE_BUSY ){ rc = SQLITE_OK; } } } serverLeaveMutex(); return rc; } /* ** Begin a transaction. */ int sqlite3ServerBegin(Server *p){ #if 1 int rc = posixLock(p->pHma->fd, p->iClient+1, SERVER_WRITE_LOCK, 1); if( rc ) return rc; #endif return sqlite3ServerLock(p, 1, 0, 0); } /* ** End a transaction (and release all locks). */ int sqlite3ServerEnd(Server *p){ int i; for(i=0; i<p->nLock; i++){ u32 *pSlot = serverPageLockSlot(p, p->aLock[i]); while( 1 ){ u32 v = *pSlot; u32 n = v; if( (v>>HMA_CLIENT_SLOTS)==p->iClient+1 ){ n = n & ((1 << HMA_CLIENT_SLOTS)-1); } n = n & ~(1 << p->iClient); if( __sync_val_compare_and_swap(pSlot, v, n)==v ) break; } } p->nLock = 0; #if 1 return posixLock(p->pHma->fd, p->iClient+1, SERVER_READ_LOCK, 0); #endif return SQLITE_OK; } /* ** Release all write-locks. */ int sqlite3ServerReleaseWriteLocks(Server *p){ int rc = SQLITE_OK; return rc; } /* ** Lock page pgno for reading (bWrite==0) or writing (bWrite==1). ** ** If parameter bBlock is non-zero, then make this a blocking lock if ** possible. */ int sqlite3ServerLock(Server *p, Pgno pgno, int bWrite, int bBlock){ int rc = SQLITE_OK; /* Grow the aLock[] array, if required */ if( p->nLock==p->nAlloc ){ int nNew = p->nAlloc ? p->nAlloc*2 : 128; u32 *aNew; aNew = (u32*)sqlite3_realloc(p->aLock, sizeof(u32)*nNew); |
︙ | ︙ | |||
471 472 473 474 475 476 477 | } while( 1 ){ u32 n; while( (bWrite && (v & ~(1 << p->iClient))) || (v >> HMA_CLIENT_SLOTS) ){ int bRetry = 0; | | | 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 | } while( 1 ){ u32 n; while( (bWrite && (v & ~(1 << p->iClient))) || (v >> HMA_CLIENT_SLOTS) ){ int bRetry = 0; rc = serverOvercomeLock(p, bWrite, bBlock, v, &bRetry); if( rc!=SQLITE_OK ) goto server_lock_out; if( bRetry==0 ){ /* There is a conflicting lock. Cannot obtain this lock. */ sqlite3_log(SQLITE_BUSY_DEADLOCK, "Conflict at page %d", (int)pgno); rc = SQLITE_BUSY_DEADLOCK; goto server_lock_out; } |
︙ | ︙ |
Changes to src/wal.c.
︙ | ︙ | |||
3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 | u32 iFirst = 0; /* First frame that may be overwritten */ WalIndexHdr *pLive; /* Pointer to shared header */ assert( pList ); assert( pWal->writeLock || walIsServer(pWal) ); if( pWal->writeLock==0 ){ int bDummy = 0; rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1); if( rc==SQLITE_OK ){ pWal->writeLock = 1; rc = walIndexTryHdr(pWal, &bDummy); } if( rc!=SQLITE_OK ){ return rc; } | > > > | 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 | u32 iFirst = 0; /* First frame that may be overwritten */ WalIndexHdr *pLive; /* Pointer to shared header */ assert( pList ); assert( pWal->writeLock || walIsServer(pWal) ); if( pWal->writeLock==0 ){ int bDummy = 0; #if 0 rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1); #endif rc = sqlite3ServerLock(pWal->pServer, 0, 1, 1); if( rc==SQLITE_OK ){ pWal->writeLock = 1; rc = walIndexTryHdr(pWal, &bDummy); } if( rc!=SQLITE_OK ){ return rc; } |
︙ | ︙ | |||
3371 3372 3373 3374 3375 3376 3377 | ** ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained ** immediately, and a busy-handler is configured, it is invoked and the ** writer lock retried until either the busy-handler returns 0 or the ** lock is successfully obtained. */ if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){ | > > > | > | 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 | ** ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained ** immediately, and a busy-handler is configured, it is invoked and the ** writer lock retried until either the busy-handler returns 0 or the ** lock is successfully obtained. */ if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){ if( walIsServer(pWal) ){ rc = sqlite3ServerLock(pWal->pServer, 0, 1, 1); }else{ rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_WRITE_LOCK, 1); } if( rc==SQLITE_OK ){ pWal->writeLock = 1; }else if( rc==SQLITE_BUSY ){ eMode2 = SQLITE_CHECKPOINT_PASSIVE; xBusy2 = 0; rc = SQLITE_OK; } |
︙ | ︙ |