fault.c
上传用户:sunhongbo
上传日期:2022-01-25
资源大小:3010k
文件大小:5k
源码类别:

数据库系统

开发平台:

C/C++

  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. #ifndef SQLITE_OMIT_BUILTIN_TEST
  31. /*
  32. ** There can be various kinds of faults.  For example, there can be
  33. ** a memory allocation failure.  Or an I/O failure.  For each different
  34. ** fault type, there is a separate FaultInjector structure to keep track
  35. ** of the status of that fault.
  36. */
  37. static struct FaultInjector {
  38.   int iCountdown;   /* Number of pending successes before we hit a failure */
  39.   int nRepeat;      /* Number of times to repeat the failure */
  40.   int nBenign;      /* Number of benign failures seen since last config */
  41.   int nFail;        /* Number of failures seen since last config */
  42.   u8 enable;        /* True if enabled */
  43.   u8 benign;        /* True if next failure will be benign */
  44. } aFault[SQLITE_FAULTINJECTOR_COUNT];
  45. /*
  46. ** This routine configures and enables a fault injector.  After
  47. ** calling this routine, aFaultStep() will return false (zero)
  48. ** nDelay times, then it will return true nRepeat times,
  49. ** then it will again begin returning false.
  50. */
  51. void sqlite3FaultConfig(int id, int nDelay, int nRepeat){
  52.   assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT );
  53.   aFault[id].iCountdown = nDelay;
  54.   aFault[id].nRepeat = nRepeat;
  55.   aFault[id].nBenign = 0;
  56.   aFault[id].nFail = 0;
  57.   aFault[id].enable = nDelay>=0;
  58.   aFault[id].benign = 0;
  59. }
  60. /*
  61. ** Return the number of faults (both hard and benign faults) that have
  62. ** occurred since the injector was last configured.
  63. */
  64. int sqlite3FaultFailures(int id){
  65.   assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT );
  66.   return aFault[id].nFail;
  67. }
  68. /*
  69. ** Return the number of benign faults that have occurred since the
  70. ** injector was last configured.
  71. */
  72. int sqlite3FaultBenignFailures(int id){
  73.   assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT );
  74.   return aFault[id].nBenign;
  75. }
  76. /*
  77. ** Return the number of successes that will occur before the next failure.
  78. ** If no failures are scheduled, return -1.
  79. */
  80. int sqlite3FaultPending(int id){
  81.   assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT );
  82.   if( aFault[id].enable ){
  83.     return aFault[id].iCountdown;
  84.   }else{
  85.     return -1;
  86.   }
  87. }
  88. /* 
  89. ** After this routine causes subsequent faults to be either benign
  90. ** or hard (not benign), according to the "enable" parameter.
  91. **
  92. ** Most faults are hard.  In other words, most faults cause
  93. ** an error to be propagated back up to the application interface.
  94. ** However, sometimes a fault is easily recoverable.  For example,
  95. ** if a malloc fails while resizing a hash table, this is completely
  96. ** recoverable simply by not carrying out the resize.  The hash table
  97. ** will continue to function normally.  So a malloc failure during
  98. ** a hash table resize is a benign fault.  
  99. */
  100. void sqlite3FaultBenign(int id, int enable){
  101.   if( id<0 ){
  102.     for(id=0; id<SQLITE_FAULTINJECTOR_COUNT; id++){
  103.       aFault[id].benign = enable;
  104.     }
  105.   }else{
  106.     assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT );
  107.     aFault[id].benign = enable;
  108.   }
  109. }
  110. /*
  111. ** This routine exists as a place to set a breakpoint that will
  112. ** fire on any simulated fault.
  113. */
  114. static void sqlite3Fault(void){
  115.   static int cnt = 0;
  116.   cnt++;
  117. }
  118. /*
  119. ** Check to see if a fault should be simulated.  Return true to simulate
  120. ** the fault.  Return false if the fault should not be simulated.
  121. */
  122. int sqlite3FaultStep(int id){
  123.   assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT );
  124.   if( likely(!aFault[id].enable) ){
  125.     return 0;
  126.   }
  127.   if( aFault[id].iCountdown>0 ){
  128.     aFault[id].iCountdown--;
  129.     return 0;
  130.   }
  131.   sqlite3Fault();
  132.   aFault[id].nFail++;
  133.   if( aFault[id].benign ){
  134.     aFault[id].nBenign++;
  135.   }
  136.   aFault[id].nRepeat--;
  137.   if( aFault[id].nRepeat<=0 ){
  138.     aFault[id].enable = 0;
  139.   }
  140.   return 1;  
  141. }
  142. #endif /* SQLITE_OMIT_BUILTIN_TEST */