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