blob: cded2351d8c0a5fc4cf18526756c26d7079e73cb [file] [log] [blame]
drh643167f2008-01-22 21:30:53 +00001/*
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
drh3088d592008-03-21 16:45:47 +000022** compiled with -DSQLITE_OMIT_BUILTIN_TEST=1. There is a very
drh643167f2008-01-22 21:30:53 +000023** 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
drh3088d592008-03-21 16:45:47 +000031#ifndef SQLITE_OMIT_BUILTIN_TEST
drh643167f2008-01-22 21:30:53 +000032
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*/
39static 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 */
drh4873d5f2008-05-13 13:27:33 +000045 i16 benign; /* Positive if next failure will be benign */
drh643167f2008-01-22 21:30:53 +000046} 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*/
54void 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*/
68int 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*/
77int 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*/
86int 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*/
drh4873d5f2008-05-13 13:27:33 +0000107void sqlite3FaultBeginBenign(int id){
drh19db9352008-03-27 22:42:51 +0000108 if( id<0 ){
109 for(id=0; id<SQLITE_FAULTINJECTOR_COUNT; id++){
drh4873d5f2008-05-13 13:27:33 +0000110 aFault[id].benign++;
drh19db9352008-03-27 22:42:51 +0000111 }
112 }else{
113 assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT );
drh4873d5f2008-05-13 13:27:33 +0000114 aFault[id].benign++;
115 }
116}
117void sqlite3FaultEndBenign(int id){
118 if( id<0 ){
119 for(id=0; id<SQLITE_FAULTINJECTOR_COUNT; id++){
120 assert( aFault[id].benign>0 );
121 aFault[id].benign--;
122 }
123 }else{
124 assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT );
125 assert( aFault[id].benign>0 );
126 aFault[id].benign--;
drh19db9352008-03-27 22:42:51 +0000127 }
drh643167f2008-01-22 21:30:53 +0000128}
129
130/*
131** This routine exists as a place to set a breakpoint that will
132** fire on any simulated fault.
133*/
134static void sqlite3Fault(void){
135 static int cnt = 0;
136 cnt++;
137}
138
139
140/*
141** Check to see if a fault should be simulated. Return true to simulate
142** the fault. Return false if the fault should not be simulated.
143*/
144int sqlite3FaultStep(int id){
145 assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT );
146 if( likely(!aFault[id].enable) ){
147 return 0;
148 }
149 if( aFault[id].iCountdown>0 ){
150 aFault[id].iCountdown--;
151 return 0;
152 }
153 sqlite3Fault();
154 aFault[id].nFail++;
drh4873d5f2008-05-13 13:27:33 +0000155 if( aFault[id].benign>0 ){
drh643167f2008-01-22 21:30:53 +0000156 aFault[id].nBenign++;
157 }
158 aFault[id].nRepeat--;
159 if( aFault[id].nRepeat<=0 ){
160 aFault[id].enable = 0;
161 }
162 return 1;
163}
164
drh3088d592008-03-21 16:45:47 +0000165#endif /* SQLITE_OMIT_BUILTIN_TEST */