SQLite

Check-in [9d3f3736be]
Login

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

Overview
Comment:Fix a couple of errors in WAL code that can occur in an OOM situation.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 9d3f3736be42ef8ab48b099d4712e08dfca97873
User & Date: dan 2010-05-03 17:18:24.000
Context
2010-05-03
17:24
Clear global variable "seconds" before use in walthread.test. (check-in: a35551a530 user: drh tags: trunk)
17:18
Fix a couple of errors in WAL code that can occur in an OOM situation. (check-in: 9d3f3736be user: dan tags: trunk)
16:36
Update the crash-test VFS in test6.c to pass-through the shared-memory methods to the real underlying VFS. This fixes the walcrash.test script. (check-in: ea09ff3791 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/os_unix.c.
4968
4969
4970
4971
4972
4973
4974

4975
4976
4977
4978
4979
4980
4981
4982
4983
  */
  p = sqlite3_malloc( sizeof(*p) );
  if( p==0 ) return SQLITE_NOMEM;
  memset(p, 0, sizeof(*p));
  nName = strlen(zName);
  pNew = sqlite3_malloc( sizeof(*pFile) + nName + 10 );
  if( pNew==0 ){

    rc = SQLITE_NOMEM;
    goto shm_open_err;
  }
  memset(pNew, 0, sizeof(*pNew));
  pNew->zFilename = (char*)&pNew[1];
  sqlite3_snprintf(nName+10, pNew->zFilename, "%s-index", zName);

  /* Look to see if there is an existing unixShmFile that can be used.
  ** If no matching unixShmFile currently exists, create a new one.







>
|
<







4968
4969
4970
4971
4972
4973
4974
4975
4976

4977
4978
4979
4980
4981
4982
4983
  */
  p = sqlite3_malloc( sizeof(*p) );
  if( p==0 ) return SQLITE_NOMEM;
  memset(p, 0, sizeof(*p));
  nName = strlen(zName);
  pNew = sqlite3_malloc( sizeof(*pFile) + nName + 10 );
  if( pNew==0 ){
    sqlite3_free(p);
    return SQLITE_NOMEM;

  }
  memset(pNew, 0, sizeof(*pNew));
  pNew->zFilename = (char*)&pNew[1];
  sqlite3_snprintf(nName+10, pNew->zFilename, "%s-index", zName);

  /* Look to see if there is an existing unixShmFile that can be used.
  ** If no matching unixShmFile currently exists, create a new one.
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
  pFile->nRef++;
  *pShm = (sqlite3_shm*)p;
  unixLeaveMutex();
  return SQLITE_OK;

  /* Jump here on any error */
shm_open_err:
  unixShmPurge();
  sqlite3_free(p);
  sqlite3_free(pFile);
  sqlite3_free(pNew);
  *pShm = 0;
  unixLeaveMutex();
  return rc;
}

/*







|

<







5055
5056
5057
5058
5059
5060
5061
5062
5063

5064
5065
5066
5067
5068
5069
5070
  pFile->nRef++;
  *pShm = (sqlite3_shm*)p;
  unixLeaveMutex();
  return SQLITE_OK;

  /* Jump here on any error */
shm_open_err:
  unixShmPurge();                 /* This call frees pFile if required */
  sqlite3_free(p);

  sqlite3_free(pNew);
  *pShm = 0;
  unixLeaveMutex();
  return rc;
}

/*
Changes to src/wal.c.
588
589
590
591
592
593
594
595



596
597
598
599
600
601
602
603

604
605
606
607
608
609
610
611
612
613

614
615
616
617
618
619
620
  assert( zDb );
  if( pVfs->xShmOpen==0 ) return SQLITE_CANTOPEN_BKPT;

  /* Allocate an instance of struct Wal to return. */
  *ppWal = 0;
  nWal = strlen(zDb);
  pRet = (Wal*)sqlite3MallocZero(sizeof(Wal) + pVfs->szOsFile + nWal+5);
  if( !pRet ) goto wal_open_out;



  pRet->pVfs = pVfs;
  pRet->pFd = (sqlite3_file *)&pRet[1];
  pRet->zName = zWal = pVfs->szOsFile + (char*)pRet->pFd;
  sqlite3_snprintf(nWal+5, zWal, "%s-wal", zDb);
  rc = pVfs->xShmOpen(pVfs, zWal, &pRet->pWIndex);
  if( rc ) goto wal_open_out;

  /* Open file handle on the write-ahead log file. */

  flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MAIN_JOURNAL);
  rc = sqlite3OsOpen(pVfs, zWal, pRet->pFd, flags, &flags);

wal_open_out:
  if( rc!=SQLITE_OK ){
    if( pRet ){
      pVfs->xShmClose(pVfs, pRet->pWIndex, 0);
      sqlite3OsClose(pRet->pFd);
      sqlite3_free(pRet);
    }

  }
  *ppWal = pRet;
  return rc;
}

static int walIteratorNext(
  WalIterator *p,               /* Iterator */







|
>
>
>





<


>
|
|
|
|






>







588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603

604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
  assert( zDb );
  if( pVfs->xShmOpen==0 ) return SQLITE_CANTOPEN_BKPT;

  /* Allocate an instance of struct Wal to return. */
  *ppWal = 0;
  nWal = strlen(zDb);
  pRet = (Wal*)sqlite3MallocZero(sizeof(Wal) + pVfs->szOsFile + nWal+5);
  if( !pRet ){
    return SQLITE_NOMEM;
  }

  pRet->pVfs = pVfs;
  pRet->pFd = (sqlite3_file *)&pRet[1];
  pRet->zName = zWal = pVfs->szOsFile + (char*)pRet->pFd;
  sqlite3_snprintf(nWal+5, zWal, "%s-wal", zDb);
  rc = pVfs->xShmOpen(pVfs, zWal, &pRet->pWIndex);


  /* Open file handle on the write-ahead log file. */
  if( rc==SQLITE_OK ){
    flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MAIN_JOURNAL);
    rc = sqlite3OsOpen(pVfs, zWal, pRet->pFd, flags, &flags);
  }

  if( rc!=SQLITE_OK ){
    if( pRet ){
      pVfs->xShmClose(pVfs, pRet->pWIndex, 0);
      sqlite3OsClose(pRet->pFd);
      sqlite3_free(pRet);
    }
    pRet = 0;
  }
  *ppWal = pRet;
  return rc;
}

static int walIteratorNext(
  WalIterator *p,               /* Iterator */
662
663
664
665
666
667
668

669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688

689
690
691
692
693
694
695
  aData = pWal->pWiData;
  iLast = pWal->hdr.iLastPg;
  nSegment = (iLast >> 8) + 1;
  nFinal = (iLast & 0x000000FF);

  nByte = sizeof(WalIterator) + (nSegment-1)*sizeof(struct WalSegment) + 512;
  p = (WalIterator *)sqlite3_malloc(nByte);

  if( p ){
    memset(p, 0, nByte);
    p->nSegment = nSegment;
    p->nFinal = nFinal;
  }

  for(i=0; i<nSegment-1; i++){
    p->aSegment[i].aDbPage = &aData[walIndexEntry(i*256+1)];
    p->aSegment[i].aIndex = (u8 *)&aData[walIndexEntry(i*256+1)+256];
  }
  pFinal = &p->aSegment[nSegment-1];

  pFinal->aDbPage = &aData[walIndexEntry((nSegment-1)*256+1)];
  pFinal->aIndex = (u8 *)&pFinal[1];
  aTmp = &pFinal->aIndex[256];
  for(i=0; i<nFinal; i++){
    pFinal->aIndex[i] = i;
  }
  walMergesort8(pFinal->aDbPage, aTmp, pFinal->aIndex, &nFinal);
  p->nFinal = nFinal;


  return p;
}

/* 
** Free a log iterator allocated by walIteratorInit().
*/







>



<
|
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>







666
667
668
669
670
671
672
673
674
675
676

677

678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
  aData = pWal->pWiData;
  iLast = pWal->hdr.iLastPg;
  nSegment = (iLast >> 8) + 1;
  nFinal = (iLast & 0x000000FF);

  nByte = sizeof(WalIterator) + (nSegment-1)*sizeof(struct WalSegment) + 512;
  p = (WalIterator *)sqlite3_malloc(nByte);

  if( p ){
    memset(p, 0, nByte);
    p->nSegment = nSegment;



    for(i=0; i<nSegment-1; i++){
      p->aSegment[i].aDbPage = &aData[walIndexEntry(i*256+1)];
      p->aSegment[i].aIndex = (u8 *)&aData[walIndexEntry(i*256+1)+256];
    }
    pFinal = &p->aSegment[nSegment-1];
  
    pFinal->aDbPage = &aData[walIndexEntry((nSegment-1)*256+1)];
    pFinal->aIndex = (u8 *)&pFinal[1];
    aTmp = &pFinal->aIndex[256];
    for(i=0; i<nFinal; i++){
      pFinal->aIndex[i] = i;
    }
    walMergesort8(pFinal->aDbPage, aTmp, pFinal->aIndex, &nFinal);
    p->nFinal = nFinal;
  }

  return p;
}

/* 
** Free a log iterator allocated by walIteratorInit().
*/
Added test/walfault.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
# 2010 May 03
#
# 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.  The
# focus of this file is testing the operation of the library in
# "PRAGMA journal_mode=WAL" mode.
#

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

ifcapable !wal {finish_test ; return }

do_malloc_test walfault-oom-1 -sqlbody {
  PRAGMA journal_mode = WAL;
  CREATE TABLE t1(a, b);
  INSERT INTO t1 VALUES(1, 2);
  PRAGMA checkpoint;
}


finish_test