blob: 7e183ed43babd1e6590b98f2617bcf6be21dde55 [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 */
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*/
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*/
107void 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*/
116static 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*/
126int 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
drh3088d592008-03-21 16:45:47 +0000147#endif /* SQLITE_OMIT_BUILTIN_TEST */