Skip to content

File broker_log_top_tran.c

File List > broker > broker_log_top_tran.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.
 *
 */


/*
 * broker_log_top_tran.c -
 */

#ident "$Id$"

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>

#include "cas_common.h"
#include "broker_log_top.h"
#include "log_top_string.h"
#include "broker_log_util.h"

#define TRAN_LOG_MAX_COUNT  1000
#define LOG_TOP_RES_FILE_TRAN   "log_top.t"

typedef struct t_log_info T_LOG_INFO;
struct t_log_info
{
  float runtime;
  char *logstr;
};

static int log_top (FILE * fp, char *filename, long start_offset, long end_offset);
static int info_delete (T_LOG_INFO * info);
static void print_result (void);
static int info_add (T_LOG_INFO * info, char *start_date, char *end_date);

static int info_arr_size = 0;
static int info_arr_max_size = TRAN_LOG_MAX_COUNT;
static T_LOG_INFO info_arr[TRAN_LOG_MAX_COUNT + 1];

int
log_top_tran (int argc, char *argv[], int arg_start)
{
  int i;
  int error = 0;
  char *filename;
  FILE *fp;
  long start_offset, end_offset;

  info_arr_size = 0;

  for (i = arg_start; i < argc; i++)
    {
      filename = argv[i];
      fprintf (stdout, "%s\n", filename);

#if defined(WINDOWS)
      fp = fopen (filename, "rb");
#else
      fp = fopen (filename, "r");
#endif
      if (fp == NULL)
    {
      fprintf (stderr, "%s[%s]\n", strerror (errno), filename);
      return -1;
    }
      if (get_file_offset (filename, &start_offset, &end_offset) < 0)
    {
      start_offset = end_offset = -1;
    }

      error = log_top (fp, filename, start_offset, end_offset);
      fclose (fp);
      if (error == LT_INVAILD_VERSION)
    {
      return error;
    }
    }

  print_result ();

  return 0;
}

static int
log_top (FILE * fp, char *filename, long start_offset, long end_offset)
{
  char *linebuf;
  T_STRING *str_buf = NULL;
  T_STRING *linebuf_tstr = NULL;
  int lineno = 0;
  int is_first = 1;
  int log_type = 0;
  char fileinfo_str[1024];
  char cur_date[DATE_STR_LEN + 1];
  char start_date[DATE_STR_LEN + 1];
  char *msg_p;

  start_date[0] = '\0';

  str_buf = t_string_make (1);
  linebuf_tstr = t_string_make (1000);
  if (str_buf == NULL || linebuf_tstr == NULL)
    {
      fprintf (stderr, "malloc error\n");
      goto error;
    }

  if (start_offset != -1)
    {
      fseek (fp, start_offset, SEEK_SET);
    }

  while (1)
    {
      if (end_offset != -1)
    {
      if (ftell (fp) > end_offset)
        {
          break;
        }
    }

      if (ut_get_line (fp, linebuf_tstr, &linebuf, &lineno) <= 0)
    {
      break;
    }

      log_type = is_cas_log (linebuf);
      if (log_type == CAS_LOG_BEGIN_WITH_MONTH)
    {
      fprintf (stderr, "invaild version of log file\n");
      t_string_free (str_buf);
      t_string_free (linebuf_tstr);
      return LT_INVAILD_VERSION;
    }
      else if (log_type != CAS_LOG_BEGIN_WITH_YEAR)
    {
      continue;
    }

      if (strncmp (linebuf + 23, "END OF LOG", 10) == 0)
    {
      break;
    }

      GET_CUR_DATE_STR (cur_date, linebuf);
      if (start_date[0] == '\0')
    {
      strcpy (start_date, cur_date);
    }

      if (is_first)
    {
      if (linebuf[0] != '\n')
        {
          sprintf (fileinfo_str, "%s:%d\n", filename, lineno);
          t_string_add (str_buf, fileinfo_str, (int) strlen (fileinfo_str));
          is_first = 0;
        }
    }

      t_string_add (str_buf, linebuf, (int) strlen (linebuf));

      msg_p = get_msg_start_ptr (linebuf);
      if (strncmp (msg_p, "***", 3) == 0)
    {
      float runtime;

      if (sscanf (msg_p + 3 + 1, "%*s %*s %f", &runtime) == 1)
        {
          T_LOG_INFO tmpinfo;
          char *log_str;
          log_str = strdup (t_string_str (str_buf));
          if (log_str == NULL)
        {
          perror ("strdup");
          goto error;
        }
          tmpinfo.runtime = runtime;
          tmpinfo.logstr = log_str;
          info_add (&tmpinfo, start_date, cur_date);
        }
      t_string_clear (str_buf);
      is_first = 1;
      start_date[0] = '\0';
    }
    }

  t_string_free (str_buf);
  t_string_free (linebuf_tstr);

  return LT_NO_ERROR;

error:
  t_string_free (str_buf);
  t_string_free (linebuf_tstr);
  return LT_OTHER_ERROR;
}

static void
print_result (void)
{
  T_LOG_INFO temp[TRAN_LOG_MAX_COUNT + 1];
  int i;
  FILE *fp_t;

  fp_t = fopen (LOG_TOP_RES_FILE_TRAN, "w");
  if (fp_t == NULL)
    {
      fprintf (stderr, "%s\n", strerror (errno));
      return;
    }

  for (i = 0;; i++)
    {
      if (info_delete (&temp[i]) < 0)
    break;
    }

  for (i--; i >= 0; i--)
    {
#if 0
      fprintf (fp_t, "-----------------------------------------------------\n");
#endif
      fprintf (fp_t, "%s\n", temp[i].logstr);
      FREE_MEM (temp[i].logstr);
    }

  fclose (fp_t);
}

static int
info_add (T_LOG_INFO * info, char *start_date, char *end_date)
{
  int i;
  T_LOG_INFO temp;

  if (check_log_time (start_date, end_date) < 0)
    return 0;

  if (info_arr_size == info_arr_max_size)
    {
      if (info_arr[1].runtime > info->runtime)
    {
      FREE_MEM (info->logstr);
      return 0;
    }
      info_delete (&temp);
      FREE_MEM (temp.logstr);
    }

  i = ++info_arr_size;
  while ((i != 1) && (info->runtime < info_arr[i / 2].runtime))
    {
      info_arr[i] = info_arr[i / 2];
      i /= 2;
    }
  info_arr[i] = *info;
  return 0;
}

static int
info_delete (T_LOG_INFO * info)
{
  T_LOG_INFO temp;
  int parent, child;

  if (info_arr_size <= 0)
    return -1;

  if (info)
    *info = info_arr[1];

  temp = info_arr[info_arr_size--];
  parent = 1;
  child = 2;
  while (child <= info_arr_size)
    {
      if ((child < info_arr_size) && (info_arr[child].runtime > info_arr[child + 1].runtime))
    child++;
      if (temp.runtime < info_arr[child].runtime)
    break;
      info_arr[parent] = info_arr[child];
      parent = child;
      child *= 2;
    }
  info_arr[parent] = temp;
  return 0;
}