/ Check-in [47e702bd]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Fix some problems with OOM handling in vdbesort.c.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | threads
Files: files | file ages | folders
SHA1: 47e702bd8392bc50c4edaf6a2c8c499af87b520e
User & Date: dan 2014-04-02 15:15:25
Context
2014-04-02
18:58
Add a big introductory comment to vdbesort.c explaining its operation at a high level. Also adjust some symbolic names and fix other comment issues in that file. check-in: eef60f1b user: drh tags: threads
15:15
Fix some problems with OOM handling in vdbesort.c. check-in: 47e702bd user: dan tags: threads
14:38
Change the name of the SorterThread object to "SortSubtask" to avoid confusion with the SQLiteThread object. check-in: 4ee2d910 user: drh tags: threads
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/vdbesort.c.

   439    439     assert( pThread->iTemp1Off>iStart );
   440    440     assert( pIter->aAlloc==0 );
   441    441     assert( pIter->aBuffer==0 );
   442    442     pIter->pFile = pThread->pTemp1;
   443    443     pIter->iReadOff = iStart;
   444    444     pIter->nAlloc = 128;
   445    445     pIter->aAlloc = (u8*)sqlite3Malloc(pIter->nAlloc);
   446         -
   447         -  /* Try to xFetch() a mapping of the entire temp file. If this is possible,
   448         -  ** the PMA will be read via the mapping. Otherwise, use xRead().  */
   449         -  rc = sqlite3OsFetch(pIter->pFile, 0, pThread->iTemp1Off, &pMap);
          446  +  if( pIter->aAlloc ){
          447  +    /* Try to xFetch() a mapping of the entire temp file. If this is possible,
          448  +    ** the PMA will be read via the mapping. Otherwise, use xRead().  */
          449  +    rc = sqlite3OsFetch(pIter->pFile, 0, pThread->iTemp1Off, &pMap);
          450  +  }else{
          451  +    rc = SQLITE_NOMEM;
          452  +  }
   450    453   
   451    454     if( rc==SQLITE_OK ){
   452    455       if( pMap ){
   453    456         pIter->aMap = (u8*)pMap;
   454    457       }else{
   455    458         pIter->nBuffer = nBuf;
   456    459         pIter->aBuffer = (u8*)sqlite3Malloc(nBuf);
................................................................................
   694    697       pNew->aIter = (VdbeSorterIter*)&pNew[1];
   695    698       pNew->aTree = (int*)&pNew->aIter[N];
   696    699     }
   697    700     return pNew;
   698    701   }
   699    702   
   700    703   /*
   701         -** Reset a merger
          704  +** Free the SorterMerger object passed as the only argument.
   702    705   */
   703         -static void vdbeSorterMergerReset(SorterMerger *pMerger){
          706  +static void vdbeSorterMergerFree(SorterMerger *pMerger){
   704    707     int i;
   705    708     if( pMerger ){
   706    709       for(i=0; i<pMerger->nTree; i++){
   707    710         vdbeSorterIterZero(&pMerger->aIter[i]);
   708    711       }
   709    712     }
   710         -}
   711         -
   712         -
   713         -/*
   714         -** Free the SorterMerger object passed as the only argument.
   715         -*/
   716         -static void vdbeSorterMergerFree(SorterMerger *pMerger){
   717         -  vdbeSorterMergerReset(pMerger);
   718    713     sqlite3_free(pMerger);
   719    714   }
   720    715   
   721    716   /*
   722    717   ** Reset a sorting cursor back to its original empty state.
   723    718   */
   724    719   void sqlite3VdbeSorterReset(sqlite3 *db, VdbeSorter *pSorter){
   725    720     int i;
   726    721     vdbeSorterJoinAll(pSorter, SQLITE_OK);
          722  +  vdbeSorterMergerFree(pSorter->pMerger);
          723  +  pSorter->pMerger = 0;
   727    724     for(i=0; i<pSorter->nThread; i++){
   728    725       SortSubtask *pThread = &pSorter->aThread[i];
   729    726       vdbeSortSubtaskCleanup(db, pThread);
   730    727     }
   731    728     if( pSorter->aMemory==0 ){
   732    729       vdbeSorterRecordFree(0, pSorter->pRecord);
   733    730     }
   734         -  vdbeSorterMergerReset(pSorter->pMerger);
   735    731     pSorter->pRecord = 0;
   736    732     pSorter->nInMemory = 0;
   737    733     pSorter->bUsePMA = 0;
   738    734     pSorter->iMemory = 0;
   739    735   }
   740    736   
   741    737   /*
................................................................................
  1288   1284           }
  1289   1285         }
  1290   1286         rc = sqlite3ThreadCreate(&pThread->pThread, vdbeSortSubtaskMain, pCtx);
  1291   1287       }else
  1292   1288   #endif
  1293   1289       {
  1294   1290         /* Use the foreground thread for this operation */
  1295         -      u8 *aMem;
  1296   1291         rc = vdbeSorterRunThread(pThread);
  1297         -      aMem = pThread->aListMemory;
  1298         -      pThread->aListMemory = pSorter->aMemory;
  1299         -      pSorter->aMemory = aMem;
         1292  +      if( rc==SQLITE_OK ){
         1293  +        u8 *aMem = pThread->aListMemory;
         1294  +        pThread->aListMemory = pSorter->aMemory;
         1295  +        pSorter->aMemory = aMem;
         1296  +        assert( pThread->pList==0 );
         1297  +      }
  1300   1298       }
  1301   1299     }
  1302   1300   
  1303   1301     return rc;
  1304   1302   }
  1305   1303   
  1306   1304   /*

Changes to test/mallocA.test.

    21     21   #
    22     22   if {!$MEMDEBUG} {
    23     23      puts "Skipping mallocA tests: not compiled with -DSQLITE_MEMDEBUG..."
    24     24      finish_test
    25     25      return
    26     26   }
    27     27   
    28         -
    29     28   # Construct a test database
    30     29   #
    31     30   forcedelete test.db.bu
    32     31   db eval {
    33     32     CREATE TABLE t1(a COLLATE NOCASE,b,c);
    34     33     INSERT INTO t1 VALUES(1,2,3);
    35     34     INSERT INTO t1 VALUES(1,2,4);
................................................................................
   111    110         ANALYZE sqlite_master;
   112    111         SELECT rowid FROM t1 WHERE a='abc' AND b<'y';
   113    112       }
   114    113     } -test {
   115    114       faultsim_test_result [list 0 {1 2}]
   116    115     }
   117    116   }
          117  +
          118  +do_execsql_test 7.0 {
          119  +  PRAGMA cache_size = 5;
          120  +}
          121  +do_faultsim_test 7 -faults oom-trans* -prep {
          122  +  if {$iFail < 500} { set iFail 2000 }
          123  +  if {$iFail > 1215} { set iFail 2000 }
          124  +} -body {
          125  +  execsql {
          126  +    WITH r(x,y) AS (
          127  +      SELECT 1, randomblob(100)
          128  +      UNION ALL
          129  +      SELECT x+1, randomblob(100) FROM r
          130  +      LIMIT 1000
          131  +    )
          132  +    SELECT count(x), length(y) FROM r GROUP BY (x%5)
          133  +  }
          134  +} -test {
          135  +  set res [list 200 100 200 100 200 100 200 100 200 100]
          136  +  faultsim_test_result [list 0 $res]
          137  +}
          138  +
   118    139   
   119    140   # Ensure that no file descriptors were leaked.
   120    141   do_test malloc-99.X {
   121    142     catch {db close}
   122    143     set sqlite_open_file_count
   123    144   } {0}
   124    145   
   125    146   forcedelete test.db.bu
   126    147   finish_test