]> git.pld-linux.org Git - packages/mysql.git/blob - mysql-response-time-distribution.patch
remove id expansion
[packages/mysql.git] / mysql-response-time-distribution.patch
1 # name       : response-time-distribution.patch
2 # introduced : 12
3 # maintainer : Oleg
4 #
5 #!!! notice !!!
6 # Any small change to this file in the main branch
7 # should be done or reviewed by the maintainer!
8 diff -ruN a/include/mysql_com.h b/include/mysql_com.h
9 --- a/include/mysql_com.h       2010-11-01 08:43:53.000000000 +0000
10 +++ b/include/mysql_com.h       2010-11-01 08:52:40.000000000 +0000
11 @@ -128,10 +128,11 @@
12  #define REFRESH_FAST           32768   /* Intern flag */
13  
14  /* RESET (remove all queries) from query cache */
15 -#define REFRESH_QUERY_CACHE    65536
16 -#define REFRESH_QUERY_CACHE_FREE 0x20000L /* pack query cache */
17 -#define REFRESH_DES_KEY_FILE   0x40000L
18 -#define REFRESH_USER_RESOURCES 0x80000L
19 +#define REFRESH_QUERY_CACHE         65536
20 +#define REFRESH_QUERY_CACHE_FREE    0x20000L /* pack query cache */
21 +#define REFRESH_DES_KEY_FILE        0x40000L
22 +#define REFRESH_USER_RESOURCES      0x80000L
23 +#define REFRESH_QUERY_RESPONSE_TIME 0x100000L /* response time distibution */
24  
25  #define CLIENT_LONG_PASSWORD   1       /* new more secure passwords */
26  #define CLIENT_FOUND_ROWS      2       /* Found instead of affected rows */
27 diff -ruN a/patch_info/response-time-distribution.info b/patch_info/response-time-distribution.info
28 --- a/patch_info/response-time-distribution.info        1970-01-01 00:00:00.000000000 +0000
29 +++ b/patch_info/response-time-distribution.info        2010-11-01 08:52:40.000000000 +0000
30 @@ -0,0 +1,9 @@
31 +File=response-time-distribution.patch
32 +Name=Response time distribution
33 +Version=1.0
34 +Author=Percona <info@percona.com>
35 +License=GPL
36 +Comment=
37 +Changelog
38 +2010-07-02 first version avaliable
39 +2010-09-15 add column 'total'
40 diff -ruN a/sql/Makefile.am b/sql/Makefile.am
41 --- a/sql/Makefile.am   2010-11-01 08:43:52.000000000 +0000
42 +++ b/sql/Makefile.am   2010-11-01 08:52:40.000000000 +0000
43 @@ -66,7 +66,7 @@
44                         sql_repl.h slave.h rpl_filter.h rpl_injector.h \
45                         log_event.h rpl_record.h \
46                         log_event_old.h rpl_record_old.h \
47 -                       sql_sort.h sql_cache.h set_var.h \
48 +                       sql_sort.h sql_cache.h set_var.h query_response_time.h \
49                         spatial.h gstream.h client_settings.h tzfile.h \
50                         tztime.h my_decimal.h\
51                         sp_head.h sp_pcontext.h sp_rcontext.h sp.h sp_cache.h \
52 @@ -89,7 +89,7 @@
53                         sql_string.cc sql_manager.cc sql_map.cc \
54                         mysqld.cc password.c hash_filo.cc hostname.cc \
55                         sql_connect.cc scheduler.cc sql_parse.cc \
56 -                       set_var.cc sql_yacc.yy \
57 +                       set_var.cc query_response_time.cc sql_yacc.yy \
58                         sql_base.cc table.cc sql_select.cc sql_insert.cc \
59                         sql_profile.cc \
60                         sql_prepare.cc sql_error.cc sql_locale.cc \
61 diff -ruN a/sql/Makefile.in b/sql/Makefile.in
62 --- a/sql/Makefile.in   2010-11-01 08:43:52.000000000 +0000
63 +++ b/sql/Makefile.in   2010-11-01 08:52:40.000000000 +0000
64 @@ -122,7 +122,7 @@
65         sql_string.$(OBJEXT) sql_manager.$(OBJEXT) sql_map.$(OBJEXT) \
66         mysqld.$(OBJEXT) password.$(OBJEXT) hash_filo.$(OBJEXT) \
67         hostname.$(OBJEXT) sql_connect.$(OBJEXT) scheduler.$(OBJEXT) \
68 -       sql_parse.$(OBJEXT) set_var.$(OBJEXT) sql_yacc.$(OBJEXT) \
69 +       sql_parse.$(OBJEXT) set_var.$(OBJEXT) query_response_time.${OBJEXT} sql_yacc.$(OBJEXT) \
70         sql_base.$(OBJEXT) table.$(OBJEXT) sql_select.$(OBJEXT) \
71         sql_insert.$(OBJEXT) sql_profile.$(OBJEXT) \
72         sql_prepare.$(OBJEXT) sql_error.$(OBJEXT) sql_locale.$(OBJEXT) \
73 @@ -562,7 +562,7 @@
74                         sql_repl.h slave.h rpl_filter.h rpl_injector.h \
75                         log_event.h rpl_record.h \
76                         log_event_old.h rpl_record_old.h \
77 -                       sql_sort.h sql_cache.h set_var.h \
78 +                       sql_sort.h sql_cache.h set_var.h query_response_time.h \
79                         spatial.h gstream.h client_settings.h tzfile.h \
80                         tztime.h my_decimal.h\
81                         sp_head.h sp_pcontext.h sp_rcontext.h sp.h sp_cache.h \
82 @@ -585,7 +585,7 @@
83                         sql_string.cc sql_manager.cc sql_map.cc \
84                         mysqld.cc password.c hash_filo.cc hostname.cc \
85                         sql_connect.cc scheduler.cc sql_parse.cc \
86 -                       set_var.cc sql_yacc.yy \
87 +                       set_var.cc query_response_time.cc sql_yacc.yy \
88                         sql_base.cc table.cc sql_select.cc sql_insert.cc \
89                         sql_profile.cc \
90                         sql_prepare.cc sql_error.cc sql_locale.cc \
91 @@ -828,6 +828,7 @@
92  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/password.Po@am__quote@
93  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/procedure.Po@am__quote@
94  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol.Po@am__quote@
95 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/query_response_time.Po@am__quote@
96  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/records.Po@am__quote@
97  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/repl_failsafe.Po@am__quote@
98  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpl_filter.Po@am__quote@
99 diff -ruN a/sql/lex.h b/sql/lex.h
100 --- a/sql/lex.h 2010-11-01 08:43:53.000000000 +0000
101 +++ b/sql/lex.h 2010-11-01 08:52:40.000000000 +0000
102 @@ -415,6 +415,7 @@
103    { "PURGE",           SYM(PURGE)},
104    { "QUARTER",          SYM(QUARTER_SYM)},
105    { "QUERY",           SYM(QUERY_SYM)},
106 +  { "QUERY_RESPONSE_TIME", SYM(QUERY_RESPONSE_TIME_SYM)},
107    { "QUICK",           SYM(QUICK)},
108    { "RANGE",            SYM(RANGE_SYM)},
109    { "READ",            SYM(READ_SYM)},
110 diff -ruN a/sql/mysql_priv.h b/sql/mysql_priv.h
111 --- a/sql/mysql_priv.h  2010-11-01 08:43:57.000000000 +0000
112 +++ b/sql/mysql_priv.h  2010-11-01 08:52:40.000000000 +0000
113 @@ -2121,6 +2121,11 @@
114  extern my_bool opt_query_cache_strip_comments;
115  extern my_bool opt_use_global_long_query_time;
116  extern my_bool opt_slow_query_log_microseconds_timestamp;
117 +#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
118 +extern ulong   opt_query_response_time_range_base;
119 +extern my_bool opt_enable_query_response_time_stats;
120 +#endif /* HAVE_RESPONSE_TIME_DISTRIBUTION */
121 +extern SHOW_COMP_OPTION have_response_time_distribution;
122  extern my_bool sp_automatic_privileges, opt_noacl;
123  extern my_bool opt_old_style_user_limits, trust_function_creators;
124  extern uint opt_crash_binlog_innodb;
125 diff -ruN a/sql/mysqld.cc b/sql/mysqld.cc
126 --- a/sql/mysqld.cc     2010-11-01 08:43:57.000000000 +0000
127 +++ b/sql/mysqld.cc     2010-11-01 08:52:40.000000000 +0000
128 @@ -32,6 +32,7 @@
129  
130  #include "rpl_injector.h"
131  
132 +#include "query_response_time.h"
133  #ifdef HAVE_SYS_PRCTL_H
134  #include <sys/prctl.h>
135  #endif
136 @@ -529,6 +530,10 @@
137  my_bool opt_query_cache_strip_comments = 0;
138  my_bool opt_use_global_long_query_time= 0;
139  my_bool opt_slow_query_log_microseconds_timestamp= 0;
140 +#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
141 +ulong   opt_query_response_time_range_base  = QRT_DEFAULT_BASE;
142 +my_bool opt_enable_query_response_time_stats= 0;
143 +#endif /* HAVE_RESPONSE_TIME_DISTRIBUTION */
144  my_bool lower_case_file_system= 0;
145  my_bool opt_large_pages= 0;
146  my_bool opt_myisam_use_mmap= 0;
147 @@ -679,6 +684,7 @@
148  MY_LOCALE *my_default_lc_time_names;
149  
150  SHOW_COMP_OPTION have_ssl, have_symlink, have_dlopen, have_query_cache;
151 +SHOW_COMP_OPTION have_response_time_distribution;
152  SHOW_COMP_OPTION have_geometry, have_rtree_keys;
153  SHOW_COMP_OPTION have_crypt, have_compress;
154  SHOW_COMP_OPTION have_community_features;
155 @@ -1389,6 +1395,9 @@
156    free_global_thread_stats();
157    free_global_table_stats();
158    free_global_index_stats();
159 +#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
160 +  query_response_time_free();
161 +#endif /* HAVE_RESPONSE_TIME_DISTRIBUTION */
162  #ifdef HAVE_REPLICATION
163    end_slave_list();
164  #endif
165 @@ -4103,6 +4112,9 @@
166  
167    init_global_table_stats();
168    init_global_index_stats();
169 +#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
170 +  query_response_time_init();
171 +#endif /* HAVE_RESPONSE_TIME_DISTRIBUTION */
172  
173    /* We have to initialize the storage engines before CSV logging */
174    if (ha_init())
175 @@ -5916,6 +5928,10 @@
176    OPT_USE_GLOBAL_LONG_QUERY_TIME,
177    OPT_USE_GLOBAL_LOG_SLOW_CONTROL,
178    OPT_SLOW_QUERY_LOG_MICROSECONDS_TIMESTAMP,
179 +#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
180 +  OPT_QRT_RANGE_BASE,
181 +  OPT_ENABLE_QRT_STATS,
182 +#endif /* HAVE_RESPONSE_TIME_DISTRIBUTION */
183    OPT_IGNORE_BUILTIN_INNODB,
184    OPT_BINLOG_DIRECT_NON_TRANS_UPDATE,
185    OPT_DEFAULT_CHARACTER_SET_OLD,
186 @@ -6987,6 +7003,23 @@
187     "Use microsecond time's precision in slow query log",
188     (uchar**) &opt_slow_query_log_microseconds_timestamp, (uchar**) &opt_slow_query_log_microseconds_timestamp,
189     0, GET_BOOL, OPT_ARG, 0, 0, 1, 0, 1, 0},
190 +#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
191 +  {"query_response_time_range_base", OPT_QRT_RANGE_BASE,
192 +     "Select base of log for query_response_time ranges. WARNING: variable change affect only after flush",
193 +   (uchar**) &opt_query_response_time_range_base, (uchar**) &opt_query_response_time_range_base,
194 +   0, GET_ULONG, REQUIRED_ARG, 
195 +   /* def_value */  QRT_DEFAULT_BASE,
196 +   /* min_value */  2,
197 +   /* max_value */  QRT_MAXIMUM_BASE, 
198 +   /* sub_size */   0,
199 +   /* block_size */ 1,
200 +   /* app_type */ 0
201 +  },
202 +  {"enable_query_response_time_stats", OPT_ENABLE_QRT_STATS,
203 +   "Enable or disable query response time statisics collecting",
204 +   (uchar**) &opt_enable_query_response_time_stats, (uchar**) &opt_enable_query_response_time_stats,
205 +   0, GET_BOOL, REQUIRED_ARG, 0, 0, 1, 0, 1, 0},
206 +#endif /* HAVE_RESPONSE_TIME_DISTRIBUTION */
207    {"lower_case_table_names", OPT_LOWER_CASE_TABLE_NAMES,
208     "If set to 1, table names are stored in lowercase on disk and table names "
209     "will be case-insensitive.  Should be set to 2 if you are using a case-"
210 @@ -8208,6 +8241,11 @@
211  #else
212    have_query_cache=SHOW_OPTION_NO;
213  #endif
214 +#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
215 +  have_response_time_distribution= SHOW_OPTION_YES;
216 +#else /* HAVE_RESPONSE_TIME_DISTRIBUTION */
217 +  have_response_time_distribution= SHOW_OPTION_NO;
218 +#endif /* HAVE_RESPONSE_TIME_DISTRIBUTION */
219  #ifdef HAVE_SPATIAL
220    have_geometry=SHOW_OPTION_YES;
221  #else
222 diff -ruN a/sql/query_response_time.cc b/sql/query_response_time.cc
223 --- a/sql/query_response_time.cc        1970-01-01 00:00:00.000000000 +0000
224 +++ b/sql/query_response_time.cc        2010-11-02 15:34:52.000000000 +0000
225 @@ -0,0 +1,369 @@
226 +#ifdef __FreeBSD__
227 +#include <sys/types.h>
228 +#include <machine/atomic.h>
229 +#endif // __FreeBSD__
230 +#include "my_global.h"
231 +#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
232 +#include "mysql_priv.h"
233 +#include "mysql_com.h"
234 +#include "rpl_tblmap.h"
235 +#include "query_response_time.h"
236 +
237 +#define TIME_STRING_POSITIVE_POWER_LENGTH QRT_TIME_STRING_POSITIVE_POWER_LENGTH
238 +#define TIME_STRING_NEGATIVE_POWER_LENGTH 6
239 +#define TOTAL_STRING_POSITIVE_POWER_LENGTH QRT_TOTAL_STRING_POSITIVE_POWER_LENGTH
240 +#define TOTAL_STRING_NEGATIVE_POWER_LENGTH 6
241 +#define MINIMUM_BASE 2
242 +#define MAXIMUM_BASE QRT_MAXIMUM_BASE
243 +#define POSITIVE_POWER_FILLER QRT_POSITIVE_POWER_FILLER
244 +#define NEGATIVE_POWER_FILLER QRT_NEGATIVE_POWER_FILLER
245 +#define STRING_OVERFLOW QRT_STRING_OVERFLOW
246 +#define TIME_OVERFLOW   QRT_TIME_OVERFLOW
247 +#define DEFAULT_BASE    QRT_DEFAULT_BASE
248 +
249 +#define do_xstr(s) do_str(s)
250 +#define do_str(s) #s
251 +#define do_format(filler,width) "%" filler width "lld"
252 +/*
253 +  Format strings for snprintf. Generate from:
254 +  POSITIVE_POWER_FILLER and TIME_STRING_POSITIVE_POWER_LENGTH
255 +  NEFATIVE_POWER_FILLER and TIME_STRING_NEGATIVE_POWER_LENGTH
256 +*/
257 +#define TIME_STRING_POSITIVE_POWER_FORMAT do_format(POSITIVE_POWER_FILLER,do_xstr(TIME_STRING_POSITIVE_POWER_LENGTH))
258 +#define TIME_STRING_NEGATIVE_POWER_FORMAT do_format(NEGATIVE_POWER_FILLER,do_xstr(TIME_STRING_NEGATIVE_POWER_LENGTH))
259 +#define TIME_STRING_FORMAT                   TIME_STRING_POSITIVE_POWER_FORMAT "." TIME_STRING_NEGATIVE_POWER_FORMAT
260 +
261 +#define TOTAL_STRING_POSITIVE_POWER_FORMAT do_format(POSITIVE_POWER_FILLER,do_xstr(TOTAL_STRING_POSITIVE_POWER_LENGTH))
262 +#define TOTAL_STRING_NEGATIVE_POWER_FORMAT do_format(NEGATIVE_POWER_FILLER,do_xstr(TOTAL_STRING_NEGATIVE_POWER_LENGTH))
263 +#define TOTAL_STRING_FORMAT                  TOTAL_STRING_POSITIVE_POWER_FORMAT "." TOTAL_STRING_NEGATIVE_POWER_FORMAT
264 +
265 +#define TIME_STRING_LENGTH     QRT_TIME_STRING_LENGTH
266 +#define TIME_STRING_BUFFER_LENGTH      (TIME_STRING_LENGTH + 1 /* '\0' */)
267 +
268 +#define TOTAL_STRING_LENGTH    QRT_TOTAL_STRING_LENGTH
269 +#define TOTAL_STRING_BUFFER_LENGTH     (TOTAL_STRING_LENGTH + 1 /* '\0' */)
270 +
271 +/*
272 +  Calculate length of "log linear"
273 +  1)
274 +  (MINIMUM_BASE ^ result) <= (10 ^ STRING_POWER_LENGTH) < (MINIMUM_BASE ^ (result + 1))
275 +
276 +  2)
277 +  (MINIMUM_BASE ^ result) <= (10 ^ STRING_POWER_LENGTH)
278 +  and
279 +  (MINIMUM_BASE ^ (result + 1)) > (10 ^ STRING_POWER_LENGTH)
280 +
281 +  3)
282 +  result     <= LOG(MINIMUM_BASE, 10 ^ STRING_POWER_LENGTH)= STRING_POWER_LENGTH * LOG(MINIMUM_BASE,10)
283 +  result + 1 >  LOG(MINIMUM_BASE, 10 ^ STRING_POWER_LENGTH)= STRING_POWER_LENGTH * LOG(MINIMUM_BASE,10)
284 +
285 +  4) STRING_POWER_LENGTH * LOG(MINIMUM_BASE,10) - 1 < result <= STRING_POWER_LENGTH * LOG(MINIMUM_BASE,10)
286 +
287 +  MINIMUM_BASE= 2 always, LOG(MINIMUM_BASE,10)= 3.3219280948873626, result= (int)3.3219280948873626 * STRING_POWER_LENGTH
288 +
289 +  Last counter always use for time overflow
290 +*/
291 +#define POSITIVE_POWER_COUNT ((int)(3.32192809 * TIME_STRING_POSITIVE_POWER_LENGTH))
292 +#define NEGATIVE_POWER_COUNT ((int)(3.32192809 * TIME_STRING_NEGATIVE_POWER_LENGTH))
293 +#define OVERALL_POWER_COUNT (NEGATIVE_POWER_COUNT + 1 + POSITIVE_POWER_COUNT)
294 +
295 +#define MILLION ((unsigned long)1000 * 1000)
296 +
297 +namespace query_response_time
298 +{
299 +
300 +class utility
301 +{
302 +public:
303 +  utility() : m_base(0)
304 +  {
305 +    m_max_dec_value= MILLION;
306 +    for(int i= 0; TIME_STRING_POSITIVE_POWER_LENGTH > i; ++i)
307 +      m_max_dec_value *= 10;
308 +    setup(DEFAULT_BASE);
309 +  }
310 +public:
311 +  uint      base()            const { return m_base; }
312 +  uint      negative_count()  const { return m_negative_count; }
313 +  uint      positive_count()  const { return m_positive_count; }
314 +  uint      bound_count()     const { return m_bound_count; }
315 +  ulonglong max_dec_value()   const { return m_max_dec_value; }
316 +  ulonglong bound(uint index) const { return m_bound[ index ]; }
317 +public:
318 +  void setup(uint base)
319 +  {
320 +    if(base != m_base)
321 +    {
322 +      m_base= base;
323 +
324 +      const ulonglong million= 1000 * 1000;
325 +      ulonglong value= million;
326 +      m_negative_count= 0;
327 +      while(value > 0)
328 +      {
329 +       m_negative_count += 1;
330 +       value /= m_base;
331 +      }
332 +      m_negative_count -= 1;
333 +
334 +      value= million;
335 +      m_positive_count= 0;
336 +      while(value < m_max_dec_value)
337 +      {
338 +       m_positive_count += 1;
339 +       value *= m_base;
340 +      }
341 +      m_bound_count= m_negative_count + m_positive_count;
342 +
343 +      value= million;
344 +      for(uint i= 0; i < m_negative_count; ++i)
345 +      {
346 +       value /= m_base;
347 +       m_bound[m_negative_count - i - 1]= value;
348 +      }
349 +      value= million;
350 +      for(uint i= 0; i < m_positive_count;  ++i)
351 +      {
352 +       m_bound[m_negative_count + i]= value;
353 +       value *= m_base;
354 +      }
355 +    }
356 +  }
357 +private:
358 +  uint      m_base;
359 +  uint      m_negative_count;
360 +  uint      m_positive_count;
361 +  uint      m_bound_count;
362 +  ulonglong m_max_dec_value; /* for TIME_STRING_POSITIVE_POWER_LENGTH=7 is 10000000 */
363 +  ulonglong m_bound[OVERALL_POWER_COUNT];
364 +};
365 +
366 +void print_time(char* buffer, std::size_t buffer_size, std::size_t string_positive_power_length, const char* format, uint64 value)
367 +{
368 +  memset(buffer,'X',buffer_size);
369 +  buffer[string_positive_power_length]= '.';
370 +  ulonglong second=      (value / MILLION);
371 +  ulonglong microsecond= (value % MILLION);
372 +  int result_length= snprintf(buffer, buffer_size, format, second, microsecond);
373 +  if(result_length < 0)
374 +  {
375 +    assert(sizeof(STRING_OVERFLOW) <= buffer_size);
376 +    memcpy(buffer, STRING_OVERFLOW, sizeof(STRING_OVERFLOW));
377 +    return;
378 +  }
379 +  buffer[result_length]= 0;
380 +}
381 +#ifdef __x86_64__
382 +typedef uint64 TimeCounter;
383 +void add_time_atomic(TimeCounter* counter, uint64 time)
384 +{
385 +  __sync_fetch_and_add(counter,time);  
386 +}
387 +#endif // __x86_64__
388 +#ifdef __i386__
389 +inline uint32 get_high(uint64 value)
390 +{
391 +  return ((value >> 32) << 32);
392 +}
393 +inline uint32 get_low(uint64 value)
394 +{
395 +  return ((value << 32) >> 32);
396 +}
397 +#ifdef __FreeBSD__
398 +inline bool compare_and_swap(volatile uint32 *target, uint32 old, uint32 new_value)
399 +{
400 +  return atomic_cmpset_32(target,old,new_value);
401 +}
402 +#else // __FreeBSD__
403 +inline bool compare_and_swap(volatile uint32* target, uint32 old, uint32 new_value)
404 +{
405 +  return __sync_bool_compare_and_swap(target,old,new_value);
406 +}
407 +#endif // __FreeBSD__
408 +class TimeCounter
409 +{
410 +public:
411 +  TimeCounter& operator=(uint64 time)
412 +  {
413 +    this->m_high= get_high(time);
414 +    this->m_low=  get_low(time);
415 +    return *this;
416 +  }
417 +  operator uint64() const
418 +  {
419 +    return ((static_cast<uint64>(m_high) << 32) + static_cast<uint64>(m_low));
420 +  }
421 +  void add(uint64 time)
422 +  {
423 +    uint32 time_high = get_high(time);
424 +    uint32 time_low  = get_low(time);
425 +    uint64 time_low64= time_low;
426 +    while(true)
427 +    {
428 +      uint32 old_low= this->m_low;
429 +      uint64 old_low64= old_low;
430 +
431 +      uint64 new_low64= old_low64 + time_low64;
432 +      uint32 new_low= (get_low(new_low64));
433 +      bool add_high= (get_high(new_low64) != 0);
434 +
435 +      if(!compare_and_swap(&m_low,old_low,new_low))
436 +      {
437 +       continue;
438 +      }
439 +      if(add_high)
440 +      {
441 +       ++time_high;
442 +      }
443 +      if(time_high > 0)
444 +      {
445 +        __sync_fetch_and_add(&m_high,time_high);
446 +      }
447 +      break;
448 +    }
449 +  }
450 +private:
451 +  uint32 m_low;
452 +  uint32 m_high;
453 +};
454 +void add_time_atomic(TimeCounter* counter, uint64 time)
455 +{
456 +  counter->add(time);
457 +}
458 +#endif // __i386__
459 +
460 +class time_collector
461 +{
462 +public:
463 +  time_collector(utility& u) : m_utility(&u)
464 +  {
465 +  }
466 +  uint32 count(uint index) const { return m_count[index]; }
467 +  uint64 total(uint index) const { return m_total[index]; }
468 +public:
469 +  void flush()
470 +  {
471 +    memset(&m_count,0,sizeof(m_count));
472 +    memset((void*)&m_total,0,sizeof(m_total));
473 +  }
474 +  void collect(uint64 time)
475 +  {
476 +    bool no_collect= false;
477 +    DBUG_EXECUTE_IF("response_time_distribution_log_only_more_300_milliseconds", {   \
478 +        no_collect= time < 300 * 1000; \
479 +      });
480 +    if(no_collect) return;
481 +    int i= 0;
482 +    for(int count= m_utility->bound_count(); count > i; ++i)
483 +    {
484 +      if(m_utility->bound(i) > time)
485 +      {
486 +        __sync_fetch_and_add(&(m_count[i]),(uint32)1);
487 +        add_time_atomic(&(m_total[i]),time);
488 +        break;
489 +      }
490 +    }
491 +  }
492 +private:
493 +  utility* m_utility;
494 +  uint32   m_count[OVERALL_POWER_COUNT + 1];
495 +  TimeCounter m_total[OVERALL_POWER_COUNT + 1];
496 +};
497 +
498 +class collector
499 +{
500 +public:
501 +  collector() : m_time(m_utility)
502 +  {
503 +    m_utility.setup(DEFAULT_BASE);
504 +    m_time.flush();
505 +  }
506 +public:
507 +  void flush()
508 +  {
509 +    m_utility.setup(opt_query_response_time_range_base);
510 +    m_time.flush();
511 +  }
512 +  int fill(THD* thd, TABLE_LIST *tables, COND *cond)
513 +  {
514 +    DBUG_ENTER("fill_schema_query_response_time");
515 +    TABLE        *table= static_cast<TABLE*>(tables->table);
516 +    Field        **fields= table->field;
517 +    for(uint i= 0, count= bound_count() + 1 /* with overflow */; count > i; ++i)
518 +    {
519 +      char time[TIME_STRING_BUFFER_LENGTH];
520 +      char total[TOTAL_STRING_BUFFER_LENGTH];
521 +      if(i == bound_count())
522 +      {        
523 +        assert(sizeof(TIME_OVERFLOW) <= TIME_STRING_BUFFER_LENGTH);
524 +        assert(sizeof(TIME_OVERFLOW) <= TOTAL_STRING_BUFFER_LENGTH);
525 +        memcpy(time,TIME_OVERFLOW,sizeof(TIME_OVERFLOW));
526 +        memcpy(total,TIME_OVERFLOW,sizeof(TIME_OVERFLOW));
527 +      }
528 +      else
529 +      {
530 +        print_time(time,sizeof(time),TIME_STRING_POSITIVE_POWER_LENGTH,TIME_STRING_FORMAT,this->bound(i));
531 +        print_time(total,sizeof(total),TOTAL_STRING_POSITIVE_POWER_LENGTH,TOTAL_STRING_FORMAT,this->total(i));
532 +      }
533 +      fields[0]->store(time,strlen(time),system_charset_info);
534 +      fields[1]->store(this->count(i));
535 +      fields[2]->store(total,strlen(total),system_charset_info);
536 +      if (schema_table_store_record(thd, table))
537 +      {
538 +       DBUG_RETURN(1);
539 +      }
540 +    }
541 +    DBUG_RETURN(0);
542 +  }
543 +  void collect(ulonglong time)
544 +  {
545 +    m_time.collect(time);
546 +  }
547 +  uint bound_count() const
548 +  {
549 +    return m_utility.bound_count();
550 +  }
551 +  ulonglong bound(uint index)
552 +  {
553 +    return m_utility.bound(index);
554 +  }
555 +  ulonglong count(uint index)
556 +  {
557 +    return m_time.count(index);
558 +  }
559 +  ulonglong total(uint index)
560 +  {
561 +    return m_time.total(index);
562 +  }
563 +private:
564 +  utility          m_utility;
565 +  time_collector   m_time;
566 +};
567 +
568 +static collector g_collector;
569 +
570 +} // namespace query_response_time
571 +
572 +void query_response_time_init()
573 +{
574 +}
575 +
576 +void query_response_time_free()
577 +{
578 +  query_response_time::g_collector.flush();
579 +}
580 +
581 +void query_response_time_flush()
582 +{
583 +  query_response_time::g_collector.flush();
584 +}
585 +void query_response_time_collect(ulonglong query_time)
586 +{
587 +  query_response_time::g_collector.collect(query_time);
588 +}
589 +
590 +int query_response_time_fill(THD* thd, TABLE_LIST *tables, COND *cond)
591 +{
592 +  return query_response_time::g_collector.fill(thd,tables,cond);
593 +}
594 +#endif /* HAVE_RESPONSE_TIME_DISTRIBUTION */
595 diff -ruN a/sql/query_response_time.h b/sql/query_response_time.h
596 --- a/sql/query_response_time.h 1970-01-01 00:00:00.000000000 +0000
597 +++ b/sql/query_response_time.h 2010-11-01 08:52:40.000000000 +0000
598 @@ -0,0 +1,71 @@
599 +#ifndef QUERY_RESPONSE_TIME_H
600 +#define QUERY_RESPONSE_TIME_H
601 +
602 +/*
603 +  Settings for query response time
604 +*/
605 +
606 +/*
607 +  Maximum string length for (10 ^ (-1 * QRT_STRING_NEGATIVE_POWER_LENGTH)) in text representation.
608 +  Example: for 6 is 0.000001
609 +  Always 2
610 +
611 +  Maximum string length for (10 ^ (QRT_STRING_POSITIVE_POWER_LENGTH + 1) - 1) in text representation.
612 +  Example: for 7 is 9999999.0
613 +*/
614 +#define QRT_TIME_STRING_POSITIVE_POWER_LENGTH 7
615 +#define QRT_TOTAL_STRING_POSITIVE_POWER_LENGTH 7
616 +
617 +/*
618 +  Minimum base for log - ALWAYS 2
619 +  Maximum base for log:
620 +*/
621 +#define QRT_MAXIMUM_BASE 1000
622 +
623 +/*
624 +  Filler for whole number (positive power)
625 +  Example: for
626 +  QRT_POSITIVE_POWER_FILLER ' '
627 +  QRT_POSITIVE_POWER_LENGTH 7
628 +  and number 7234 result is:
629 +  '   7234'
630 +*/
631 +#define QRT_POSITIVE_POWER_FILLER " "
632 +/*
633 +  Filler for fractional number. Similiary to whole number
634 +*/
635 +#define QRT_NEGATIVE_POWER_FILLER "0"
636 +
637 +/*
638 +  Message if string overflow (string overflow - internal error, this string say about bug in QRT)
639 +*/
640 +#define QRT_STRING_OVERFLOW "TOO BIG STRING"
641 +
642 +/*
643 +  Message if time too big for statistic collecting (very long query)
644 +*/
645 +#define QRT_TIME_OVERFLOW "TOO LONG"
646 +
647 +#define QRT_DEFAULT_BASE 10
648 +
649 +#define QRT_TIME_STRING_LENGTH                         \
650 +  max( (QRT_TIME_STRING_POSITIVE_POWER_LENGTH + 1 /* '.' */ + 6 /*QRT_TIME_STRING_NEGATIVE_POWER_LENGTH*/), \
651 +       max( (sizeof(QRT_TIME_OVERFLOW) - 1),           \
652 +           (sizeof(QRT_STRING_OVERFLOW) - 1) ) )
653 +
654 +#define QRT_TOTAL_STRING_LENGTH                                \
655 +  max( (QRT_TOTAL_STRING_POSITIVE_POWER_LENGTH + 1 /* '.' */ + 6 /*QRT_TOTAL_STRING_NEGATIVE_POWER_LENGTH*/), \
656 +       max( (sizeof(QRT_TIME_OVERFLOW) - 1),           \
657 +           (sizeof(QRT_STRING_OVERFLOW) - 1) ) )
658 +
659 +extern ST_SCHEMA_TABLE query_response_time_table;
660 +
661 +#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
662 +extern void query_response_time_init   ();
663 +extern void query_response_time_free   ();
664 +extern void query_response_time_flush  ();
665 +extern void query_response_time_collect(ulonglong query_time);
666 +extern int  query_response_time_fill   (THD* thd, TABLE_LIST *tables, COND *cond);
667 +#endif /* HAVE_RESPONSE_TIME_DISTRIBUTION */
668 +
669 +#endif // QUERY_RESPONSE_TIME_H
670 diff -ruN a/sql/set_var.cc b/sql/set_var.cc
671 --- a/sql/set_var.cc    2010-11-01 08:43:57.000000000 +0000
672 +++ b/sql/set_var.cc    2010-11-01 08:52:40.000000000 +0000
673 @@ -1017,6 +1017,14 @@
674  static sys_var_use_global_long_query_time sys_use_global_long_query_time;
675  static sys_var_bool_ptr       sys_slow_query_log_microseconds_timestamp(&vars, "slow_query_log_microseconds_timestamp",
676                                                         &opt_slow_query_log_microseconds_timestamp);
677 +#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
678 +static sys_var_bool_ptr       sys_enable_query_response_time_stats(&vars, "enable_query_response_time_stats",
679 +                                                       &opt_enable_query_response_time_stats);
680 +static sys_var_long_ptr       sys_query_response_time_range_base(&vars, "query_response_time_range_base",
681 +                                                      &opt_query_response_time_range_base);
682 +#endif /* HAVE_RESPONSE_TIME_DISTRIBUTION */
683 +static sys_var_have_variable sys_have_response_time_distribution(&vars, "have_response_time_distribution",
684 +                                                       &have_response_time_distribution);
685  /* Synonym of "slow_query_log" for consistency with SHOW VARIABLES output */
686  static sys_var_log_state sys_var_log_slow(&vars, "log_slow_queries",
687                                            &opt_slow_log, QUERY_LOG_SLOW);
688 diff -ruN a/sql/sql_parse.cc b/sql/sql_parse.cc
689 --- a/sql/sql_parse.cc  2010-11-01 08:43:57.000000000 +0000
690 +++ b/sql/sql_parse.cc  2010-11-01 08:52:40.000000000 +0000
691 @@ -28,6 +28,7 @@
692  #include "events.h"
693  #include "sql_trigger.h"
694  #include "debug_sync.h"
695 +#include "query_response_time.h"
696  
697  /**
698    @defgroup Runtime_Environment Runtime Environment
699 @@ -1764,23 +1765,37 @@
700      Do not log administrative statements unless the appropriate option is
701      set.
702    */
703 +#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
704 +  if (opt_enable_query_response_time_stats || thd->enable_slow_log)
705 +#else /* HAVE_RESPONSE_TIME_DISTRIBUTION */
706    if (thd->enable_slow_log)
707 +#endif /* HAVE_RESPONSE_TIME_DISTRIBUTION */
708    {
709 -    ulonglong end_utime_of_query= thd->current_utime();
710 -    thd_proc_info(thd, "logging slow query");
711 -
712 -    if (((end_utime_of_query - thd->utime_after_lock) >
713 -         thd->variables.long_query_time ||
714 -         ((thd->server_status &
715 -           (SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)) &&
716 -          opt_log_queries_not_using_indexes &&
717 -           !(sql_command_flags[thd->lex->sql_command] & CF_STATUS_COMMAND))) &&
718 -        thd->examined_row_count >= thd->variables.min_examined_row_limit)
719 +    ulonglong end_utime_of_query   = thd->current_utime();
720 +    ulonglong query_execution_time = end_utime_of_query - thd->utime_after_lock;
721 +    #ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
722 +    if(opt_enable_query_response_time_stats)
723 +    {
724 +      query_response_time_collect(query_execution_time);
725 +    }
726 +    #endif /* HAVE_RESPONSE_TIME_DISTRIBUTION */
727 +    if (thd->enable_slow_log)
728      {
729        thd_proc_info(thd, "logging slow query");
730 -      thd->status_var.long_query_count++;
731 -      slow_log_print(thd, thd->query(), thd->query_length(), 
732 -                     end_utime_of_query);
733 +
734 +      if ((query_execution_time >
735 +           thd->variables.long_query_time ||
736 +           ((thd->server_status &
737 +             (SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)) &&
738 +            opt_log_queries_not_using_indexes &&
739 +             !(sql_command_flags[thd->lex->sql_command] & CF_STATUS_COMMAND))) &&
740 +          thd->examined_row_count >= thd->variables.min_examined_row_limit)
741 +      {
742 +        thd_proc_info(thd, "logging slow query");
743 +        thd->status_var.long_query_count++;
744 +        slow_log_print(thd, thd->query(), thd->query_length(), 
745 +                       end_utime_of_query);
746 +      }
747      }
748    }
749    DBUG_VOID_RETURN;
750 @@ -1905,6 +1920,7 @@
751    case SCH_CHARSETS:
752    case SCH_ENGINES:
753    case SCH_COLLATIONS:
754 +  case SCH_QUERY_RESPONSE_TIME:
755    case SCH_COLLATION_CHARACTER_SET_APPLICABILITY:
756    case SCH_USER_PRIVILEGES:
757    case SCH_SCHEMA_PRIVILEGES:
758 @@ -7265,6 +7281,12 @@
759      init_global_index_stats();
760      pthread_mutex_unlock(&LOCK_global_index_stats);
761    }
762 +#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
763 +  if (options & REFRESH_QUERY_RESPONSE_TIME)
764 +  {
765 +    query_response_time_flush();
766 +  }
767 +#endif /* HAVE_RESPONSE_TIME_DISTRIBUTION */
768    if (options & (REFRESH_USER_STATS | REFRESH_CLIENT_STATS | REFRESH_THREAD_STATS))
769    {
770      pthread_mutex_lock(&LOCK_global_user_client_stats);
771 diff -ruN a/sql/sql_show.cc b/sql/sql_show.cc
772 --- a/sql/sql_show.cc   2010-11-01 08:43:53.000000000 +0000
773 +++ b/sql/sql_show.cc   2010-11-01 08:52:40.000000000 +0000
774 @@ -31,6 +31,7 @@
775  #include "event_data_objects.h"
776  #endif
777  #include <my_dir.h>
778 +#include "query_response_time.h"
779  #include "debug_sync.h"
780  
781  #define STR_OR_NIL(S) ((S) ? (S) : "<nil>")
782 @@ -7490,6 +7491,13 @@
783  
784  */
785  
786 +ST_FIELD_INFO query_response_time_fields_info[] =
787 +  {
788 +    {"time",  QRT_TIME_STRING_LENGTH,      MYSQL_TYPE_STRING,  0, 0,            "", SKIP_OPEN_TABLE },
789 +    {"count", MY_INT32_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, MY_I_S_UNSIGNED, "", SKIP_OPEN_TABLE },
790 +    {"total",  QRT_TIME_STRING_LENGTH,     MYSQL_TYPE_STRING,  0, 0,            "", SKIP_OPEN_TABLE },
791 +    {0,       0,                           MYSQL_TYPE_STRING,  0, 0,             0, SKIP_OPEN_TABLE }
792 +  };
793  ST_SCHEMA_TABLE schema_tables[]=
794  {
795    {"CHARACTER_SETS", charsets_fields_info, create_schema_table, 
796 @@ -7544,6 +7552,13 @@
797     1, 9, 0, OPEN_TABLE_ONLY},
798    {"ROUTINES", proc_fields_info, create_schema_table, 
799     fill_schema_proc, make_proc_old_format, 0, -1, -1, 0, 0},
800 +#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
801 +  {"QUERY_RESPONSE_TIME", query_response_time_fields_info, create_schema_table, 
802 +   query_response_time_fill, make_old_format, 0, -1, -1, 0, 0},
803 +#else /* HAVE_RESPONSE_TIME_DISTRIBUTION */
804 +  {"QUERY_RESPONSE_TIME", query_response_time_fields_info, create_schema_table, 
805 +   0, make_old_format, 0, -1, -1, 0, 0},
806 +#endif /* HAVE_RESPONSE_TIME_DISTRIBUTION */
807    {"SCHEMATA", schema_fields_info, create_schema_table,
808     fill_schema_schemata, make_schemata_old_format, 0, 1, -1, 0, 0},
809    {"SCHEMA_PRIVILEGES", schema_privileges_fields_info, create_schema_table,
810 diff -ruN a/sql/sql_yacc.yy b/sql/sql_yacc.yy
811 --- a/sql/sql_yacc.yy   2010-11-01 08:43:53.000000000 +0000
812 +++ b/sql/sql_yacc.yy   2010-11-01 08:52:40.000000000 +0000
813 @@ -1079,6 +1079,7 @@
814  %token  PURGE
815  %token  QUARTER_SYM
816  %token  QUERY_SYM
817 +%token  QUERY_RESPONSE_TIME_SYM
818  %token  QUICK
819  %token  RANGE_SYM                     /* SQL-2003-R */
820  %token  READS_SYM                     /* SQL-2003-R */
821 @@ -10396,6 +10397,15 @@
822             if (prepare_schema_table(YYTHD, lex, 0, SCH_INDEX_STATS))
823               MYSQL_YYABORT;
824            }
825 +        | QUERY_RESPONSE_TIME_SYM wild_and_where
826 +         {
827 +#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
828 +           LEX *lex= Lex;
829 +           lex->sql_command= SQLCOM_SELECT;
830 +           if (prepare_schema_table(YYTHD, lex, 0, SCH_QUERY_RESPONSE_TIME))
831 +             MYSQL_YYABORT;      
832 +#endif /* HAVE_RESPONSE_TIME_DISTRIBUTION */
833 +         }
834          | CREATE PROCEDURE sp_name
835            {
836              LEX *lex= Lex;
837 @@ -10616,6 +10626,12 @@
838            { Lex->type|= REFRESH_TABLE_STATS; }
839          | INDEX_STATS_SYM
840            { Lex->type|= REFRESH_INDEX_STATS; }
841 +        | QUERY_RESPONSE_TIME_SYM
842 +          { 
843 +#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
844 +            Lex->type|= REFRESH_QUERY_RESPONSE_TIME; 
845 +#endif /* HAVE_RESPONSE_TIME_DISTRIBUTION */
846 +          }
847          | MASTER_SYM
848            { Lex->type|= REFRESH_MASTER; }
849          | DES_KEY_FILE
850 @@ -11895,6 +11911,7 @@
851          | PROFILES_SYM             {}
852          | QUARTER_SYM              {}
853          | QUERY_SYM                {}
854 +        | QUERY_RESPONSE_TIME_SYM  {}
855          | QUICK                    {}
856          | READ_ONLY_SYM            {}
857          | REBUILD_SYM              {}
858 diff -ruN a/sql/table.h b/sql/table.h
859 --- a/sql/table.h       2010-11-01 08:43:53.000000000 +0000
860 +++ b/sql/table.h       2010-11-01 08:52:40.000000000 +0000
861 @@ -964,6 +964,7 @@
862    SCH_PROFILES,
863    SCH_REFERENTIAL_CONSTRAINTS,
864    SCH_PROCEDURES,
865 +  SCH_QUERY_RESPONSE_TIME,
866    SCH_SCHEMATA,
867    SCH_SCHEMA_PRIVILEGES,
868    SCH_SESSION_STATUS,
869 diff -ruN a/configure.in b/configure.in
870 --- a/configure.in      2010-12-07 19:19:42.000000000 +0300
871 +++ b/configure.in      2010-12-07 19:21:39.000000000 +0300
872 @@ -2687,7 +2687,16 @@
873  AC_SUBST(readline_link)
874  AC_SUBST(readline_h_ln_cmd)
875  
876 +AC_ARG_WITH(response_time_distribution,
877 +    AC_HELP_STRING([--without-response_time_distribution],[Disable response_time_distribution feature.]),
878 +    [with_response_time_distribution=$withval],
879 +    [with_response_time_distribution=yes]
880 +)
881  
882 +if test "$with_response_time_distribution" = "yes"
883 +then
884 +  AC_DEFINE([HAVE_RESPONSE_TIME_DISTRIBUTION], [1], [If we want to have response_time_distribution])
885 +fi
886  
887  # Include man pages, if desired, adapted to the configured parts.
888  if test X"$with_man" = Xyes
This page took 0.096798 seconds and 3 git commands to generate.