/ Check-in [2f94f9ce]
Login

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

Overview
Comment:Fix some problems to do with OOM conditions in vdbesort.c. Some problems remain.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | threads
Files: files | file ages | folders
SHA1: 2f94f9ce9bf11f1599bbc640b3fc8c15da588416
User & Date: dan 2014-04-15 20:52:27
Context
2014-04-16
16:43
Rework the way trees of MergeEngine objects are built in vdbesort.c to make it easier to follow. Fix memory leaks that could follow an OOM or IO error. Add various comments to explain functions in vdbesort.c. check-in: 69026ec7 user: dan tags: threads
2014-04-15
20:52
Fix some problems to do with OOM conditions in vdbesort.c. Some problems remain. check-in: 2f94f9ce user: dan tags: threads
19:52
Fix further code and documentation issues in vdbesort.c. check-in: d03f5b86 user: dan tags: threads
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/vdbesort.c.

621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
....
1986
1987
1988
1989
1990
1991
1992

1993
1994
1995
1996
1997
1998
1999
....
2013
2014
2015
2016
2017
2018
2019




2020
2021
2022
2023
2024
2025
2026
....
2046
2047
2048
2049
2050
2051
2052

2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063

2064
2065
2066







2067
2068
2069
2070
2071
2072
2073
    int pgsz = pTask->pSorter->pgsz;
    int iBuf = pIter->iReadOff % pgsz;
    if( pIter->aBuffer==0 ){
      pIter->aBuffer = (u8*)sqlite3Malloc(pgsz);
      if( pIter->aBuffer==0 ) rc = SQLITE_NOMEM;
      pIter->nBuffer = pgsz;
    }
    if( iBuf ){
      int nRead = pgsz - iBuf;
      if( (pIter->iReadOff + nRead) > pIter->iEof ){
        nRead = (int)(pIter->iEof - pIter->iReadOff);
      }
      rc = sqlite3OsRead(
          pIter->pFile, &pIter->aBuffer[iBuf], nRead, pIter->iReadOff
      );
................................................................................
          pRoot = 0;
          if( rc!=SQLITE_OK ){
            vdbeMergeEngineFree(pMerger);
            break;
          }
        }
        rc = vdbeAddToBuilder(pTask, &aMerge[0], pMerger);

      }
    }

    if( pRoot==0 ){
      int i;
      for(i=0; rc==SQLITE_OK && i<nMerge; i++){
        if( aMerge[i].pMerger ){
................................................................................
      }else{
        IncrMerger *pNew = vdbeIncrNew(pTask, pRoot);
        pMain->aIter[iTask].pIncr = pNew;
        if( pNew==0 ) rc = SQLITE_NOMEM;
      }
      memset(aMerge, 0, nMerge*sizeof(aMerge[0]));
    }




  }

  if( rc==SQLITE_OK ){
#if SQLITE_MAX_WORKER_THREADS
    if( pSorter->bUseThreads ){
      PmaReader *pIter;
      SortSubtask *pLast = &pSorter->aTask[pSorter->nTask-1];
................................................................................
          if( pSorter->nTask>1 ){
            for(iTask=0; rc==SQLITE_OK && iTask<pSorter->nTask; iTask++){
              PmaReader *p = &pMain->aIter[iTask];
              assert( p->pIncr==0 || p->pIncr->pTask==&pSorter->aTask[iTask] );
              if( p->pIncr ){ rc = vdbeIncrBgInit2(p); }
            }
          }

        }
      }
      if( rc==SQLITE_OK ){
        int eMode = (pSorter->nTask>1 ? INCRINIT2_ROOT : INCRINIT2_NORMAL);
        rc = vdbeIncrInit2(pIter, eMode);
      }
    }else
#endif
    {
      pSorter->pMerger = pMain;
      rc = vdbeIncrInitMerger(pTask0, pMain, INCRINIT2_NORMAL);

    }
  }








  sqlite3_free(aMerge);
  return rc;
}


/*
** Once the sorter has been populated by calls to sqlite3VdbeSorterWrite,







|







 







>







 







>
>
>
>







 







>











>



>
>
>
>
>
>
>







621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
....
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
....
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
....
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
    int pgsz = pTask->pSorter->pgsz;
    int iBuf = pIter->iReadOff % pgsz;
    if( pIter->aBuffer==0 ){
      pIter->aBuffer = (u8*)sqlite3Malloc(pgsz);
      if( pIter->aBuffer==0 ) rc = SQLITE_NOMEM;
      pIter->nBuffer = pgsz;
    }
    if( rc==SQLITE_OK && iBuf ){
      int nRead = pgsz - iBuf;
      if( (pIter->iReadOff + nRead) > pIter->iEof ){
        nRead = (int)(pIter->iEof - pIter->iReadOff);
      }
      rc = sqlite3OsRead(
          pIter->pFile, &pIter->aBuffer[iBuf], nRead, pIter->iReadOff
      );
................................................................................
          pRoot = 0;
          if( rc!=SQLITE_OK ){
            vdbeMergeEngineFree(pMerger);
            break;
          }
        }
        rc = vdbeAddToBuilder(pTask, &aMerge[0], pMerger);
        if( rc!=SQLITE_OK ) break;
      }
    }

    if( pRoot==0 ){
      int i;
      for(i=0; rc==SQLITE_OK && i<nMerge; i++){
        if( aMerge[i].pMerger ){
................................................................................
      }else{
        IncrMerger *pNew = vdbeIncrNew(pTask, pRoot);
        pMain->aIter[iTask].pIncr = pNew;
        if( pNew==0 ) rc = SQLITE_NOMEM;
      }
      memset(aMerge, 0, nMerge*sizeof(aMerge[0]));
    }

    if( rc!=SQLITE_OK ){
      vdbeMergeEngineFree(pRoot);
    }
  }

  if( rc==SQLITE_OK ){
#if SQLITE_MAX_WORKER_THREADS
    if( pSorter->bUseThreads ){
      PmaReader *pIter;
      SortSubtask *pLast = &pSorter->aTask[pSorter->nTask-1];
................................................................................
          if( pSorter->nTask>1 ){
            for(iTask=0; rc==SQLITE_OK && iTask<pSorter->nTask; iTask++){
              PmaReader *p = &pMain->aIter[iTask];
              assert( p->pIncr==0 || p->pIncr->pTask==&pSorter->aTask[iTask] );
              if( p->pIncr ){ rc = vdbeIncrBgInit2(p); }
            }
          }
          pMain = 0;
        }
      }
      if( rc==SQLITE_OK ){
        int eMode = (pSorter->nTask>1 ? INCRINIT2_ROOT : INCRINIT2_NORMAL);
        rc = vdbeIncrInit2(pIter, eMode);
      }
    }else
#endif
    {
      pSorter->pMerger = pMain;
      rc = vdbeIncrInitMerger(pTask0, pMain, INCRINIT2_NORMAL);
      pMain = 0;
    }
  }

  if( rc!=SQLITE_OK ){
    int i;
    for(i=0; rc==SQLITE_OK && i<nMerge; i++){
      vdbeMergeEngineFree(aMerge[i].pMerger);
    }
    vdbeMergeEngineFree(pMain);
  }
  sqlite3_free(aMerge);
  return rc;
}


/*
** Once the sorter has been populated by calls to sqlite3VdbeSorterWrite,

Added test/sortfault.test.

















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 2014 March 25.
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. 
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix sortfault


do_execsql_test 1.0 {
  PRAGMA cache_size = 5;
}

do_faultsim_test 1 -prep {
  sqlite3 db test.db
} -body {
  execsql { 
    WITH r(x,y) AS (
      SELECT 1, randomblob(1000)
      UNION ALL
      SELECT x+1, randomblob(1000) FROM r
      LIMIT 500
    )
    SELECT count(x), length(y) FROM r GROUP BY (x%5)
  } 
} -test {
  faultsim_test_result {0 {100 1000 100 1000 100 1000 100 1000 100 1000}}
}

finish_test