1 /* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 2 3 This program is free software; you can redistribute it and/or modify 4 it under the terms of the GNU General Public License, version 2.0, 5 as published by the Free Software Foundation. 6 7 This program is also distributed with certain software (including 8 but not limited to OpenSSL) that is licensed under separate terms, 9 as designated in a particular file or component or in included license 10 documentation. The authors of MySQL hereby grant you an additional 11 permission to link the program and your derivative works with the 12 separately licensed software that they have included with MySQL. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License, version 2.0, for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software Foundation, 21 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ 22 23 #ifndef _SQL_PROFILE_H 24 #define _SQL_PROFILE_H 25 26 class Item; 27 struct TABLE_LIST; 28 class THD; 29 typedef struct st_field_info ST_FIELD_INFO; 30 typedef struct st_schema_table ST_SCHEMA_TABLE; 31 32 extern ST_FIELD_INFO query_profile_statistics_info[]; 33 int fill_query_profile_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond); 34 int make_profile_table_for_show(THD *thd, ST_SCHEMA_TABLE *schema_table); 35 36 37 #define PROFILE_NONE (uint)0 38 #define PROFILE_CPU (uint)(1<<0) 39 #define PROFILE_MEMORY (uint)(1<<1) 40 #define PROFILE_BLOCK_IO (uint)(1<<2) 41 #define PROFILE_CONTEXT (uint)(1<<3) 42 #define PROFILE_PAGE_FAULTS (uint)(1<<4) 43 #define PROFILE_IPC (uint)(1<<5) 44 #define PROFILE_SWAPS (uint)(1<<6) 45 #define PROFILE_SOURCE (uint)(1<<16) 46 #define PROFILE_ALL (uint)(~0) 47 48 49 #if defined(ENABLED_PROFILING) 50 #include "sql_priv.h" 51 #include "unireg.h" 52 53 #ifdef HAVE_SYS_RESOURCE_H 54 #include <sys/resource.h> 55 #endif 56 57 58 class PROF_MEASUREMENT; 59 class QUERY_PROFILE; 60 class PROFILING; 61 62 63 /** 64 Implements a persistent FIFO using server List method names. Not 65 thread-safe. Intended to be used on thread-local data only. 66 */ 67 template <class T> class Queue 68 { 69 private: 70 71 struct queue_item 72 { 73 T *payload; 74 struct queue_item *next, *previous; 75 }; 76 77 struct queue_item *first, *last; 78 79 public: Queue()80 Queue() 81 { 82 elements= 0; 83 first= last= NULL; 84 } 85 empty()86 void empty() 87 { 88 struct queue_item *i, *after_i; 89 for (i= first; i != NULL; i= after_i) 90 { 91 after_i= i->next; 92 my_free(i); 93 } 94 elements= 0; 95 } 96 97 ulong elements; /* The count of items in the Queue */ 98 push_back(T * payload)99 void push_back(T *payload) 100 { 101 struct queue_item *new_item; 102 103 new_item= (struct queue_item *) my_malloc(sizeof(struct queue_item), MYF(0)); 104 105 new_item->payload= payload; 106 107 if (first == NULL) 108 first= new_item; 109 if (last != NULL) 110 { 111 DBUG_ASSERT(last->next == NULL); 112 last->next= new_item; 113 } 114 new_item->previous= last; 115 new_item->next= NULL; 116 last= new_item; 117 118 elements++; 119 } 120 pop()121 T *pop() 122 { 123 struct queue_item *old_item= first; 124 T *ret= NULL; 125 126 if (first == NULL) 127 { 128 DBUG_PRINT("warning", ("tried to pop nonexistent item from Queue")); 129 return NULL; 130 } 131 132 ret= old_item->payload; 133 if (first->next != NULL) 134 first->next->previous= NULL; 135 else 136 last= NULL; 137 first= first->next; 138 139 my_free(old_item); 140 elements--; 141 142 return ret; 143 } 144 is_empty()145 bool is_empty() 146 { 147 DBUG_ASSERT(((elements > 0) && (first != NULL)) || ((elements == 0) || (first == NULL))); 148 return (elements == 0); 149 } 150 new_iterator()151 void *new_iterator() 152 { 153 return first; 154 } 155 iterator_next(void * current)156 void *iterator_next(void *current) 157 { 158 return ((struct queue_item *) current)->next; 159 } 160 iterator_value(void * current)161 T *iterator_value(void *current) 162 { 163 return ((struct queue_item *) current)->payload; 164 } 165 166 }; 167 168 169 /** 170 A single entry in a single profile. 171 */ 172 class PROF_MEASUREMENT 173 { 174 private: 175 friend class QUERY_PROFILE; 176 friend class PROFILING; 177 178 QUERY_PROFILE *profile; 179 char *status; 180 #ifdef HAVE_GETRUSAGE 181 struct rusage rusage; 182 #elif defined(_WIN32) 183 FILETIME ftKernel, ftUser; 184 #endif 185 186 char *function; 187 char *file; 188 unsigned int line; 189 190 ulong m_seq; 191 double time_usecs; 192 char *allocated_status_memory; 193 194 void set_label(const char *status_arg, const char *function_arg, 195 const char *file_arg, unsigned int line_arg); 196 void clean_up(); 197 198 PROF_MEASUREMENT(); 199 PROF_MEASUREMENT(QUERY_PROFILE *profile_arg, const char *status_arg); 200 PROF_MEASUREMENT(QUERY_PROFILE *profile_arg, const char *status_arg, 201 const char *function_arg, 202 const char *file_arg, unsigned int line_arg); 203 ~PROF_MEASUREMENT(); 204 void collect(); 205 }; 206 207 208 /** 209 The full profile for a single query, and includes multiple PROF_MEASUREMENT 210 objects. 211 */ 212 class QUERY_PROFILE 213 { 214 private: 215 friend class PROFILING; 216 217 PROFILING *profiling; 218 219 query_id_t profiling_query_id; /* Session-specific id. */ 220 char *query_source; 221 222 double m_start_time_usecs; 223 double m_end_time_usecs; 224 ulong m_seq_counter; 225 Queue<PROF_MEASUREMENT> entries; 226 227 228 QUERY_PROFILE(PROFILING *profiling_arg, const char *status_arg); 229 ~QUERY_PROFILE(); 230 231 void set_query_source(char *query_source_arg, uint query_length_arg); 232 233 /* Add a profile status change to the current profile. */ 234 void new_status(const char *status_arg, 235 const char *function_arg, 236 const char *file_arg, unsigned int line_arg); 237 238 /* Reset the contents of this profile entry. */ 239 void reset(); 240 241 /* Show this profile. This is called by PROFILING. */ 242 bool show(uint options); 243 }; 244 245 246 /** 247 Profiling state for a single THD; contains multiple QUERY_PROFILE objects. 248 */ 249 class PROFILING 250 { 251 private: 252 friend class PROF_MEASUREMENT; 253 friend class QUERY_PROFILE; 254 255 /* 256 Not the system query_id, but a counter unique to profiling. 257 */ 258 query_id_t profile_id_counter; 259 THD *thd; 260 bool keeping; 261 bool enabled; 262 263 QUERY_PROFILE *current; 264 QUERY_PROFILE *last; 265 Queue<QUERY_PROFILE> history; 266 next_profile_id()267 query_id_t next_profile_id() { return(profile_id_counter++); } 268 269 public: 270 PROFILING(); 271 ~PROFILING(); 272 void set_query_source(char *query_source_arg, uint query_length_arg); 273 274 void start_new_query(const char *initial_state= "starting"); 275 276 void discard_current_query(); 277 278 void finish_current_query(); 279 280 void status_change(const char *status_arg, 281 const char *function_arg, 282 const char *file_arg, unsigned int line_arg); 283 set_thd(THD * thd_arg)284 inline void set_thd(THD *thd_arg) { thd= thd_arg; }; 285 286 /* SHOW PROFILES */ 287 bool show_profiles(); 288 289 /* ... from INFORMATION_SCHEMA.PROFILING ... */ 290 int fill_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond); 291 }; 292 293 # endif /* HAVE_PROFILING */ 294 #endif /* _SQL_PROFILE_H */ 295