]>
Commit | Line | Data |
---|---|---|
7c673cae | 1 | // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. |
11fdf7f2 TL |
2 | // This source code is licensed under both the GPLv2 (found in the |
3 | // COPYING file in the root directory) and Apache 2.0 License | |
4 | // (found in the LICENSE.Apache file in the root directory). | |
7c673cae FG |
5 | #pragma once |
6 | ||
7 | #include <assert.h> | |
7c673cae FG |
8 | #include <functional> |
9 | #include <mutex> | |
10 | #include <string> | |
11 | #include <thread> | |
7c673cae FG |
12 | #include <vector> |
13 | ||
14 | // This is only set from db_stress.cc and for testing only. | |
15 | // If non-zero, kill at various points in source code with probability 1/this | |
16 | extern int rocksdb_kill_odds; | |
17 | // If kill point has a prefix on this list, will skip killing. | |
18 | extern std::vector<std::string> rocksdb_kill_prefix_blacklist; | |
19 | ||
20 | #ifdef NDEBUG | |
21 | // empty in release build | |
22 | #define TEST_KILL_RANDOM(kill_point, rocksdb_kill_odds) | |
23 | #else | |
24 | ||
25 | namespace rocksdb { | |
11fdf7f2 | 26 | // Kill the process with probability 1/odds for testing. |
7c673cae FG |
27 | extern void TestKillRandom(std::string kill_point, int odds, |
28 | const std::string& srcfile, int srcline); | |
29 | ||
30 | // To avoid crashing always at some frequently executed codepaths (during | |
31 | // kill random test), use this factor to reduce odds | |
32 | #define REDUCE_ODDS 2 | |
33 | #define REDUCE_ODDS2 4 | |
34 | ||
35 | #define TEST_KILL_RANDOM(kill_point, rocksdb_kill_odds) \ | |
36 | { \ | |
37 | if (rocksdb_kill_odds > 0) { \ | |
38 | TestKillRandom(kill_point, rocksdb_kill_odds, __FILE__, __LINE__); \ | |
39 | } \ | |
40 | } | |
41 | } // namespace rocksdb | |
42 | #endif | |
43 | ||
44 | #ifdef NDEBUG | |
45 | #define TEST_SYNC_POINT(x) | |
11fdf7f2 | 46 | #define TEST_IDX_SYNC_POINT(x, index) |
7c673cae | 47 | #define TEST_SYNC_POINT_CALLBACK(x, y) |
11fdf7f2 | 48 | #define INIT_SYNC_POINT_SINGLETONS() |
7c673cae FG |
49 | #else |
50 | ||
51 | namespace rocksdb { | |
52 | ||
53 | // This class provides facility to reproduce race conditions deterministically | |
54 | // in unit tests. | |
55 | // Developer could specify sync points in the codebase via TEST_SYNC_POINT. | |
56 | // Each sync point represents a position in the execution stream of a thread. | |
57 | // In the unit test, 'Happens After' relationship among sync points could be | |
58 | // setup via SyncPoint::LoadDependency, to reproduce a desired interleave of | |
59 | // threads execution. | |
60 | // Refer to (DBTest,TransactionLogIteratorRace), for an example use case. | |
61 | ||
62 | class SyncPoint { | |
63 | public: | |
64 | static SyncPoint* GetInstance(); | |
65 | ||
11fdf7f2 TL |
66 | SyncPoint(const SyncPoint&) = delete; |
67 | SyncPoint& operator=(const SyncPoint&) = delete; | |
68 | ~SyncPoint(); | |
69 | ||
7c673cae FG |
70 | struct SyncPointPair { |
71 | std::string predecessor; | |
72 | std::string successor; | |
73 | }; | |
74 | ||
75 | // call once at the beginning of a test to setup the dependency between | |
76 | // sync points | |
77 | void LoadDependency(const std::vector<SyncPointPair>& dependencies); | |
78 | ||
79 | // call once at the beginning of a test to setup the dependency between | |
80 | // sync points and setup markers indicating the successor is only enabled | |
81 | // when it is processed on the same thread as the predecessor. | |
82 | // When adding a marker, it implicitly adds a dependency for the marker pair. | |
83 | void LoadDependencyAndMarkers(const std::vector<SyncPointPair>& dependencies, | |
84 | const std::vector<SyncPointPair>& markers); | |
85 | ||
11fdf7f2 TL |
86 | // The argument to the callback is passed through from |
87 | // TEST_SYNC_POINT_CALLBACK(); nullptr if TEST_SYNC_POINT or | |
88 | // TEST_IDX_SYNC_POINT was used. | |
89 | void SetCallBack(const std::string& point, | |
90 | const std::function<void(void*)>& callback); | |
91 | ||
92 | // Clear callback function by point | |
93 | void ClearCallBack(const std::string& point); | |
94 | ||
7c673cae FG |
95 | // Clear all call back functions. |
96 | void ClearAllCallBacks(); | |
97 | ||
98 | // enable sync point processing (disabled on startup) | |
99 | void EnableProcessing(); | |
100 | ||
101 | // disable sync point processing | |
102 | void DisableProcessing(); | |
103 | ||
104 | // remove the execution trace of all sync points | |
105 | void ClearTrace(); | |
106 | ||
107 | // triggered by TEST_SYNC_POINT, blocking execution until all predecessors | |
108 | // are executed. | |
11fdf7f2 | 109 | // And/or call registered callback function, with argument `cb_arg` |
7c673cae FG |
110 | void Process(const std::string& point, void* cb_arg = nullptr); |
111 | ||
112 | // TODO: it might be useful to provide a function that blocks until all | |
113 | // sync points are cleared. | |
114 | ||
11fdf7f2 TL |
115 | // We want this to be public so we can |
116 | // subclass the implementation | |
117 | struct Data; | |
118 | ||
7c673cae | 119 | private: |
11fdf7f2 TL |
120 | // Singleton |
121 | SyncPoint(); | |
122 | Data* impl_; | |
7c673cae FG |
123 | }; |
124 | ||
125 | } // namespace rocksdb | |
126 | ||
127 | // Use TEST_SYNC_POINT to specify sync points inside code base. | |
128 | // Sync points can have happens-after depedency on other sync points, | |
129 | // configured at runtime via SyncPoint::LoadDependency. This could be | |
130 | // utilized to re-produce race conditions between threads. | |
131 | // See TransactionLogIteratorRace in db_test.cc for an example use case. | |
132 | // TEST_SYNC_POINT is no op in release build. | |
133 | #define TEST_SYNC_POINT(x) rocksdb::SyncPoint::GetInstance()->Process(x) | |
11fdf7f2 TL |
134 | #define TEST_IDX_SYNC_POINT(x, index) \ |
135 | rocksdb::SyncPoint::GetInstance()->Process(x + std::to_string(index)) | |
7c673cae FG |
136 | #define TEST_SYNC_POINT_CALLBACK(x, y) \ |
137 | rocksdb::SyncPoint::GetInstance()->Process(x, y) | |
11fdf7f2 TL |
138 | #define INIT_SYNC_POINT_SINGLETONS() \ |
139 | (void)rocksdb::SyncPoint::GetInstance(); | |
7c673cae | 140 | #endif // NDEBUG |