/ Check-in [09be42d5]
Login

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

Overview
Comment:Begin making experimental changes to use mmap() for reading content from a database. The code compiles, but crashes on the test suite.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | mmap-experimental
Files: files | file ages | folders
SHA1: 09be42d5fa7ef692428579d4d8d48b3316190945
User & Date: drh 2011-11-14 01:55:02
Context
2011-11-14
12:34
Further work on mmap(). Still does not work right - autovacuum tests are the first to fail. Closed-Leaf check-in: 638a39bb user: drh tags: mmap-experimental
01:55
Begin making experimental changes to use mmap() for reading content from a database. The code compiles, but crashes on the test suite. check-in: 09be42d5 user: drh tags: mmap-experimental
2011-11-13
21:44
Add a version number to the sqlite3_pcache_methods2 object. Other PCACHE2 documentation improvements. Closed-Leaf check-in: 9f839ac0 user: drh tags: experimental-pcache
Changes
Hide Diffs Side-by-Side Diffs Show Whitespace Changes Patch

Changes to src/btree.c.

   723    723     if( pCur->eState!=CURSOR_VALID || pCur->skipNext!=0 ){
   724    724       *pHasMoved = 1;
   725    725     }else{
   726    726       *pHasMoved = 0;
   727    727     }
   728    728     return SQLITE_OK;
   729    729   }
          730  +
          731  +/*
          732  +** Make a btree page is writable.
          733  +*/
          734  +static int btreeMakePageWriteable(MemPage *pPage){
          735  +  int rc;
          736  +  if( sqlite3PagerIswriteable(pPage->pDbPage) ) return SQLITE_OK;
          737  +  rc = sqlite3PagerWrite(pPage->pDbPage);
          738  +  pPage->aData = sqlite3PagerGetData(pPage->pDbPage);
          739  +  pPage->aDataEnd = &pPage->aData[pPage->pBt->usableSize];
          740  +  pPage->aCellIdx = &pPage->aData[pPage->cellOffset];
          741  +  return rc;
          742  +}
   730    743   
   731    744   #ifndef SQLITE_OMIT_AUTOVACUUM
   732    745   /*
   733    746   ** Given a page number of a regular database page, return the page
   734    747   ** number for the pointer-map page that contains the entry for the
   735    748   ** input page number.
   736    749   **
................................................................................
  1541   1554   /*
  1542   1555   ** Get a page from the pager.  Initialize the MemPage.pBt and
  1543   1556   ** MemPage.aData elements if needed.
  1544   1557   **
  1545   1558   ** If the noContent flag is set, it means that we do not care about
  1546   1559   ** the content of the page at this time.  So do not go to the disk
  1547   1560   ** to fetch the content.  Just fill in the content with zeros for now.
  1548         -** If in the future we call sqlite3PagerWrite() on this page, that
         1561  +** If in the future we call btreeMakePageWriteable() on this page, that
  1549   1562   ** means we have started to be concerned about content and the disk
  1550   1563   ** read should occur at that point.
  1551   1564   */
  1552   1565   static int btreeGetPage(
  1553   1566     BtShared *pBt,       /* The btree */
  1554   1567     Pgno pgno,           /* Number of the page to fetch */
  1555   1568     MemPage **ppPage,    /* Return the page in this parameter */
................................................................................
  2478   2491   
  2479   2492     assert( sqlite3_mutex_held(pBt->mutex) );
  2480   2493     if( pBt->nPage>0 ){
  2481   2494       return SQLITE_OK;
  2482   2495     }
  2483   2496     pP1 = pBt->pPage1;
  2484   2497     assert( pP1!=0 );
  2485         -  rc = sqlite3PagerWrite(pP1->pDbPage);
         2498  +  rc = btreeMakePageWriteable(pP1);
  2486   2499     if( rc ) return rc;
  2487   2500     data = pP1->aData;
  2488   2501     memcpy(data, zMagicHeader, sizeof(zMagicHeader));
  2489   2502     assert( sizeof(zMagicHeader)==16 );
  2490   2503     data[16] = (u8)((pBt->pageSize>>8)&0xff);
  2491   2504     data[17] = (u8)((pBt->pageSize>>16)&0xff);
  2492   2505     data[18] = 1;
................................................................................
  2651   2664         /* If the db-size header field is incorrect (as it may be if an old
  2652   2665         ** client has been writing the database file), update it now. Doing
  2653   2666         ** this sooner rather than later means the database size can safely 
  2654   2667         ** re-read the database size from page 1 if a savepoint or transaction
  2655   2668         ** rollback occurs within the transaction.
  2656   2669         */
  2657   2670         if( pBt->nPage!=get4byte(&pPage1->aData[28]) ){
  2658         -        rc = sqlite3PagerWrite(pPage1->pDbPage);
         2671  +        rc = btreeMakePageWriteable(pPage1);
  2659   2672           if( rc==SQLITE_OK ){
  2660   2673             put4byte(&pPage1->aData[28], pBt->nPage);
  2661   2674           }
  2662   2675         }
  2663   2676       }
  2664   2677     }
  2665   2678   
................................................................................
  2850   2863     ** iPtrPage.
  2851   2864     */
  2852   2865     if( eType!=PTRMAP_ROOTPAGE ){
  2853   2866       rc = btreeGetPage(pBt, iPtrPage, &pPtrPage, 0);
  2854   2867       if( rc!=SQLITE_OK ){
  2855   2868         return rc;
  2856   2869       }
  2857         -    rc = sqlite3PagerWrite(pPtrPage->pDbPage);
         2870  +    rc = btreeMakePageWriteable(pPtrPage);
  2858   2871       if( rc!=SQLITE_OK ){
  2859   2872         releasePage(pPtrPage);
  2860   2873         return rc;
  2861   2874       }
  2862   2875       rc = modifyPagePointer(pPtrPage, iDbPage, iFreePage, eType);
  2863   2876       releasePage(pPtrPage);
  2864   2877       if( rc==SQLITE_OK ){
................................................................................
  2952   2965             releasePage(pLastPg);
  2953   2966             return rc;
  2954   2967           }
  2955   2968           releasePage(pFreePg);
  2956   2969         }while( nFin!=0 && iFreePg>nFin );
  2957   2970         assert( iFreePg<iLastPg );
  2958   2971         
  2959         -      rc = sqlite3PagerWrite(pLastPg->pDbPage);
         2972  +      rc = btreeMakePageWriteable(pLastPg);
  2960   2973         if( rc==SQLITE_OK ){
  2961   2974           rc = relocatePage(pBt, pLastPg, eType, iPtrPage, iFreePg, nFin!=0);
  2962   2975         }
  2963   2976         releasePage(pLastPg);
  2964   2977         if( rc!=SQLITE_OK ){
  2965   2978           return rc;
  2966   2979         }
................................................................................
  2972   2985       while( iLastPg==PENDING_BYTE_PAGE(pBt)||PTRMAP_ISPAGE(pBt, iLastPg) ){
  2973   2986         if( PTRMAP_ISPAGE(pBt, iLastPg) ){
  2974   2987           MemPage *pPg;
  2975   2988           rc = btreeGetPage(pBt, iLastPg, &pPg, 0);
  2976   2989           if( rc!=SQLITE_OK ){
  2977   2990             return rc;
  2978   2991           }
  2979         -        rc = sqlite3PagerWrite(pPg->pDbPage);
         2992  +        rc = btreeMakePageWriteable(pPg);
  2980   2993           releasePage(pPg);
  2981   2994           if( rc!=SQLITE_OK ){
  2982   2995             return rc;
  2983   2996           }
  2984   2997         }
  2985   2998         iLastPg--;
  2986   2999       }
................................................................................
  3006   3019     assert( pBt->inTransaction==TRANS_WRITE && p->inTrans==TRANS_WRITE );
  3007   3020     if( !pBt->autoVacuum ){
  3008   3021       rc = SQLITE_DONE;
  3009   3022     }else{
  3010   3023       invalidateAllOverflowCache(pBt);
  3011   3024       rc = incrVacuumStep(pBt, 0, btreePagecount(pBt));
  3012   3025       if( rc==SQLITE_OK ){
  3013         -      rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
         3026  +      rc = btreeMakePageWriteable(pBt->pPage1);
  3014   3027         put4byte(&pBt->pPage1->aData[28], pBt->nPage);
  3015   3028       }
  3016   3029     }
  3017   3030     sqlite3BtreeLeave(p);
  3018   3031     return rc;
  3019   3032   }
  3020   3033   
................................................................................
  3064   3077       }
  3065   3078       if( nFin>nOrig ) return SQLITE_CORRUPT_BKPT;
  3066   3079   
  3067   3080       for(iFree=nOrig; iFree>nFin && rc==SQLITE_OK; iFree--){
  3068   3081         rc = incrVacuumStep(pBt, nFin, iFree);
  3069   3082       }
  3070   3083       if( (rc==SQLITE_DONE || rc==SQLITE_OK) && nFree>0 ){
  3071         -      rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
         3084  +      rc = btreeMakePageWriteable(pBt->pPage1);
  3072   3085         put4byte(&pBt->pPage1->aData[32], 0);
  3073   3086         put4byte(&pBt->pPage1->aData[36], 0);
  3074   3087         put4byte(&pBt->pPage1->aData[28], nFin);
  3075   3088         sqlite3PagerTruncateImage(pBt->pPager, nFin);
  3076   3089         pBt->nPage = nFin;
  3077   3090       }
  3078   3091       if( rc!=SQLITE_OK ){
................................................................................
  3844   3857     /* Check if data must be read/written to/from the btree page itself. */
  3845   3858     if( offset<pCur->info.nLocal ){
  3846   3859       int a = amt;
  3847   3860       if( a+offset>pCur->info.nLocal ){
  3848   3861         a = pCur->info.nLocal - offset;
  3849   3862       }
  3850   3863       if( eOp ){
  3851         -      if( (rc = sqlite3PagerWrite(pPage->pDbPage))!=SQLITE_OK ) return rc;
         3864  +      if( (rc = btreeMakePageWriteable(pPage))!=SQLITE_OK ) return rc;
  3852   3865         getCellInfo(pCur);
  3853   3866         aPayload = pCur->info.pCell + pCur->info.nHeader;
  3854   3867         memcpy(aPayload+offset, pBuf, a);
  3855   3868       }else{
  3856   3869         memcpy(pBuf, aPayload+offset, a);
  3857   3870       }
  3858   3871       offset = 0;
................................................................................
  4772   4785     *pRes = 0;
  4773   4786     return rc;
  4774   4787   }
  4775   4788   
  4776   4789   /*
  4777   4790   ** Allocate a new page from the database file.
  4778   4791   **
  4779         -** The new page is marked as dirty.  (In other words, sqlite3PagerWrite()
         4792  +** The new page is marked as dirty.  (In other words, btreeMakePageWriteable()
  4780   4793   ** has already been called on the new page.)  The new page has also
  4781   4794   ** been referenced and the calling routine is responsible for calling
  4782   4795   ** sqlite3PagerUnref() on the new page when it is done.
  4783   4796   **
  4784   4797   ** SQLITE_OK is returned on success.  Any other return value indicates
  4785   4798   ** an error.  *ppPage and *pPgno are undefined in the event of an error.
  4786   4799   ** Do not invoke sqlite3PagerUnref() on *ppPage if an error is returned.
................................................................................
  4839   4852         *pPgno = nearby;
  4840   4853       }
  4841   4854   #endif
  4842   4855   
  4843   4856       /* Decrement the free-list count by 1. Set iTrunk to the index of the
  4844   4857       ** first free-list trunk page. iPrevTrunk is initially 1.
  4845   4858       */
  4846         -    rc = sqlite3PagerWrite(pPage1->pDbPage);
         4859  +    rc = btreeMakePageWriteable(pPage1);
  4847   4860       if( rc ) return rc;
  4848   4861       put4byte(&pPage1->aData[36], n-1);
  4849   4862   
  4850   4863       /* The code within this loop is run only once if the 'searchList' variable
  4851   4864       ** is not true. Otherwise, it runs once for each trunk-page on the
  4852   4865       ** free-list until the page 'nearby' is located.
  4853   4866       */
................................................................................
  4873   4886   
  4874   4887         k = get4byte(&pTrunk->aData[4]); /* # of leaves on this trunk page */
  4875   4888         if( k==0 && !searchList ){
  4876   4889           /* The trunk has no leaves and the list is not being searched. 
  4877   4890           ** So extract the trunk page itself and use it as the newly 
  4878   4891           ** allocated page */
  4879   4892           assert( pPrevTrunk==0 );
  4880         -        rc = sqlite3PagerWrite(pTrunk->pDbPage);
         4893  +        rc = btreeMakePageWriteable(pTrunk);
  4881   4894           if( rc ){
  4882   4895             goto end_allocate_page;
  4883   4896           }
  4884   4897           *pPgno = iTrunk;
  4885   4898           memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4);
  4886   4899           *ppPage = pTrunk;
  4887   4900           pTrunk = 0;
................................................................................
  4894   4907         }else if( searchList && nearby==iTrunk ){
  4895   4908           /* The list is being searched and this trunk page is the page
  4896   4909           ** to allocate, regardless of whether it has leaves.
  4897   4910           */
  4898   4911           assert( *pPgno==iTrunk );
  4899   4912           *ppPage = pTrunk;
  4900   4913           searchList = 0;
  4901         -        rc = sqlite3PagerWrite(pTrunk->pDbPage);
         4914  +        rc = btreeMakePageWriteable(pTrunk);
  4902   4915           if( rc ){
  4903   4916             goto end_allocate_page;
  4904   4917           }
  4905   4918           if( k==0 ){
  4906   4919             if( !pPrevTrunk ){
  4907   4920               memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4);
  4908   4921             }else{
  4909         -            rc = sqlite3PagerWrite(pPrevTrunk->pDbPage);
         4922  +            rc = btreeMakePageWriteable(pPrevTrunk);
  4910   4923               if( rc!=SQLITE_OK ){
  4911   4924                 goto end_allocate_page;
  4912   4925               }
  4913   4926               memcpy(&pPrevTrunk->aData[0], &pTrunk->aData[0], 4);
  4914   4927             }
  4915   4928           }else{
  4916   4929             /* The trunk page is required by the caller but it contains 
................................................................................
  4924   4937               goto end_allocate_page;
  4925   4938             }
  4926   4939             testcase( iNewTrunk==mxPage );
  4927   4940             rc = btreeGetPage(pBt, iNewTrunk, &pNewTrunk, 0);
  4928   4941             if( rc!=SQLITE_OK ){
  4929   4942               goto end_allocate_page;
  4930   4943             }
  4931         -          rc = sqlite3PagerWrite(pNewTrunk->pDbPage);
         4944  +          rc = btreeMakePageWriteable(pNewTrunk);
  4932   4945             if( rc!=SQLITE_OK ){
  4933   4946               releasePage(pNewTrunk);
  4934   4947               goto end_allocate_page;
  4935   4948             }
  4936   4949             memcpy(&pNewTrunk->aData[0], &pTrunk->aData[0], 4);
  4937   4950             put4byte(&pNewTrunk->aData[4], k-1);
  4938   4951             memcpy(&pNewTrunk->aData[8], &pTrunk->aData[12], (k-1)*4);
  4939   4952             releasePage(pNewTrunk);
  4940   4953             if( !pPrevTrunk ){
  4941   4954               assert( sqlite3PagerIswriteable(pPage1->pDbPage) );
  4942   4955               put4byte(&pPage1->aData[32], iNewTrunk);
  4943   4956             }else{
  4944         -            rc = sqlite3PagerWrite(pPrevTrunk->pDbPage);
         4957  +            rc = btreeMakePageWriteable(pPrevTrunk);
  4945   4958               if( rc ){
  4946   4959                 goto end_allocate_page;
  4947   4960               }
  4948   4961               put4byte(&pPrevTrunk->aData[0], iNewTrunk);
  4949   4962             }
  4950   4963           }
  4951   4964           pTrunk = 0;
................................................................................
  4981   4994           testcase( iPage==mxPage );
  4982   4995           if( !searchList || iPage==nearby ){
  4983   4996             int noContent;
  4984   4997             *pPgno = iPage;
  4985   4998             TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d"
  4986   4999                    ": %d more free pages\n",
  4987   5000                    *pPgno, closest+1, k, pTrunk->pgno, n-1));
  4988         -          rc = sqlite3PagerWrite(pTrunk->pDbPage);
         5001  +          rc = btreeMakePageWriteable(pTrunk);
  4989   5002             if( rc ) goto end_allocate_page;
  4990   5003             if( closest<k-1 ){
  4991   5004               memcpy(&aData[8+closest*4], &aData[4+k*4], 4);
  4992   5005             }
  4993   5006             put4byte(&aData[4], k-1);
  4994   5007             noContent = !btreeGetHasContent(pBt, *pPgno);
  4995   5008             rc = btreeGetPage(pBt, *pPgno, ppPage, noContent);
  4996   5009             if( rc==SQLITE_OK ){
  4997         -            rc = sqlite3PagerWrite((*ppPage)->pDbPage);
         5010  +            rc = btreeMakePageWriteable(*ppPage);
  4998   5011               if( rc!=SQLITE_OK ){
  4999   5012                 releasePage(*ppPage);
  5000   5013               }
  5001   5014             }
  5002   5015             searchList = 0;
  5003   5016           }
  5004   5017         }
  5005   5018         releasePage(pPrevTrunk);
  5006   5019         pPrevTrunk = 0;
  5007   5020       }while( searchList );
  5008   5021     }else{
  5009   5022       /* There are no pages on the freelist, so create a new page at the
  5010   5023       ** end of the file */
  5011         -    rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
         5024  +    rc = btreeMakePageWriteable(pBt->pPage1);
  5012   5025       if( rc ) return rc;
  5013   5026       pBt->nPage++;
  5014   5027       if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ) pBt->nPage++;
  5015   5028   
  5016   5029   #ifndef SQLITE_OMIT_AUTOVACUUM
  5017   5030       if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt, pBt->nPage) ){
  5018   5031         /* If *pPgno refers to a pointer-map page, allocate two new pages
................................................................................
  5020   5033         ** becomes a new pointer-map page, the second is used by the caller.
  5021   5034         */
  5022   5035         MemPage *pPg = 0;
  5023   5036         TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", pBt->nPage));
  5024   5037         assert( pBt->nPage!=PENDING_BYTE_PAGE(pBt) );
  5025   5038         rc = btreeGetPage(pBt, pBt->nPage, &pPg, 1);
  5026   5039         if( rc==SQLITE_OK ){
  5027         -        rc = sqlite3PagerWrite(pPg->pDbPage);
         5040  +        rc = btreeMakePageWriteable(pPg);
  5028   5041           releasePage(pPg);
  5029   5042         }
  5030   5043         if( rc ) return rc;
  5031   5044         pBt->nPage++;
  5032   5045         if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ){ pBt->nPage++; }
  5033   5046       }
  5034   5047   #endif
  5035   5048       put4byte(28 + (u8*)pBt->pPage1->aData, pBt->nPage);
  5036   5049       *pPgno = pBt->nPage;
  5037   5050   
  5038   5051       assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
  5039   5052       rc = btreeGetPage(pBt, *pPgno, ppPage, 1);
  5040   5053       if( rc ) return rc;
  5041         -    rc = sqlite3PagerWrite((*ppPage)->pDbPage);
         5054  +    rc = btreeMakePageWriteable(*ppPage);
  5042   5055       if( rc!=SQLITE_OK ){
  5043   5056         releasePage(*ppPage);
  5044   5057       }
  5045   5058       TRACE(("ALLOCATE: %d from end of file\n", *pPgno));
  5046   5059     }
  5047   5060   
  5048   5061     assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
................................................................................
  5091   5104       pPage = pMemPage;
  5092   5105       sqlite3PagerRef(pPage->pDbPage);
  5093   5106     }else{
  5094   5107       pPage = btreePageLookup(pBt, iPage);
  5095   5108     }
  5096   5109   
  5097   5110     /* Increment the free page count on pPage1 */
  5098         -  rc = sqlite3PagerWrite(pPage1->pDbPage);
         5111  +  rc = btreeMakePageWriteable(pPage1);
  5099   5112     if( rc ) goto freepage_out;
  5100   5113     nFree = get4byte(&pPage1->aData[36]);
  5101   5114     put4byte(&pPage1->aData[36], nFree+1);
  5102   5115   
  5103   5116     if( pBt->secureDelete ){
  5104   5117       /* If the secure_delete option is enabled, then
  5105   5118       ** always fully overwrite deleted information with zeros.
  5106   5119       */
  5107   5120       if( (!pPage && ((rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0) )
  5108         -     ||            ((rc = sqlite3PagerWrite(pPage->pDbPage))!=0)
         5121  +     ||            ((rc = btreeMakePageWriteable(pPage))!=0)
  5109   5122       ){
  5110   5123         goto freepage_out;
  5111   5124       }
  5112   5125       memset(pPage->aData, 0, pPage->pBt->pageSize);
  5113   5126     }
  5114   5127   
  5115   5128     /* If the database supports auto-vacuum, write an entry in the pointer-map
................................................................................
  5153   5166         ** usableSize/4 - 8 entries will be reported as corrupt.  In order
  5154   5167         ** to maintain backwards compatibility with older versions of SQLite,
  5155   5168         ** we will continue to restrict the number of entries to usableSize/4 - 8
  5156   5169         ** for now.  At some point in the future (once everyone has upgraded
  5157   5170         ** to 3.6.0 or later) we should consider fixing the conditional above
  5158   5171         ** to read "usableSize/4-2" instead of "usableSize/4-8".
  5159   5172         */
  5160         -      rc = sqlite3PagerWrite(pTrunk->pDbPage);
         5173  +      rc = btreeMakePageWriteable(pTrunk);
  5161   5174         if( rc==SQLITE_OK ){
  5162   5175           put4byte(&pTrunk->aData[4], nLeaf+1);
  5163   5176           put4byte(&pTrunk->aData[8+nLeaf*4], iPage);
  5164   5177           if( pPage && !pBt->secureDelete ){
  5165   5178             sqlite3PagerDontWrite(pPage->pDbPage);
  5166   5179           }
  5167   5180           rc = btreeSetHasContent(pBt, iPage);
................................................................................
  5176   5189     ** Possibly because the free-list is empty, or possibly because the 
  5177   5190     ** first trunk in the free-list is full. Either way, the page being freed
  5178   5191     ** will become the new first trunk page in the free-list.
  5179   5192     */
  5180   5193     if( pPage==0 && SQLITE_OK!=(rc = btreeGetPage(pBt, iPage, &pPage, 0)) ){
  5181   5194       goto freepage_out;
  5182   5195     }
  5183         -  rc = sqlite3PagerWrite(pPage->pDbPage);
         5196  +  rc = btreeMakePageWriteable(pPage);
  5184   5197     if( rc!=SQLITE_OK ){
  5185   5198       goto freepage_out;
  5186   5199     }
  5187   5200     put4byte(pPage->aData, iTrunk);
  5188   5201     put4byte(&pPage->aData[4], 0);
  5189   5202     put4byte(&pPage1->aData[32], iPage);
  5190   5203     TRACE(("FREE-PAGE: %d new trunk page replacing %d\n", pPage->pgno, iTrunk));
................................................................................
  5536   5549         put4byte(pCell, iChild);
  5537   5550       }
  5538   5551       j = pPage->nOverflow++;
  5539   5552       assert( j<(int)(sizeof(pPage->aOvfl)/sizeof(pPage->aOvfl[0])) );
  5540   5553       pPage->aOvfl[j].pCell = pCell;
  5541   5554       pPage->aOvfl[j].idx = (u16)i;
  5542   5555     }else{
  5543         -    int rc = sqlite3PagerWrite(pPage->pDbPage);
         5556  +    int rc = btreeMakePageWriteable(pPage);
  5544   5557       if( rc!=SQLITE_OK ){
  5545   5558         *pRC = rc;
  5546   5559         return;
  5547   5560       }
  5548   5561       assert( sqlite3PagerIswriteable(pPage->pDbPage) );
  5549   5562       data = pPage->aData;
  5550   5563       cellOffset = pPage->cellOffset;
................................................................................
  6205   6218     }
  6206   6219     pageFlags = apOld[0]->aData[0];
  6207   6220     for(i=0; i<k; i++){
  6208   6221       MemPage *pNew;
  6209   6222       if( i<nOld ){
  6210   6223         pNew = apNew[i] = apOld[i];
  6211   6224         apOld[i] = 0;
  6212         -      rc = sqlite3PagerWrite(pNew->pDbPage);
         6225  +      rc = btreeMakePageWriteable(pNew);
  6213   6226         nNew++;
  6214   6227         if( rc ) goto balance_cleanup;
  6215   6228       }else{
  6216   6229         assert( i>0 );
  6217   6230         rc = allocateBtreePage(pBt, &pNew, &pgno, pgno, 0);
  6218   6231         if( rc ) goto balance_cleanup;
  6219   6232         apNew[i] = pNew;
................................................................................
  6534   6547     assert( pRoot->nOverflow>0 );
  6535   6548     assert( sqlite3_mutex_held(pBt->mutex) );
  6536   6549   
  6537   6550     /* Make pRoot, the root page of the b-tree, writable. Allocate a new 
  6538   6551     ** page that will become the new right-child of pPage. Copy the contents
  6539   6552     ** of the node stored on pRoot into the new child page.
  6540   6553     */
  6541         -  rc = sqlite3PagerWrite(pRoot->pDbPage);
         6554  +  rc = btreeMakePageWriteable(pRoot);
  6542   6555     if( rc==SQLITE_OK ){
  6543   6556       rc = allocateBtreePage(pBt,&pChild,&pgnoChild,pRoot->pgno,0);
  6544   6557       copyNodeContent(pRoot, pChild, &rc);
  6545   6558       if( ISAUTOVACUUM ){
  6546   6559         ptrmapPut(pBt, pgnoChild, PTRMAP_BTREE, pRoot->pgno, &rc);
  6547   6560       }
  6548   6561     }
................................................................................
  6612   6625         }
  6613   6626       }else if( pPage->nOverflow==0 && pPage->nFree<=nMin ){
  6614   6627         break;
  6615   6628       }else{
  6616   6629         MemPage * const pParent = pCur->apPage[iPage-1];
  6617   6630         int const iIdx = pCur->aiIdx[iPage-1];
  6618   6631   
  6619         -      rc = sqlite3PagerWrite(pParent->pDbPage);
         6632  +      rc = btreeMakePageWriteable(pParent);
  6620   6633         if( rc==SQLITE_OK ){
  6621   6634   #ifndef SQLITE_OMIT_QUICKBALANCE
  6622   6635           if( pPage->hasData
  6623   6636            && pPage->nOverflow==1
  6624   6637            && pPage->aOvfl[0].idx==pPage->nCell
  6625   6638            && pParent->pgno!=1
  6626   6639            && pParent->nCell==iIdx
................................................................................
  6789   6802     if( rc ) goto end_insert;
  6790   6803     assert( szNew==cellSizePtr(pPage, newCell) );
  6791   6804     assert( szNew <= MX_CELL_SIZE(pBt) );
  6792   6805     idx = pCur->aiIdx[pCur->iPage];
  6793   6806     if( loc==0 ){
  6794   6807       u16 szOld;
  6795   6808       assert( idx<pPage->nCell );
  6796         -    rc = sqlite3PagerWrite(pPage->pDbPage);
         6809  +    rc = btreeMakePageWriteable(pPage);
  6797   6810       if( rc ){
  6798   6811         goto end_insert;
  6799   6812       }
  6800   6813       oldCell = findCell(pPage, idx);
  6801   6814       if( !pPage->leaf ){
  6802   6815         memcpy(newCell, oldCell, 4);
  6803   6816       }
................................................................................
  6905   6918     /* Save the positions of any other cursors open on this table before
  6906   6919     ** making any modifications. Make the page containing the entry to be 
  6907   6920     ** deleted writable. Then free any overflow pages associated with the 
  6908   6921     ** entry and finally remove the cell itself from within the page.  
  6909   6922     */
  6910   6923     rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
  6911   6924     if( rc ) return rc;
  6912         -  rc = sqlite3PagerWrite(pPage->pDbPage);
         6925  +  rc = btreeMakePageWriteable(pPage);
  6913   6926     if( rc ) return rc;
  6914   6927     rc = clearCell(pPage, pCell);
  6915   6928     dropCell(pPage, iCellIdx, cellSizePtr(pPage, pCell), &rc);
  6916   6929     if( rc ) return rc;
  6917   6930   
  6918   6931     /* If the cell deleted was not located on a leaf page, then the cursor
  6919   6932     ** is currently pointing to the largest entry in the sub-tree headed
................................................................................
  6929   6942       pCell = findCell(pLeaf, pLeaf->nCell-1);
  6930   6943       nCell = cellSizePtr(pLeaf, pCell);
  6931   6944       assert( MX_CELL_SIZE(pBt) >= nCell );
  6932   6945   
  6933   6946       allocateTempSpace(pBt);
  6934   6947       pTmp = pBt->pTmpSpace;
  6935   6948   
  6936         -    rc = sqlite3PagerWrite(pLeaf->pDbPage);
         6949  +    rc = btreeMakePageWriteable(pLeaf);
  6937   6950       insertCell(pPage, iCellIdx, pCell-4, nCell+4, pTmp, n, &rc);
  6938   6951       dropCell(pLeaf, pLeaf->nCell-1, nCell, &rc);
  6939   6952       if( rc ) return rc;
  6940   6953     }
  6941   6954   
  6942   6955     /* Balance the tree. If the entry deleted was located on a leaf page,
  6943   6956     ** then the cursor still points to that page. In this case the first
................................................................................
  7066   7079         if( rc!=SQLITE_OK ){
  7067   7080           return rc;
  7068   7081         }
  7069   7082         rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0);
  7070   7083         if( rc!=SQLITE_OK ){
  7071   7084           return rc;
  7072   7085         }
  7073         -      rc = sqlite3PagerWrite(pRoot->pDbPage);
         7086  +      rc = btreeMakePageWriteable(pRoot);
  7074   7087         if( rc!=SQLITE_OK ){
  7075   7088           releasePage(pRoot);
  7076   7089           return rc;
  7077   7090         }
  7078   7091       }else{
  7079   7092         pRoot = pPageMove;
  7080   7093       } 
................................................................................
  7158   7171       if( rc ) goto cleardatabasepage_out;
  7159   7172     }else if( pnChange ){
  7160   7173       assert( pPage->intKey );
  7161   7174       *pnChange += pPage->nCell;
  7162   7175     }
  7163   7176     if( freePageFlag ){
  7164   7177       freePage(pPage, &rc);
  7165         -  }else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){
         7178  +  }else if( (rc = btreeMakePageWriteable(pPage))==0 ){
  7166   7179       zeroPage(pPage, pPage->aData[0] | PTF_LEAF);
  7167   7180     }
  7168   7181   
  7169   7182   cleardatabasepage_out:
  7170   7183     releasePage(pPage);
  7171   7184     return rc;
  7172   7185   }
................................................................................
  7375   7388   int sqlite3BtreeUpdateMeta(Btree *p, int idx, u32 iMeta){
  7376   7389     BtShared *pBt = p->pBt;
  7377   7390     int rc;
  7378   7391     assert( idx>=1 && idx<=15 );
  7379   7392     sqlite3BtreeEnter(p);
  7380   7393     assert( p->inTrans==TRANS_WRITE );
  7381   7394     assert( pBt->pPage1!=0 );
  7382         -  rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
         7395  +  rc = btreeMakePageWriteable(pBt->pPage1);
  7383   7396     if( rc==SQLITE_OK ){
  7384   7397       put4byte(&pBt->pPage1->aData[36 + idx*4], iMeta);
  7385   7398   #ifndef SQLITE_OMIT_AUTOVACUUM
  7386   7399       if( idx==BTREE_INCR_VACUUM ){
  7387   7400         assert( pBt->autoVacuum || iMeta==0 );
  7388   7401         assert( iMeta==0 || iMeta==1 );
  7389   7402         pBt->incrVacuum = (u8)iMeta;
................................................................................
  8204   8217   
  8205   8218     rc = sqlite3BtreeBeginTrans(pBtree, 0);
  8206   8219     if( rc==SQLITE_OK ){
  8207   8220       u8 *aData = pBt->pPage1->aData;
  8208   8221       if( aData[18]!=(u8)iVersion || aData[19]!=(u8)iVersion ){
  8209   8222         rc = sqlite3BtreeBeginTrans(pBtree, 2);
  8210   8223         if( rc==SQLITE_OK ){
  8211         -        rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
         8224  +        rc = btreeMakePageWriteable(pBt->pPage1);
  8212   8225           if( rc==SQLITE_OK ){
  8213   8226             aData = pBt->pPage1->aData;
  8214   8227             aData[18] = (u8)iVersion;
  8215   8228             aData[19] = (u8)iVersion;
  8216   8229           }
  8217   8230         }
  8218   8231       }
  8219   8232     }
  8220   8233   
  8221   8234     pBt->doNotUseWAL = 0;
  8222   8235     return rc;
  8223   8236   }

Changes to src/os.c.

   194    194     }else{
   195    195       double r;
   196    196       rc = pVfs->xCurrentTime(pVfs, &r);
   197    197       *pTimeOut = (sqlite3_int64)(r*86400000.0);
   198    198     }
   199    199     return rc;
   200    200   }
          201  +
          202  +/* Attempt to map all or part of a file into memory.  VFSes are not
          203  +** required to implement this.  The VFS might be an older version (less then
          204  +** 3) that does not have an xMap pointer.  Or the xMap pointer might be NULL.
          205  +*/
          206  +int sqlite3OsMap(
          207  +  sqlite3_file *pFile,    /* The file to be mapped into memory */
          208  +  sqlite3_int64 ofst,     /* Index of the first byte to map */
          209  +  sqlite3_int64 len,      /* Number of bytes to be mapped */
          210  +  int mmapFlags,          /* Map control flags */
          211  +  void **ppMemObj,        /* Write a mapping object here */
          212  +  void **ppMem            /* Write the start of the mapped file here */
          213  +){
          214  +  int rc;
          215  +
          216  +  /* The current implementation only does read-only mmap.  This could change
          217  +  ** in the future. */
          218  +  assert( mmapFlags==SQLITE_OPEN_READONLY );
          219  +
          220  +  /* The current implementation currently only maps the whole file.  This
          221  +  ** could change in the future. */
          222  +  assert( ofst==0 );
          223  +
          224  +  if( pFile->pMethods==0 || pFile->pMethods->iVersion<3
          225  +     || pFile->pMethods->xMap==0 ){
          226  +    *ppMemObj = 0;
          227  +    *ppMem = 0;
          228  +    rc = SQLITE_CANTOPEN;
          229  +  }else{
          230  +    rc = pFile->pMethods->xMap(pFile, ofst, len, mmapFlags, ppMemObj, ppMem);
          231  +  }
          232  +  return rc;
          233  +}
          234  +
          235  +/* Undo a mapping.
          236  +**
          237  +** The pMemObj parameter will have been obtained by a prior call to
          238  +** sqlite3OsMap().  So if pMemObj is not NULL, we know that the current
          239  +** VFS does support xMap and xUnmap.
          240  +*/
          241  +int sqlite3OsUnmap(sqlite3_file *pFile, void *pMemObj){
          242  +  int rc = SQLITE_OK;
          243  +  if( pMemObj ) rc = pFile->pMethods->xUnmap(pFile, pMemObj);
          244  +  return rc;
          245  +}
          246  +
   201    247   
   202    248   int sqlite3OsOpenMalloc(
   203    249     sqlite3_vfs *pVfs, 
   204    250     const char *zFile, 
   205    251     sqlite3_file **ppFile, 
   206    252     int flags,
   207    253     int *pOutFlags

Changes to src/os.h.

   247    247   #define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0
   248    248   int sqlite3OsSectorSize(sqlite3_file *id);
   249    249   int sqlite3OsDeviceCharacteristics(sqlite3_file *id);
   250    250   int sqlite3OsShmMap(sqlite3_file *,int,int,int,void volatile **);
   251    251   int sqlite3OsShmLock(sqlite3_file *id, int, int, int);
   252    252   void sqlite3OsShmBarrier(sqlite3_file *id);
   253    253   int sqlite3OsShmUnmap(sqlite3_file *id, int);
          254  +int sqlite3OsMap(sqlite3_file*,sqlite3_int64,sqlite3_int64,int,void**,void**);
          255  +int sqlite3OsUnmap(sqlite3_file*,void*);
   254    256   
   255    257   /* 
   256    258   ** Functions for accessing sqlite3_vfs methods 
   257    259   */
   258    260   int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *);
   259    261   int sqlite3OsDelete(sqlite3_vfs *, const char *, int);
   260    262   int sqlite3OsAccess(sqlite3_vfs *, const char *, int, int *pResOut);

Changes to src/os_unix.c.

   115    115   #include <sys/types.h>
   116    116   #include <sys/stat.h>
   117    117   #include <fcntl.h>
   118    118   #include <unistd.h>
   119    119   #include <time.h>
   120    120   #include <sys/time.h>
   121    121   #include <errno.h>
   122         -#ifndef SQLITE_OMIT_WAL
   123    122   #include <sys/mman.h>
   124         -#endif
   125    123   
   126    124   #if SQLITE_ENABLE_LOCKING_STYLE
   127    125   # include <sys/ioctl.h>
   128    126   # if OS_VXWORKS
   129    127   #  include <semaphore.h>
   130    128   #  include <limits.h>
   131    129   # else
................................................................................
   408    406   #define osOpenDirectory ((int(*)(const char*,int*))aSyscall[17].pCurrent)
   409    407   
   410    408     { "mkdir",        (sqlite3_syscall_ptr)mkdir,           0 },
   411    409   #define osMkdir     ((int(*)(const char*,mode_t))aSyscall[18].pCurrent)
   412    410   
   413    411     { "rmdir",        (sqlite3_syscall_ptr)rmdir,           0 },
   414    412   #define osRmdir     ((int(*)(const char*))aSyscall[19].pCurrent)
          413  +
          414  +  { "mmap",         (sqlite3_syscall_ptr)mmap,            0 },
          415  +#define osMmap  ((int(*)(void*,size_t,int,int,int,off_t))aSyscall[20].pCurrent)
          416  +
          417  +  { "munmap",       (sqlite3_syscall_ptr)munmap,          0 },
          418  +#define osMunmap    ((int(*)(void*,size_t))aSyscall[21].pCurrent)
          419  +
          420  +
   415    421   
   416    422   }; /* End of the overrideable system calls */
   417    423   
   418    424   /*
   419    425   ** This is the xSetSystemCall() method of sqlite3_vfs for all of the
   420    426   ** "unix" VFSes.  Return SQLITE_OK opon successfully updating the
   421    427   ** system call pointer, or SQLITE_NOTFOUND if there is no configurable
................................................................................
  4224   4230   
  4225   4231   #else
  4226   4232   # define unixShmMap     0
  4227   4233   # define unixShmLock    0
  4228   4234   # define unixShmBarrier 0
  4229   4235   # define unixShmUnmap   0
  4230   4236   #endif /* #ifndef SQLITE_OMIT_WAL */
         4237  +
         4238  +/*
         4239  +** An object used to record enough information about a file mapping to
         4240  +** undo that mapping.
         4241  +*/
         4242  +struct unixMapping {
         4243  +  sqlite3_int64 len;
         4244  +  void *p;
         4245  +};
         4246  +
         4247  +/*
         4248  +** Try to map some or all of a file into memory
         4249  +*/
         4250  +static int unixMap(
         4251  +  sqlite3_file *pFile,   /* File to be mapped */
         4252  +  sqlite3_int64 ofst,    /* Offset of start of section to be mapped */
         4253  +  sqlite3_int64 len,     /* Length of the section to be mapped */
         4254  +  int mmapFlags,         /* Flags controlling the mapping */
         4255  +  void **ppMapObj,       /* Write here an object to undo the mapping */
         4256  +  void **ppMem           /* Write here a pointer to the mapped file */
         4257  +){
         4258  +  struct unixMapping *pNew;
         4259  +  unixFile *pUFile = (unixFile*)pFile;
         4260  +
         4261  +  assert( mmapFlags==SQLITE_OPEN_READONLY );
         4262  +  sqlite3BeginBenignMalloc();
         4263  +  pNew = sqlite3_malloc( sizeof(*pNew) );
         4264  +  sqlite3EndBenignMalloc();
         4265  +  if( pNew==0 ){
         4266  +    *ppMapObj = 0;
         4267  +    *ppMem = 0;
         4268  +    return SQLITE_CANTOPEN;
         4269  +  }
         4270  +  pNew->len = len;
         4271  +  pNew->p = *ppMem = mmap(0, len, PROT_READ, MAP_SHARED, pUFile->h, 0);
         4272  +  if( pNew->p==0 ){
         4273  +    sqlite3_free(pNew);
         4274  +    return SQLITE_CANTOPEN;
         4275  +  }else{
         4276  +    *ppMapObj = pNew;
         4277  +    return SQLITE_OK;
         4278  +  }
         4279  +}
         4280  +
         4281  +/*
         4282  +** Undo a prior memory mapping.
         4283  +*/
         4284  +static int unixUnmap(
         4285  +  sqlite3_file *pFile,
         4286  +  void *pMapObj
         4287  +){
         4288  +  struct unixMapping *pMap = (struct unixMapping*)pMapObj;
         4289  +  assert( pMap!=0 );
         4290  +  munmap(pMap->p, pMap->len);
         4291  +  sqlite3_free(pMap);
         4292  +  return SQLITE_OK;
         4293  +}
  4231   4294   
  4232   4295   /*
  4233   4296   ** Here ends the implementation of all sqlite3_file methods.
  4234   4297   **
  4235   4298   ********************** End sqlite3_file Methods *******************************
  4236   4299   ******************************************************************************/
  4237   4300   
................................................................................
  4265   4328   **
  4266   4329   **   *  A constant sqlite3_io_methods object call METHOD that has locking
  4267   4330   **      methods CLOSE, LOCK, UNLOCK, CKRESLOCK.
  4268   4331   **
  4269   4332   **   *  An I/O method finder function called FINDER that returns a pointer
  4270   4333   **      to the METHOD object in the previous bullet.
  4271   4334   */
  4272         -#define IOMETHODS(FINDER, METHOD, VERSION, CLOSE, LOCK, UNLOCK, CKLOCK)      \
         4335  +#define IOMETHODS(FINDER, METHOD, CLOSE, LOCK, UNLOCK, CKLOCK, SHMMAP)       \
  4273   4336   static const sqlite3_io_methods METHOD = {                                   \
  4274         -   VERSION,                    /* iVersion */                                \
         4337  +   3,                          /* iVersion */                                \
  4275   4338      CLOSE,                      /* xClose */                                  \
  4276   4339      unixRead,                   /* xRead */                                   \
  4277   4340      unixWrite,                  /* xWrite */                                  \
  4278   4341      unixTruncate,               /* xTruncate */                               \
  4279   4342      unixSync,                   /* xSync */                                   \
  4280   4343      unixFileSize,               /* xFileSize */                               \
  4281   4344      LOCK,                       /* xLock */                                   \
  4282   4345      UNLOCK,                     /* xUnlock */                                 \
  4283   4346      CKLOCK,                     /* xCheckReservedLock */                      \
  4284   4347      unixFileControl,            /* xFileControl */                            \
  4285   4348      unixSectorSize,             /* xSectorSize */                             \
  4286   4349      unixDeviceCharacteristics,  /* xDeviceCapabilities */                     \
  4287         -   unixShmMap,                 /* xShmMap */                                 \
         4350  +   SHMMAP,                     /* xShmMap */                                 \
  4288   4351      unixShmLock,                /* xShmLock */                                \
  4289   4352      unixShmBarrier,             /* xShmBarrier */                             \
  4290         -   unixShmUnmap                /* xShmUnmap */                               \
         4353  +   unixShmUnmap,               /* xShmUnmap */                               \
         4354  +   unixMap,                    /* xMap */                                    \
         4355  +   unixUnmap                   /* xUnmap */                                  \
  4291   4356   };                                                                           \
  4292   4357   static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){   \
  4293   4358     UNUSED_PARAMETER(z); UNUSED_PARAMETER(p);                                  \
  4294   4359     return &METHOD;                                                            \
  4295   4360   }                                                                            \
  4296   4361   static const sqlite3_io_methods *(*const FINDER)(const char*,unixFile *p)    \
  4297   4362       = FINDER##Impl;
................................................................................
  4300   4365   ** Here are all of the sqlite3_io_methods objects for each of the
  4301   4366   ** locking strategies.  Functions that return pointers to these methods
  4302   4367   ** are also created.
  4303   4368   */
  4304   4369   IOMETHODS(
  4305   4370     posixIoFinder,            /* Finder function name */
  4306   4371     posixIoMethods,           /* sqlite3_io_methods object name */
  4307         -  2,                        /* shared memory is enabled */
  4308   4372     unixClose,                /* xClose method */
  4309   4373     unixLock,                 /* xLock method */
  4310   4374     unixUnlock,               /* xUnlock method */
  4311         -  unixCheckReservedLock     /* xCheckReservedLock method */
         4375  +  unixCheckReservedLock,    /* xCheckReservedLock method */
         4376  +  unixShmMap                /* Shared memory enabled */
  4312   4377   )
  4313   4378   IOMETHODS(
  4314   4379     nolockIoFinder,           /* Finder function name */
  4315   4380     nolockIoMethods,          /* sqlite3_io_methods object name */
  4316         -  1,                        /* shared memory is disabled */
  4317   4381     nolockClose,              /* xClose method */
  4318   4382     nolockLock,               /* xLock method */
  4319   4383     nolockUnlock,             /* xUnlock method */
  4320         -  nolockCheckReservedLock   /* xCheckReservedLock method */
         4384  +  nolockCheckReservedLock,  /* xCheckReservedLock method */
         4385  +  0                         /* Shared memory disabled */
  4321   4386   )
  4322   4387   IOMETHODS(
  4323   4388     dotlockIoFinder,          /* Finder function name */
  4324   4389     dotlockIoMethods,         /* sqlite3_io_methods object name */
  4325         -  1,                        /* shared memory is disabled */
  4326   4390     dotlockClose,             /* xClose method */
  4327   4391     dotlockLock,              /* xLock method */
  4328   4392     dotlockUnlock,            /* xUnlock method */
  4329         -  dotlockCheckReservedLock  /* xCheckReservedLock method */
         4393  +  dotlockCheckReservedLock, /* xCheckReservedLock method */
         4394  +  0                         /* Shared memory disabled */
  4330   4395   )
  4331   4396   
  4332   4397   #if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS
  4333   4398   IOMETHODS(
  4334   4399     flockIoFinder,            /* Finder function name */
  4335   4400     flockIoMethods,           /* sqlite3_io_methods object name */
  4336         -  1,                        /* shared memory is disabled */
  4337   4401     flockClose,               /* xClose method */
  4338   4402     flockLock,                /* xLock method */
  4339   4403     flockUnlock,              /* xUnlock method */
  4340         -  flockCheckReservedLock    /* xCheckReservedLock method */
         4404  +  flockCheckReservedLock,   /* xCheckReservedLock method */
         4405  +  0                         /* Shared memory disabled */
  4341   4406   )
  4342   4407   #endif
  4343   4408   
  4344   4409   #if OS_VXWORKS
  4345   4410   IOMETHODS(
  4346   4411     semIoFinder,              /* Finder function name */
  4347   4412     semIoMethods,             /* sqlite3_io_methods object name */
  4348         -  1,                        /* shared memory is disabled */
  4349   4413     semClose,                 /* xClose method */
  4350   4414     semLock,                  /* xLock method */
  4351   4415     semUnlock,                /* xUnlock method */
  4352         -  semCheckReservedLock      /* xCheckReservedLock method */
         4416  +  semCheckReservedLock,     /* xCheckReservedLock method */
         4417  +  0                         /* Shared memory disabled */
  4353   4418   )
  4354   4419   #endif
  4355   4420   
  4356   4421   #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
  4357   4422   IOMETHODS(
  4358   4423     afpIoFinder,              /* Finder function name */
  4359   4424     afpIoMethods,             /* sqlite3_io_methods object name */
  4360         -  1,                        /* shared memory is disabled */
  4361   4425     afpClose,                 /* xClose method */
  4362   4426     afpLock,                  /* xLock method */
  4363   4427     afpUnlock,                /* xUnlock method */
  4364         -  afpCheckReservedLock      /* xCheckReservedLock method */
         4428  +  afpCheckReservedLock,     /* xCheckReservedLock method */
         4429  +  0                         /* Shared memory disabled */
  4365   4430   )
  4366   4431   #endif
  4367   4432   
  4368   4433   /*
  4369   4434   ** The proxy locking method is a "super-method" in the sense that it
  4370   4435   ** opens secondary file descriptors for the conch and lock files and
  4371   4436   ** it uses proxy, dot-file, AFP, and flock() locking methods on those
................................................................................
  4378   4443   static int proxyClose(sqlite3_file*);
  4379   4444   static int proxyLock(sqlite3_file*, int);
  4380   4445   static int proxyUnlock(sqlite3_file*, int);
  4381   4446   static int proxyCheckReservedLock(sqlite3_file*, int*);
  4382   4447   IOMETHODS(
  4383   4448     proxyIoFinder,            /* Finder function name */
  4384   4449     proxyIoMethods,           /* sqlite3_io_methods object name */
  4385         -  1,                        /* shared memory is disabled */
  4386   4450     proxyClose,               /* xClose method */
  4387   4451     proxyLock,                /* xLock method */
  4388   4452     proxyUnlock,              /* xUnlock method */
  4389         -  proxyCheckReservedLock    /* xCheckReservedLock method */
         4453  +  proxyCheckReservedLock,   /* xCheckReservedLock method */
         4454  +  0                         /* Shared memory disabled */
  4390   4455   )
  4391   4456   #endif
  4392   4457   
  4393   4458   /* nfs lockd on OSX 10.3+ doesn't clear write locks when a read lock is set */
  4394   4459   #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
  4395   4460   IOMETHODS(
  4396   4461     nfsIoFinder,               /* Finder function name */
  4397   4462     nfsIoMethods,              /* sqlite3_io_methods object name */
  4398         -  1,                         /* shared memory is disabled */
  4399   4463     unixClose,                 /* xClose method */
  4400   4464     unixLock,                  /* xLock method */
  4401   4465     nfsUnlock,                 /* xUnlock method */
  4402         -  unixCheckReservedLock      /* xCheckReservedLock method */
         4466  +  unixCheckReservedLock,     /* xCheckReservedLock method */
         4467  +  0                          /* Shared memory disabled */
  4403   4468   )
  4404   4469   #endif
  4405   4470   
  4406   4471   #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
  4407   4472   /* 
  4408   4473   ** This "finder" function attempts to determine the best locking strategy 
  4409   4474   ** for the database file "filePath".  It then returns the sqlite3_io_methods
................................................................................
  6767   6832       UNIXVFS("unix-proxy",    proxyIoFinder ),
  6768   6833   #endif
  6769   6834     };
  6770   6835     unsigned int i;          /* Loop counter */
  6771   6836   
  6772   6837     /* Double-check that the aSyscall[] array has been constructed
  6773   6838     ** correctly.  See ticket [bb3a86e890c8e96ab] */
  6774         -  assert( ArraySize(aSyscall)==20 );
         6839  +  assert( ArraySize(aSyscall)==22 );
  6775   6840   
  6776   6841     /* Register all VFSes defined in the aVfs[] array */
  6777   6842     for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
  6778   6843       sqlite3_vfs_register(&aVfs[i], i==0);
  6779   6844     }
  6780   6845     return SQLITE_OK; 
  6781   6846   }

Changes to src/pager.c.

   651    651     sqlite3_file *sjfd;         /* File descriptor for sub-journal */
   652    652     i64 journalOff;             /* Current write offset in the journal file */
   653    653     i64 journalHdr;             /* Byte offset to previous journal header */
   654    654     sqlite3_backup *pBackup;    /* Pointer to list of ongoing backup processes */
   655    655     PagerSavepoint *aSavepoint; /* Array of active savepoints */
   656    656     int nSavepoint;             /* Number of elements in aSavepoint[] */
   657    657     char dbFileVers[16];        /* Changes whenever database file changes */
          658  +  u8 *aFileContent;           /* File mapped into memory */
          659  +  sqlite3_int64 nFileContent; /* Bytes of memory mapped into aFileContent */
          660  +  void *pMapObject;           /* Used to unmap the file */
   658    661     /*
   659    662     ** End of the routinely-changing class members
   660    663     ***************************************************************************/
   661    664   
   662    665     u16 nExtra;                 /* Add this many bytes to each in-memory page */
   663    666     i16 nReserve;               /* Number of unused bytes at end of each page */
   664    667     u32 vfsFlags;               /* Flags for sqlite3_vfs.xOpen() */
................................................................................
  1778   1781     }
  1779   1782   
  1780   1783     /* If Pager.errCode is set, the contents of the pager cache cannot be
  1781   1784     ** trusted. Now that there are no outstanding references to the pager,
  1782   1785     ** it can safely move back to PAGER_OPEN state. This happens in both
  1783   1786     ** normal and exclusive-locking mode.
  1784   1787     */
  1785         -  if( pPager->errCode ){
         1788  +  if( pPager->errCode || pPager->pMapObject ){
  1786   1789       assert( !MEMDB );
  1787   1790       pager_reset(pPager);
  1788   1791       pPager->changeCountDone = pPager->tempFile;
  1789   1792       pPager->eState = PAGER_OPEN;
  1790   1793       pPager->errCode = SQLITE_OK;
         1794  +    sqlite3OsUnmap(pPager->fd, pPager->pMapObject);
         1795  +    pPager->pMapObject = 0;
         1796  +    pPager->aFileContent = 0;
         1797  +    pPager->nFileContent = 0;
  1791   1798     }
  1792   1799   
  1793   1800     pPager->journalOff = 0;
  1794   1801     pPager->journalHdr = 0;
  1795   1802     pPager->setMaster = 0;
         1803  +
  1796   1804   }
  1797   1805   
  1798   1806   /*
  1799   1807   ** This function is called whenever an IOERR or FULL error that requires
  1800   1808   ** the pager to transition into the ERROR state may ahve occurred.
  1801   1809   ** The first argument is a pointer to the pager structure, the second 
  1802   1810   ** the error-code about to be returned by a pager API function. The 
................................................................................
  2796   2804     Pgno pgno = pPg->pgno;       /* Page number to read */
  2797   2805     int rc = SQLITE_OK;          /* Return code */
  2798   2806     int isInWal = 0;             /* True if page is in log file */
  2799   2807     int pgsz = pPager->pageSize; /* Number of bytes to read */
  2800   2808   
  2801   2809     assert( pPager->eState>=PAGER_READER && !MEMDB );
  2802   2810     assert( isOpen(pPager->fd) );
  2803         -
  2804         -  if( NEVER(!isOpen(pPager->fd)) ){
  2805         -    assert( pPager->tempFile );
  2806         -    memset(pPg->pData, 0, pPager->pageSize);
  2807         -    return SQLITE_OK;
  2808         -  }
         2811  +  assert( pPg->pBuf==pPg->pData );
  2809   2812   
  2810   2813     if( pagerUseWal(pPager) ){
  2811   2814       /* Try to pull the page from the write-ahead log. */
  2812   2815       rc = sqlite3WalRead(pPager->pWal, pgno, &isInWal, pgsz, pPg->pData);
  2813   2816     }
  2814   2817     if( rc==SQLITE_OK && !isInWal ){
  2815         -    i64 iOffset = (pgno-1)*(i64)pPager->pageSize;
         2818  +    i64 iOffset = (pgno-1)*(i64)pgsz;
         2819  +    if( iOffset+pgsz <= pPager->nFileContent ){
         2820  +      pPg->pData = &pPager->aFileContent[iOffset];
         2821  +    }else{
  2816   2822       rc = sqlite3OsRead(pPager->fd, pPg->pData, pgsz, iOffset);
  2817   2823       if( rc==SQLITE_IOERR_SHORT_READ ){
  2818   2824         rc = SQLITE_OK;
  2819   2825       }
  2820   2826     }
         2827  +  }
  2821   2828   
  2822   2829     if( pgno==1 ){
  2823   2830       if( rc ){
  2824   2831         /* If the read is unsuccessful, set the dbFileVers[] to something
  2825   2832         ** that will never be a valid file version.  dbFileVers[] is a copy
  2826   2833         ** of bytes 24..39 of the database.  Bytes 28..31 should always be
  2827   2834         ** zero or the size of the database in page. Bytes 32..35 and 35..39
................................................................................
  4888   4895       rc = pagerBeginReadTransaction(pPager);
  4889   4896     }
  4890   4897   
  4891   4898     if( pPager->eState==PAGER_OPEN && rc==SQLITE_OK ){
  4892   4899       rc = pagerPagecount(pPager, &pPager->dbSize);
  4893   4900     }
  4894   4901   
         4902  +  assert( pPager->aFileContent==0 );
         4903  +  pPager->nFileContent = pPager->dbSize*(sqlite3_int64)pPager->pageSize;
         4904  +  sqlite3OsMap(pPager->fd, 0, pPager->nFileContent,
         4905  +               SQLITE_OPEN_READONLY, (void**)&pPager->pMapObject,
         4906  +               (void**)&pPager->aFileContent);
         4907  +  if( pPager->aFileContent==0 ) pPager->nFileContent = 0;
         4908  +
  4895   4909    failed:
  4896   4910     if( rc!=SQLITE_OK ){
  4897   4911       assert( !MEMDB );
  4898   4912       pager_unlock(pPager);
  4899   4913       assert( pPager->eState==PAGER_OPEN );
  4900   4914     }else{
  4901   4915       pPager->eState = PAGER_READER;
................................................................................
  5320   5334     */
  5321   5335     if( pPager->eState==PAGER_WRITER_LOCKED ){
  5322   5336       rc = pager_open_journal(pPager);
  5323   5337       if( rc!=SQLITE_OK ) return rc;
  5324   5338     }
  5325   5339     assert( pPager->eState>=PAGER_WRITER_CACHEMOD );
  5326   5340     assert( assert_pager_state(pPager) );
         5341  +
         5342  +  /* Make sure page content is held in malloced memory */
         5343  +  if( pPg->pData!=pPg->pBuf ){
         5344  +    memcpy(pPg->pBuf, pPg->pData, pPager->pageSize);
         5345  +    pData = pPg->pData = pPg->pBuf;
         5346  +  }
  5327   5347   
  5328   5348     /* Mark the page as dirty.  If the page has already been written
  5329   5349     ** to the journal then we can return right away.
  5330   5350     */
  5331   5351     sqlite3PcacheMakeDirty(pPg);
  5332   5352     if( pageInJournal(pPg) && !subjRequiresPage(pPg) ){
  5333   5353       assert( !pagerUseWal(pPager) );
................................................................................
  5521   5541   }
  5522   5542   
  5523   5543   /*
  5524   5544   ** Return TRUE if the page given in the argument was previously passed
  5525   5545   ** to sqlite3PagerWrite().  In other words, return TRUE if it is ok
  5526   5546   ** to change the content of the page.
  5527   5547   */
  5528         -#ifndef NDEBUG
  5529   5548   int sqlite3PagerIswriteable(DbPage *pPg){
  5530   5549     return pPg->flags&PGHDR_DIRTY;
  5531   5550   }
  5532         -#endif
  5533   5551   
  5534   5552   /*
  5535   5553   ** A call to this routine tells the pager that it is not necessary to
  5536   5554   ** write the information on page pPg back to the disk, even though
  5537   5555   ** that page might be marked as dirty.  This happens, for example, when
  5538   5556   ** the page has been added as a leaf of the freelist and so its
  5539   5557   ** content no longer matters.

Changes to src/pager.h.

   164    164   #if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL)
   165    165   void *sqlite3PagerCodec(DbPage *);
   166    166   #endif
   167    167   
   168    168   /* Functions to support testing and debugging. */
   169    169   #if !defined(NDEBUG) || defined(SQLITE_TEST)
   170    170     Pgno sqlite3PagerPagenumber(DbPage*);
   171         -  int sqlite3PagerIswriteable(DbPage*);
   172    171   #endif
          172  +int sqlite3PagerIswriteable(DbPage*);
   173    173   #ifdef SQLITE_TEST
   174    174     int *sqlite3PagerStats(Pager*);
   175    175     void sqlite3PagerRefdump(Pager*);
   176    176     void disable_simulated_io_errors(void);
   177    177     void enable_simulated_io_errors(void);
   178    178   #else
   179    179   # define disable_simulated_io_errors()
   180    180   # define enable_simulated_io_errors()
   181    181   #endif
   182    182   
   183    183   #endif /* _PAGER_H_ */

Changes to src/pcache.c.

   283    283   
   284    284     if( pPage ){
   285    285       pPgHdr = (PgHdr *)pPage->pExtra;
   286    286   
   287    287       if( !pPgHdr->pPage ){
   288    288         memset(pPgHdr, 0, sizeof(PgHdr));
   289    289         pPgHdr->pPage = pPage;
   290         -      pPgHdr->pData = pPage->pBuf;
          290  +      pPgHdr->pData = pPgHdr->pBuf = pPage->pBuf;
   291    291         pPgHdr->pExtra = (void *)&pPgHdr[1];
   292    292         memset(pPgHdr->pExtra, 0, pCache->szExtra);
   293    293         pPgHdr->pCache = pCache;
   294    294         pPgHdr->pgno = pgno;
   295    295       }
   296    296       assert( pPgHdr->pCache==pCache );
   297    297       assert( pPgHdr->pgno==pgno );
   298         -    assert( pPgHdr->pData==pPage->pBuf );
          298  +    assert( pPgHdr->pBuf==pPage->pBuf );
   299    299       assert( pPgHdr->pExtra==(void *)&pPgHdr[1] );
   300    300   
   301    301       if( 0==pPgHdr->nRef ){
   302    302         pCache->nRef++;
   303    303       }
   304    304       pPgHdr->nRef++;
   305    305       if( pgno==1 ){

Changes to src/pcache.h.

    20     20   
    21     21   /*
    22     22   ** Every page in the cache is controlled by an instance of the following
    23     23   ** structure.
    24     24   */
    25     25   struct PgHdr {
    26     26     sqlite3_pcache_page *pPage;    /* Pcache object page handle */
    27         -  void *pData;                   /* Page data */
           27  +  void *pData;                   /* Page data to actually use */
           28  +  void *pBuf;                    /* Malloced buffer to hold pData */
    28     29     void *pExtra;                  /* Extra content */
    29     30     PgHdr *pDirty;                 /* Transient list of dirty pages */
    30     31     Pgno pgno;                     /* Page number for this page */
    31     32     Pager *pPager;                 /* The pager this page is part of */
    32     33   #ifdef SQLITE_CHECK_PAGES
    33     34     u32 pageHash;                  /* Hash of page content */
    34     35   #endif

Changes to src/sqlite.h.in.

   685    685     int (*xDeviceCharacteristics)(sqlite3_file*);
   686    686     /* Methods above are valid for version 1 */
   687    687     int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
   688    688     int (*xShmLock)(sqlite3_file*, int offset, int n, int flags);
   689    689     void (*xShmBarrier)(sqlite3_file*);
   690    690     int (*xShmUnmap)(sqlite3_file*, int deleteFlag);
   691    691     /* Methods above are valid for version 2 */
          692  +  int (*xMap)(sqlite3_file*, sqlite3_int64 ofst, sqlite3_int64 len,
          693  +              int mmapFlags, void **ppMemObj, void **ppMem);
          694  +  int (*xUnmap)(sqlite3_file*, void *pMemObj);
          695  +  /* Methods above are valid for version 3 */
   692    696     /* Additional methods may be added in future releases */
   693    697   };
   694    698   
   695    699   /*
   696    700   ** CAPI3REF: Standard File Control Opcodes
   697    701   **
   698    702   ** These integer constants are opcodes for the xFileControl method

Changes to test/syscall.test.

    56     56   #-------------------------------------------------------------------------
    57     57   # Tests for the xNextSystemCall method.
    58     58   #
    59     59   foreach s {
    60     60       open close access getcwd stat fstat ftruncate
    61     61       fcntl read pread write pwrite fchmod fallocate
    62     62       pread64 pwrite64 unlink openDirectory mkdir rmdir
           63  +    mmap munmap
    63     64   } {
    64     65     if {[test_syscall exists $s]} {lappend syscall_list $s}
    65     66   }
    66     67   do_test 3.1 { lsort [test_syscall list] } [lsort $syscall_list]
    67     68   
    68     69   #-------------------------------------------------------------------------
    69     70   # This test verifies that if a call to open() fails and errno is set to