php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
mysqlnd_debug.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Authors: Andrey Hristov <andrey@php.net> |
14 | Ulf Wendel <uw@php.net> |
15 +----------------------------------------------------------------------+
16*/
17
18#include "php.h"
19#include "mysqlnd.h"
20#include "mysqlnd_priv.h"
21#include "mysqlnd_debug.h"
22
23static const char * const mysqlnd_debug_default_trace_file = "/tmp/mysqlnd.trace";
24static const char * const mysqlnd_debug_empty_string = "";
25
26
27/* {{{ mysqlnd_debug::open */
29MYSQLND_METHOD(mysqlnd_debug, open)(MYSQLND_DEBUG * self, bool reopen)
30{
31 if (!self->file_name) {
32 return FAIL;
33 }
34
35 self->stream = php_stream_open_wrapper(self->file_name,
36 reopen == TRUE || self->flags & MYSQLND_DEBUG_APPEND? "ab":"wb",
38 return self->stream? PASS:FAIL;
39}
40/* }}} */
41
42
43/* {{{ mysqlnd_debug::log */
46 unsigned int line, const char * const file,
47 unsigned int level, const char * type, const char * message)
48{
49 char pipe_buffer[512];
51 int i;
52 char * message_line;
53 unsigned int message_line_len;
54 unsigned int flags = self->flags;
55 char pid_buffer[10], time_buffer[30], file_buffer[200],
56 line_buffer[6], level_buffer[7];
57
58 if (!self->stream && FAIL == self->m->open(self, FALSE)) {
59 return FAIL;
60 }
61
62 if (level == -1) {
63 level = zend_stack_count(&self->call_stack);
64 }
65 i = MIN(level, sizeof(pipe_buffer) / 2 - 1);
66 pipe_buffer[i*2] = '\0';
67 for (;i > 0;i--) {
68 pipe_buffer[i*2 - 1] = ' ';
69 pipe_buffer[i*2 - 2] = '|';
70 }
71
72
74 snprintf(pid_buffer, sizeof(pid_buffer) - 1, "%5u: ", self->pid);
75 pid_buffer[sizeof(pid_buffer) - 1 ] = '\0';
76 }
78 /* The following from FF's DBUG library, which is in the public domain */
79 struct timeval tv;
80 struct tm *tm_p;
81 if (gettimeofday(&tv, NULL) != -1) {
82 const time_t sec = tv.tv_sec;
83 if ((tm_p = localtime((const time_t *)&sec))) {
84 snprintf(time_buffer, sizeof(time_buffer) - 1,
85 /* "%04d-%02d-%02d " */
86 "%02d:%02d:%02d.%06d ",
87 /*tm_p->tm_year + 1900, tm_p->tm_mon + 1, tm_p->tm_mday,*/
88 tm_p->tm_hour, tm_p->tm_min, tm_p->tm_sec,
89 (int) (tv.tv_usec));
90 time_buffer[sizeof(time_buffer) - 1 ] = '\0';
91 } else {
92 time_buffer[0] = '\0';
93 }
94 }
95 }
97 snprintf(file_buffer, sizeof(file_buffer) - 1, "%14s: ", file);
98 file_buffer[sizeof(file_buffer) - 1 ] = '\0';
99 }
101 snprintf(line_buffer, sizeof(line_buffer) - 1, "%5u: ", line);
102 line_buffer[sizeof(line_buffer) - 1 ] = '\0';
103 }
105 snprintf(level_buffer, sizeof(level_buffer) - 1, "%4u: ", level);
106 level_buffer[sizeof(level_buffer) - 1 ] = '\0';
107 }
108
109 message_line_len = mnd_sprintf(&message_line, 0, "%s%s%s%s%s%s%s%s\n",
110 flags & MYSQLND_DEBUG_DUMP_PID? pid_buffer:"",
111 flags & MYSQLND_DEBUG_DUMP_TIME? time_buffer:"",
113 flags & MYSQLND_DEBUG_DUMP_LINE? line_buffer:"",
114 flags & MYSQLND_DEBUG_DUMP_LEVEL? level_buffer:"",
115 pipe_buffer, type? type:"", message);
116
117 ret = php_stream_write(self->stream, message_line, message_line_len)? PASS:FAIL;
118 mnd_sprintf_free(message_line);
120 self->m->close(self);
121 self->m->open(self, TRUE);
122 }
123 return ret;
124}
125/* }}} */
126
127
128/* {{{ mysqlnd_debug::log_va */
129static enum_func_status
131 unsigned int line, const char * const file,
132 unsigned int level, const char * type,
133 const char *format, ...)
134{
135 char pipe_buffer[512];
136 int i;
138 char * message_line, *buffer;
139 unsigned int message_line_len;
140 va_list args;
141 unsigned int flags = self->flags;
142 char pid_buffer[10], time_buffer[30], file_buffer[200],
143 line_buffer[6], level_buffer[7];
144
145 if (!self->stream && FAIL == self->m->open(self, FALSE)) {
146 return FAIL;
147 }
148
149 if (level == -1) {
150 level = zend_stack_count(&self->call_stack);
151 }
152 i = MIN(level, sizeof(pipe_buffer) / 2 - 1);
153 pipe_buffer[i*2] = '\0';
154 for (;i > 0;i--) {
155 pipe_buffer[i*2 - 1] = ' ';
156 pipe_buffer[i*2 - 2] = '|';
157 }
158
159
161 snprintf(pid_buffer, sizeof(pid_buffer) - 1, "%5u: ", self->pid);
162 pid_buffer[sizeof(pid_buffer) - 1 ] = '\0';
163 }
165 /* The following from FF's DBUG library, which is in the public domain */
166 struct timeval tv;
167 struct tm *tm_p;
168 if (gettimeofday(&tv, NULL) != -1) {
169 const time_t sec = tv.tv_sec;
170 if ((tm_p = localtime((const time_t *)&sec))) {
171 snprintf(time_buffer, sizeof(time_buffer) - 1,
172 /* "%04d-%02d-%02d " */
173 "%02d:%02d:%02d.%06d ",
174 /*tm_p->tm_year + 1900, tm_p->tm_mon + 1, tm_p->tm_mday,*/
175 tm_p->tm_hour, tm_p->tm_min, tm_p->tm_sec,
176 (int) (tv.tv_usec));
177 time_buffer[sizeof(time_buffer) - 1 ] = '\0';
178 } else {
179 time_buffer[0] = '\0';
180 }
181 }
182 }
184 snprintf(file_buffer, sizeof(file_buffer) - 1, "%14s: ", file);
185 file_buffer[sizeof(file_buffer) - 1 ] = '\0';
186 }
188 snprintf(line_buffer, sizeof(line_buffer) - 1, "%5u: ", line);
189 line_buffer[sizeof(line_buffer) - 1 ] = '\0';
190 }
192 snprintf(level_buffer, sizeof(level_buffer) - 1, "%4u: ", level);
193 level_buffer[sizeof(level_buffer) - 1 ] = '\0';
194 }
195
196 va_start(args, format);
197 mnd_vsprintf(&buffer, 0, format, args);
198 va_end(args);
199
200 message_line_len = mnd_sprintf(&message_line, 0, "%s%s%s%s%s%s%s%s\n",
201 flags & MYSQLND_DEBUG_DUMP_PID? pid_buffer:"",
202 flags & MYSQLND_DEBUG_DUMP_TIME? time_buffer:"",
204 flags & MYSQLND_DEBUG_DUMP_LINE? line_buffer:"",
205 flags & MYSQLND_DEBUG_DUMP_LEVEL? level_buffer:"",
206 pipe_buffer, type? type:"", buffer);
208 ret = php_stream_write(self->stream, message_line, message_line_len)? PASS:FAIL;
209 mnd_sprintf_free(message_line);
210
212 self->m->close(self);
213 self->m->open(self, TRUE);
214 }
215 return ret;
216}
217/* }}} */
218
219
220/* FALSE - The DBG_ calls won't be traced, TRUE - will be traced */
221/* {{{ mysqlnd_debug::func_enter */
222static bool
223MYSQLND_METHOD(mysqlnd_debug, func_enter)(MYSQLND_DEBUG * self,
224 unsigned int line, const char * const file,
225 const char * const func_name, unsigned int func_name_len)
226{
227 if ((self->flags & MYSQLND_DEBUG_DUMP_TRACE) == 0 || self->file_name == NULL) {
228 return FALSE;
229 }
230 if ((uint32_t) zend_stack_count(&self->call_stack) >= self->nest_level_limit) {
231 return FALSE;
232 }
233
234 if ((self->flags & MYSQLND_DEBUG_TRACE_MEMORY_CALLS) == 0 && self->skip_functions) {
235 const char ** p = self->skip_functions;
236 while (*p) {
237 if (*p == func_name) {
238 zend_stack_push(&self->call_stack, &mysqlnd_debug_empty_string);
239#ifndef MYSQLND_PROFILING_DISABLED
240 if (self->flags & MYSQLND_DEBUG_PROFILE_CALLS) {
241 uint64_t some_time = 0;
242 zend_stack_push(&self->call_time_stack, &some_time);
243 }
244#endif
245 return FALSE;
246 }
247 p++;
248 }
249 }
250
251 zend_stack_push(&self->call_stack, &func_name);
252#ifndef MYSQLND_PROFILING_DISABLED
253 if (self->flags & MYSQLND_DEBUG_PROFILE_CALLS) {
254 uint64_t some_time = 0;
255 zend_stack_push(&self->call_time_stack, &some_time);
256 }
257#endif
258
259 if (zend_hash_num_elements(&self->not_filtered_functions) &&
260 0 == zend_hash_str_exists(&self->not_filtered_functions, func_name, strlen(func_name)))
261 {
262 return FALSE;
263 }
264
265 self->m->log_va(self, line, file, zend_stack_count(&self->call_stack) - 1, NULL, ">%s", func_name);
266 return TRUE;
267}
268/* }}} */
269
270#ifndef MYSQLND_PROFILING_DISABLED
286#define PROFILE_UNDERPERFORM_THRESHOLD 10
287#endif
288
289/* {{{ mysqlnd_debug::func_leave */
290static enum_func_status
291MYSQLND_METHOD(mysqlnd_debug, func_leave)(MYSQLND_DEBUG * self, unsigned int line, const char * const file, uint64_t call_time)
292{
293 char **func_name;
294 uint64_t * parent_non_own_time_ptr = NULL, * mine_non_own_time_ptr = NULL;
295 uint64_t mine_non_own_time = 0;
296 bool profile_calls = self->flags & MYSQLND_DEBUG_PROFILE_CALLS? TRUE:FALSE;
297
298 if ((self->flags & MYSQLND_DEBUG_DUMP_TRACE) == 0 || self->file_name == NULL) {
299 return PASS;
300 }
301 if ((uint32_t) zend_stack_count(&self->call_stack) >= self->nest_level_limit) {
302 return PASS;
303 }
304
305 func_name = zend_stack_top(&self->call_stack);
306
307#ifndef MYSQLND_PROFILING_DISABLED
308 if (profile_calls) {
309 mine_non_own_time_ptr = zend_stack_top(&self->call_time_stack);
310 mine_non_own_time = *mine_non_own_time_ptr;
311 zend_stack_del_top(&self->call_time_stack); /* callee - removing ourselves */
312 }
313#endif
314
315 if ((*func_name)[0] == '\0') {
316 ; /* don't log that function */
317 } else if (!zend_hash_num_elements(&self->not_filtered_functions) ||
318 1 == zend_hash_str_exists(&self->not_filtered_functions, (*func_name), strlen((*func_name))))
319 {
320#ifndef MYSQLND_PROFILING_DISABLED
321 if (FALSE == profile_calls) {
322#endif
323 self->m->log_va(self, line, file, zend_stack_count(&self->call_stack) - 1, NULL, "<%s", *func_name);
324
325#ifndef MYSQLND_PROFILING_DISABLED
326 } else {
327 struct st_mysqlnd_dbg_function_profile f_profile_stack = {0};
328 struct st_mysqlnd_dbg_function_profile * f_profile = NULL;
329 uint64_t own_time = call_time - mine_non_own_time;
330 uint32_t func_name_len = strlen(*func_name);
331
332 self->m->log_va(self, line, file, zend_stack_count(&self->call_stack) - 1, NULL, "<%s (total=%u own=%u in_calls=%u)",
333 *func_name, (unsigned int) call_time, (unsigned int) own_time, (unsigned int) mine_non_own_time
334 );
335
336 if ((f_profile = zend_hash_str_find_ptr(&self->function_profiles, *func_name, func_name_len)) != NULL) {
337 /* found */
338 if (f_profile) {
339 if (mine_non_own_time < f_profile->min_in_calls) {
340 f_profile->min_in_calls = mine_non_own_time;
341 } else if (mine_non_own_time > f_profile->max_in_calls) {
342 f_profile->max_in_calls = mine_non_own_time;
343 }
344 f_profile->avg_in_calls = (f_profile->avg_in_calls * f_profile->calls + mine_non_own_time) / (f_profile->calls + 1);
345
346 if (own_time < f_profile->min_own) {
347 f_profile->min_own = own_time;
348 } else if (own_time > f_profile->max_own) {
349 f_profile->max_own = own_time;
350 }
351 f_profile->avg_own = (f_profile->avg_own * f_profile->calls + own_time) / (f_profile->calls + 1);
352
353 if (call_time < f_profile->min_total) {
354 f_profile->min_total = call_time;
355 } else if (call_time > f_profile->max_total) {
356 f_profile->max_total = call_time;
357 }
358 f_profile->avg_total = (f_profile->avg_total * f_profile->calls + call_time) / (f_profile->calls + 1);
359
360 ++f_profile->calls;
361 if (f_profile->calls > PROFILE_UNDERPERFORM_THRESHOLD) {
362 if (f_profile->avg_in_calls < mine_non_own_time) {
363 f_profile->in_calls_underporm_calls++;
364 }
365 if (f_profile->avg_own < own_time) {
366 f_profile->own_underporm_calls++;
367 }
368 if (f_profile->avg_total < call_time) {
369 f_profile->total_underporm_calls++;
370 }
371 }
372 }
373 } else {
374 /* add */
375 f_profile = &f_profile_stack;
376 f_profile->min_in_calls = f_profile->max_in_calls = f_profile->avg_in_calls = mine_non_own_time;
377 f_profile->min_total = f_profile->max_total = f_profile->avg_total = call_time;
378 f_profile->min_own = f_profile->max_own = f_profile->avg_own = own_time;
379 f_profile->calls = 1;
380 zend_hash_str_add_mem(&self->function_profiles, *func_name, func_name_len, f_profile, sizeof(struct st_mysqlnd_dbg_function_profile));
381 }
382 if ((uint32_t) zend_stack_count(&self->call_time_stack)) {
383 uint64_t parent_non_own_time = 0;
384
385 parent_non_own_time_ptr = zend_stack_top(&self->call_time_stack);
386 parent_non_own_time = *parent_non_own_time_ptr;
387 parent_non_own_time += call_time;
388 zend_stack_del_top(&self->call_time_stack); /* the caller */
389 zend_stack_push(&self->call_time_stack, &parent_non_own_time); /* add back the caller */
390 }
391 }
392#endif
393 }
394
395 zend_stack_del_top(&self->call_stack);
396 return PASS;
397}
398/* }}} */
399
400
401/* {{{ mysqlnd_debug::close */
402static enum_func_status
404{
405 if (self->stream) {
406#ifndef MYSQLND_PROFILING_DISABLED
407 if (!(self->flags & MYSQLND_DEBUG_FLUSH) && (self->flags & MYSQLND_DEBUG_PROFILE_CALLS)) {
408 struct st_mysqlnd_dbg_function_profile * f_profile;
409 zend_string *string_key = NULL;
410
411 self->m->log_va(self, __LINE__, __FILE__, 0, "info : ",
412 "number of functions: %d", zend_hash_num_elements(&self->function_profiles));
413 ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&self->function_profiles, string_key, f_profile) {
414 self->m->log_va(self, __LINE__, __FILE__, -1, "info : ",
415 "%-40s\tcalls=%5" PRIu64
416 " own_slow=%5" PRIu64
417 " in_calls_slow=%5" PRIu64
418 " total_slow=%5" PRIu64
419 " min_own=%5" PRIu64
420 " max_own=%7" PRIu64
421 " avg_own=%7" PRIu64
422 " min_in_calls=%5" PRIu64
423 " max_in_calls=%7" PRIu64
424 " avg_in_calls=%7" PRIu64
425 " min_total=%5" PRIu64
426 " max_total=%7" PRIu64
427 " avg_total=%7" PRIu64
428 ,ZSTR_VAL(string_key)
429 ,(uint64_t) f_profile->calls
430 ,(uint64_t) f_profile->own_underporm_calls
431 ,(uint64_t) f_profile->in_calls_underporm_calls
432 ,(uint64_t) f_profile->total_underporm_calls
433
434 ,(uint64_t) f_profile->min_own
435 ,(uint64_t) f_profile->max_own
436 ,(uint64_t) f_profile->avg_own
437 ,(uint64_t) f_profile->min_in_calls
438 ,(uint64_t) f_profile->max_in_calls
439 ,(uint64_t) f_profile->avg_in_calls
440 ,(uint64_t) f_profile->min_total
441 ,(uint64_t) f_profile->max_total
442 ,(uint64_t) f_profile->avg_total
443 );
445 }
446#endif
447
448 php_stream_close(self->stream);
449 self->stream = NULL;
450 }
451 /* no DBG_RETURN please */
452 return PASS;
453}
454/* }}} */
455
456
457/* {{{ mysqlnd_res_meta::free */
458static enum_func_status
460{
461 if (self->file_name && self->file_name != mysqlnd_debug_default_trace_file) {
462 efree(self->file_name);
463 self->file_name = NULL;
464 }
465 zend_stack_destroy(&self->call_stack);
466 zend_stack_destroy(&self->call_time_stack);
467 zend_hash_destroy(&self->not_filtered_functions);
468 zend_hash_destroy(&self->function_profiles);
469 free(self);
470 return PASS;
471}
472/* }}} */
473
480
481
482/* {{{ mysqlnd_res_meta::set_mode */
483static void
484MYSQLND_METHOD(mysqlnd_debug, set_mode)(MYSQLND_DEBUG * self, const char * const mode)
485{
486 unsigned int mode_len, i;
488
489 mode_len = mode? strlen(mode) : 0;
490
491 self->flags = 0;
492 self->nest_level_limit = 0;
493 if (self->file_name && self->file_name != mysqlnd_debug_default_trace_file) {
494 efree(self->file_name);
495 self->file_name = NULL;
496 }
497 if (zend_hash_num_elements(&self->not_filtered_functions)) {
498 zend_hash_destroy(&self->not_filtered_functions);
499 zend_hash_init(&self->not_filtered_functions, 0, NULL, NULL, 0);
500 }
501
502 for (i = 0; i < mode_len; i++) {
503 switch (mode[i]) {
504 case 'O':
505 case 'A':
506 self->flags |= MYSQLND_DEBUG_FLUSH;
508 case 'a':
509 case 'o':
510 if (mode[i] == 'a' || mode[i] == 'A') {
511 self->flags |= MYSQLND_DEBUG_APPEND;
512 }
513 if (i + 1 < mode_len && mode[i+1] == ',') {
514 unsigned int j = i + 2;
515#ifdef PHP_WIN32
516 if (i+4 < mode_len && mode[i+3] == ':' && (mode[i+4] == '\\' || mode[i+4] == '/')) {
517 j = i + 5;
518 }
519#endif
520 while (j < mode_len) {
521 if (mode[j] == ':') {
522 break;
523 }
524 j++;
525 }
526 if (j > i + 2) {
527 self->file_name = estrndup(mode + i + 2, j - i - 2);
528 }
529 i = j;
530 } else {
531 if (!self->file_name)
532 self->file_name = (char *) mysqlnd_debug_default_trace_file;
533 }
535 break;
536 case ':':
537 if (state != PARSER_WAIT_COLON) {
538 php_error_docref(NULL, E_WARNING, "Consecutive semicolons at position %u", i);
539 }
541 break;
542 case 'f': /* limit output to these functions */
543 if (i + 1 < mode_len && mode[i+1] == ',') {
544 unsigned int j = i + 2;
545 i++;
546 while (j < mode_len) {
547 if (mode[j] == ':') {
548 /* function names with :: */
549 if ((j + 1 < mode_len) && mode[j+1] == ':') {
550 j += 2;
551 continue;
552 }
553 }
554 if (mode[j] == ',' || mode[j] == ':') {
555 if (j > i + 2) {
556 char func_name[1024];
557 unsigned int func_name_len = MIN(sizeof(func_name) - 1, j - i - 1);
559 func_name[func_name_len] = '\0';
560
561 zend_hash_str_add_empty_element(&self->not_filtered_functions,
563 i = j;
564 }
565 if (mode[j] == ':') {
566 break;
567 }
568 }
569 j++;
570 }
571 i = j;
572 } else {
574 "Expected list of functions for '%c' found none", mode[i]);
575 }
577 break;
578 case 'D':
579 case 'd':
580 case 'g':
581 case 'p':
582 /* unsupported */
583 if ((i + 1) < mode_len && mode[i+1] == ',') {
584 i+= 2;
585 while (i < mode_len) {
586 if (mode[i] == ':') {
587 break;
588 }
589 i++;
590 }
591 }
593 break;
594 case 'F':
595 self->flags |= MYSQLND_DEBUG_DUMP_FILE;
597 break;
598 case 'i':
599 self->flags |= MYSQLND_DEBUG_DUMP_PID;
601 break;
602 case 'L':
603 self->flags |= MYSQLND_DEBUG_DUMP_LINE;
605 break;
606 case 'n':
607 self->flags |= MYSQLND_DEBUG_DUMP_LEVEL;
609 break;
610 case 't':
611 if (mode[i+1] == ',') {
612 unsigned int j = i + 2;
613 while (j < mode_len) {
614 if (mode[j] == ':') {
615 break;
616 }
617 j++;
618 }
619 if (j > i + 2) {
620 char *value_str = estrndup(mode + i + 2, j - i - 2);
621 self->nest_level_limit = atoi(value_str);
622 efree(value_str);
623 }
624 i = j;
625 } else {
626 self->nest_level_limit = 200; /* default value for FF DBUG */
627 }
628 self->flags |= MYSQLND_DEBUG_DUMP_TRACE;
630 break;
631 case 'T':
632 self->flags |= MYSQLND_DEBUG_DUMP_TIME;
634 break;
635 case 'N':
636 case 'P':
637 case 'r':
638 case 'S':
640 break;
641 case 'm': /* mysqlnd extension - trace memory functions */
644 break;
645 case 'x': /* mysqlnd extension - profile calls */
646 self->flags |= MYSQLND_DEBUG_PROFILE_CALLS;
648 break;
649 default:
651 php_error_docref(NULL, E_WARNING, "Unrecognized format '%c'", mode[i]);
652 if (i+1 < mode_len && mode[i+1] == ',') {
653 i+= 2;
654 while (i < mode_len) {
655 if (mode[i] == ':') {
656 break;
657 }
658 i++;
659 }
660 }
662 } else if (state == PARSER_WAIT_COLON) {
663 php_error_docref(NULL, E_WARNING, "Colon expected, '%c' found", mode[i]);
664 }
665 break;
666 }
667 }
668}
669/* }}} */
670
673 MYSQLND_METHOD(mysqlnd_debug, set_mode),
676 MYSQLND_METHOD(mysqlnd_debug, func_enter),
677 MYSQLND_METHOD(mysqlnd_debug, func_leave),
681
682
683static void free_ptr(zval *zv) {
684 efree(Z_PTR_P(zv));
685}
686
687/* {{{ mysqlnd_debug_init */
689mysqlnd_debug_init(const char * skip_functions[])
690{
691 MYSQLND_DEBUG *ret = calloc(1, sizeof(MYSQLND_DEBUG));
692
693 ret->nest_level_limit = 0;
694 ret->pid = getpid();
695 zend_stack_init(&ret->call_stack, sizeof(char *));
696 zend_stack_init(&ret->call_time_stack, sizeof(uint64_t));
697 zend_hash_init(&ret->not_filtered_functions, 0, NULL, NULL, 0);
698 zend_hash_init(&ret->function_profiles, 0, NULL, free_ptr, 0);
699
700 ret->m = & mysqlnd_mysqlnd_debug_methods;
701 ret->skip_functions = skip_functions;
702
703 return ret;
704}
705/* }}} */
706
707
708/* {{{ mysqlnd_debug */
709PHPAPI void mysqlnd_debug(const char * mode)
710{
711#if PHP_DEBUG
713 if (!dbg) {
714 struct st_mysqlnd_plugin_trace_log * trace_log_plugin = mysqlnd_plugin_find("debug_trace");
715 if (trace_log_plugin) {
717 if (!dbg) {
718 return;
719 }
720 MYSQLND_G(dbg) = dbg;
721 }
722 }
723 if (dbg) {
724 dbg->m->close(dbg);
725 dbg->m->set_mode(dbg, mode);
726 while (zend_stack_count(&dbg->call_stack)) {
727 zend_stack_del_top(&dbg->call_stack);
728 }
729 while (zend_stack_count(&dbg->call_time_stack)) {
730 zend_stack_del_top(&dbg->call_time_stack);
731 }
732 }
733#endif
734}
735/* }}} */
736
737
738static struct st_mysqlnd_plugin_trace_log mysqlnd_plugin_trace_log_plugin =
739{
740 {
742 "debug_trace",
745 "PHP License 3.01",
746 "Andrey Hristov <andrey@php.net>, Ulf Wendel <uw@php.net>, Georg Richter <georg@php.net>",
747 {
748 NULL, /* no statistics , will be filled later if there are some */
749 NULL, /* no statistics */
750 },
751 {
752 NULL /* plugin shutdown */
753 }
754 },
755 {/* methods */
757 }
758};
759
760
761/* {{{ mysqlnd_debug_trace_plugin_register */
762void
764{
765 mysqlnd_plugin_register_ex((struct st_mysqlnd_plugin_header *) &mysqlnd_plugin_trace_log_plugin);
766}
767/* }}} */
file(string $filename, int $flags=0, $context=null)
gettimeofday(bool $as_float=false)
log(float $num, float $base=M_E)
zend_ffi_type * type
Definition ffi.c:3812
zval * zv
Definition ffi.c:3975
memcpy(ptr1, ptr2, size)
file_protected int file_buffer(struct magic_set *, php_stream *, zend_stat_t *, const char *, const void *, size_t)
size_t mode_len
char * mode
#define TRUE
Definition gd_gd.c:7
#define FALSE
Definition gd_gd.c:8
#define NULL
Definition gdcache.h:45
#define PASS(tables)
Definition hash_gost.c:193
again j
PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format,...)
Definition main.c:1173
MYSQLND_DEBUG * dbg
Definition mysqlnd.h:300
#define PHP_MYSQLND_VERSION
Definition mysqlnd.h:22
PHPAPI unsigned int mysqlnd_plugin_register_ex(struct st_mysqlnd_plugin_header *plugin)
#define MYSQLND_PLUGIN_API_VERSION
Definition mysqlnd.h:25
PHPAPI void * mysqlnd_plugin_find(const char *const name)
#define MYSQLND_VERSION_ID
Definition mysqlnd.h:23
#define MYSQLND_G(v)
#define MYSQLND_METHOD(class, method)
Definition mysqlnd.h:294
PHPAPI void mysqlnd_debug(const char *mode)
PHPAPI const char * mysqlnd_debug_std_no_trace_funcs[]
#define mnd_sprintf_free(p)
#define mnd_sprintf(p, mx_len, fmt,...)
#define mnd_vsprintf(p, mx_len, fmt, ap)
PHPAPI MYSQLND_DEBUG * mysqlnd_debug_init(const char *skip_functions[])
mysqlnd_debug_parser_state
@ PARSER_WAIT_MODIFIER
@ PARSER_WAIT_VALUE
@ PARSER_WAIT_COLON
PHPAPI void mysqlnd_debug(const char *mode)
#define PROFILE_UNDERPERFORM_THRESHOLD
void mysqlnd_debug_trace_plugin_register(void)
#define MYSQLND_DEBUG_DUMP_PID
#define MYSQLND_DEBUG_DUMP_LEVEL
#define MYSQLND_DEBUG_PROFILE_CALLS
#define MYSQLND_DEBUG_APPEND
#define MYSQLND_DEBUG_FLUSH
#define MYSQLND_DEBUG_DUMP_FILE
#define MYSQLND_DEBUG_TRACE_MEMORY_CALLS
#define MYSQLND_DEBUG_DUMP_TRACE
#define MYSQLND_DEBUG_DUMP_LINE
#define MYSQLND_DEBUG_DUMP_TIME
enum func_status enum_func_status
#define MYSQLND_CLASS_METHODS_END
struct st_mysqlnd_debug MYSQLND_DEBUG
#define MYSQLND_CLASS_METHODS_START(class)
#define PHPAPI
Definition php.h:71
localtime(?int $timestamp=null, bool $associative=false)
int line
Definition php_ffi.h:54
#define REPORT_ERRORS
#define php_stream_close(stream)
#define php_stream_open_wrapper(path, mode, options, opened)
#define php_stream_write(stream, buf, count)
const char * func_name
size_t func_name_len
struct timeval tv
Definition session.c:1280
p
Definition session.c:1105
#define FAIL(...)
Definition file.h:177
struct st_mysqlnd_plugin_trace_log::@135250356370041002364233320207075236242207017335 methods
MYSQLND_DEBUG *(* trace_instance_init)(const char *skip_functions[])
#define close(a)
#define estrndup(s, length)
Definition zend_alloc.h:165
#define efree(ptr)
Definition zend_alloc.h:155
struct _zval_struct zval
strlen(string $string)
zval * args
#define snprintf
#define E_WARNING
Definition zend_errors.h:24
ZEND_API void ZEND_FASTCALL zend_hash_destroy(HashTable *ht)
Definition zend_hash.c:1727
ZEND_API zval *ZEND_FASTCALL zend_hash_str_add_empty_element(HashTable *ht, const char *str, size_t len)
Definition zend_hash.c:1075
#define zend_hash_init(ht, nSize, pHashFunction, pDestructor, persistent)
Definition zend_hash.h:108
#define ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(ht, _key, _ptr)
Definition zend_hash.h:1433
#define ZEND_HASH_FOREACH_END()
Definition zend_hash.h:1086
struct _zend_string zend_string
#define MIN(a, b)
#define ZEND_FALLTHROUGH
ZEND_API int zend_stack_push(zend_stack *stack, const void *element)
Definition zend_stack.c:33
ZEND_API void * zend_stack_top(const zend_stack *stack)
Definition zend_stack.c:45
ZEND_API int zend_stack_count(const zend_stack *stack)
Definition zend_stack.c:93
ZEND_API void zend_stack_destroy(zend_stack *stack)
Definition zend_stack.c:78
ZEND_API void zend_stack_init(zend_stack *stack, int size)
Definition zend_stack.c:25
ZEND_API void zend_stack_del_top(zend_stack *stack)
Definition zend_stack.c:55
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define Z_PTR_P(zval_p)
zval * ret