drh | 643167f | 2008-01-22 21:30:53 +0000 | [diff] [blame] | 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 |
drh | 3088d59 | 2008-03-21 16:45:47 +0000 | [diff] [blame^] | 22 | ** compiled with -DSQLITE_OMIT_BUILTIN_TEST=1. There is a very |
drh | 643167f | 2008-01-22 21:30:53 +0000 | [diff] [blame] | 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 | |
drh | 3088d59 | 2008-03-21 16:45:47 +0000 | [diff] [blame^] | 31 | #ifndef SQLITE_OMIT_BUILTIN_TEST |
drh | 643167f | 2008-01-22 21:30:53 +0000 | [diff] [blame] | 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; /* Ture 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 | assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT ); |
| 109 | aFault[id].benign = enable; |
| 110 | } |
| 111 | |
| 112 | /* |
| 113 | ** This routine exists as a place to set a breakpoint that will |
| 114 | ** fire on any simulated fault. |
| 115 | */ |
| 116 | static void sqlite3Fault(void){ |
| 117 | static int cnt = 0; |
| 118 | cnt++; |
| 119 | } |
| 120 | |
| 121 | |
| 122 | /* |
| 123 | ** Check to see if a fault should be simulated. Return true to simulate |
| 124 | ** the fault. Return false if the fault should not be simulated. |
| 125 | */ |
| 126 | int sqlite3FaultStep(int id){ |
| 127 | assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT ); |
| 128 | if( likely(!aFault[id].enable) ){ |
| 129 | return 0; |
| 130 | } |
| 131 | if( aFault[id].iCountdown>0 ){ |
| 132 | aFault[id].iCountdown--; |
| 133 | return 0; |
| 134 | } |
| 135 | sqlite3Fault(); |
| 136 | aFault[id].nFail++; |
| 137 | if( aFault[id].benign ){ |
| 138 | aFault[id].nBenign++; |
| 139 | } |
| 140 | aFault[id].nRepeat--; |
| 141 | if( aFault[id].nRepeat<=0 ){ |
| 142 | aFault[id].enable = 0; |
| 143 | } |
| 144 | return 1; |
| 145 | } |
| 146 | |
drh | 3088d59 | 2008-03-21 16:45:47 +0000 | [diff] [blame^] | 147 | #endif /* SQLITE_OMIT_BUILTIN_TEST */ |