Skip to content

File shard_proxy_log.c

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


/*
 * shard_proxy_log.c -
 */

#ident "$Id$"

#include <assert.h>

#include "shard_proxy_log.h"
#include "broker_util.h"
#include "cas_util.h"

#define PROXY_LOG_BUFFER_SIZE   (8192)

static char *make_proxy_log_filename (char *filepath_buf, size_t buf_size, const char *br_name, int proxy_index);
static void proxy_log_backup (void);
static void proxy_log_write_internal (int level, char *svc_code, bool do_flush, const char *fmt, va_list ap);
static void proxy_log_reset (void);

static FILE *log_open (char *log_file_name);

#ifdef CAS_ERROR_LOG
static int error_file_offset;
static char cas_log_error_flag;
#endif
static FILE *log_fp = NULL;
static FILE *access_log_fp = NULL;
static char log_filepath[BROKER_PATH_MAX];

extern int proxy_id;
extern T_SHM_APPL_SERVER *shm_as_p;
extern T_SHM_PROXY *shm_proxy_p;
extern T_PROXY_INFO *proxy_info_p;

static const char *proxy_log_level_str[] = {
  "NUL",
  "ERR",
  "TMO",
  "NTC",
  "SRD",
  "SCH",
  "DBG"
};

static char *
make_proxy_log_filename (char *filepath_buf, size_t buf_size, const char *br_name, int proxy_index)
{
  char dirname[BROKER_PATH_MAX];

  assert (filepath_buf != NULL);

  strcpy (dirname, shm_as_p->proxy_log_dir);

  if (snprintf (filepath_buf, buf_size, "%s/%s_%d.log", dirname, br_name, proxy_index + 1) < 0)
    {
      filepath_buf[0] = '\0';
    }
  return filepath_buf;
}

void
proxy_log_open (char *br_name, int proxy_index)
{
  if (log_fp != NULL)
    {
      proxy_log_close ();
    }

  if (proxy_info_p->cur_proxy_log_mode != PROXY_LOG_MODE_NONE)
    {
      if (br_name != NULL)
    {
      make_proxy_log_filename (log_filepath, BROKER_PATH_MAX, br_name, proxy_id);
    }

      /* note: in "a+" mode, output is always appended */
      log_fp = fopen (log_filepath, "r+");
      if (log_fp != NULL)
    {
      fseek (log_fp, 0, SEEK_END);
    }
      else
    {
      log_fp = fopen (log_filepath, "w");
    }
    }
  else
    {
      log_fp = NULL;
    }

  proxy_info_p->proxy_log_reset = 0;
}

static void
proxy_log_reset (void)
{
  if (proxy_info_p->proxy_log_reset)
    {
      if (log_fp != NULL)
    {
      proxy_log_close ();
    }

      proxy_log_open (shm_as_p->broker_name, proxy_id);
    }
}

void
proxy_log_close (void)
{
  if (log_fp != NULL)
    {
      fclose (log_fp);
      log_fp = NULL;
    }
}

static void
proxy_log_backup (void)
{
  char backup_filepath[BROKER_PATH_MAX];

  assert (log_filepath[0] != '\0');

  if (snprintf (backup_filepath, BROKER_PATH_MAX - 1, "%s.bak", log_filepath) < 0)
    {
      abort ();
    }

  unlink (backup_filepath);
  rename (log_filepath, backup_filepath);
}

void
proxy_log_end (void)
{
  long log_fpos;
  long log_size_max;

  log_size_max = shm_as_p->proxy_log_max_size;

  log_fpos = ftell (log_fp);
  if ((log_fpos / 1000) > log_size_max)
    {
      proxy_log_close ();
      proxy_log_backup ();
      proxy_log_open (shm_as_p->broker_name, proxy_id);
    }

  return;
}

static void
proxy_log_write_internal (int level, char *svc_code, bool do_flush, const char *fmt, va_list ap)
{
  char buf[PROXY_LOG_BUFFER_SIZE], *p;
  int write_len, remain, n;

  p = buf;
  remain = PROXY_LOG_BUFFER_SIZE;

  n = ut_time_string (p, NULL);
  remain -= n;
  p += n;

  if (remain > 0)
    {
      if (svc_code == NULL)
    {
      n = snprintf (p, remain, " [%s] ", proxy_log_level_str[level]);
    }
      else
    {
      n = snprintf (p, remain, " [%s][%s] ", proxy_log_level_str[level], svc_code);
    }

      if (n < 0)
    {
      n = 0;
    }
      else if (n >= remain)
    {
      n = (remain - 1);
    }

      remain -= n;
      p += n;

      if (remain > 0)
    {
      n = vsnprintf (p, remain, fmt, ap);
      if (n < 0)
        {
          n = 0;
        }
      else if (n >= remain)
        {
          n = (remain - 1);
        }

      remain -= n;
      p += n;
    }
    }

  write_len = MIN ((int) (p - buf), PROXY_LOG_BUFFER_SIZE);
  fwrite (buf, write_len, 1, log_fp);
  fputc ('\n', log_fp);

  if (do_flush == true)
    {
      fflush (log_fp);
    }
}

void
proxy_log_write (int level, char *svc_code, const char *fmt, ...)
{
  if (log_fp == NULL)
    {
      proxy_log_open (shm_as_p->broker_name, proxy_id);
    }

  if (level <= PROXY_LOG_MODE_NONE || level > PROXY_LOG_MODE_ALL)
    {
      return;
    }

  if (level > proxy_info_p->cur_proxy_log_mode)
    {
      return;
    }

  proxy_log_reset ();

  if (log_fp != NULL)
    {
      va_list ap;

      va_start (ap, fmt);
      proxy_log_write_internal (level, svc_code, true, fmt, ap);
      va_end (ap);

      proxy_log_end ();
    }
}

int
proxy_log_get_level (void)
{
  return proxy_info_p->cur_proxy_log_mode;
}

int
proxy_access_log (struct timeval *start_time, int client_ip_addr, const char *dbname, const char *dbuser, bool accepted)
{
  char *access_log_file;
  char *script = NULL;
  char *clt_ip;
  char *clt_appl = NULL;
  struct tm ct1, ct2;
  time_t t1, t2;
  char *p;
  char err_str[4];
  struct timeval end_time;

  access_log_file = proxy_info_p->access_log_file;

  gettimeofday (&end_time, NULL);

  t1 = start_time->tv_sec;
  t2 = end_time.tv_sec;
#if defined (WINDOWS)
  if (localtime_s (&ct1, &t1) != 0 || localtime_s (&ct2, &t2) != 0)
#else /* !WINDOWS */
  if (localtime_r (&t1, &ct1) == NULL || localtime_r (&t2, &ct2) == NULL)
#endif /* !WINDOWS */
    {
      return -1;
    }
  ct1.tm_year += 1900;
  ct2.tm_year += 1900;

  if (proxy_info_p->proxy_access_log_reset)
    {
      if (access_log_fp != NULL)
    {
      fclose (access_log_fp);
      access_log_fp = NULL;
    }
      proxy_info_p->proxy_access_log_reset = 0;
    }

  if (access_log_fp == NULL)
    {
      access_log_fp = log_open (access_log_file);
      if (access_log_fp == NULL)
    {
      return -1;
    }
      proxy_info_p->proxy_access_log_reset = 0;
    }

  if (script == NULL)
    script = (char *) "-";
  if (clt_appl == NULL || clt_appl[0] == '\0')
    clt_appl = (char *) "-";

  clt_ip = ut_uchar2ipstr ((unsigned char *) (&client_ip_addr));

  for (p = clt_appl; *p; p++)
    {
      if (char_isspace2 (*p))
    *p = '_';
    }

#ifdef CAS_ERROR_LOG
  if (error_file_offset >= 0)
    sprintf (err_str, "ERR");
  else
#endif
    sprintf (err_str, "-");

  fprintf (access_log_fp,
       "%s %s %s %d.%03d %d.%03d %02d/%02d/%02d %02d:%02d:%02d ~ "
       "%02d/%02d/%02d %02d:%02d:%02d %d %s %d %s %s %s\n", clt_ip, clt_appl, script, (int) start_time->tv_sec,
       (int) (start_time->tv_usec / 1000), (int) end_time.tv_sec, (int) (end_time.tv_usec / 1000), ct1.tm_year,
       ct1.tm_mon + 1, ct1.tm_mday, ct1.tm_hour, ct1.tm_min, ct1.tm_sec, ct2.tm_year, ct2.tm_mon + 1, ct2.tm_mday,
       ct2.tm_hour, ct2.tm_min, ct2.tm_sec, (int) getpid (), err_str, -1, dbname, dbuser,
       ((accepted) ? "" : " : rejected"));
  fflush (access_log_fp);

  return (end_time.tv_sec - start_time->tv_sec);
}

void
proxy_access_log_close (void)
{
  if (access_log_fp != NULL)
    {
      fclose (access_log_fp);
      access_log_fp = NULL;
    }
}

static FILE *
log_open (char *log_file_name)
{
  FILE *fp;
  int ret;
  char *tmp_dirname;
  char *tmp_filename;

  if (log_file_name == NULL)
    return NULL;

  fp = fopen (log_file_name, "a");
  if (fp == NULL)
    {
      if (errno == ENOENT)
    {
      tmp_filename = strdup (log_file_name);
      if (tmp_filename == NULL)
        {
          return NULL;
        }
      tmp_dirname = dirname (tmp_filename);
      ret = mkdir (tmp_dirname, 0777);
      free (tmp_filename);
      if (ret == 0)
        {
          fp = fopen (log_file_name, "a");
          if (fp == NULL)
        {
          return NULL;
        }
        }
      else
        {
          return NULL;
        }
    }
      else
    {
      return NULL;
    }
    }
  return fp;
}