1#ifdef TOKU_INSTR_MYSQL_H
2// This file can be included only from toku_instumentation.h because
3// it replaces the defintitions for the case if MySQL PFS is available
4#error "toku_instr_mysql.h can be included only once"
5#else // TOKU_INSTR_MYSQL_H
6#define TOKU_INSTR_MYSQL_H
7
8#include <memory>
9
10// As these macros are defined in my_global.h
11// and they are also defined in command line
12// undefine them here to avoid compilation errors.
13#undef __STDC_FORMAT_MACROS
14#undef __STDC_LIMIT_MACROS
15#include <mysql/psi/mysql_file.h> // PSI_file
16#include <mysql/psi/mysql_thread.h> // PSI_mutex
17
18#ifndef HAVE_PSI_MUTEX_INTERFACE
19#error HAVE_PSI_MUTEX_INTERFACE required
20#endif
21#ifndef HAVE_PSI_RWLOCK_INTERFACE
22#error HAVE_PSI_RWLOCK_INTERFACE required
23#endif
24#ifndef HAVE_PSI_THREAD_INTERFACE
25#error HAVE_PSI_THREAD_INTERFACE required
26#endif
27
28// Instrumentation keys
29
30class toku_instr_key {
31 private:
32 pfs_key_t m_id;
33
34 public:
35 toku_instr_key(toku_instr_object_type type,
36 const char *group,
37 const char *name) {
38 switch (type) {
39 case toku_instr_object_type::mutex: {
40 PSI_mutex_info mutex_info{&m_id, name, 0};
41 mysql_mutex_register(group, &mutex_info, 1);
42 } break;
43 case toku_instr_object_type::rwlock: {
44 PSI_rwlock_info rwlock_info{&m_id, name, 0};
45 mysql_rwlock_register(group, &rwlock_info, 1);
46 } break;
47 case toku_instr_object_type::cond: {
48 PSI_cond_info cond_info{&m_id, name, 0};
49 mysql_cond_register(group, &cond_info, 1);
50 } break;
51 case toku_instr_object_type::thread: {
52 PSI_thread_info thread_info{&m_id, name, 0};
53 mysql_thread_register(group, &thread_info, 1);
54 } break;
55 case toku_instr_object_type::file: {
56 PSI_file_info file_info{&m_id, name, 0};
57 mysql_file_register(group, &file_info, 1);
58 } break;
59 }
60 }
61
62 explicit toku_instr_key(pfs_key_t key_id) : m_id(key_id) {}
63
64 pfs_key_t id() const { return m_id; }
65};
66
67// Thread instrumentation
68int toku_pthread_create(const toku_instr_key &key,
69 pthread_t *thread,
70 const pthread_attr_t *attr,
71 void *(*start_routine)(void *),
72 void *arg);
73void toku_instr_register_current_thread(const toku_instr_key &key);
74void toku_instr_delete_current_thread();
75
76// I/O instrumentation
77
78enum class toku_instr_file_op {
79 file_stream_open = PSI_FILE_STREAM_OPEN,
80 file_create = PSI_FILE_CREATE,
81 file_open = PSI_FILE_OPEN,
82 file_delete = PSI_FILE_DELETE,
83 file_rename = PSI_FILE_RENAME,
84 file_read = PSI_FILE_READ,
85 file_write = PSI_FILE_WRITE,
86 file_sync = PSI_FILE_SYNC,
87 file_stream_close = PSI_FILE_STREAM_CLOSE,
88 file_close = PSI_FILE_CLOSE,
89 file_stat = PSI_FILE_STAT
90};
91
92struct toku_io_instrumentation {
93 struct PSI_file_locker *locker;
94 PSI_file_locker_state state;
95
96 toku_io_instrumentation() : locker(nullptr) {}
97};
98
99void toku_instr_file_open_begin(toku_io_instrumentation &io_instr,
100 const toku_instr_key &key,
101 toku_instr_file_op op,
102 const char *name,
103 const char *src_file,
104 int src_line);
105void toku_instr_file_stream_open_end(toku_io_instrumentation &io_instr,
106 TOKU_FILE &file);
107void toku_instr_file_open_end(toku_io_instrumentation &io_instr, int fd);
108void toku_instr_file_name_close_begin(toku_io_instrumentation &io_instr,
109 const toku_instr_key &key,
110 toku_instr_file_op op,
111 const char *name,
112 const char *src_file,
113 int src_line);
114void toku_instr_file_stream_close_begin(toku_io_instrumentation &io_instr,
115 toku_instr_file_op op,
116 const TOKU_FILE &file,
117 const char *src_file,
118 int src_line);
119void toku_instr_file_fd_close_begin(toku_io_instrumentation &io_instr,
120 toku_instr_file_op op,
121 int fd,
122 const char *src_file,
123 int src_line);
124void toku_instr_file_close_end(const toku_io_instrumentation &io_instr,
125 int result);
126void toku_instr_file_io_begin(toku_io_instrumentation &io_instr,
127 toku_instr_file_op op,
128 int fd,
129 ssize_t count,
130 const char *src_file,
131 int src_line);
132void toku_instr_file_name_io_begin(toku_io_instrumentation &io_instr,
133 const toku_instr_key &key,
134 toku_instr_file_op op,
135 const char *name,
136 ssize_t count,
137 const char *src_file,
138 int src_line);
139void toku_instr_file_stream_io_begin(toku_io_instrumentation &io_instr,
140 toku_instr_file_op op,
141 const TOKU_FILE &file,
142 ssize_t count,
143 const char *src_file,
144 int src_line);
145void toku_instr_file_io_end(toku_io_instrumentation &io_instr, ssize_t count);
146
147// Mutex instrumentation
148
149struct toku_mutex_instrumentation {
150 struct PSI_mutex_locker *locker;
151 PSI_mutex_locker_state state;
152
153 toku_mutex_instrumentation() : locker(nullptr) {}
154};
155
156void toku_instr_mutex_init(const toku_instr_key &key, toku_mutex_t &mutex);
157void toku_instr_mutex_destroy(PSI_mutex *&mutex_instr);
158void toku_instr_mutex_lock_start(toku_mutex_instrumentation &mutex_instr,
159 toku_mutex_t &mutex,
160 const char *src_file,
161 int src_line);
162void toku_instr_mutex_trylock_start(toku_mutex_instrumentation &mutex_instr,
163 toku_mutex_t &mutex,
164 const char *src_file,
165 int src_line);
166void toku_instr_mutex_lock_end(toku_mutex_instrumentation &mutex_instr,
167 int pthread_mutex_lock_result);
168void toku_instr_mutex_unlock(PSI_mutex *mutex_instr);
169
170// Instrumentation probes
171
172class toku_instr_probe_pfs {
173 private:
174 std::unique_ptr<toku_mutex_t> mutex;
175 toku_mutex_instrumentation mutex_instr;
176
177 public:
178 explicit toku_instr_probe_pfs(const toku_instr_key &key);
179
180 ~toku_instr_probe_pfs();
181
182 void start_with_source_location(const char *src_file, int src_line) {
183 mutex_instr.locker = nullptr;
184 toku_instr_mutex_lock_start(mutex_instr, *mutex, src_file, src_line);
185 }
186
187 void stop() { toku_instr_mutex_lock_end(mutex_instr, 0); }
188};
189
190typedef toku_instr_probe_pfs toku_instr_probe;
191
192// Condvar instrumentation
193
194struct toku_cond_instrumentation {
195 struct PSI_cond_locker *locker;
196 PSI_cond_locker_state state;
197
198 toku_cond_instrumentation() : locker(nullptr) {}
199};
200
201enum class toku_instr_cond_op {
202 cond_wait = PSI_COND_WAIT,
203 cond_timedwait = PSI_COND_TIMEDWAIT,
204};
205
206void toku_instr_cond_init(const toku_instr_key &key, toku_cond_t &cond);
207void toku_instr_cond_destroy(PSI_cond *&cond_instr);
208void toku_instr_cond_wait_start(toku_cond_instrumentation &cond_instr,
209 toku_instr_cond_op op,
210 toku_cond_t &cond,
211 toku_mutex_t &mutex,
212 const char *src_file,
213 int src_line);
214void toku_instr_cond_wait_end(toku_cond_instrumentation &cond_instr,
215 int pthread_cond_wait_result);
216void toku_instr_cond_signal(const toku_cond_t &cond);
217void toku_instr_cond_broadcast(const toku_cond_t &cond);
218
219// rwlock instrumentation
220
221struct toku_rwlock_instrumentation {
222 struct PSI_rwlock_locker *locker;
223 PSI_rwlock_locker_state state;
224
225 toku_rwlock_instrumentation() : locker(nullptr) { }
226};
227
228void toku_instr_rwlock_init(const toku_instr_key &key,
229 toku_pthread_rwlock_t &rwlock);
230void toku_instr_rwlock_destroy(PSI_rwlock *&rwlock_instr);
231void toku_instr_rwlock_rdlock_wait_start(
232 toku_rwlock_instrumentation &rwlock_instr,
233 toku_pthread_rwlock_t &rwlock,
234 const char *src_file,
235 int src_line);
236void toku_instr_rwlock_wrlock_wait_start(
237 toku_rwlock_instrumentation &rwlock_instr,
238 toku_pthread_rwlock_t &rwlock,
239 const char *src_file,
240 int src_line);
241void toku_instr_rwlock_rdlock_wait_end(
242 toku_rwlock_instrumentation &rwlock_instr,
243 int pthread_rwlock_wait_result);
244void toku_instr_rwlock_wrlock_wait_end(
245 toku_rwlock_instrumentation &rwlock_instr,
246 int pthread_rwlock_wait_result);
247void toku_instr_rwlock_unlock(toku_pthread_rwlock_t &rwlock);
248
249#endif // TOKU_INSTR_MYSQL_H
250