My Project
sql_profile.h
00001 /* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
00002 
00003    This program is free software; you can redistribute it and/or modify
00004    it under the terms of the GNU General Public License as published by
00005    the Free Software Foundation; version 2 of the License.
00006 
00007    This program is distributed in the hope that it will be useful,
00008    but WITHOUT ANY WARRANTY; without even the implied warranty of
00009    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010    GNU General Public License for more details.
00011 
00012    You should have received a copy of the GNU General Public License
00013    along with this program; if not, write to the Free Software Foundation,
00014    51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
00015 
00016 #ifndef _SQL_PROFILE_H
00017 #define _SQL_PROFILE_H
00018 
00019 class Item;
00020 struct TABLE_LIST;
00021 class THD;
00022 typedef struct st_field_info ST_FIELD_INFO;
00023 typedef struct st_schema_table ST_SCHEMA_TABLE;
00024 
00025 extern ST_FIELD_INFO query_profile_statistics_info[];
00026 int fill_query_profile_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond);
00027 int make_profile_table_for_show(THD *thd, ST_SCHEMA_TABLE *schema_table);
00028 
00029 
00030 #define PROFILE_NONE         (uint)0
00031 #define PROFILE_CPU          (uint)(1<<0)
00032 #define PROFILE_MEMORY       (uint)(1<<1)
00033 #define PROFILE_BLOCK_IO     (uint)(1<<2)
00034 #define PROFILE_CONTEXT      (uint)(1<<3)
00035 #define PROFILE_PAGE_FAULTS  (uint)(1<<4)
00036 #define PROFILE_IPC          (uint)(1<<5)
00037 #define PROFILE_SWAPS        (uint)(1<<6)
00038 #define PROFILE_SOURCE       (uint)(1<<16)
00039 #define PROFILE_ALL          (uint)(~0)
00040 
00041 
00042 #if defined(ENABLED_PROFILING)
00043 #include "sql_priv.h"
00044 #include "unireg.h"
00045 
00046 #ifdef HAVE_SYS_RESOURCE_H
00047 #include <sys/resource.h>
00048 #endif
00049 
00050 
00051 class PROF_MEASUREMENT;
00052 class QUERY_PROFILE;
00053 class PROFILING;
00054 
00055 
00060 template <class T> class Queue
00061 {
00062 private:
00063 
00064   struct queue_item
00065   {
00066     T *payload;
00067     struct queue_item *next, *previous;
00068   };
00069 
00070   struct queue_item *first, *last;
00071 
00072 public:
00073   Queue()
00074   {
00075     elements= 0;
00076     first= last= NULL;
00077   }
00078 
00079   void empty()
00080   {
00081     struct queue_item *i, *after_i;
00082     for (i= first; i != NULL; i= after_i)
00083     {
00084       after_i= i->next;
00085       my_free(i);
00086     }
00087     elements= 0;
00088   }
00089 
00090   ulong elements;                       /* The count of items in the Queue */
00091 
00092   void push_back(T *payload)
00093   {
00094     struct queue_item *new_item;
00095 
00096     new_item= (struct queue_item *) my_malloc(sizeof(struct queue_item), MYF(0));
00097 
00098     new_item->payload= payload;
00099 
00100     if (first == NULL)
00101       first= new_item;
00102     if (last != NULL)
00103     {
00104       DBUG_ASSERT(last->next == NULL);
00105       last->next= new_item;
00106     }
00107     new_item->previous= last;
00108     new_item->next= NULL;
00109     last= new_item;
00110 
00111     elements++;
00112   }
00113 
00114   T *pop()
00115   {
00116     struct queue_item *old_item= first;
00117     T *ret= NULL;
00118 
00119     if (first == NULL)
00120     {
00121       DBUG_PRINT("warning", ("tried to pop nonexistent item from Queue"));
00122       return NULL;
00123     }
00124 
00125     ret= old_item->payload;
00126     if (first->next != NULL)
00127       first->next->previous= NULL;
00128     else
00129       last= NULL;
00130     first= first->next;
00131 
00132     my_free(old_item);
00133     elements--;
00134 
00135     return ret;
00136   }
00137 
00138   bool is_empty()
00139   {
00140     DBUG_ASSERT(((elements > 0) && (first != NULL)) || ((elements == 0) || (first == NULL)));
00141     return (elements == 0);
00142   }
00143 
00144   void *new_iterator()
00145   {
00146     return first;
00147   }
00148 
00149   void *iterator_next(void *current)
00150   {
00151     return ((struct queue_item *) current)->next;
00152   }
00153 
00154   T *iterator_value(void *current)
00155   {
00156     return ((struct queue_item *) current)->payload;
00157   }
00158 
00159 };
00160 
00161 
00165 class PROF_MEASUREMENT
00166 {
00167 private:
00168   friend class QUERY_PROFILE;
00169   friend class PROFILING;
00170 
00171   QUERY_PROFILE *profile;
00172   char *status;
00173 #ifdef HAVE_GETRUSAGE
00174   struct rusage rusage;
00175 #elif defined(_WIN32)
00176   FILETIME ftKernel, ftUser;
00177 #endif
00178 
00179   char *function;
00180   char *file;
00181   unsigned int line;
00182 
00183   ulong m_seq;
00184   double time_usecs;
00185   char *allocated_status_memory;
00186 
00187   void set_label(const char *status_arg, const char *function_arg, 
00188                   const char *file_arg, unsigned int line_arg);
00189   void clean_up();
00190   
00191   PROF_MEASUREMENT();
00192   PROF_MEASUREMENT(QUERY_PROFILE *profile_arg, const char *status_arg);
00193   PROF_MEASUREMENT(QUERY_PROFILE *profile_arg, const char *status_arg,
00194                 const char *function_arg,
00195                 const char *file_arg, unsigned int line_arg);
00196   ~PROF_MEASUREMENT();
00197   void collect();
00198 };
00199 
00200 
00205 class QUERY_PROFILE
00206 {
00207 private:
00208   friend class PROFILING;
00209 
00210   PROFILING *profiling;
00211 
00212   query_id_t profiling_query_id;        /* Session-specific id. */
00213   char *query_source;
00214 
00215   double m_start_time_usecs;
00216   double m_end_time_usecs;
00217   ulong m_seq_counter;
00218   Queue<PROF_MEASUREMENT> entries;
00219 
00220 
00221   QUERY_PROFILE(PROFILING *profiling_arg, const char *status_arg);
00222   ~QUERY_PROFILE();
00223 
00224   void set_query_source(char *query_source_arg, uint query_length_arg);
00225 
00226   /* Add a profile status change to the current profile. */
00227   void new_status(const char *status_arg,
00228               const char *function_arg,
00229               const char *file_arg, unsigned int line_arg);
00230 
00231   /* Reset the contents of this profile entry. */
00232   void reset();
00233 
00234   /* Show this profile.  This is called by PROFILING. */
00235   bool show(uint options);
00236 };
00237 
00238 
00242 class PROFILING
00243 {
00244 private:
00245   friend class PROF_MEASUREMENT;
00246   friend class QUERY_PROFILE;
00247 
00248   /* 
00249     Not the system query_id, but a counter unique to profiling. 
00250   */
00251   query_id_t profile_id_counter;     
00252   THD *thd;
00253   bool keeping;
00254   bool enabled;
00255 
00256   QUERY_PROFILE *current;
00257   QUERY_PROFILE *last;
00258   Queue<QUERY_PROFILE> history;
00259  
00260   query_id_t next_profile_id() { return(profile_id_counter++); }
00261 
00262 public:
00263   PROFILING();
00264   ~PROFILING();
00265   void set_query_source(char *query_source_arg, uint query_length_arg);
00266 
00267   void start_new_query(const char *initial_state= "starting");
00268 
00269   void discard_current_query();
00270 
00271   void finish_current_query();
00272 
00273   void status_change(const char *status_arg,
00274                      const char *function_arg,
00275                      const char *file_arg, unsigned int line_arg);
00276 
00277   inline void set_thd(THD *thd_arg) { thd= thd_arg; };
00278 
00279   /* SHOW PROFILES */
00280   bool show_profiles();
00281 
00282   /* ... from INFORMATION_SCHEMA.PROFILING ... */
00283   int fill_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond);
00284 };
00285 
00286 #  endif /* HAVE_PROFILING */
00287 #endif /* _SQL_PROFILE_H */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines