Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add experimental API sqlite3_db_cacheflush(). |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | cacheflush |
Files: | files | file ages | folders |
SHA1: |
65b86dc1fa4a57cc3cde86a820d9f848 |
User & Date: | dan 2015-10-28 19:46:57.460 |
Context
2015-10-29
| ||
18:16 | Avoid automatically rolling back the transaction if an SQLITE_IOERR or SQLITE_FULL error occurs within sqlite3_db_cacheflush(). (check-in: 370b5d520c user: dan tags: cacheflush) | |
2015-10-28
| ||
19:46 | Add experimental API sqlite3_db_cacheflush(). (check-in: 65b86dc1fa user: dan tags: cacheflush) | |
16:05 | Factor out adding NOT expression nodes in the parser into a subroutine. (check-in: 0018541816 user: drh tags: trunk) | |
Changes
Changes to src/main.c.
︙ | ︙ | |||
735 736 737 738 739 740 741 742 743 744 745 746 747 748 | sqlite3PagerShrink(pPager); } } sqlite3BtreeLeaveAll(db); sqlite3_mutex_leave(db->mutex); return SQLITE_OK; } /* ** Configuration settings for an individual database connection */ int sqlite3_db_config(sqlite3 *db, int op, ...){ va_list ap; int rc; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 | sqlite3PagerShrink(pPager); } } sqlite3BtreeLeaveAll(db); sqlite3_mutex_leave(db->mutex); return SQLITE_OK; } /* ** Flush any dirty pages in the pager-cache for any attached database ** to disk. */ int sqlite3_db_cacheflush(sqlite3 *db){ int i; int rc = SQLITE_OK; int bSeenBusy = 0; #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; #endif sqlite3_mutex_enter(db->mutex); sqlite3BtreeEnterAll(db); for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ Btree *pBt = db->aDb[i].pBt; if( pBt && sqlite3BtreeIsInTrans(pBt) ){ Pager *pPager = sqlite3BtreePager(pBt); rc = sqlite3PagerFlush(pPager); if( rc==SQLITE_BUSY ){ bSeenBusy = 1; rc = SQLITE_OK; } } } if( rc!=SQLITE_OK ){ sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); } sqlite3BtreeLeaveAll(db); sqlite3_mutex_leave(db->mutex); return ((rc==SQLITE_OK && bSeenBusy) ? SQLITE_BUSY : rc); } /* ** Configuration settings for an individual database connection */ int sqlite3_db_config(sqlite3 *db, int op, ...){ va_list ap; int rc; |
︙ | ︙ |
Changes to src/pager.c.
︙ | ︙ | |||
4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 | PAGERTRACE(("STRESS %d page %d\n", PAGERID(pPager), pPg->pgno)); sqlite3PcacheMakeClean(pPg); } return pager_error(pPager, rc); } /* ** Allocate and initialize a new Pager object and put a pointer to it ** in *ppPager. The pager should eventually be freed by passing it ** to sqlite3PagerClose(). ** ** The zFilename argument is the path to the database file to open. | > > > > > > > > > > > > > > > > > | 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 | PAGERTRACE(("STRESS %d page %d\n", PAGERID(pPager), pPg->pgno)); sqlite3PcacheMakeClean(pPg); } return pager_error(pPager, rc); } /* ** Flush all unreferenced dirty pages to disk. */ int sqlite3PagerFlush(Pager *pPager){ int rc = SQLITE_OK; PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache); while( rc==SQLITE_OK && pList ){ PgHdr *pNext = pList->pDirty; if( pList->nRef==0 ){ rc = pagerStress((void*)pPager, pList); } pList = pNext; } return rc; } /* ** Allocate and initialize a new Pager object and put a pointer to it ** in *ppPager. The pager should eventually be freed by passing it ** to sqlite3PagerClose(). ** ** The zFilename argument is the path to the database file to open. |
︙ | ︙ |
Changes to src/pager.h.
︙ | ︙ | |||
128 129 130 131 132 133 134 135 136 137 138 139 140 141 | void sqlite3PagerSetFlags(Pager*,unsigned); int sqlite3PagerLockingMode(Pager *, int); int sqlite3PagerSetJournalMode(Pager *, int); int sqlite3PagerGetJournalMode(Pager*); int sqlite3PagerOkToChangeJournalMode(Pager*); i64 sqlite3PagerJournalSizeLimit(Pager *, i64); sqlite3_backup **sqlite3PagerBackupPtr(Pager*); /* Functions used to obtain and release page references. */ int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag); #define sqlite3PagerGet(A,B,C) sqlite3PagerAcquire(A,B,C,0) DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno); void sqlite3PagerRef(DbPage*); void sqlite3PagerUnref(DbPage*); | > | 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | void sqlite3PagerSetFlags(Pager*,unsigned); int sqlite3PagerLockingMode(Pager *, int); int sqlite3PagerSetJournalMode(Pager *, int); int sqlite3PagerGetJournalMode(Pager*); int sqlite3PagerOkToChangeJournalMode(Pager*); i64 sqlite3PagerJournalSizeLimit(Pager *, i64); sqlite3_backup **sqlite3PagerBackupPtr(Pager*); int sqlite3PagerFlush(Pager*); /* Functions used to obtain and release page references. */ int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag); #define sqlite3PagerGet(A,B,C) sqlite3PagerAcquire(A,B,C,0) DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno); void sqlite3PagerRef(DbPage*); void sqlite3PagerUnref(DbPage*); |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
7788 7789 7790 7791 7792 7793 7794 7795 7796 7797 7798 7799 7800 7801 | ** ^Zero all [sqlite3_stmt_scanstatus()] related event counters. ** ** This API is only available if the library is built with pre-processor ** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined. */ void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. */ #ifdef SQLITE_OMIT_FLOATING_POINT # undef double | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 7788 7789 7790 7791 7792 7793 7794 7795 7796 7797 7798 7799 7800 7801 7802 7803 7804 7805 7806 7807 7808 7809 7810 7811 7812 7813 7814 7815 7816 7817 7818 7819 7820 7821 7822 7823 7824 7825 7826 7827 7828 7829 7830 7831 | ** ^Zero all [sqlite3_stmt_scanstatus()] related event counters. ** ** This API is only available if the library is built with pre-processor ** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined. */ void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); /* ** CAPI3REF: Flush caches to disk mid-transaction ** ** If a write-transaction is open when this function is called, any dirty ** pages in the pager-cache that are not currently in use are written out ** to disk. A dirty page may be in use if a database cursor created by an ** active SQL statement is reading from it, or if it is page 1 of a database ** file (page 1 is always "in use"). Dirty pages are flushed for all ** databases - "main", "temp" and any attached databases. ** ** If this function needs to obtain extra database locks before dirty pages ** can be flushed to disk, it does so. If said locks cannot be obtained ** immediately and there is a busy-handler callback configured, it is invoked ** in the usual manner. If the required lock still cannot be obtained, then ** the database is skipped and an attempt made to flush any dirty pages ** belonging to the next (if any) database. If any databases are skipped ** because locks cannot be obtained, but no other error occurs, this ** function returns SQLITE_BUSY. ** ** If any other error occurs while flushing dirty pages to disk (for ** example an IO error or out-of-memory condition), then processing is ** abandoned and an SQLite error code returned to the caller immediately. ** In this case the open transaction may be automatically rolled back. ** ** Otherwise, if no error occurs, SQLITE_OK is returned. ** ** This function does not set the database handle error code or message ** returned by the sqlite3_errcode() and sqlite3_errmsg() functions. */ int sqlite3_db_cacheflush(sqlite3*); /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. */ #ifdef SQLITE_OMIT_FLOATING_POINT # undef double |
︙ | ︙ |
Changes to src/test1.c.
︙ | ︙ | |||
4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 | return TCL_ERROR; } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; rc = sqlite3_db_release_memory(db); Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); return TCL_OK; } /* ** Usage: sqlite3_db_filename DB DBNAME ** ** Return the name of a file associated with a database. */ static int test_db_filename( | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 | return TCL_ERROR; } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; rc = sqlite3_db_release_memory(db); Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); return TCL_OK; } /* ** Usage: sqlite3_db_cacheflush DB ** ** Attempt to flush any dirty pages to disk. */ static int test_db_cacheflush( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ sqlite3 *db; int rc; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "DB"); return TCL_ERROR; } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; rc = sqlite3_db_cacheflush(db); if( rc ){ Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC); return TCL_ERROR; } Tcl_ResetResult(interp); return TCL_OK; } /* ** Usage: sqlite3_db_filename DB DBNAME ** ** Return the name of a file associated with a database. */ static int test_db_filename( |
︙ | ︙ | |||
6872 6873 6874 6875 6876 6877 6878 6879 6880 6881 6882 6883 6884 6885 | { "sqlite3_next_stmt", test_next_stmt ,0 }, { "sqlite3_stmt_readonly", test_stmt_readonly ,0 }, { "sqlite3_stmt_busy", test_stmt_busy ,0 }, { "uses_stmt_journal", uses_stmt_journal ,0 }, { "sqlite3_release_memory", test_release_memory, 0}, { "sqlite3_db_release_memory", test_db_release_memory, 0}, { "sqlite3_db_filename", test_db_filename, 0}, { "sqlite3_db_readonly", test_db_readonly, 0}, { "sqlite3_soft_heap_limit", test_soft_heap_limit, 0}, { "sqlite3_thread_cleanup", test_thread_cleanup, 0}, { "sqlite3_pager_refcounts", test_pager_refcounts, 0}, { "sqlite3_load_extension", test_load_extension, 0}, | > | 6900 6901 6902 6903 6904 6905 6906 6907 6908 6909 6910 6911 6912 6913 6914 | { "sqlite3_next_stmt", test_next_stmt ,0 }, { "sqlite3_stmt_readonly", test_stmt_readonly ,0 }, { "sqlite3_stmt_busy", test_stmt_busy ,0 }, { "uses_stmt_journal", uses_stmt_journal ,0 }, { "sqlite3_release_memory", test_release_memory, 0}, { "sqlite3_db_release_memory", test_db_release_memory, 0}, { "sqlite3_db_cacheflush", test_db_cacheflush, 0}, { "sqlite3_db_filename", test_db_filename, 0}, { "sqlite3_db_readonly", test_db_readonly, 0}, { "sqlite3_soft_heap_limit", test_soft_heap_limit, 0}, { "sqlite3_thread_cleanup", test_thread_cleanup, 0}, { "sqlite3_pager_refcounts", test_pager_refcounts, 0}, { "sqlite3_load_extension", test_load_extension, 0}, |
︙ | ︙ |
Added test/cacheflush.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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | # 2011 November 16 # # 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 contains test cases for sqlite3_db_cacheflush API. # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix cacheflush test_set_config_pagecache 0 0 # Run the supplied SQL on a copy of the database currently stored on # disk in file $dbfile. proc diskquery {dbfile sql} { forcecopy $dbfile dq.db sqlite3 dq dq.db set res [execsql $sql dq] dq close set res } # Simplest possible test. # do_execsql_test 1.1.0 { CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); BEGIN; INSERT INTO t1 VALUES(3, 4); } do_test 1.1.1 { diskquery test.db { SELECT * FROM t1 } } {1 2} do_test 1.1.2 { sqlite3_db_cacheflush db diskquery test.db { SELECT * FROM t1 } } {1 2 3 4} # Test that multiple pages may be flushed to disk. # do_execsql_test 1.2.0 { COMMIT; CREATE TABLE t2(a, b); BEGIN; INSERT INTO t1 VALUES(5, 6); INSERT INTO t2 VALUES('a', 'b'); } do_test 1.2.1 { diskquery test.db { SELECT * FROM t1; SELECT * FROM t2; } } {1 2 3 4} do_test 1.2.2 { sqlite3_db_cacheflush db diskquery test.db { SELECT * FROM t1; SELECT * FROM t2; } } {1 2 3 4 5 6 a b} # Test that pages with nRef!=0 are not flushed to disk. # do_execsql_test 1.3.0 { COMMIT; CREATE TABLE t3(a, b); BEGIN; INSERT INTO t1 VALUES(7, 8); INSERT INTO t2 VALUES('c', 'd'); INSERT INTO t3 VALUES('i', 'ii'); } do_test 1.3.1 { diskquery test.db { SELECT * FROM t1; SELECT * FROM t2; SELECT * FROM t3; } } {1 2 3 4 5 6 a b} do_test 1.3.2 { db eval { SELECT a FROM t1 } { if {$a==3} { sqlite3_db_cacheflush db } } diskquery test.db { SELECT * FROM t1; SELECT * FROM t2; SELECT * FROM t3; } } {1 2 3 4 5 6 a b c d i ii} do_test 1.3.2 { sqlite3_db_cacheflush db diskquery test.db { SELECT * FROM t1; SELECT * FROM t2; SELECT * FROM t3; } } {1 2 3 4 5 6 7 8 a b c d i ii} # Check that SQLITE_BUSY is returned if pages cannot be flushed due to # conflicting read locks. # do_execsql_test 1.4.0 { COMMIT; BEGIN; INSERT INTO t1 VALUES(9, 10); } do_test 1.4.1 { sqlite3 db2 test.db db2 eval { BEGIN; SELECT * FROM t1; } diskquery test.db { SELECT * FROM t1; } } {1 2 3 4 5 6 7 8} do_test 1.4.2 { list [catch { sqlite3_db_cacheflush db } msg] $msg } {1 {database is locked}} do_test 1.4.3 { diskquery test.db { SELECT * FROM t1; } } {1 2 3 4 5 6 7 8} do_test 1.4.4 { db2 close sqlite3_db_cacheflush db diskquery test.db { SELECT * FROM t1; } } {1 2 3 4 5 6 7 8 9 10} do_execsql_test 1.4.5 { COMMIT } #------------------------------------------------------------------------- # Test that ATTACHed database caches are also flushed. # forcedelete test.db2 do_execsql_test 2.1.0 { ATTACH 'test.db2' AS aux; CREATE TABLE aux.t4(x, y); INSERT INTO t4 VALUES('A', 'B'); BEGIN; INSERT INTO t1 VALUES(11, 12); INSERT INTO t4 VALUES('C', 'D'); } do_test 2.1.1 { diskquery test.db { SELECT * FROM t1; } } {1 2 3 4 5 6 7 8 9 10} do_test 2.1.2 { diskquery test.db2 { SELECT * FROM t4; } } {A B} do_test 2.1.3 { sqlite3_db_cacheflush db diskquery test.db { SELECT * FROM t1; } } {1 2 3 4 5 6 7 8 9 10 11 12} do_test 2.1.4 { sqlite3_db_cacheflush db diskquery test.db2 { SELECT * FROM t4; } } {A B C D} do_execsql_test 2.1.5 { COMMIT } # And that hitting an SQLITE_BUSY when flushing "main" does not stop # SQLite from going on to flush "aux". # do_execsql_test 2.2.0 { BEGIN; INSERT INTO t1 VALUES(13, 14); INSERT INTO t4 VALUES('E', 'F'); } do_test 2.2.1 { diskquery test.db { SELECT * FROM t1; } } {1 2 3 4 5 6 7 8 9 10 11 12} do_test 2.2.2 { diskquery test.db2 { SELECT * FROM t4; } } {A B C D} do_test 2.2.3 { sqlite3 db2 test.db execsql { BEGIN; SELECT * FROM t1; } db2 list [catch { sqlite3_db_cacheflush db } msg] $msg } {1 {database is locked}} do_test 2.2.4 { diskquery test.db { SELECT * FROM t1; } } {1 2 3 4 5 6 7 8 9 10 11 12} do_test 2.2.5 { diskquery test.db2 { SELECT * FROM t4; } } {A B C D E F} do_test 2.2.6 { db2 close sqlite3_db_cacheflush db diskquery test.db { SELECT * FROM t1; } } {1 2 3 4 5 6 7 8 9 10 11 12 13 14} do_execsql_test 2.2.7 { COMMIT } test_restore_config_pagecache finish_test |
Added test/cffault.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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | # 2011 November 16 # # 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 contains fault-injection test cases for the # sqlite3_db_cacheflush API. # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix cacheflush source $testdir/malloc_common.tcl # Run the supplied SQL on a copy of the database currently stored on # disk in file $dbfile. proc diskquery {dbfile sql} { forcecopy $dbfile dq.db sqlite3 dq dq.db set res [execsql $sql dq] dq close set res } do_execsql_test 1.0 { CREATE TABLE t1(a PRIMARY KEY, b); CREATE INDEX i1 ON t1(b); INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(3, 4); INSERT INTO t1 VALUES(5, 6); INSERT INTO t1 VALUES(7, 8); } faultsim_save_and_close do_faultsim_test 1 -prep { faultsim_restore_and_reopen db eval { BEGIN; UPDATE t1 SET b=b+1; } } -body { sqlite3_db_cacheflush db } -test { faultsim_test_result {0 {}} {1 {disk I/O error}} catch { db eval COMMIT } faultsim_integrity_check } finish_test |