Skip to content

File cas_query_info.c

File List > broker > cas_query_info.c

Go to the documentation of this file

/*
 * Copyright 2008 Search Solution Corporation
 * Copyright 2016 CUBRID Corporation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */


/*
 * cas_query_info.c -
 */

#ident "$Id$"

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#ifdef MT_MODE
#include <pthread.h>
#endif

#include "cas_common.h"
#include "cas_query_info.h"
#include "broker_log_sql_list.h"
#include "broker_log_top.h"

#define LOG_TOP_RES_FILE    "log_top.res"
#define LOG_TOP_Q_FILE      "log_top.q"
#define LOG_TOP_TAG_FILE    "tags"
#define LOG_TOP_NE_FILE     "log_top.ne"

static int sort_func (const void *arg1, const void *arg2);
static char *time2str (int t, char *buf);

static T_QUERY_INFO *query_info_arr = NULL;
static int num_query_info = 0;

#ifdef TEST
static T_QUERY_INFO *query_info_arr_ne = NULL;
static int num_query_info_ne = 0;
#endif

#ifdef MT_MODE
static T_MUTEX query_info_mutex;
#endif

#ifdef MT_MODE
void
query_info_mutex_init ()
{
  MUTEX_INIT (query_info_mutex);
}
#endif

void
query_info_init (T_QUERY_INFO * qi)
{
  memset (qi, 0, sizeof (T_QUERY_INFO));
  qi->min = 9999999;
  qi->max = -1;
}

void
query_info_clear (T_QUERY_INFO * qi)
{
  FREE_MEM (qi->sql);
  FREE_MEM (qi->organized_sql);
  FREE_MEM (qi->cas_log);
  qi->start_date[0] = '\0';
}

void
query_info_print (void)
{
  int i;
  char buf[1024];
  FILE *fp_res, *fp_q;
#ifdef TEST
  FILE *fp_tag, *fp_ne;
#endif
  char minstr[64], maxstr[64], avgstr[64];
  int xml_found;

#ifdef MT_MODE
  MUTEX_LOCK (query_info_mutex);
#endif

  fp_res = fopen (LOG_TOP_RES_FILE, "w");
  fp_q = fopen (LOG_TOP_Q_FILE, "w");
#ifdef TEST
  fp_tag = fopen (LOG_TOP_TAG_FILE, "w");
  fp_ne = fopen (LOG_TOP_NE_FILE, "w");
#endif
  if (fp_res == NULL || fp_q == NULL
#ifdef TEST
      || fp_tag == NULL || fp_ne == NULL
#endif
    )
    {
      fprintf (stderr, "%s\n", strerror (errno));
      goto query_info_print_end;
    }

  qsort (query_info_arr, num_query_info, sizeof (T_QUERY_INFO), sort_func);

  if (log_top_mode == MODE_PROC_TIME)
    fprintf (fp_res, "%8s %8s %9s %9s %10s\n", "", "max", "min", "avg", "cnt(err)");
  else
    fprintf (fp_res, "%8s %8s %10s\n", "", "max", "cnt");

  fprintf (fp_res, "-----------------------------------------------------\n");

  for (i = 0; i < num_query_info; i++)
    {
      sprintf (buf, "[Q%d]", i + 1);
      if (log_top_mode == MODE_PROC_TIME)
    {
      fprintf (fp_res, "%-8s %9s %9s %9s %4d (%d)", buf, time2str (query_info_arr[i].max, maxstr),
           time2str (query_info_arr[i].min, minstr), time2str (query_info_arr[i].sum / query_info_arr[i].count,
                                       avgstr), query_info_arr[i].count,
           query_info_arr[i].err_count);
    }
      else
    {
      fprintf (fp_res, "%-8s %8d %10d", buf, query_info_arr[i].max, query_info_arr[i].count);
    }

      fprintf (fp_q, "%s-------------------------------------------\n", buf);

      xml_found = sql_info_write (query_info_arr[i].sql, buf, fp_q);
      if (xml_found)
    {
      fprintf (fp_res, "%5s", "X");
    }

      fprintf (fp_res, "\n");

      fwrite (query_info_arr[i].cas_log, query_info_arr[i].cas_log_len, 1, fp_q);
      fprintf (fp_q, "\n");

#ifdef TEST
      fprintf (fp_tag, "Q%d %s  /^%s\n", i + 1, LOG_TOP_Q_FILE, buf);
#endif
    }

#ifdef TEST
  for (i = 0; i < num_query_info_ne; i++)
    {
      sprintf (buf, "[N%d]", i + 1);
      fprintf (fp_ne, "%s-------------------------------------------\n", buf);

      if (sql_info_write (query_info_arr_ne[i].sql, buf, fp_ne) < 0)
    {
      break;
    }

      fprintf (fp_ne, "%s\n", query_info_arr_ne[i].cas_log);
    }
#endif

  fclose (fp_res);
  fclose (fp_q);
#ifdef TEST
  fclose (fp_tag);
  fclose (fp_ne);
#endif

#ifdef TEST
  sprintf (buf, "sort %s -o %s", LOG_TOP_TAG_FILE, LOG_TOP_TAG_FILE);
  system (buf);
#endif

query_info_print_end:
#ifdef MT_MODE
  MUTEX_UNLOCK (query_info_mutex);
#endif
  return;
}

int
query_info_add (T_QUERY_INFO * qi, int exec_time, int execute_res, char *filename, int lineno, char *end_date)
{
  int qi_idx = -1;
  int i;
  int retval;

  if (check_log_time (qi->start_date, end_date) < 0)
    return 0;

#ifdef MT_MODE
  MUTEX_LOCK (query_info_mutex);
#endif

#if 0
  if (qi->sql == NULL)
    goto query_info_add_end;
#endif

  for (i = 0; i < num_query_info; i++)
    {
      if (strcmp (query_info_arr[i].organized_sql, qi->organized_sql) == 0)
    {
      qi_idx = i;
      break;
    }
    }

  if (qi_idx == -1)
    {
      query_info_arr = (T_QUERY_INFO *) REALLOC (query_info_arr, sizeof (T_QUERY_INFO) * (num_query_info + 1));
      if (query_info_arr == NULL)
    {
      fprintf (stderr, "%s\n", strerror (errno));
      retval = -1;
      goto query_info_add_end;
    }
      qi_idx = num_query_info;
      query_info_init (&query_info_arr[qi_idx]);
      query_info_arr[qi_idx].sql = strdup (qi->sql);
      query_info_arr[qi_idx].organized_sql = strdup (qi->organized_sql);
      num_query_info++;
    }

  if (exec_time < query_info_arr[qi_idx].min)
    {
      query_info_arr[qi_idx].min = exec_time;
    }
  if (exec_time > query_info_arr[qi_idx].max)
    {
      query_info_arr[qi_idx].max = exec_time;
      FREE_MEM (query_info_arr[qi_idx].cas_log);
      query_info_arr[qi_idx].cas_log = (char *) MALLOC (strlen (filename) + qi->cas_log_len + 20);
      if (query_info_arr[qi_idx].cas_log == NULL)
    {
      fprintf (stderr, "%s\n", strerror (errno));
      retval = -1;
      goto query_info_add_end;
    }
      sprintf (query_info_arr[qi_idx].cas_log, "%s:%d\n", filename, lineno);
      query_info_arr[qi_idx].cas_log_len = (int) strlen (query_info_arr[qi_idx].cas_log);
      memcpy (query_info_arr[qi_idx].cas_log + query_info_arr[qi_idx].cas_log_len, qi->cas_log, qi->cas_log_len);
      query_info_arr[qi_idx].cas_log_len += qi->cas_log_len;
    }
  query_info_arr[qi_idx].count++;
  query_info_arr[qi_idx].sum += exec_time;
  if (execute_res < 0)
    {
      query_info_arr[qi_idx].err_count++;
    }
  retval = 0;

query_info_add_end:

#ifdef MT_MODE
  MUTEX_UNLOCK (query_info_mutex);
#endif
  return retval;
}

int
query_info_add_ne (T_QUERY_INFO * qi, char *end_date)
{
#ifndef TEST
  /* query_info_arr_ne is used only in TEST mode */
  return 0;
#else
  int qi_idx = -1;
  int i;
  int retval;

  if (check_log_time (qi->start_date, end_date) < 0)
    {
      return 0;
    }

#ifdef MT_MODE
  MUTEX_LOCK (query_info_mutex);
#endif

  for (i = 0; i < num_query_info; i++)
    {
      if (strcmp (query_info_arr[i].organized_sql, qi->organized_sql) == 0)
    {
      retval = 0;
      goto query_info_add_ne_end;
    }
    }

  for (i = 0; i < num_query_info_ne; i++)
    {
      if (strcmp (query_info_arr_ne[i].organized_sql, qi->organized_sql) == 0)
    {
      qi_idx = i;
      break;
    }
    }

  if (qi_idx == -1)
    {
      query_info_arr_ne = (T_QUERY_INFO *) REALLOC (query_info_arr_ne, sizeof (T_QUERY_INFO) * (num_query_info_ne + 1));
      if (query_info_arr_ne == NULL)
    {
      fprintf (stderr, "%s\n", strerror (errno));
      retval = -1;
      goto query_info_add_ne_end;
    }
      qi_idx = num_query_info_ne;
      query_info_init (&query_info_arr_ne[qi_idx]);
      query_info_arr_ne[qi_idx].sql = strdup (qi->sql);
      query_info_arr_ne[qi_idx].organized_sql = strdup (qi->organized_sql);
      num_query_info_ne++;
    }

  FREE_MEM (query_info_arr_ne[qi_idx].cas_log);
  query_info_arr_ne[qi_idx].cas_log = strdup (qi->cas_log);
  if (query_info_arr_ne[qi_idx].cas_log == NULL)
    {
      fprintf (stderr, "%s\n", strerror (errno));
      retval = -1;
      goto query_info_add_ne_end;
    }

  retval = 0;

query_info_add_ne_end:
#ifdef MT_MODE
  MUTEX_UNLOCK (query_info_mutex);
#endif
  return retval;
#endif /* define TEST */
}

static int
sort_func (const void *arg1, const void *arg2)
{
  return (((T_QUERY_INFO *) arg1)->max < ((T_QUERY_INFO *) arg2)->max);
}

static char *
time2str (int t, char *buf)
{
  int sec, msec;
  sec = t / 1000;
  msec = t % 1000;
  if (sec >= 60)
    sprintf (buf, "%d:%02d.%03d", sec / 60, sec % 60, msec);
  else
    sprintf (buf, "%d.%03d", sec, msec);

  return buf;
}