Skip to content

File broker_util.c

File List > broker > broker_util.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_util.c -
 */

#ident "$Id$"

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <assert.h>
#include <ctype.h>

#if defined(WINDOWS)
#include <winsock2.h>
#include <windows.h>
#include <direct.h>
#include <io.h>
#include <process.h>
#include <sys/timeb.h>
#include <mstcpip.h>
#else
#include <unistd.h>
#include <sys/time.h>
#include <sys/timeb.h>
#include <netinet/tcp.h>
#endif

#ifdef V3_TEST
#include <sys/procfs.h>
#endif

#include "porting.h"
#include "cas_common.h"
#include "broker_env_def.h"
#include "broker_util.h"
#include "broker_filename.h"
#include "environment_variable.h"
#include "porting.h"
#include "util_func.h"

char db_err_log_file[BROKER_PATH_MAX];

#if defined (ENABLE_UNUSED_FUNCTION)
int
ut_access_log (int as_index, struct timeval *start_time, char error_flag, int error_log_offset)
{
  FILE *fp;
  char *access_log = getenv (ACCESS_LOG_ENV_STR);
  char *script = getenv (PATH_INFO_ENV_STR);
  char *clt_ip = getenv (REMOTE_ADDR_ENV_STR);
  char *clt_appl = getenv (CLT_APPL_NAME_ENV_STR);
  struct tm ct1, ct2;
  time_t t1, t2;
  char *p;
  char err_str[4];
  struct timeval end_time;

  gettimeofday (&end_time, NULL);

  t1 = start_time->tv_sec;
  t2 = end_time.tv_sec;
  if (localtime_r (&t1, &ct1) == NULL || localtime_r (&t2, &ct2) == NULL)
    {
      return -1;
    }
  ct1.tm_year += 1900;
  ct2.tm_year += 1900;

  if (access_log == NULL)
    return -1;
  fp = fopen (access_log, "a");
  if (fp == NULL)
    return -1;
  if (script == NULL)
    script = (char *) "-";
  if (clt_ip == NULL)
    clt_ip = (char *) "-";
  if (clt_appl == NULL)
    clt_appl = (char *) "-";
  for (p = clt_appl; *p; p++)
    {
      if (char_isspace2 (*p))
    *p = '_';
    }

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

  if (error_flag == 1)
    sprintf (err_str, "ERR");
  else
    sprintf (err_str, "-");

#ifdef V3_TEST
  fprintf (fp,
       "%d %s %s %s %d.%03d %d.%03d %02d/%02d/%02d %02d:%02d:%02d ~ " "%02d/%02d/%02d %02d:%02d:%02d %d %s %d %d\n",
       as_index + 1, 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, error_file_offset, uts_size ());
#else
  fprintf (fp,
       "%d %s %s %s %d.%03d %d.%03d %02d/%02d/%02d %02d:%02d:%02d ~ " "%02d/%02d/%02d %02d:%02d:%02d %d %s %d\n",
       as_index + 1, 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);
#endif

  fclose (fp);
  return (end_time.tv_sec - start_time->tv_sec);
}
#endif /* ENABLE_UNUSED_FUNCTION */

#if defined (ENABLE_UNUSED_FUNCTION)
int
ut_file_lock (char *lock_file)
{
  int fd;

  fd = open (lock_file, O_CREAT | O_EXCL, 0666);
  if (fd < 0)
    {
      if (errno == EEXIST)
    return -1;
#ifdef LOCK_FILE_DEBUG
      {
    FILE *fp;
    fp = fopen ("uts_file_lock.log", "a");
    if (fp != NULL)
      {
        fprintf (fp, "[%d] file lock error. err = [%d], [%s]\n", (int) getpid (), errno, strerror (errno));
        fclose (fp);
      }
      }
#endif
      return 0;
    }
  close (fd);
  return 0;
}

void
ut_file_unlock (char *lock_file)
{
  unlink (lock_file);
}
#endif /* ENABLE_UNUSED_FUNCTION */

#if defined(WINDOWS)
int
ut_kill_process (int pid)
{
  HANDLE phandle;

  if (pid <= 0)
    {
      return 0;
    }

  phandle = OpenProcess (PROCESS_TERMINATE, FALSE, pid);
  if (phandle)
    {
      TerminateProcess (phandle, 0);
      CloseHandle (phandle);
      return 0;
    }
  return -1;
}
#else
int
ut_kill_process (int pid)
{
  int i;

  if (pid > 0)
    {
      for (i = 0; i < 10; i++)
    {
      if (kill (pid, SIGTERM) < 0)
        {
          return 0;
        }
      SLEEP_MILISEC (0, 30);
      if (kill (pid, 0) < 0)
        {
          break;
        }
    }
      if (i >= 10)
    {
      kill (pid, SIGKILL);
    }
    }

  return 0;
}
#endif

int
ut_kill_broker_process (int pid, char *broker_name)
{
  ut_kill_process (pid);

  if (broker_name != NULL)
    {
      char tmp[BROKER_PATH_MAX];

      ut_get_broker_port_name (tmp, broker_name, BROKER_PATH_MAX);

      unlink (tmp);

      return 0;
    }
  return -1;
}

int
ut_kill_proxy_process (int pid, char *broker_name, int proxy_id)
{
  ut_kill_process (pid);

  if (broker_name != NULL && proxy_id >= 0)
    {
      char tmp[BROKER_PATH_MAX];

      ut_get_proxy_port_name (tmp, broker_name, proxy_id, BROKER_PATH_MAX);

      unlink (tmp);

      return 0;
    }
  return -1;
}

int
ut_kill_as_process (int pid, char *broker_name, int as_index, int shard_flag)
{
  ut_kill_process (pid);

  if (broker_name != NULL)
    {
      char tmp[BROKER_PATH_MAX];

      /*
       * shard_cas does not have unix-domain socket and pid lock file.
       * so, we need not delete socket and lock file.
       */
      if (shard_flag == OFF)
    {
      ut_get_as_port_name (tmp, broker_name, as_index, BROKER_PATH_MAX);

      unlink (tmp);
    }

      ut_get_as_pid_name (tmp, broker_name, as_index, BROKER_PATH_MAX);

      unlink (tmp);

      return 0;
    }
  return -1;
}

int
ut_set_keepalive (int sock)
{
  int optval, optlen;

  optlen = sizeof (optval);
  optval = 1;           /* true for SO_KEEPALIVE */
  setsockopt (sock, SOL_SOCKET, SO_KEEPALIVE, (const char *) &optval, optlen);

  return 0;
}

#if defined(WINDOWS)
int
run_child (const char *appl_name)
{
  int new_pid;
  char cwd[1024];
  char cmd[1024];
  STARTUPINFO start_info;
  PROCESS_INFORMATION proc_info;
  BOOL res;

  memset (cwd, 0, sizeof (cwd));
  getcwd (cwd, sizeof (cwd));

  GetStartupInfo (&start_info);

  sprintf (cmd, "%s/%s.exe", cwd, appl_name);

  res = CreateProcess (cmd, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &start_info, &proc_info);

  if (res == FALSE)
    {
      return 0;
    }

  new_pid = proc_info.dwProcessId;

  CloseHandle (proc_info.hProcess);
  CloseHandle (proc_info.hThread);

  return new_pid;
}
#endif

void
ut_cd_work_dir (void)
{
  char path[BROKER_PATH_MAX];

  chdir (envvar_bindir_file (path, BROKER_PATH_MAX, ""));
}

void
ut_cd_root_dir (void)
{
  chdir (envvar_root ());
}

#ifdef V3_TEST
int
uts_size (void)
{
  int procfd;
  struct prpsinfo info;
  const char *procdir = "/proc";
  char pname[128];
  int pid = getpid ();

  sprintf (pname, "%s/%05d", procdir, pid);

retry:
  if ((procfd = open (pname, O_RDONLY)) == -1)
    {
      return -1;
    }

  if (ioctl (procfd, PIOCPSINFO, (char *) &info) == -1)
    {
      int saverr = errno;

      close (procfd);
      if (saverr == EAGAIN)
    goto retry;
      if (saverr != ENOENT)
    ;
      return 1;
    }

  close (procfd);

  return (info.pr_bysize);
}
#endif

void
as_pid_file_create (char *br_name, int as_index)
{
  FILE *fp;
  char as_pid_file_name[BROKER_PATH_MAX];

  ut_get_as_pid_name (as_pid_file_name, br_name, as_index, BROKER_PATH_MAX);

  fp = fopen (as_pid_file_name, "w");
  if (fp)
    {
      fprintf (fp, "%d\n", (int) getpid ());
      fclose (fp);
    }
}

void
as_db_err_log_set (char *br_name, int proxy_index, int shard_id, int shard_cas_id, int as_index, int shard_flag)
{
  char buf[BROKER_PATH_MAX];

  if (shard_flag == ON)
    {
      sprintf (db_err_log_file, "CUBRID_ERROR_LOG=%s%s_%d_%d_%d.err",
           get_cubrid_file (FID_CUBRID_ERR_DIR, buf, BROKER_PATH_MAX), br_name, proxy_index + 1, shard_id,
           shard_cas_id + 1);
    }
  else
    {
      sprintf (db_err_log_file, "CUBRID_ERROR_LOG=%s%s_%d.err",
           get_cubrid_file (FID_CUBRID_ERR_DIR, buf, BROKER_PATH_MAX), br_name, as_index + 1);
    }

  putenv (db_err_log_file);
}

int
ut_time_string (char *buf, struct timeval *time_val)
{
  struct tm tm, *tm_p;
  time_t sec;
  int millisec;

  if (buf == NULL)
    {
      return 0;
    }

  if (time_val == NULL)
    {
      util_get_second_and_ms_since_epoch (&sec, &millisec);
    }
  else
    {
      sec = time_val->tv_sec;
      millisec = time_val->tv_usec / 1000;
    }

  tm_p = localtime_r (&sec, &tm);
  tm.tm_mon++;

  buf[0] = ((tm.tm_year % 100) / 10) + '0';
  buf[1] = (tm.tm_year % 10) + '0';
  buf[2] = '-';
  buf[3] = (tm.tm_mon / 10) + '0';
  buf[4] = (tm.tm_mon % 10) + '0';
  buf[5] = '-';
  buf[6] = (tm.tm_mday / 10) + '0';
  buf[7] = (tm.tm_mday % 10) + '0';
  buf[8] = ' ';
  buf[9] = (tm.tm_hour / 10) + '0';
  buf[10] = (tm.tm_hour % 10) + '0';
  buf[11] = ':';
  buf[12] = (tm.tm_min / 10) + '0';
  buf[13] = (tm.tm_min % 10) + '0';
  buf[14] = ':';
  buf[15] = (tm.tm_sec / 10) + '0';
  buf[16] = (tm.tm_sec % 10) + '0';
  buf[17] = '.';
  buf[20] = (millisec % 10) + '0';
  millisec /= 10;
  buf[19] = (millisec % 10) + '0';
  millisec /= 10;
  buf[18] = (millisec % 10) + '0';
  buf[21] = '\0';

  return 21;
}

char *
ut_get_ipv4_string (char *ip_str, int len, const unsigned char *ip_addr)
{
  assert (ip_addr != NULL);
  assert (ip_str != NULL);
  assert (len >= 16);       /* xxx.xxx.xxx.xxx\0 */

  snprintf (ip_str, len, "%d.%d.%d.%d", (unsigned char) ip_addr[0], (unsigned char) ip_addr[1],
        (unsigned char) ip_addr[2], (unsigned char) ip_addr[3]);
  return (ip_str);
}

float
ut_get_avg_from_array (int array[], int size)
{
  int i, total = 0;
  for (i = 0; i < size; i++)
    {
      total += array[i];
    }

  return (float) total / size;
}

bool
ut_is_appl_server_ready (int pid, char *ready_flag)
{
  unsigned int i;

  for (i = 0; i < SERVICE_READY_WAIT_COUNT; i++)
    {
      if (*ready_flag != 0)
    {
      return true;
    }
      else
    {
#if defined(WINDOWS)
      HANDLE h_process;

      h_process = OpenProcess (PROCESS_QUERY_INFORMATION, FALSE, pid);
      if (h_process != NULL)
        {
          CloseHandle (h_process);
          SLEEP_MILISEC (0, 10);
          continue;
        }
      else
        {
          return false;
        }
#else /* WINDOWS */
      if (kill (pid, 0) == 0)
        {
          SLEEP_MILISEC (0, 10);
          continue;
        }
      else
        {
          return false;
        }
#endif /* WINDOWS */
    }
    }

  return false;
}

void
ut_get_broker_port_name (char *port_name, char *broker_name, int len)
{
  char dir_name[BROKER_PATH_MAX];

  get_cubrid_file (FID_SOCK_DIR, dir_name, BROKER_PATH_MAX);

  if (snprintf (port_name, len, "%s%s.B", dir_name, broker_name) < 0)
    {
      assert (false);
      port_name[0] = '\0';
    }
}

void
ut_get_proxy_port_name (char *port_name, char *broker_name, int proxy_id, int len)
{
  char dir_name[BROKER_PATH_MAX];

  get_cubrid_file (FID_SOCK_DIR, dir_name, BROKER_PATH_MAX);

  if (snprintf (port_name, len, "%s%s.P%d", dir_name, broker_name, proxy_id + 1) < 0)
    {
      assert (false);
      port_name[0] = '\0';
    }
}

void
ut_get_as_port_name (char *port_name, char *broker_name, int as_id, int len)
{
  char dir_name[BROKER_PATH_MAX];

  get_cubrid_file (FID_SOCK_DIR, dir_name, BROKER_PATH_MAX);

  if (snprintf (port_name, len, "%s%s.%d", dir_name, broker_name, as_id + 1) < 0)
    {
      assert (false);
      port_name[0] = '\0';
    }
}

double
ut_size_string_to_kbyte (const char *size_str, const char *default_unit)
{
  double val;
  char *end;
  char *unit;

  if (size_str == NULL || default_unit == NULL)
    {
      assert (false);
    }

  val = strtod (size_str, &end);
  if (end == (char *) size_str)
    {
      return -1.0;
    }

  if (isalpha (*end))
    {
      unit = end;
    }
  else
    {
      unit = (char *) default_unit;
    }

  if (strcasecmp (unit, "b") == 0)
    {
      /* byte */
      val = val / ONE_K;
    }
  else if ((strcasecmp (unit, "k") == 0) || (strcasecmp (unit, "kb") == 0))
    {
      /* kilo */
    }
  else if ((strcasecmp (unit, "m") == 0) || (strcasecmp (unit, "mb") == 0))
    {
      /* mega */
      val = val * ONE_K;
    }
  else if ((strcasecmp (unit, "g") == 0) || (strcasecmp (unit, "gb") == 0))
    {
      /* giga */
      val = val * ONE_M;
    }
  else
    {
      return -1.0;
    }

  if (val > INT_MAX)        /* spec */
    {
      return -1.0;
    }

  return val;
}

double
ut_time_string_to_sec (const char *time_str, const char *default_unit)
{
  double val;
  char *end;
  char *unit;

  if (time_str == NULL || default_unit == NULL)
    {
      assert (false);
    }

  val = strtod (time_str, &end);
  if (end == (char *) time_str)
    {
      return -1.0;
    }

  if (isalpha (*end))
    {
      unit = end;
    }
  else
    {
      unit = (char *) default_unit;
    }

  if ((strcasecmp (unit, "ms") == 0) || (strcasecmp (unit, "msec") == 0))
    {
      /* millisecond */
      val = val / ONE_SEC;
    }
  else if ((strcasecmp (unit, "s") == 0) || (strcasecmp (unit, "sec") == 0))
    {
      /* second */
    }
  else if (strcasecmp (unit, "min") == 0)
    {
      /* minute */
      val = val * ONE_MIN / ONE_SEC;
    }
  else if (strcasecmp (unit, "h") == 0)
    {
      /* hours */
      val = val * ONE_HOUR / ONE_SEC;
    }
  else
    {
      return -1.0;
    }

  if (val > INT_MAX)        /* spec */
    {
      return -1.0;
    }

  return val;
}

void
ut_get_as_pid_name (char *pid_name, char *br_name, int as_index, int len)
{
  char dir_name[BROKER_PATH_MAX];

  get_cubrid_file (FID_AS_PID_DIR, dir_name, BROKER_PATH_MAX);

  if (snprintf (pid_name, len, "%s%s_%d.pid", dir_name, br_name, as_index + 1) < 0)
    {
      assert (false);
      pid_name[0] = '\0';
    }
}