Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch server-edition Excluding Merge-Ins
This is equivalent to a diff from b9a58daca8 to 093b9108ea
2017-06-28
| ||
20:21 | Merge tserver fixes with this branch. (check-in: 58a0aab8fd user: dan tags: server-process-edition) | |
20:12 | Fix bugs in test program tserver.c. (Leaf check-in: 093b9108ea user: dan tags: server-edition) | |
2017-06-20
| ||
19:20 | Ensure that test tool "tserver" finalizes all statements before attempting to close a database handle. (check-in: d8568aacf0 user: dan tags: server-edition) | |
2017-05-06
| ||
17:12 | Fix requirements marks and harmless compiler warnings. (check-in: 198ff4c01d user: drh tags: trunk) | |
16:04 | Update this branch with latest trunk changes. (check-in: ed6bad67f5 user: dan tags: server-edition) | |
2017-05-04
| ||
11:13 | Fix a collision of the "B0" identifier name between the termios.h header file and the SHA3 implementation in the shell. (check-in: b9a58daca8 user: drh tags: trunk) | |
2017-05-03
| ||
19:36 | Remove the unused "sqlite3_stack_used" TCL command from the test harness. (check-in: e24b73820c user: drh tags: trunk) | |
Changes to main.mk.
︙ | |||
65 66 67 68 69 70 71 72 73 74 75 76 77 78 | 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | + | icu.o insert.o json1.o legacy.o loadext.o \ main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \ memjournal.o \ mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \ notify.o opcodes.o os.o os_unix.o os_win.o \ pager.o pcache.o pcache1.o pragma.o prepare.o printf.o \ random.o resolve.o rowset.o rtree.o select.o sqlite3rbu.o status.o \ server.o \ table.o threads.o tokenize.o treeview.o trigger.o \ update.o userauth.o util.o vacuum.o \ vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o vdbesort.o \ vdbetrace.o wal.o walker.o where.o wherecode.o whereexpr.o \ utf.o vtab.o LIBOBJ += sqlite3session.o |
︙ | |||
140 141 142 143 144 145 146 147 148 149 150 151 152 153 | 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | + + | $(TOP)/src/pragma.h \ $(TOP)/src/prepare.c \ $(TOP)/src/printf.c \ $(TOP)/src/random.c \ $(TOP)/src/resolve.c \ $(TOP)/src/rowset.c \ $(TOP)/src/select.c \ $(TOP)/src/server.c \ $(TOP)/src/server.h \ $(TOP)/src/status.c \ $(TOP)/src/shell.c \ $(TOP)/src/sqlite.h.in \ $(TOP)/src/sqlite3ext.h \ $(TOP)/src/sqliteInt.h \ $(TOP)/src/sqliteLimit.h \ $(TOP)/src/table.c \ |
︙ |
Changes to src/btree.c.
︙ | |||
5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623 5624 5625 | 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 5850 5851 5852 5853 5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | ){ return btreePrevious(pCur, pRes); } pCur->ix--; return SQLITE_OK; } #ifdef SQLITE_SERVER_EDITION #define SERVER_DEFAULT_FREELISTS 16 #define SERVER_DEFAULT_FREELIST_SIZE 128 /* ** Allocate the free-node and the first SERVER_DEFAULT_FREELISTS ** trunk pages. */ static int allocateServerFreenode(BtShared *pBt){ int rc; MemPage *pPage1 = pBt->pPage1; rc = sqlite3PagerWrite(pPage1->pDbPage); if( rc==SQLITE_OK ){ Pgno pgnoNode = (++pBt->nPage); MemPage *pNode = 0; int i; put4byte(&pPage1->aData[32], pgnoNode); rc = btreeGetUnusedPage(pBt, pgnoNode, &pNode, PAGER_GET_NOCONTENT); if( rc==SQLITE_OK ){ rc = sqlite3PagerWrite(pNode->pDbPage); } if( rc==SQLITE_OK ){ put4byte(&pNode->aData[0], 0); put4byte(&pNode->aData[4], SERVER_DEFAULT_FREELISTS); } for(i=0; rc==SQLITE_OK && i<SERVER_DEFAULT_FREELISTS; i++){ MemPage *pTrunk = 0; Pgno pgnoTrunk; if( ++pBt->nPage==PENDING_BYTE_PAGE(pBt) ) pBt->nPage++; pgnoTrunk = pBt->nPage; rc = btreeGetUnusedPage(pBt, pgnoTrunk, &pTrunk, PAGER_GET_NOCONTENT); if( rc==SQLITE_OK ){ rc = sqlite3PagerWrite(pTrunk->pDbPage); } if( rc==SQLITE_OK ){ memset(pTrunk->aData, 0, 8); put4byte(&pNode->aData[8+i*4], pgnoTrunk); } releasePage(pTrunk); } releasePage(pNode); } return rc; } /* ** Return a reference to the first trunk page in one of the database free-lists. ** Allocate the database free-lists if required. */ static int findServerTrunk(BtShared *pBt, int bAlloc, MemPage **ppTrunk){ MemPage *pPage1 = pBt->pPage1; MemPage *pNode = 0; /* The node page */ MemPage *pTrunk = 0; /* The returned page */ Pgno iNode; /* Page number of node page */ int rc = SQLITE_OK; /* If the node page and free-list trunks have not yet been allocated, allocate ** them now. */ pPage1 = pBt->pPage1; iNode = get4byte(&pPage1->aData[32]); if( iNode==0 ){ rc = allocateServerFreenode(pBt); iNode = get4byte(&pPage1->aData[32]); } /* Grab the node page */ if( rc==SQLITE_OK ){ rc = btreeGetUnusedPage(pBt, iNode, &pNode, 0); } if( rc==SQLITE_OK ){ int nList; /* Number of free-lists in this db */ int i; /* Try to lock a free-list trunk. If bAlloc is true, it has to be a ** free-list trunk with at least one entry in the free-list. */ nList = (int)get4byte(&pNode->aData[4]); for(i=0; i<nList; i++){ Pgno iTrunk = get4byte(&pNode->aData[8+i*4]); if( SQLITE_OK==sqlite3PagerPagelock(pBt->pPager, iTrunk, 1) ){ rc = btreeGetUnusedPage(pBt, iTrunk, &pTrunk, 0); if( rc==SQLITE_OK && bAlloc ){ if( !get4byte(&pTrunk->aData[0]) && !get4byte(&pTrunk->aData[4]) ){ releasePage(pTrunk); pTrunk = 0; } } if( rc!=SQLITE_OK || pTrunk ) break; } } /* No free pages in any free-list. Or perhaps we were locked out. In ** either case, try to allocate more from the end of the file now. */ if( i==nList ){ assert( rc==SQLITE_OK && pTrunk==0 ); rc = sqlite3PagerWrite(pPage1->pDbPage); for(i=0; rc==SQLITE_OK && i<nList; i++){ /* Add some free pages to each free-list. No server-locks are required ** to do this as we have a write-lock on page 1 - guaranteeing ** exclusive access to the db file. */ MemPage *pT = 0; Pgno iTrunk = get4byte(&pNode->aData[8+i*4]); rc = btreeGetUnusedPage(pBt, iTrunk, &pT, 0); if( rc==SQLITE_OK ){ rc = sqlite3PagerWrite(pT->pDbPage); } if( rc==SQLITE_OK ){ int iPg = get4byte(&pT->aData[4]); for(/*no-op*/; iPg<SERVER_DEFAULT_FREELIST_SIZE; iPg++){ if( ++pBt->nPage==PENDING_BYTE_PAGE(pBt) ) pBt->nPage++; put4byte(&pT->aData[8+iPg*4], pBt->nPage); } put4byte(&pT->aData[4], iPg); if( pTrunk==0 ){ pTrunk = pT; pT = 0; } } releasePage(pT); } if( rc==SQLITE_OK ){ MemPage *pLast = 0; rc = btreeGetUnusedPage(pBt, pBt->nPage, &pLast, 0); if( rc==SQLITE_OK ){ rc = sqlite3PagerWrite(pLast->pDbPage); releasePage(pLast); put4byte(28 + (u8*)pPage1->aData, pBt->nPage); } } } } releasePage(pNode); if( rc==SQLITE_OK ){ assert( pTrunk ); rc = sqlite3PagerWrite(pTrunk->pDbPage); } if( rc!=SQLITE_OK ){ releasePage(pTrunk); pTrunk = 0; } *ppTrunk = pTrunk; return rc; } static int allocateServerPage( BtShared *pBt, /* The btree */ MemPage **ppPage, /* Store pointer to the allocated page here */ Pgno *pPgno, /* Store the page number here */ Pgno nearby, /* Search for a page near this one */ u8 eMode /* BTALLOC_EXACT, BTALLOC_LT, or BTALLOC_ANY */ ){ int rc; /* Return code */ MemPage *pTrunk = 0; /* The node page */ Pgno pgnoNew = 0; #ifdef SQLITE_DEBUG int nRef = sqlite3PagerRefcount(pBt->pPager); #endif assert( eMode==BTALLOC_ANY ); assert( sqlite3_mutex_held(pBt->mutex) ); *ppPage = 0; rc = findServerTrunk(pBt, 1, &pTrunk); if( rc==SQLITE_OK ){ int nFree; /* Number of free pages on this trunk page */ nFree = (int)get4byte(&pTrunk->aData[4]); if( nFree==0 ){ pgnoNew = get4byte(&pTrunk->aData[0]); assert( pgnoNew ); }else{ nFree--; pgnoNew = get4byte(&pTrunk->aData[8+4*nFree]); put4byte(&pTrunk->aData[4], (u32)nFree); releasePage(pTrunk); pTrunk = 0; } } if( rc==SQLITE_OK ){ MemPage *pNew = 0; int flags = pTrunk ? 0 : PAGER_GET_NOCONTENT; rc = btreeGetUnusedPage(pBt, pgnoNew, &pNew, flags); if( rc==SQLITE_OK ){ rc = sqlite3PagerWrite(pNew->pDbPage); if( rc!=SQLITE_OK ){ releasePage(pNew); pNew = 0; } } if( rc==SQLITE_OK && pTrunk ){ memcpy(pTrunk->aData, pNew->aData, pBt->usableSize); } *ppPage = pNew; *pPgno = pgnoNew; } releasePage(pTrunk); assert( (rc==SQLITE_OK)==(*ppPage!=0) ); assert( sqlite3PagerRefcount(pBt->pPager)==(nRef+(*ppPage!=0)) ); return rc; } static int freeServerPage2(BtShared *pBt, MemPage *pPage, Pgno iPage){ int rc; /* Return code */ MemPage *pTrunk = 0; /* The node page */ #ifdef SQLITE_DEBUG int nRef = sqlite3PagerRefcount(pBt->pPager); #endif assert( sqlite3_mutex_held(pBt->mutex) ); rc = findServerTrunk(pBt, 0, &pTrunk); if( rc==SQLITE_OK ){ int nFree; /* Number of free pages on this trunk page */ nFree = (int)get4byte(&pTrunk->aData[4]); if( nFree>=((pBt->usableSize / 4) - 2) ){ if( pPage==0 ){ rc = btreeGetUnusedPage(pBt, iPage, &pPage, 0); }else{ sqlite3PagerRef(pPage->pDbPage); } rc = sqlite3PagerWrite(pPage->pDbPage); if( rc==SQLITE_OK ){ memcpy(pPage->aData, pTrunk->aData, pBt->usableSize); put4byte(&pTrunk->aData[0], iPage); put4byte(&pTrunk->aData[4], 0); } releasePage(pPage); }else{ put4byte(&pTrunk->aData[8+nFree*4], iPage); put4byte(&pTrunk->aData[4], (u32)nFree+1); } releasePage(pTrunk); } assert( nRef==sqlite3PagerRefcount(pBt->pPager) ); return rc; } #else # define allocateServerPage(v, w, x, y, z) SQLITE_OK # define freeServerPage2(x, y, z) SQLITE_OK #endif /* SQLITE_SERVER_EDITION */ /* ** Allocate a new page from the database file. ** ** The new page is marked as dirty. (In other words, sqlite3PagerWrite() ** has already been called on the new page.) The new page has also ** been referenced and the calling routine is responsible for calling ** sqlite3PagerUnref() on the new page when it is done. |
︙ | |||
5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 | 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 | + + + + | MemPage *pPage1; int rc; u32 n; /* Number of pages on the freelist */ u32 k; /* Number of leaves on the trunk of the freelist */ MemPage *pTrunk = 0; MemPage *pPrevTrunk = 0; Pgno mxPage; /* Total size of the database file */ if( sqlite3PagerIsServer(pBt->pPager) ){ return allocateServerPage(pBt, ppPage, pPgno, nearby, eMode); } assert( sqlite3_mutex_held(pBt->mutex) ); assert( eMode==BTALLOC_ANY || (nearby>0 && IfNotOmitAV(pBt->autoVacuum)) ); pPage1 = pBt->pPage1; mxPage = btreePagecount(pBt); /* EVIDENCE-OF: R-05119-02637 The 4-byte big-endian integer at offset 36 ** stores stores the total number of pages on the freelist. */ |
︙ | |||
5976 5977 5978 5979 5980 5981 5982 | 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 | - - - - - - + + + + + + + + + + + | if( pMemPage ){ pPage = pMemPage; sqlite3PagerRef(pPage->pDbPage); }else{ pPage = btreePageLookup(pBt, iPage); } |
︙ | |||
9440 9441 9442 9443 9444 9445 9446 9447 9448 9449 9450 9451 9452 9453 | 9698 9699 9700 9701 9702 9703 9704 9705 9706 9707 9708 9709 9710 9711 9712 9713 9714 9715 9716 9717 9718 9719 9720 9721 9722 9723 9724 9725 9726 9727 9728 9729 9730 9731 9732 9733 9734 9735 9736 9737 9738 9739 9740 9741 9742 9743 9744 9745 9746 9747 9748 9749 9750 9751 9752 9753 9754 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | pCheck->v1 = saved_v1; pCheck->v2 = saved_v2; return depth+1; } #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ #ifndef SQLITE_OMIT_INTEGRITY_CHECK #if !defined(SQLITE_OMIT_INTEGRITY_CHECK) && defined(SQLITE_SERVER_EDITION) static void checkServerList(IntegrityCk *pCheck){ u32 pgnoNode = get4byte(&pCheck->pBt->pPage1->aData[32]); if( pgnoNode ){ DbPage *pNode = 0; u8 *aNodeData; u32 nList; /* Number of free-lists */ int i; checkRef(pCheck, pgnoNode); if( sqlite3PagerGet(pCheck->pPager, (Pgno)pgnoNode, &pNode, 0) ){ checkAppendMsg(pCheck, "failed to get node page %d", pgnoNode); return; } aNodeData = sqlite3PagerGetData(pNode); nList = get4byte(&aNodeData[4]); for(i=0; i<nList; i++){ u32 pgnoTrunk = get4byte(&aNodeData[8+4*i]); while( pgnoTrunk ){ DbPage *pTrunk = 0; checkRef(pCheck, pgnoTrunk); if( sqlite3PagerGet(pCheck->pPager, (Pgno)pgnoTrunk, &pTrunk, 0) ){ checkAppendMsg(pCheck, "failed to get page %d", pgnoTrunk); pgnoTrunk = 0; }else{ u8 *aTrunkData = sqlite3PagerGetData(pTrunk); int nLeaf = (int)get4byte(&aTrunkData[4]); int iLeaf; for(iLeaf=0; iLeaf<nLeaf; iLeaf++){ u32 pgnoLeaf = get4byte(&aTrunkData[8+iLeaf*4]); checkRef(pCheck, pgnoLeaf); } pgnoTrunk = get4byte(&aTrunkData[0]); sqlite3PagerUnref(pTrunk); } } } sqlite3PagerUnref(pNode); } } #endif /* ** This routine does a complete check of the given BTree file. aRoot[] is ** an array of pages numbers were each page number is the root page of ** a table. nRoot is the number of entries in aRoot. ** ** A read-only or read-write transaction must be opened before calling ** this function. |
︙ | |||
9505 9506 9507 9508 9509 9510 9511 | 9806 9807 9808 9809 9810 9811 9812 9813 9814 9815 9816 9817 9818 9819 9820 9821 9822 9823 9824 9825 9826 9827 9828 | + + + + + + - - + + + | i = PENDING_BYTE_PAGE(pBt); if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i); /* Check the integrity of the freelist */ sCheck.zPfx = "Main freelist: "; #ifdef SQLITE_SERVER_EDITION if( sqlite3PagerIsServer(pBt->pPager) ){ checkServerList(&sCheck); }else #endif { |
︙ |
Changes to src/pager.c.
︙ | |||
702 703 704 705 706 707 708 709 710 711 712 713 714 715 | 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 | + + + | #endif char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */ PCache *pPCache; /* Pointer to page cache object */ #ifndef SQLITE_OMIT_WAL Wal *pWal; /* Write-ahead log used by "journal_mode=wal" */ char *zWal; /* File name for write-ahead log */ #endif #ifdef SQLITE_SERVER_EDITION Server *pServer; #endif }; /* ** Indexes for use with Pager.aStat[]. The Pager.aStat[] array contains ** the values accessed by passing SQLITE_DBSTATUS_CACHE_HIT, CACHE_MISS ** or CACHE_WRITE to sqlite3_db_status(). */ |
︙ | |||
831 832 833 834 835 836 837 838 839 840 841 842 843 844 | 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 | + + + + + + | #else # define pagerUseWal(x) 0 # define pagerRollbackWal(x) 0 # define pagerWalFrames(v,w,x,y) 0 # define pagerOpenWalIfPresent(z) SQLITE_OK # define pagerBeginReadTransaction(z) SQLITE_OK #endif #ifdef SQLITE_SERVER_EDITION # define pagerIsServer(x) ((x)->pServer!=0) #else # define pagerIsServer(x) 0 #endif #ifndef NDEBUG /* ** Usage: ** ** assert( assert_pager_state(pPager) ); ** |
︙ | |||
1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 | 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 | + | */ static int pagerUnlockDb(Pager *pPager, int eLock){ int rc = SQLITE_OK; assert( !pPager->exclusiveMode || pPager->eLock==eLock ); assert( eLock==NO_LOCK || eLock==SHARED_LOCK ); assert( eLock!=NO_LOCK || pagerUseWal(pPager)==0 ); assert( eLock!=NO_LOCK || pagerIsServer(pPager)==0 ); if( isOpen(pPager->fd) ){ assert( pPager->eLock>=eLock ); rc = pPager->noLock ? SQLITE_OK : sqlite3OsUnlock(pPager->fd, eLock); if( pPager->eLock!=UNKNOWN_LOCK ){ pPager->eLock = (u8)eLock; } IOTRACE(("UNLOCK %p %d\n", pPager, eLock)) |
︙ | |||
1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 | 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 | + + + + + + | || pPager->eState==PAGER_ERROR ); sqlite3BitvecDestroy(pPager->pInJournal); pPager->pInJournal = 0; releaseAllSavepoints(pPager); #ifdef SQLITE_SERVER_EDITION if( pagerIsServer(pPager) ){ sqlite3ServerEnd(pPager->pServer); pPager->eState = PAGER_OPEN; }else #endif if( pagerUseWal(pPager) ){ assert( !isOpen(pPager->jfd) ); sqlite3WalEndReadTransaction(pPager->pWal); pPager->eState = PAGER_OPEN; }else if( !pPager->exclusiveMode ){ int rc; /* Error code returned by pagerUnlockDb() */ int iDc = isOpen(pPager->fd)?sqlite3OsDeviceCharacteristics(pPager->fd):0; |
︙ | |||
2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 | 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 | + + + + + | } if( rc==SQLITE_OK && bCommit && isOpen(pPager->fd) ){ rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_COMMIT_PHASETWO, 0); if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; } #ifdef SQLITE_SERVER_EDITION if( pagerIsServer(pPager) ){ rc2 = sqlite3ServerReleaseWriteLocks(pPager->pServer); }else #endif if( !pPager->exclusiveMode && (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0)) ){ rc2 = pagerUnlockDb(pPager, SHARED_LOCK); pPager->changeCountDone = 0; } pPager->eState = PAGER_READER; |
︙ | |||
4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 | 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 | + + + + + + + + + + + + + + | ** If an error occurs while trying to sync the journal, shift the pager ** into the ERROR state. This causes UnlockAndRollback to unlock the ** database and close the journal file without attempting to roll it ** back or finalize it. The next database user will have to do hot-journal ** rollback before accessing the database file. */ if( isOpen(pPager->jfd) ){ if( pagerIsServer(pPager) ){ assert( pPager->journalMode==PAGER_JOURNALMODE_PERSIST ); pPager->journalMode = PAGER_JOURNALMODE_DELETE; /* If necessary, change the pager state so that the journal file ** is deleted by the call to pagerUnlockAndRollback() below. */ if( pPager->eState==PAGER_OPEN ) pPager->eState = PAGER_READER; } pager_error(pPager, pagerSyncHotJournal(pPager)); } pagerUnlockAndRollback(pPager); } #ifdef SQLITE_SERVER_EDITION if( pagerIsServer(pPager) ){ sqlite3ServerDisconnect(pPager->pServer, pPager->fd); pPager->pServer = 0; sqlite3_free(pPager->zJournal); } #endif sqlite3EndBenignMalloc(); enable_simulated_io_errors(); PAGERTRACE(("CLOSE %d\n", PAGERID(pPager))); IOTRACE(("CLOSE %p\n", pPager)) sqlite3OsClose(pPager->jfd); sqlite3OsClose(pPager->fd); sqlite3PageFree(pTmp); |
︙ | |||
5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 | 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | } } } } return rc; } #ifdef SQLITE_SERVER_EDITION static int pagerServerConnect(Pager *pPager){ int rc = SQLITE_OK; if( pPager->tempFile==0 ){ int iClient = 0; pPager->noLock = 1; pPager->journalMode = PAGER_JOURNALMODE_PERSIST; rc = sqlite3ServerConnect(pPager, &pPager->pServer, &iClient); if( rc==SQLITE_OK ){ pPager->zJournal = sqlite3_mprintf( "%s-journal%d", pPager->zFilename, iClient ); if( pPager->zJournal==0 ){ rc = SQLITE_NOMEM_BKPT; } } } return rc; } int sqlite3PagerRollbackJournal(Pager *pPager, int iClient){ int rc; char *zJrnl = sqlite3_mprintf("%s-journal%d", pPager->zFilename, iClient); if( zJrnl ){ int bExists = 0; sqlite3_file *jfd = 0; sqlite3_vfs * const pVfs = pPager->pVfs; rc = sqlite3OsAccess(pVfs, zJrnl, SQLITE_ACCESS_EXISTS, &bExists); if( rc==SQLITE_OK && bExists ){ int flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL; rc = sqlite3OsOpenMalloc(pVfs, zJrnl, &jfd, flags, &flags); } assert( rc==SQLITE_OK || jfd==0 ); if( jfd ){ sqlite3_file *saved_jfd = pPager->jfd; u8 saved_eState = pPager->eState; u8 saved_eLock = pPager->eLock; i64 saved_journalOff = pPager->journalOff; i64 saved_journalHdr = pPager->journalHdr; char *saved_zJournal = pPager->zJournal; pPager->eLock = EXCLUSIVE_LOCK; pPager->eState = PAGER_WRITER_DBMOD; pPager->jfd = jfd; rc = pagerSyncHotJournal(pPager); if( rc==SQLITE_OK ) rc = pager_playback(pPager, 1); pPager->jfd = saved_jfd; pPager->eState = saved_eState; pPager->eLock = saved_eLock; pPager->journalOff = saved_journalOff; pPager->journalHdr = saved_journalHdr; pPager->zJournal = saved_zJournal; sqlite3OsCloseFree(jfd); if( rc==SQLITE_OK ){ rc = sqlite3OsDelete(pVfs, zJrnl, 0); } } sqlite3_free(zJrnl); }else{ rc = SQLITE_NOMEM_BKPT; } return rc; } #else # define pagerServerConnect(pPager) SQLITE_OK #endif /* ** This function is called to obtain a shared lock on the database file. ** It is illegal to call sqlite3PagerGet() until after this function ** has been successfully called. If a shared-lock is already held when ** this function is called, it is a no-op. ** |
︙ | |||
5086 5087 5088 5089 5090 5091 5092 | 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 | - + + + | ** be OPEN or READER. READER is only possible if the pager is or was in ** exclusive access mode. */ assert( sqlite3PcacheRefCount(pPager->pPCache)==0 ); assert( assert_pager_state(pPager) ); assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER ); assert( pPager->errCode==SQLITE_OK ); |
︙ | |||
5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 | 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 | + + + - + + + + + + + + + - + | ** to be the right size but is not actually valid. Avoid this ** possibility by unmapping the db here. */ if( USEFETCH(pPager) ){ sqlite3OsUnfetch(pPager->fd, 0, 0); } } } rc = pagerServerConnect(pPager); /* If there is a WAL file in the file-system, open this database in WAL ** mode. Otherwise, the following function call is a no-op. */ if( rc==SQLITE_OK ){ |
︙ | |||
5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 | 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 | + + + + + + | */ int sqlite3PagerGet( 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); } /* ** Acquire a page if it is already in the in-memory cache. Do ** not read the page from disk. Return a pointer to the page, ** or 0 if the page is not in cache. |
︙ | |||
5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 | 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 | + + + + + + + | || pPager->eState==PAGER_WRITER_CACHEMOD || pPager->eState==PAGER_WRITER_DBMOD ); 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. ** ** This is done before calling sqlite3PcacheMakeDirty() on the page. ** Otherwise, if it were done after calling sqlite3PcacheMakeDirty(), then |
︙ | |||
6140 6141 6142 6143 6144 6145 6146 | 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 | + + - + + | # define DIRECT_MODE 0 assert( isDirectMode==0 ); UNUSED_PARAMETER(isDirectMode); #else # define DIRECT_MODE isDirectMode #endif if( 0==pagerIsServer(pPager) && !pPager->changeCountDone |
︙ | |||
6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 | 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 | + + + + | assert( isOpen(pPager->fd) || pPager->tempFile ); if( 0==pagerFlushOnCommit(pPager, 1) ){ /* If this is an in-memory db, or no pages have been written to, or this ** function has already been called, it is mostly a no-op. However, any ** backup in progress needs to be restarted. */ sqlite3BackupRestart(pPager->pBackup); }else{ /* If this connection is in server mode, ignore any master journal. */ if( pagerIsServer(pPager) ){ zMaster = 0; } if( pagerUseWal(pPager) ){ PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache); PgHdr *pPageOne = 0; if( pList==0 ){ /* Must have at least one page for the WAL commit flag. ** Ticket [2d1a5c67dfc2363e44f29d9bbd57f] 2011-05-18 */ rc = sqlite3PagerGet(pPager, 1, &pPageOne, 0); |
︙ | |||
7309 7310 7311 7312 7313 7314 7315 | 7451 7452 7453 7454 7455 7456 7457 7458 7459 7460 7461 7462 7463 7464 7465 | - + | /* ** Return true if the underlying VFS for the given pager supports the ** primitives necessary for write-ahead logging. */ int sqlite3PagerWalSupported(Pager *pPager){ const sqlite3_io_methods *pMethods = pPager->fd->pMethods; |
︙ | |||
7404 7405 7406 7407 7408 7409 7410 7411 7412 7413 7414 7415 7416 7417 | 7546 7547 7548 7549 7550 7551 7552 7553 7554 7555 7556 7557 7558 7559 7560 7561 7562 | + + + | /* Close any rollback journal previously open */ sqlite3OsClose(pPager->jfd); rc = pagerOpenWal(pPager); if( rc==SQLITE_OK ){ pPager->journalMode = PAGER_JOURNALMODE_WAL; pPager->eState = PAGER_OPEN; #ifdef SQLITE_SERVER_EDITION sqlite3WalServer(pPager->pWal, pPager->pServer); #endif } }else{ *pbOpen = 1; } return rc; } |
︙ | |||
7516 7517 7518 7519 7520 7521 7522 7523 7524 | 7661 7662 7663 7664 7665 7666 7667 7668 7669 7670 7671 7672 7673 7674 7675 7676 7677 7678 | + + + + + + + + + | ** is empty, return 0. */ int sqlite3PagerWalFramesize(Pager *pPager){ assert( pPager->eState>=PAGER_READER ); return sqlite3WalFramesize(pPager->pWal); } #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/pager.h.
︙ | |||
231 232 233 234 235 236 237 238 239 | 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 | + + + + + + | void sqlite3PagerRefdump(Pager*); void disable_simulated_io_errors(void); void enable_simulated_io_errors(void); #else # define disable_simulated_io_errors() # define enable_simulated_io_errors() #endif #ifdef SQLITE_SERVER_EDITION int sqlite3PagerRollbackJournal(Pager*, int); int sqlite3PagerIsServer(Pager *pPager); int sqlite3PagerPagelock(Pager *pPager, Pgno, int); #endif #endif /* SQLITE_PAGER_H */ |
Added src/server.c.