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