1 /* 2 ** 2008 Jan 22 3 ** 4 ** The author disclaims copyright to this source code. In place of 5 ** a legal notice, here is a blessing: 6 ** 7 ** May you do good and not evil. 8 ** May you find forgiveness for yourself and forgive others. 9 ** May you share freely, never taking more than you give. 10 ** 11 ************************************************************************* 12 ** This file contains code to implement a fault-injector used for 13 ** testing and verification of SQLite. 14 ** 15 ** Subsystems within SQLite can call sqlite3FaultStep() to see if 16 ** they should simulate a fault. sqlite3FaultStep() normally returns 17 ** zero but will return non-zero if a fault should be simulated. 18 ** Fault injectors can be used, for example, to simulate memory 19 ** allocation failures or I/O errors. 20 ** 21 ** The fault injector is omitted from the code if SQLite is 22 ** compiled with -DSQLITE_OMIT_BUILTIN_TEST=1. There is a very 23 ** small performance hit for leaving the fault injector in the code. 24 ** Commerical products will probably want to omit the fault injector 25 ** from production builds. But safety-critical systems who work 26 ** under the motto "fly what you test and test what you fly" may 27 ** choose to leave the fault injector enabled even in production. 28 */ 29 #include "sqliteInt.h" 30 31 #ifndef SQLITE_OMIT_BUILTIN_TEST 32 33 /* 34 ** There can be various kinds of faults. For example, there can be 35 ** a memory allocation failure. Or an I/O failure. For each different 36 ** fault type, there is a separate FaultInjector structure to keep track 37 ** of the status of that fault. 38 */ 39 static struct FaultInjector { 40 int iCountdown; /* Number of pending successes before we hit a failure */ 41 int nRepeat; /* Number of times to repeat the failure */ 42 int nBenign; /* Number of benign failures seen since last config */ 43 int nFail; /* Number of failures seen since last config */ 44 u8 enable; /* True if enabled */ 45 u8 benign; /* True if next failure will be benign */ 46 } aFault[SQLITE_FAULTINJECTOR_COUNT]; 47 48 /* 49 ** This routine configures and enables a fault injector. After 50 ** calling this routine, aFaultStep() will return false (zero) 51 ** nDelay times, then it will return true nRepeat times, 52 ** then it will again begin returning false. 53 */ 54 void sqlite3FaultConfig(int id, int nDelay, int nRepeat){ 55 assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT ); 56 aFault[id].iCountdown = nDelay; 57 aFault[id].nRepeat = nRepeat; 58 aFault[id].nBenign = 0; 59 aFault[id].nFail = 0; 60 aFault[id].enable = nDelay>=0; 61 aFault[id].benign = 0; 62 } 63 64 /* 65 ** Return the number of faults (both hard and benign faults) that have 66 ** occurred since the injector was last configured. 67 */ 68 int sqlite3FaultFailures(int id){ 69 assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT ); 70 return aFault[id].nFail; 71 } 72 73 /* 74 ** Return the number of benign faults that have occurred since the 75 ** injector was last configured. 76 */ 77 int sqlite3FaultBenignFailures(int id){ 78 assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT ); 79 return aFault[id].nBenign; 80 } 81 82 /* 83 ** Return the number of successes that will occur before the next failure. 84 ** If no failures are scheduled, return -1. 85 */ 86 int sqlite3FaultPending(int id){ 87 assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT ); 88 if( aFault[id].enable ){ 89 return aFault[id].iCountdown; 90 }else{ 91 return -1; 92 } 93 } 94 95 /* 96 ** After this routine causes subsequent faults to be either benign 97 ** or hard (not benign), according to the "enable" parameter. 98 ** 99 ** Most faults are hard. In other words, most faults cause 100 ** an error to be propagated back up to the application interface. 101 ** However, sometimes a fault is easily recoverable. For example, 102 ** if a malloc fails while resizing a hash table, this is completely 103 ** recoverable simply by not carrying out the resize. The hash table 104 ** will continue to function normally. So a malloc failure during 105 ** a hash table resize is a benign fault. 106 */ 107 void sqlite3FaultBenign(int id, int enable){ 108 if( id<0 ){ 109 for(id=0; id<SQLITE_FAULTINJECTOR_COUNT; id++){ 110 aFault[id].benign = enable; 111 } 112 }else{ 113 assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT ); 114 aFault[id].benign = enable; 115 } 116 } 117 118 /* 119 ** This routine exists as a place to set a breakpoint that will 120 ** fire on any simulated fault. 121 */ 122 static void sqlite3Fault(void){ 123 static int cnt = 0; 124 cnt++; 125 } 126 127 128 /* 129 ** Check to see if a fault should be simulated. Return true to simulate 130 ** the fault. Return false if the fault should not be simulated. 131 */ 132 int sqlite3FaultStep(int id){ 133 assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT ); 134 if( likely(!aFault[id].enable) ){ 135 return 0; 136 } 137 if( aFault[id].iCountdown>0 ){ 138 aFault[id].iCountdown--; 139 return 0; 140 } 141 sqlite3Fault(); 142 aFault[id].nFail++; 143 if( aFault[id].benign ){ 144 aFault[id].nBenign++; 145 } 146 aFault[id].nRepeat--; 147 if( aFault[id].nRepeat<=0 ){ 148 aFault[id].enable = 0; 149 } 150 return 1; 151 } 152 153 #endif /* SQLITE_OMIT_BUILTIN_TEST */ 154