YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/rocksdb/util/sync_point.h
Line
Count
Source (jump to first uncovered line)
1
//  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2
//  This source code is licensed under the BSD-style license found in the
3
//  LICENSE file in the root directory of this source tree. An additional grant
4
//  of patent rights can be found in the PATENTS file in the same directory.
5
//
6
// The following only applies to changes made to this file as part of YugaByte development.
7
//
8
// Portions Copyright (c) YugaByte, Inc.
9
//
10
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
11
// in compliance with the License.  You may obtain a copy of the License at
12
//
13
// http://www.apache.org/licenses/LICENSE-2.0
14
//
15
// Unless required by applicable law or agreed to in writing, software distributed under the License
16
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
17
// or implied.  See the License for the specific language governing permissions and limitations
18
// under the License.
19
//
20
#pragma once
21
22
#include <condition_variable>
23
#include <functional>
24
#include <unordered_map>
25
#include <unordered_set>
26
#include <vector>
27
28
// This is only set from db_stress.cc and for testing only.
29
// If non-zero, kill at various points in source code with probability 1/this
30
extern int rocksdb_kill_odds;
31
// If kill point has a prefix on this list, will skip killing.
32
extern std::vector<std::string> rocksdb_kill_prefix_blacklist;
33
34
#ifdef NDEBUG
35
// empty in release build
36
#define TEST_KILL_RANDOM(kill_point, rocksdb_kill_odds)
37
#else
38
39
namespace rocksdb {
40
// Kill the process with probablity 1/odds for testing.
41
extern void TestKillRandom(std::string kill_point, int odds,
42
                           const std::string& srcfile, int srcline);
43
44
// To avoid crashing always at some frequently executed codepaths (during
45
// kill random test), use this factor to reduce odds
46
#define REDUCE_ODDS 2
47
#define REDUCE_ODDS2 4
48
49
#define TEST_KILL_RANDOM(kill_point, rocksdb_kill_odds)                  \
50
150M
  {                                                                      \
51
150M
    if (rocksdb_kill_odds > 0) {                                         \
52
0
      TestKillRandom(kill_point, rocksdb_kill_odds, __FILE__, __LINE__); \
53
0
    }                                                                    \
54
150M
  }
55
}  // namespace rocksdb
56
#endif
57
58
#ifdef NDEBUG
59
#define TEST_SYNC_POINT(x)
60
#define TEST_SYNC_POINT_CALLBACK(x, y)
61
#else
62
63
namespace rocksdb {
64
65
// This class provides facility to reproduce race conditions deterministically
66
// in unit tests.
67
// Developer could specify sync points in the codebase via TEST_SYNC_POINT.
68
// Each sync point represents a position in the execution stream of a thread.
69
// In the unit test, 'Happens After' relationship among sync points could be
70
// setup via SyncPoint::LoadDependency, to reproduce a desired interleave of
71
// threads execution.
72
// Refer to (DBTest,TransactionLogIteratorRace), for an example use case.
73
74
class SyncPoint {
75
 public:
76
  static SyncPoint* GetInstance();
77
78
  struct Dependency {
79
    std::string predecessor;
80
    std::string successor;
81
  };
82
  // call once at the beginning of a test to setup the dependency between
83
  // sync points
84
  void LoadDependency(const std::vector<Dependency>& dependencies);
85
86
  // Set up a call back function in sync point.
87
  void SetCallBack(const std::string point,
88
                   std::function<void(void*)> callback);
89
  // Clear all call back functions.
90
  void ClearAllCallBacks();
91
92
  // enable sync point processing (disabled on startup)
93
  void EnableProcessing();
94
95
  // disable sync point processing
96
  void DisableProcessing();
97
98
  // remove the execution trace of all sync points
99
  void ClearTrace();
100
101
  // triggered by TEST_SYNC_POINT, blocking execution until all predecessors
102
  // are executed.
103
  // And/or call registered callback functionn, with argument `cb_arg`
104
  void Process(const std::string& point, void* cb_arg = nullptr);
105
106
  // TODO: it might be useful to provide a function that blocks until all
107
  // sync points are cleared.
108
109
 private:
110
  bool PredecessorsAllCleared(const std::string& point);
111
112
  // successor/predecessor map loaded from LoadDependency
113
  std::unordered_map<std::string, std::vector<std::string>> successors_;
114
  std::unordered_map<std::string, std::vector<std::string>> predecessors_;
115
  std::unordered_map<std::string, std::function<void(void*)> > callbacks_;
116
117
  std::mutex mutex_;
118
  std::condition_variable cv_;
119
  // sync points that have been passed through
120
  std::unordered_set<std::string> cleared_points_;
121
  bool enabled_ = false;
122
  int num_callbacks_running_ = 0;
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
109M
#define TEST_SYNC_POINT(x) rocksdb::SyncPoint::GetInstance()->Process(x)
134
#define TEST_SYNC_POINT_CALLBACK(x, y) \
135
42.0M
  rocksdb::SyncPoint::GetInstance()->Process(x, y)
136
#endif  // NDEBUG