Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Additional changes in the pager and os interface layers to fix problems that might be contributing to recently observed database corruption. (CVS 3549) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
a593d5743eab12c0f93a7bc436f0d69d |
User & Date: | drh 2007-01-03 23:36:22.000 |
Context
2007-01-03
| ||
23:37 | Clean up memory leaks and uninitialized variables detected by valgrind. Identify all tests where we deliberately derefence freed memory by adding a "-misuse" tag. (CVS 3550) (check-in: 70a862702d user: drh tags: trunk) | |
23:36 | Additional changes in the pager and os interface layers to fix problems that might be contributing to recently observed database corruption. (CVS 3549) (check-in: a593d5743e user: drh tags: trunk) | |
15:34 | Make sure that the database size cache in the pager is invalidated whenever the database is unlocked. A stale value in the database size cache can result in database corruption on a heavily loaded system running autovacuum. (CVS 3548) (check-in: 6806b9ecb5 user: drh tags: trunk) | |
Changes
Changes to src/os_unix.c.
︙ | ︙ | |||
1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 | SEEK(0); SimulateIOError( got = -1 ); if( got==amt ){ return SQLITE_OK; }else if( got<0 ){ return SQLITE_IOERR_READ; }else{ return SQLITE_IOERR_SHORT_READ; } } /* ** Seek to the offset in id->offset then read cnt bytes into pBuf. ** Return the number of bytes actually read. Update the offset. | > | 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 | SEEK(0); SimulateIOError( got = -1 ); if( got==amt ){ return SQLITE_OK; }else if( got<0 ){ return SQLITE_IOERR_READ; }else{ memset(&((char*)pBuf)[got], 0, amt-got); return SQLITE_IOERR_SHORT_READ; } } /* ** Seek to the offset in id->offset then read cnt bytes into pBuf. ** Return the number of bytes actually read. Update the offset. |
︙ | ︙ |
Changes to src/os_win.c.
︙ | ︙ | |||
1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 | got = -1; } if( got==(DWORD)amt ){ return SQLITE_OK; }else if( got<0 ){ return SQLITE_IOERR_READ; }else{ return SQLITE_IOERR_SHORT_READ; } } /* ** Write data from a buffer into a file. Return SQLITE_OK on success ** or some other error code on failure. | > | 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 | got = -1; } if( got==(DWORD)amt ){ return SQLITE_OK; }else if( got<0 ){ return SQLITE_IOERR_READ; }else{ memset(&((char*)pBuf)[got], 0, amt-got); return SQLITE_IOERR_SHORT_READ; } } /* ** Write data from a buffer into a file. Return SQLITE_OK on success ** or some other error code on failure. |
︙ | ︙ |
Changes to src/pager.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 | ** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** | | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | ** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** ** @(#) $Id: pager.c,v 1.280 2007/01/03 23:36:22 drh Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" #include "os.h" #include "pager.h" #include <assert.h> #include <string.h> |
︙ | ︙ | |||
859 860 861 862 863 864 865 866 867 868 869 870 871 872 | */ static void pager_unlock(Pager *pPager){ if( !MEMDB ){ sqlite3OsUnlock(pPager->fd, NO_LOCK); pPager->dbSize = -1; } pPager->state = PAGER_UNLOCK; } /* ** Unlock the database and clear the in-memory cache. This routine ** sets the state of the pager back to what it was when it was first ** opened. Any outstanding pages are invalidated and subsequent attempts | > | 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 | */ static void pager_unlock(Pager *pPager){ if( !MEMDB ){ sqlite3OsUnlock(pPager->fd, NO_LOCK); pPager->dbSize = -1; } pPager->state = PAGER_UNLOCK; assert( pPager->pAll==0 ); } /* ** Unlock the database and clear the in-memory cache. This routine ** sets the state of the pager back to what it was when it was first ** opened. Any outstanding pages are invalidated and subsequent attempts |
︙ | ︙ | |||
888 889 890 891 892 893 894 | pPager->nPage = 0; pPager->aHash = 0; if( pPager->state>=PAGER_RESERVED ){ sqlite3pager_rollback(pPager); } pager_unlock(pPager); pPager->nRef = 0; | | | 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 | pPager->nPage = 0; pPager->aHash = 0; if( pPager->state>=PAGER_RESERVED ){ sqlite3pager_rollback(pPager); } pager_unlock(pPager); pPager->nRef = 0; assert( pPager->errCode || (pPager->journalOpen==0 && pPager->stmtOpen==0) ); } /* ** When this routine is called, the pager has the journal file open and ** a RESERVED or EXCLUSIVE lock on the database. This routine releases ** the database lock and acquires a SHARED lock in its place. The journal ** file is deleted and closed. |
︙ | ︙ | |||
2059 2060 2061 2062 2063 2064 2065 | ** ** This function always succeeds. If a transaction is active an attempt ** is made to roll it back. If an error occurs during the rollback ** a hot journal may be left in the filesystem but no error is returned ** to the caller. */ int sqlite3pager_close(Pager *pPager){ | < < < < < < < < < | | | < < < < < < < < < < < < < < < < < < < < < < < < < | 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 | ** ** This function always succeeds. If a transaction is active an attempt ** is made to roll it back. If an error occurs during the rollback ** a hot journal may be left in the filesystem but no error is returned ** to the caller. */ int sqlite3pager_close(Pager *pPager){ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT /* A malloc() cannot fail in sqlite3ThreadData() as one or more calls to ** malloc() must have already been made by this thread before it gets ** to this point. This means the ThreadData must have been allocated already ** so that ThreadData.nAlloc can be set. */ ThreadData *pTsd = sqlite3ThreadData(); assert( pPager ); assert( pTsd && pTsd->nAlloc ); #endif disable_simulated_io_errors(); pager_reset(pPager); enable_simulated_io_errors(); TRACE2("CLOSE %d\n", PAGERID(pPager)); assert( pPager->errCode || (pPager->journalOpen==0 && pPager->stmtOpen==0) ); if( pPager->journalOpen ){ sqlite3OsClose(&pPager->jfd); } sqliteFree(pPager->aInJournal); if( pPager->stmtOpen ){ |
︙ | ︙ | |||
2985 2986 2987 2988 2989 2990 2991 | /* If this was a malloc() failure, then we will not be closing the pager ** file. So delete any journal file we may have just created. Otherwise, ** the system will get confused, we have a read-lock on the file and a ** mysterious journal has appeared in the filesystem. */ sqlite3OsDelete(pPager->zJournal); }else{ | | | 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 | /* If this was a malloc() failure, then we will not be closing the pager ** file. So delete any journal file we may have just created. Otherwise, ** the system will get confused, we have a read-lock on the file and a ** mysterious journal has appeared in the filesystem. */ sqlite3OsDelete(pPager->zJournal); }else{ pager_reset(pPager); } return rc; } /* ** Acquire a write-lock on the database. The lock is removed when ** the any of the following happen: |
︙ | ︙ |