Index: src/vdbesort.c ================================================================== --- src/vdbesort.c +++ src/vdbesort.c @@ -123,15 +123,17 @@ u8 *aBuffer; /* Current read buffer */ int nBuffer; /* Size of read buffer in bytes */ }; /* -** An instance of this structure is used to separate the stream of records +** An instance of this structure is used to organize the stream of records ** being written to files by the merge-sort code into aligned, page-sized -** blocks. +** blocks. Doing all I/O in aligned page-sized blocks helps I/O to go +** faster on many operating systems. */ struct FileWriter { + int eFWErr; /* Non-zero if in an error state */ u8 *aBuffer; /* Pointer to write buffer */ int nBuffer; /* Size of write buffer in bytes */ int iBufStart; /* First byte of buffer to write */ int iBufEnd; /* Last byte of buffer to write */ i64 iWriteOff; /* Offset of start of buffer in file */ @@ -262,19 +264,17 @@ iBuf = p->iReadOff % p->nBuffer; if( iBuf && (p->nBuffer-iBuf)>=9 ){ p->iReadOff += sqlite3GetVarint(&p->aBuffer[iBuf], pnOut); }else{ - u8 aVarint[9]; - int i; - for(i=0; iaDb[0].pBt); memset(p, 0, sizeof(FileWriter)); p->aBuffer = (u8 *)sqlite3DbMallocRaw(db, nBuf); - if( !p->aBuffer ) return SQLITE_NOMEM; - - p->iBufEnd = p->iBufStart = (iStart % nBuf); - p->iWriteOff = iStart - p->iBufStart; - p->nBuffer = nBuf; - p->pFile = pFile; - return SQLITE_OK; + if( !p->aBuffer ){ + p->eFWErr = SQLITE_NOMEM; + }else{ + p->iBufEnd = p->iBufStart = (iStart % nBuf); + p->iWriteOff = iStart - p->iBufStart; + p->nBuffer = nBuf; + p->pFile = pFile; + } } /* ** Write nData bytes of data to the file-write object. Return SQLITE_OK ** if successful, or an SQLite error code if an error occurs. */ -static int fileWriterWrite(FileWriter *p, u8 *pData, int nData){ +static void fileWriterWrite(FileWriter *p, u8 *pData, int nData){ int nRem = nData; - while( nRem>0 ){ + while( nRem>0 && p->eFWErr==0 ){ int nCopy = nRem; if( nCopy>(p->nBuffer - p->iBufEnd) ){ nCopy = p->nBuffer - p->iBufEnd; } memcpy(&p->aBuffer[p->iBufEnd], &pData[nData-nRem], nCopy); p->iBufEnd += nCopy; if( p->iBufEnd==p->nBuffer ){ - int rc = sqlite3OsWrite(p->pFile, + p->eFWErr = sqlite3OsWrite(p->pFile, &p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart, p->iWriteOff + p->iBufStart ); - if( rc!=SQLITE_OK ) return rc; p->iBufStart = p->iBufEnd = 0; p->iWriteOff += p->nBuffer; } assert( p->iBufEndnBuffer ); nRem -= nCopy; } - - return SQLITE_OK; } /* ** Flush any buffered data to disk and clean up the file-writer object. ** The results of using the file-writer after this call are undefined. @@ -672,32 +670,33 @@ ** ** Before returning, set *piEof to the offset immediately following the ** last byte written to the file. */ static int fileWriterFinish(sqlite3 *db, FileWriter *p, i64 *piEof){ - int rc = SQLITE_OK; - if( p->aBuffer && p->iBufEnd>p->iBufStart ){ - rc = sqlite3OsWrite(p->pFile, + int rc; + if( p->eFWErr==0 && ALWAYS(p->aBuffer) && p->iBufEnd>p->iBufStart ){ + p->eFWErr = sqlite3OsWrite(p->pFile, &p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart, p->iWriteOff + p->iBufStart ); } *piEof = (p->iWriteOff + p->iBufEnd); sqlite3DbFree(db, p->aBuffer); + rc = p->eFWErr; memset(p, 0, sizeof(FileWriter)); return rc; } /* ** Write value iVal encoded as a varint to the file-write object. Return ** SQLITE_OK if successful, or an SQLite error code if an error occurs. */ -static int fileWriterWriteVarint(FileWriter *p, u64 iVal){ +static void fileWriterWriteVarint(FileWriter *p, u64 iVal){ int nByte; u8 aByte[10]; nByte = sqlite3PutVarint(aByte, iVal); - return fileWriterWrite(p, aByte, nByte); + fileWriterWrite(p, aByte, nByte); } /* ** Write the current contents of the in-memory linked-list to a PMA. Return ** SQLITE_OK if successful, or an SQLite error code otherwise. @@ -711,11 +710,10 @@ ** Each record consists of a varint followed by a blob of data (the ** key). The varint is the number of bytes in the blob of data. */ static int vdbeSorterListToPMA(sqlite3 *db, const VdbeCursor *pCsr){ int rc = SQLITE_OK; /* Return code */ - int rc2; /* fileWriterFinish return code */ VdbeSorter *pSorter = pCsr->pSorter; FileWriter writer; memset(&writer, 0, sizeof(FileWriter)); @@ -732,37 +730,27 @@ assert( rc!=SQLITE_OK || pSorter->pTemp1 ); assert( pSorter->iWriteOff==0 ); assert( pSorter->nPMA==0 ); } - if( rc==SQLITE_OK ){ - rc = fileWriterInit(db, pSorter->pTemp1, &writer, pSorter->iWriteOff); - } - if( rc==SQLITE_OK ){ SorterRecord *p; SorterRecord *pNext = 0; - + fileWriterInit(db, pSorter->pTemp1, &writer, pSorter->iWriteOff); pSorter->nPMA++; - rc = fileWriterWriteVarint(&writer, pSorter->nInMemory); - for(p=pSorter->pRecord; rc==SQLITE_OK && p; p=pNext){ + fileWriterWriteVarint(&writer, pSorter->nInMemory); + for(p=pSorter->pRecord; p; p=pNext){ pNext = p->pNext; - rc = fileWriterWriteVarint(&writer, p->nVal); - if( rc==SQLITE_OK ){ - rc = fileWriterWrite(&writer, p->pVal, p->nVal); - } - + fileWriterWriteVarint(&writer, p->nVal); + fileWriterWrite(&writer, p->pVal, p->nVal); sqlite3DbFree(db, p); } - pSorter->pRecord = p; + rc = fileWriterFinish(db, &writer, &pSorter->iWriteOff); } - rc2 = fileWriterFinish(db, &writer, &pSorter->iWriteOff); - if( rc==SQLITE_OK ) rc = rc2; - return rc; } /* ** Add a record to the sorter. @@ -918,35 +906,25 @@ if( pTemp2==0 ){ assert( iWrite2==0 ); rc = vdbeSorterOpenTempFile(db, &pTemp2); } - if( rc==SQLITE_OK ){ - rc = fileWriterInit(db, pTemp2, &writer, iWrite2); - } - if( rc==SQLITE_OK ){ - rc = fileWriterWriteVarint(&writer, nWrite); - } - if( rc==SQLITE_OK ){ int bEof = 0; + fileWriterInit(db, pTemp2, &writer, iWrite2); + fileWriterWriteVarint(&writer, nWrite); while( rc==SQLITE_OK && bEof==0 ){ VdbeSorterIter *pIter = &pSorter->aIter[ pSorter->aTree[1] ]; assert( pIter->pFile ); - rc = fileWriterWriteVarint(&writer, pIter->nKey); - if( rc==SQLITE_OK ){ - rc = fileWriterWrite(&writer, pIter->aKey, pIter->nKey); - } - if( rc==SQLITE_OK ){ - rc = sqlite3VdbeSorterNext(db, pCsr, &bEof); - } - } - } - - rc2 = fileWriterFinish(db, &writer, &iWrite2); - if( rc==SQLITE_OK ) rc = rc2; + fileWriterWriteVarint(&writer, pIter->nKey); + fileWriterWrite(&writer, pIter->aKey, pIter->nKey); + rc = sqlite3VdbeSorterNext(db, pCsr, &bEof); + } + rc2 = fileWriterFinish(db, &writer, &iWrite2); + if( rc==SQLITE_OK ) rc = rc2; + } } if( pSorter->nPMA<=SORTER_MAX_MERGE_COUNT ){ break; }else{