Skip to content

File util_cs.c

File List > cubrid > src > executables > util_cs.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.
 *
 */

/*
 * util_cs.c : Implementations of utilities that operate in both
 *             client/server and standalone modes.
 */

#ident "$Id$"

#include "config.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <signal.h>
#include <errno.h>
#include <assert.h>
#if !defined(WINDOWS)
#include <fcntl.h>
#include <unistd.h>
#endif

#include "utility.h"
#include "error_manager.h"
#include "message_catalog.h"
#include "system_parameter.h"
#include "environment_variable.h"
#include "databases_file.h"
#include "boot_cl.h"
#include "boot_sr.h"
#include "db.h"
#include "authenticate.h"
#include "server_interface.h"
#include "object_representation.h"
#include "transaction_cl.h"
#include "porting.h"
#include "network_interface_cl.h"
#include "connection_defs.h"
#include "log_writer.h"
#include "log_applier.h"
#include "log_lsa.hpp"
#include "schema_manager.h"
#include "locator_cl.h"
#include "dynamic_array.h"
#include "util_func.h"
#include "xasl.h"
#include "log_volids.hpp"
#include "tde.h"
#include "flashback_cl.h"
#include "connection_support.hpp"
#include "memory_monitor_cl.hpp"
#if !defined(WINDOWS)
#include "heartbeat.h"
#endif
#include "network_histogram.hpp"

#define PASSBUF_SIZE 12
#define SPACEDB_NUM_VOL_PURPOSE 2
#define MAX_KILLTRAN_INDEX_LIST_NUM  64
#define MAX_DELVOL_ID_LIST_NUM       64

#define VOL_PURPOSE_STRING(VOL_PURPOSE)     \
        ((VOL_PURPOSE == DB_PERMANENT_DATA_PURPOSE) ? "PERMANENT DATA"  \
        : (VOL_PURPOSE == DB_TEMPORARY_DATA_PURPOSE) ? "TEMPORARY DATA"     \
        : "UNKNOWN")

#if defined(WINDOWS)
#define STDIN_FILENO  _fileno (stdin)
#endif

typedef enum
{
  SPACEDB_SIZE_UNIT_PAGE = 0,
  SPACEDB_SIZE_UNIT_MBYTES,
  SPACEDB_SIZE_UNIT_GBYTES,
  SPACEDB_SIZE_UNIT_TBYTES,
  SPACEDB_SIZE_UNIT_HUMAN_READABLE
} T_SPACEDB_SIZE_UNIT;

typedef enum
{
  TRANDUMP_SUMMARY,
  TRANDUMP_QUERY_INFO,
  TRANDUMP_FULL_INFO
} TRANDUMP_LEVEL;

typedef enum
{
  SORT_COLUMN_TYPE_INT,
  SORT_COLUMN_TYPE_FLOAT,
  SORT_COLUMN_TYPE_STR,
} SORT_COLUMN_TYPE;

#if defined(CS_MODE) && !defined(WINDOWS)
static volatile sig_atomic_t sigusr1_running = 0;
static volatile sig_atomic_t sigusr1_pipe_write_fd = -1;
static bool sigusr1_started = false;
static bool sigusr1_old_action_saved = false;
static pthread_t sigusr1_tid;
static struct sigaction sigusr1_old_action;
static int sigusr1_pipe_fds[2] = { -1, -1 };

static int sigusr1_saved_stdout_fd = -1;
static FILE *sigusr1_dump_outfp = NULL;
#endif /* CS_MODE && !WINDOWS */

static int tranlist_Sort_column = 0;
static bool tranlist_Sort_desc = false;

static bool is_Sigint_caught = false;
#if defined(WINDOWS)
static BOOL WINAPI intr_handler (int sig_no);
#else
static void intr_handler (int sig_no);
#endif

static void crash_handler (int sig_no);
static void backupdb_sig_interrupt_handler (int sig_no);
STATIC_INLINE char *spacedb_get_size_str (char *buf, UINT64 num_pages, T_SPACEDB_SIZE_UNIT size_unit);
static void print_timestamp (FILE * outfp);
static int print_tran_entry (const ONE_TRAN_INFO * tran_info, TRANDUMP_LEVEL dump_level, bool full_sqltext);
static int tranlist_cmp_f (const void *p1, const void *p2);
static OID *util_get_class_oids_and_index_btid (dynamic_array * darray, const char *index_name, BTID * index_btid);

/*
 * backupdb() - backupdb main routine
 *   return: EXIT_SUCCESS/EXIT_FAILURE
 */
int
backupdb (UTIL_FUNCTION_ARG * arg)
{
  UTIL_ARG_MAP *arg_map = arg->arg_map;
  char er_msg_file[PATH_MAX];
  const char *database_name;
  const char *backup_path = NULL;
  bool remove_log_archives = false;
  int backup_level = FILEIO_BACKUP_FULL_LEVEL;
  const char *backup_verbose_file = NULL;
  bool no_check = false;
  bool check = true;
  int backup_num_threads;
  bool no_compress_flag;
  bool sa_mode;
  bool separate_keys;
  FILEIO_ZIP_METHOD backup_zip_method = FILEIO_ZIP_LZ4_METHOD;
  FILEIO_ZIP_LEVEL backup_zip_level = FILEIO_ZIP_LZ4_DEFAULT_LEVEL;
  bool skip_activelog = false;
  int sleep_msecs;
  struct stat st_buf;
  char real_pathbuf[PATH_MAX];
  char verbose_file_realpath[PATH_MAX];

  if (utility_get_option_string_table_size (arg_map) != 1)
    {
      goto print_backup_usage;
    }

  database_name = utility_get_option_string_value (arg_map, OPTION_STRING_TABLE, 0);
  if (database_name == NULL)
    {
      goto print_backup_usage;
    }

  backup_path = utility_get_option_string_value (arg_map, BACKUP_DESTINATION_PATH_S, 0);
  remove_log_archives = utility_get_option_bool_value (arg_map, BACKUP_REMOVE_ARCHIVE_S);
  backup_level = utility_get_option_int_value (arg_map, BACKUP_LEVEL_S);
  backup_verbose_file = utility_get_option_string_value (arg_map, BACKUP_OUTPUT_FILE_S, 0);
  no_check = utility_get_option_bool_value (arg_map, BACKUP_NO_CHECK_S);
  check = !no_check;
  backup_num_threads = utility_get_option_int_value (arg_map, BACKUP_THREAD_COUNT_S);
  no_compress_flag = utility_get_option_bool_value (arg_map, BACKUP_NO_COMPRESS_S);

  // BACKUP_EXCEPT_ACTIVE_LOG_S is obsoleted. This means backup will always include active log.
  skip_activelog = false;

  sleep_msecs = utility_get_option_int_value (arg_map, BACKUP_SLEEP_MSECS_S);
  sa_mode = utility_get_option_bool_value (arg_map, BACKUP_SA_MODE_S);
  separate_keys = utility_get_option_bool_value (arg_map, BACKUP_SEPARATE_KEYS_S);

  /* Range checking of input */
  if (backup_level < 0 || backup_level >= FILEIO_BACKUP_UNDEFINED_LEVEL)
    {
      goto print_backup_usage;
    }

  if (sa_mode && backup_num_threads > 1)
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_BACKUPDB,
                         BACKUPDB_INVALID_THREAD_NUM_OPT));
    }

  if (backup_num_threads < FILEIO_BACKUP_NUM_THREADS_AUTO)
    {
      goto print_backup_usage;
    }

  if (sleep_msecs < FILEIO_BACKUP_SLEEP_MSECS_AUTO)
    {
      goto print_backup_usage;
    }

  if (no_compress_flag)
    {
      backup_zip_method = FILEIO_ZIP_NONE_METHOD;
      backup_zip_level = FILEIO_ZIP_NONE_LEVEL;
    }

  /* extra validation */
  if (check_database_name (database_name))
    {
      goto error_exit;
    }

  if (backup_path != NULL)
    {
      memset (real_pathbuf, 0, sizeof (real_pathbuf));
      if (realpath (backup_path, real_pathbuf) != NULL)
    {
      backup_path = real_pathbuf;
    }

      // accept directory and FIFO (named pipe) file as backup destination.
      if (stat (backup_path, &st_buf) != 0)
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_BACKUPDB,
                         BACKUPDB_INVALID_PATH));
      goto error_exit;
    }
      else if (!S_ISDIR (st_buf.st_mode))
    {
#if !defined (WINDOWS)
      // Unfortunately, Windows does not support FIFO file.
      if (!S_ISFIFO (st_buf.st_mode))
#endif /* !WINDOWS */
        {
          PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_BACKUPDB,
                             BACKUPDB_INVALID_PATH));
          goto error_exit;
        }
#if !defined (WINDOWS)
      else if (separate_keys)   /* FIFO file and --separate_keys is exclusive */
        {
          PRINT_AND_LOG_ERR_MSG (msgcat_message
                     (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_BACKUPDB,
                      BACKUPDB_FIFO_KEYS_NOT_SUPPORTED));
          goto error_exit;
        }
#endif /* !WINDOWS */
    }
    }

  if (separate_keys)
    {
      util_log_write_warnstr (msgcat_message
                  (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_BACKUPDB, BACKUPDB_USING_SEPARATE_KEYS));
    }
  else
    {
      util_log_write_warnstr (msgcat_message
                  (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_BACKUPDB, BACKUPDB_NOT_USING_SEPARATE_KEYS));
    }

  /* error message log file */
  snprintf (er_msg_file, sizeof (er_msg_file) - 1, "%s_%s.err", database_name, arg->command_name);
  er_init (er_msg_file, ER_NEVER_EXIT);

  AU_DISABLE_PASSWORDS ();  /* disable authorization for this operation */
  db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY);
  db_login ("DBA", NULL);

  if (db_restart (arg->command_name, TRUE, database_name) != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      goto error_exit;
    }

  if (check)
    {
      int check_flag = 0;

      check_flag |= CHECKDB_FILE_TRACKER_CHECK;
      check_flag |= CHECKDB_HEAP_CHECK_ALLHEAPS;
      check_flag |= CHECKDB_CT_CHECK_CAT_CONSISTENCY;
      check_flag |= CHECKDB_BTREE_CHECK_ALL_BTREES;
      check_flag |= CHECKDB_LC_CHECK_CLASSNAMES;

      if (db_set_isolation (TRAN_READ_COMMITTED) != NO_ERROR
      || boot_check_db_consistency (check_flag, 0, 0, NULL) != NO_ERROR)
    {
      const char *tmpname;

      tmpname = er_get_msglog_filename ();
      if (tmpname == NULL)
        {
          tmpname = "/dev/null";
        }
      PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_CHECKDB,
                         CHECKDB_MSG_INCONSISTENT), tmpname);
      db_shutdown ();
      goto error_exit;
    }
    }

  /* some other utilities may need interrupt handler too */
  if (os_set_signal_handler (SIGINT, backupdb_sig_interrupt_handler) == SIG_ERR)
    {
      er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_GENERIC_ERROR, 0);
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      db_shutdown ();
      goto error_exit;
    }

  if (backup_verbose_file && *backup_verbose_file && *backup_verbose_file != '/')
    {
      char dirname[PATH_MAX];

      /* resolve relative path */
      if (getcwd (dirname, PATH_MAX) != NULL)
    {
      if (snprintf (verbose_file_realpath, PATH_MAX - 1, "%s/%s", dirname, backup_verbose_file) < 0)
        {
          assert (false);
          db_shutdown ();
          goto error_exit;
        }
      backup_verbose_file = verbose_file_realpath;
    }
    }

  if (boot_backup (backup_path, (FILEIO_BACKUP_LEVEL) backup_level, remove_log_archives, backup_verbose_file,
           backup_num_threads, backup_zip_method, backup_zip_level, skip_activelog, sleep_msecs,
           separate_keys) != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      db_shutdown ();
      goto error_exit;
    }

  if (db_commit_transaction () != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
    }

  db_shutdown ();

  return EXIT_SUCCESS;

print_backup_usage:
  fprintf (stderr, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_BACKUPDB, BACKUPDB_MSG_USAGE),
       basename (arg->argv0));
  util_log_write_errid (MSGCAT_UTIL_GENERIC_INVALID_ARGUMENT);

error_exit:
  return EXIT_FAILURE;
}

/*
 * addvoldb() - addvoldb main routine
 *   return: EXIT_SUCCESS/EXIT_FAILURE
 */
int
addvoldb (UTIL_FUNCTION_ARG * arg)
{
  UTIL_ARG_MAP *arg_map = arg->arg_map;
  char er_msg_file[PATH_MAX];
  const char *database_name;
  UINT64 volext_size;
  UINT64 volext_max_writesize;
  const char *volext_string_purpose = NULL;
  const char *volext_string_voltype = NULL;
  const char *volext_npages_string = NULL;
  const char *volext_size_str = NULL;
  const char *volext_max_writesize_in_sec_str = NULL;
  char real_volext_path_buf[PATH_MAX];
  bool sa_mode;
  DBDEF_VOL_EXT_INFO ext_info;

  ext_info.overwrite = false;
  ext_info.max_npages = 0;
  if (utility_get_option_string_table_size (arg_map) < 1)
    {
      goto print_addvol_usage;
    }

  database_name = utility_get_option_string_value (arg_map, OPTION_STRING_TABLE, 0);
  if (database_name == NULL)
    {
      goto print_addvol_usage;
    }

  volext_npages_string = utility_get_option_string_value (arg_map, OPTION_STRING_TABLE, 1);
  if (volext_npages_string)
    {
      util_print_deprecated ("number-of-pages");
      ext_info.max_npages = atoi (volext_npages_string);
    }

  volext_size = 0;
  volext_size_str = utility_get_option_string_value (arg_map, ADDVOL_VOLUME_SIZE_S, 0);
  if (volext_size_str)
    {
      if (util_size_string_to_byte (&volext_size, volext_size_str) != NO_ERROR)
    {
      goto print_addvol_usage;
    }
    }

  volext_max_writesize_in_sec_str = utility_get_option_string_value (arg_map, ADDVOL_MAX_WRITESIZE_IN_SEC_S, 0);
  if (volext_max_writesize_in_sec_str)
    {
      if (util_size_string_to_byte (&volext_max_writesize, volext_max_writesize_in_sec_str) != NO_ERROR)
    {
      goto print_addvol_usage;
    }
      ext_info.max_writesize_in_sec = (int) volext_max_writesize / ONE_K;
    }
  else
    {
      ext_info.max_writesize_in_sec = 0;
    }

  ext_info.name = utility_get_option_string_value (arg_map, ADDVOL_VOLUME_NAME_S, 0);
  ext_info.path = utility_get_option_string_value (arg_map, ADDVOL_FILE_PATH_S, 0);
  if (ext_info.path != NULL)
    {
      memset (real_volext_path_buf, 0, sizeof (real_volext_path_buf));
      if (realpath (ext_info.path, real_volext_path_buf) != NULL)
    {
      ext_info.path = real_volext_path_buf;
    }
    }
  ext_info.comments = utility_get_option_string_value (arg_map, ADDVOL_COMMENT_S, 0);
  volext_string_purpose = utility_get_option_string_value (arg_map, ADDVOL_PURPOSE_S, 0);
  if (volext_string_purpose == NULL)
    {
      ext_info.purpose = DB_PERMANENT_DATA_PURPOSE;
    }
  else if (strcasecmp (volext_string_purpose, "data") == 0)
    {
      ext_info.purpose = DB_PERMANENT_DATA_PURPOSE;
    }
  else if (strcasecmp (volext_string_purpose, "index") == 0)
    {
      ext_info.purpose = DB_PERMANENT_DATA_PURPOSE;
    }
  else if (strcasecmp (volext_string_purpose, "temp") == 0)
    {
      ext_info.purpose = DB_TEMPORARY_DATA_PURPOSE;
    }
  else if (strcasecmp (volext_string_purpose, "generic") == 0)
    {
      ext_info.purpose = DB_PERMANENT_DATA_PURPOSE;
    }
  else
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_ADDVOLDB, ADDVOLDB_MSG_BAD_PURPOSE),
                 volext_string_purpose);

      goto error_exit;
    }

  sa_mode = utility_get_option_bool_value (arg_map, ADDVOL_SA_MODE_S);
  if (sa_mode && ext_info.max_writesize_in_sec > 0)
    {
      ext_info.max_writesize_in_sec = 0;
      fprintf (stderr,
           msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_ADDVOLDB, ADDVOLDB_INVALID_MAX_WRITESIZE_IN_SEC));
    }

  volext_string_voltype = utility_get_option_string_value (arg_map, ADDVOL_VOLTYPE_S, 0);
  if (volext_string_voltype == NULL || strcasecmp (volext_string_voltype, "perm") == 0)
    {
      ext_info.voltype = DB_PERMANENT_VOLTYPE;
    }
  else if (strcasecmp (volext_string_voltype, "temp") == 0)
    {
      if (sa_mode)
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message
                 (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_ADDVOLDB, ADDVOLDB_VOLTYPE_NOT_SUPPORT_SAMODE));
      goto error_exit;
    }

      if (volext_string_purpose != NULL && ext_info.purpose != DB_TEMPORARY_DATA_PURPOSE)
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message
                 (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_ADDVOLDB,
                  ADDVOLDB_VOLTYPE_MUSTBE_TEMP_PURPOSE));
      goto error_exit;
    }
      else
    {
      ext_info.purpose = DB_TEMPORARY_DATA_PURPOSE;
    }

      if (ext_info.name != NULL || ext_info.path != NULL)
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message
                 (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_ADDVOLDB, ADDVOLDB_VOLTYPE_NOT_USED_PATH_NAME));
      goto error_exit;
    }

      ext_info.voltype = DB_TEMPORARY_VOLTYPE;
    }
  else
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_ADDVOLDB, ADDVOLDB_MSG_BAD_VOLTYPE),
                 volext_string_voltype);
      goto error_exit;
    }

  /* extra validation */
  if (check_database_name (database_name) || check_volume_name (ext_info.name))
    {
      goto error_exit;
    }

  /* error message log file */
  snprintf (er_msg_file, sizeof (er_msg_file) - 1, "%s_%s.err", database_name, arg->command_name);
  er_init (er_msg_file, ER_NEVER_EXIT);

  /* tuning system parameters */
  sysprm_set_force (PRM_ID_PB_NBUFFERS, "1024");

  AU_DISABLE_PASSWORDS ();
  db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY);
  db_login ("DBA", NULL);
  if (db_restart (arg->command_name, TRUE, database_name) == NO_ERROR)
    {
      if (volext_size == 0)
    {
      volext_size = prm_get_bigint_value (PRM_ID_DB_VOLUME_SIZE);
    }

      if (ext_info.max_npages == 0)
    {
      ext_info.max_npages = (int) (volext_size / IO_PAGESIZE);
    }

      if (ext_info.max_npages <= 0)
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_ADDVOLDB,
                         ADDVOLDB_MSG_BAD_NPAGES), ext_info.max_npages);
      db_shutdown ();
      goto error_exit;
    }

      if (db_add_volume_ex (&ext_info) == NO_ERROR)
    {
      db_commit_transaction ();
    }
      else
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      db_shutdown ();
      goto error_exit;
    }
      db_shutdown ();
    }
  else
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      goto error_exit;
    }

  return EXIT_SUCCESS;

print_addvol_usage:
  fprintf (stderr, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_ADDVOLDB, ADDVOLDB_MSG_USAGE),
       basename (arg->argv0));
  util_log_write_errid (MSGCAT_UTIL_GENERIC_INVALID_ARGUMENT);
error_exit:
  return EXIT_FAILURE;
}

/*
 * util_get_class_oids_and_index_btid() -
 *   return: OID array/NULL
 *   index_name(in)
 *   index_btid(out)
 */
static OID *
util_get_class_oids_and_index_btid (dynamic_array * darray, const char *index_name, BTID * index_btid)
{
  MOP cls_mop;
  OID *oids;
  OID *cls_oid;
  SM_CLASS *cls_sm;
  SM_CLASS_CONSTRAINT *constraint;
  char table[SM_MAX_IDENTIFIER_LENGTH];
  char name[SM_MAX_IDENTIFIER_LENGTH];
  int i;
  int num_tables = da_size (darray);
  MOBJ *obj;

  oids = (OID *) malloc (sizeof (OID) * num_tables);
  if (oids == NULL)
    {
      perror ("malloc");
      util_log_write_errid (MSGCAT_UTIL_GENERIC_NO_MEM);
      return NULL;
    }

  for (i = 0; i < num_tables; i++)
    {
      const char *class_name_p = NULL;
      const char *class_name_only = NULL;
      char owner_name[DB_MAX_USER_LENGTH] = { '\0' };

      if (da_get (darray, i, table) != NO_ERROR)
    {
      free (oids);
      return NULL;
    }

      OID_SET_NULL (&oids[i]);
      if (table == NULL || table[0] == '\0')
    {
      continue;
    }

      sm_qualifier_name (table, owner_name, DB_MAX_USER_LENGTH);
      class_name_only = sm_remove_qualifier_name (table);
      if (strcasecmp (owner_name, "dba") == 0 && sm_check_system_class_by_name (class_name_only))
    {
      class_name_p = class_name_only;
    }
      else
    {
      class_name_p = table;
    }

      sm_user_specified_name (class_name_p, name, SM_MAX_IDENTIFIER_LENGTH);
      cls_mop = locator_find_class (name);

      obj = (MOBJ *) & cls_sm;
      ws_find (cls_mop, obj);
      if (cls_sm == NULL || cls_sm->class_type != SM_CLASS_CT)
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_CHECKDB,
                         CHECKDB_MSG_NO_SUCH_CLASS), table);
      continue;
    }

      cls_oid = ws_oid (cls_mop);
      if (cls_oid)
    {
      oids[i] = *cls_oid;
    }
      else
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_CHECKDB,
                         CHECKDB_MSG_NO_SUCH_CLASS), table);
      continue;
    }

      if (index_name != NULL)
    {
      constraint = classobj_find_class_index (cls_sm, index_name);
      if (constraint == NULL)
        {
          PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_CHECKDB,
                             CHECKDB_MSG_NO_SUCH_INDEX), index_name, name);
          free_and_init (oids);
          return NULL;
        }

      db_constraint_index (constraint, index_btid);

      assert (i == 0);
    }
    }

  return oids;
}

/*
 * checkdb() - checkdb main routine
 *   return: EXIT_SUCCESS/EXIT_FAILURE
 */
int
checkdb (UTIL_FUNCTION_ARG * arg)
{
  UTIL_ARG_MAP *arg_map = arg->arg_map;
  char er_msg_file[PATH_MAX];
  const char *database_name;
  char *fname;
  char *index_name = NULL;
  bool repair = false;
  bool repair_plink = false;
  int flag = 0;
  int i, num_tables;
  OID *oids = NULL;
  BTID index_btid;
  dynamic_array *darray = NULL;

  if (utility_get_option_string_table_size (arg_map) < 1)
    {
      goto print_check_usage;
    }

  database_name = utility_get_option_string_value (arg_map, OPTION_STRING_TABLE, 0);
  if (database_name == NULL)
    {
      goto print_check_usage;
    }

  /* extra validation */
  if (check_database_name (database_name))
    {
      goto error_exit;
    }

  if (utility_get_option_bool_value (arg_map, CHECK_FILE_TRACKER_S))
    {
      flag |= CHECKDB_FILE_TRACKER_CHECK;
    }

  if (utility_get_option_bool_value (arg_map, CHECK_HEAP_ALLHEAPS_S))
    {
      flag |= CHECKDB_HEAP_CHECK_ALLHEAPS;
    }

  if (utility_get_option_bool_value (arg_map, CHECK_CAT_CONSISTENCY_S))
    {
      flag |= CHECKDB_CT_CHECK_CAT_CONSISTENCY;
    }

  if (utility_get_option_bool_value (arg_map, CHECK_BTREE_ALL_BTREES_S))
    {
      flag |= CHECKDB_BTREE_CHECK_ALL_BTREES;
    }

  if (utility_get_option_bool_value (arg_map, CHECK_LC_CLASSNAMES_S))
    {
      flag |= CHECKDB_LC_CHECK_CLASSNAMES;
    }

  if (utility_get_option_bool_value (arg_map, CHECK_LC_ALLENTRIES_OF_ALLBTREES_S))
    {
      flag |= CHECKDB_LC_CHECK_ALLENTRIES_OF_ALLBTREES;
    }

  repair_plink = utility_get_option_bool_value (arg_map, CHECK_REPAIR_PREV_LINK_S);
  if (repair_plink)
    {
      flag |= CHECKDB_REPAIR_PREV_LINK;
    }
  else if (utility_get_option_bool_value (arg_map, CHECK_CHECK_PREV_LINK_S))
    {
      flag |= CHECKDB_CHECK_PREV_LINK;
    }

  if (flag == 0)
    {
      flag = CHECKDB_ALL_CHECK_EXCEPT_PREV_LINK;
    }

  repair = utility_get_option_bool_value (arg_map, CHECK_REPAIR_S);
  if (repair)
    {
      flag |= CHECKDB_REPAIR;
    }

  fname = utility_get_option_string_value (arg_map, CHECK_INPUT_FILE_S, 0);
  index_name = utility_get_option_string_value (arg_map, CHECK_INDEXNAME_S, 0);
  num_tables = utility_get_option_string_table_size (arg_map);
  num_tables -= 1;

  if (index_name != NULL && num_tables != 1)
    {
      PRINT_AND_LOG_ERR_MSG ("Only one table is supported to check specific index.\n");
      goto error_exit;
    }

  darray = da_create (num_tables, SM_MAX_IDENTIFIER_LENGTH);
  if (darray == NULL)
    {
      perror ("calloc");
      util_log_write_errid (MSGCAT_UTIL_GENERIC_NO_MEM);
      goto error_exit;
    }

  if (num_tables > 0)
    {
      char class_name_buf[SM_MAX_IDENTIFIER_LENGTH];
      char *class_name;

      for (i = 0; i < num_tables; i++)
    {
      class_name = utility_get_option_string_value (arg_map, OPTION_STRING_TABLE, i + 1);
      if (class_name == NULL)
        {
          continue;
        }

      if (utility_check_class_name (class_name) != NO_ERROR)
        {
          goto error_exit;
        }

      strncpy_bufsize (class_name_buf, class_name);

      if (da_add (darray, class_name_buf) != NO_ERROR)
        {
          util_log_write_errid (MSGCAT_UTIL_GENERIC_NO_MEM);
          perror ("calloc");
          goto error_exit;
        }
    }
    }

  if (fname != NULL)
    {
      if (util_get_table_list_from_file (fname, darray) != NO_ERROR)
    {
      goto error_exit;
    }
    }

  num_tables = da_size (darray);

  /* error message log file */
  snprintf (er_msg_file, sizeof (er_msg_file) - 1, "%s_%s.err", database_name, arg->command_name);
  er_init (er_msg_file, ER_NEVER_EXIT);

  AU_DISABLE_PASSWORDS ();
  db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY);
  db_login ("DBA", NULL);
  if (db_restart (arg->command_name, TRUE, database_name) == NO_ERROR)
    {
      if (num_tables > 0)
    {
      BTID_SET_NULL (&index_btid);
      oids = util_get_class_oids_and_index_btid (darray, index_name, &index_btid);
      if (oids == NULL)
        {
          db_shutdown ();
          goto error_exit;
        }
    }

      if (db_set_isolation (TRAN_READ_COMMITTED) != NO_ERROR
      || boot_check_db_consistency (flag, oids, num_tables, &index_btid) != NO_ERROR)
    {
      const char *tmpname;

      if ((tmpname = er_get_msglog_filename ()) == NULL)
        {
          tmpname = "/dev/null";
        }
      PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_CHECKDB,
                         CHECKDB_MSG_INCONSISTENT), tmpname);

      if (repair_plink || repair)
        {
          db_commit_transaction ();
        }
      util_log_write_errstr ("%s\n", db_error_string (3));
      db_shutdown ();
      goto error_exit;
    }
      if (repair_plink || repair)
    {
      db_commit_transaction ();
    }
      db_shutdown ();
    }
  else
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      goto error_exit;
    }

  if (darray != NULL)
    {
      da_destroy (darray);
    }
  if (oids != NULL)
    {
      free (oids);
    }

  return EXIT_SUCCESS;

print_check_usage:
  fprintf (stderr, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_CHECKDB, CHECKDB_MSG_USAGE),
       basename (arg->argv0));
  util_log_write_errid (MSGCAT_UTIL_GENERIC_INVALID_ARGUMENT);

error_exit:
  if (darray != NULL)
    {
      da_destroy (darray);
    }
  if (oids != NULL)
    {
      free (oids);
    }

  return EXIT_FAILURE;
}


/*
 * spacedb() - spacedb main routine
 *   return: EXIT_SUCCESS/EXIT_FAILURE
 */
int
spacedb (UTIL_FUNCTION_ARG * arg)
{
#define SPACEDB_TO_SIZE_ARG(no, npage) spacedb_get_size_str (size_str_##no, npage, size_unit_type)

  UTIL_ARG_MAP *arg_map = arg->arg_map;
  char er_msg_file[PATH_MAX];
  const char *database_name;
  const char *output_file = NULL;
  int i;
  const char *size_unit;
  T_SPACEDB_SIZE_UNIT size_unit_type;

  bool summarize, purpose;
  FILE *outfp = NULL;
  char io_size_str[64], log_size_str[64];

  SPACEDB_ALL all[SPACEDB_ALL_COUNT];
  SPACEDB_ONEVOL *vols = NULL;
  SPACEDB_ONEVOL **volsp = NULL;
  SPACEDB_FILES files[SPACEDB_FILE_COUNT];
  SPACEDB_FILES *filesp = NULL;

  char size_str_1[64];
  char size_str_2[64];
  char size_str_3[64];
  char size_str_4[64];

  const char *file_type_strings[] = {
    "INDEX", "HEAP", "SYSTEM", "TEMP", "-"
  };

  /* todo: there is a lot of work to do here */

  if (utility_get_option_string_table_size (arg_map) != 1)
    {
      goto print_space_usage;
    }

  database_name = utility_get_option_string_value (arg_map, OPTION_STRING_TABLE, 0);
  if (database_name == NULL)
    {
      goto print_space_usage;
    }

  output_file = utility_get_option_string_value (arg_map, SPACE_OUTPUT_FILE_S, 0);
  size_unit = utility_get_option_string_value (arg_map, SPACE_SIZE_UNIT_S, 0);
  summarize = utility_get_option_bool_value (arg_map, SPACE_SUMMARIZE_S);
  purpose = utility_get_option_bool_value (arg_map, SPACE_PURPOSE_S);

  size_unit_type = SPACEDB_SIZE_UNIT_HUMAN_READABLE;

  if (size_unit != NULL)
    {
      if (strcasecmp (size_unit, "page") == 0)
    {
      size_unit_type = SPACEDB_SIZE_UNIT_PAGE;
    }
      else if (strcasecmp (size_unit, "m") == 0)
    {
      size_unit_type = SPACEDB_SIZE_UNIT_MBYTES;
    }
      else if (strcasecmp (size_unit, "g") == 0)
    {
      size_unit_type = SPACEDB_SIZE_UNIT_GBYTES;
    }
      else if (strcasecmp (size_unit, "t") == 0)
    {
      size_unit_type = SPACEDB_SIZE_UNIT_TBYTES;
    }
      else if (strcasecmp (size_unit, "h") != 0)
    {
      /* invalid option string */
      goto print_space_usage;
    }
    }

  if (output_file == NULL)
    {
      outfp = stdout;
    }
  else
    {
      outfp = fopen (output_file, "w");
      if (outfp == NULL)
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_SPACEDB, SPACEDB_MSG_BAD_OUTPUT),
                 output_file);
      goto error_exit;
    }
    }

  if (check_database_name (database_name))
    {
      goto error_exit;
    }

  /* error message log file */
  snprintf (er_msg_file, sizeof (er_msg_file) - 1, "%s_%s.err", database_name, arg->command_name);
  er_init (er_msg_file, ER_NEVER_EXIT);

  /* tuning system parameters */
  sysprm_set_force (PRM_ID_PB_NBUFFERS, "1024");

  /* should have little copyright herald message ? */
  AU_DISABLE_PASSWORDS ();
  db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY);
  db_login ("DBA", NULL);

  if (db_restart (arg->command_name, TRUE, database_name) != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (ER_WARNING_SEVERITY));
      goto error_exit;
    }

  util_byte_to_size_string (io_size_str, 64, IO_PAGESIZE);
  util_byte_to_size_string (log_size_str, 64, LOG_PAGESIZE);

  if (!summarize)
    {
      /* we need space info per each volume. set volsp to non-NULL value */
      volsp = &vols;
    }
  if (purpose)
    {
      /* we need detailed space info for file usage. set filesp to non-NULL value */
      filesp = files;
    }

  if (netcl_spacedb (all, volsp, filesp) != NO_ERROR)
    {
      ASSERT_ERROR ();
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (ER_WARNING_SEVERITY));
      db_shutdown ();
      goto error_exit;
    }

  /* print title */
  fprintf (outfp, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_SPACEDB, SPACEDB_OUTPUT_TITLE), database_name,
       io_size_str, log_size_str);
  fprintf (outfp, "\n");

  /* print aggregated info */
  /* print header */
  if (size_unit_type == SPACEDB_SIZE_UNIT_PAGE)
    {
      fprintf (outfp, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_SPACEDB, SPACEDB_MSG_ALL_HEADER_PAGES));
    }
  else
    {
      fprintf (outfp, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_SPACEDB, SPACEDB_MSG_ALL_HEADER_SIZE));
    }
  /* print values. the format is:
   * type, purpose, used pages/size, free pages/size, total pages/size */
  /* print perm perm values */
  for (i = 0; i < SPACEDB_ALL_COUNT; i++)
    {
      fprintf (outfp, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_SPACEDB, SPACEDB_MSG_PERM_PERM_FORMAT + i),
           all[i].nvols, SPACEDB_TO_SIZE_ARG (1, all[i].npage_used),
           SPACEDB_TO_SIZE_ARG (2, all[i].npage_free),
           SPACEDB_TO_SIZE_ARG (3, all[i].npage_used + all[i].npage_free));
    }
  fprintf (outfp, "\n");

  if (volsp != NULL)
    {
      /* print information on all volumes */
      MSGCAT_SPACEDB_MSG msg_vols_format;

      /* print title */
      fprintf (outfp, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_SPACEDB, SPACEDB_MSG_VOLS_TITLE));
      /* print header */
      if (size_unit_type == SPACEDB_SIZE_UNIT_PAGE)
    {
      fprintf (outfp,
           msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_SPACEDB, SPACEDB_MSG_VOLS_HEADER_PAGES));
    }
      else
    {
      fprintf (outfp, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_SPACEDB, SPACEDB_MSG_VOLS_HEADER_SIZE));
    }

      /* print each volume */
      for (i = 0; i < all[SPACEDB_TOTAL_ALL].nvols; i++)
    {
      if (vols[i].type == DB_PERMANENT_VOLTYPE)
        {
          if (vols[i].purpose == DB_PERMANENT_DATA_PURPOSE)
        {
          msg_vols_format = SPACEDB_MSG_VOLS_PERM_PERM_FORMAT;
        }
          else
        {
          msg_vols_format = SPACEDB_MSG_VOLS_PERM_TEMP_FORMAT;
        }
        }
      else
        {
          msg_vols_format = SPACEDB_MSG_VOLS_TEMP_TEMP_FORMAT;
        }
      /* the format is:
       * volid, type, purpose, used pages/size, free pages/size, total pages/size, volume name */
      fprintf (outfp, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_SPACEDB, msg_vols_format),
           vols[i].volid, SPACEDB_TO_SIZE_ARG (1, vols[i].npage_used),
           SPACEDB_TO_SIZE_ARG (2, vols[i].npage_free),
           SPACEDB_TO_SIZE_ARG (3, vols[i].npage_used + vols[i].npage_free), vols[i].name);
    }
      fprintf (outfp, "\n");
    }

  if (filesp != NULL)
    {
      /* print detailed files information */

      /* print title */
      fprintf (outfp, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_SPACEDB, SPACEDB_MSG_FILES_TITLE));
      /* print header */
      if (size_unit_type == SPACEDB_SIZE_UNIT_PAGE)
    {
      fprintf (outfp,
           msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_SPACEDB, SPACEDB_MSG_FILES_HEADER_PAGES));
    }
      else
    {
      fprintf (outfp,
           msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_SPACEDB, SPACEDB_MSG_FILES_HEADER_SIZE));
    }

      /* the format is:
       * data_type, file_count, used pages/size, ftab pages/size, reserved pages/size, total pages/size */
      for (i = 0; i < SPACEDB_FILE_COUNT; i++)
    {
      fprintf (outfp, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_SPACEDB, SPACEDB_MSG_FILES_FORMAT),
           file_type_strings[i], files[i].nfile,
           SPACEDB_TO_SIZE_ARG (1, files[i].npage_user), SPACEDB_TO_SIZE_ARG (2, files[i].npage_ftab),
           SPACEDB_TO_SIZE_ARG (3, files[i].npage_reserved),
           SPACEDB_TO_SIZE_ARG (4, files[i].npage_user + files[i].npage_ftab + files[i].npage_reserved));
    }
      fprintf (outfp, "\n");
    }

  if (!summarize)
    {
      fprintf (outfp, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_SPACEDB, SPACEDB_OUTPUT_TITLE_LOB),
           boot_get_lob_path ());
    }

  db_shutdown ();
  if (outfp != stdout)
    {
      fclose (outfp);
    }

  if (vols != NULL)
    {
      free_and_init (vols);
    }

  return EXIT_SUCCESS;

print_space_usage:
  fprintf (stderr, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_SPACEDB, SPACEDB_MSG_USAGE),
       basename (arg->argv0));
  util_log_write_errid (MSGCAT_UTIL_GENERIC_INVALID_ARGUMENT);

error_exit:
  if (outfp != stdout && outfp != NULL)
    {
      fclose (outfp);
    }
  if (vols != NULL)
    {
      free_and_init (vols);
    }
  return EXIT_FAILURE;

#undef SPACEDB_TO_SIZE_ARG
}

/*
 * acldb() -
 *   return: EXIT_SUCCESS/EXIT_FAILURE
 */
int
acldb (UTIL_FUNCTION_ARG * arg)
{
#if defined (CS_MODE)
  UTIL_ARG_MAP *arg_map = arg->arg_map;
  char er_msg_file[PATH_MAX];
  const char *database_name;
  bool reload;
  int ret_code = EXIT_SUCCESS;

  if (utility_get_option_string_table_size (arg_map) != 1)
    {
      goto print_acl_usage;
    }

  reload = utility_get_option_bool_value (arg_map, ACLDB_RELOAD_S);

  database_name = utility_get_option_string_value (arg_map, OPTION_STRING_TABLE, 0);
  if (database_name == NULL)
    {
      goto print_acl_usage;
    }

  if (check_database_name (database_name))
    {
      goto error_exit;
    }

  /* error message log file */
  sprintf (er_msg_file, "%s_%s.err", database_name, arg->command_name);
  er_init (er_msg_file, ER_NEVER_EXIT);

  /* should have little copyright herald message ? */
  AU_DISABLE_PASSWORDS ();
  db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY);
  db_login ("DBA", NULL);

  if (db_restart (arg->command_name, TRUE, database_name) != NO_ERROR)
    {
      fprintf (stderr, "%s\n", db_error_string (3));
      goto error_exit;
    }

  if (reload)
    {
      ret_code = acl_reload ();
      if (ret_code != NO_ERROR)
    {
      fprintf (stderr, "%s\n", db_error_string (3));
    }
    }
  else
    {
      acl_dump (stdout);
    }
  db_shutdown ();

  return ret_code;

print_acl_usage:
  fprintf (stderr, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_ACLDB, ACLDB_MSG_USAGE),
       basename (arg->argv0));
error_exit:
  return EXIT_FAILURE;
#else /* CS_MODE */
  fprintf (stderr, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_ACLDB, ACLDB_MSG_NOT_IN_STANDALONE),
       basename (arg->argv0));
  return EXIT_FAILURE;
#endif /* !CS_MODE */
}

/*
 * lockdb() - lockdb main routine
 *   return: EXIT_SUCCESS/EXIT_FAILURE
 */
int
lockdb (UTIL_FUNCTION_ARG * arg)
{
#if defined (CS_MODE)
  UTIL_ARG_MAP *arg_map = arg->arg_map;
  char er_msg_file[PATH_MAX];
  const char *database_name;
  const char *output_file = NULL;
  FILE *outfp = NULL;
  int is_contention;

  if (utility_get_option_string_table_size (arg_map) != 1)
    {
      goto print_lock_usage;
    }

  database_name = utility_get_option_string_value (arg_map, OPTION_STRING_TABLE, 0);
  if (database_name == NULL)
    {
      goto print_lock_usage;
    }

  is_contention = utility_get_option_bool_value (arg_map, LOCK_DISPLAY_CONTENTION_S);
  output_file = utility_get_option_string_value (arg_map, LOCK_OUTPUT_FILE_S, 0);
  if (output_file == NULL)
    {
      outfp = stdout;
    }
  else
    {
      outfp = fopen (output_file, "w");
      if (outfp == NULL)
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_LOCKDB, LOCKDB_MSG_BAD_OUTPUT),
                 output_file);
      goto error_exit;
    }
    }

  if (check_database_name (database_name))
    {
      goto error_exit;
    }

  /* error message log file */
  snprintf (er_msg_file, sizeof (er_msg_file) - 1, "%s_%s.err", database_name, arg->command_name);
  er_init (er_msg_file, ER_NEVER_EXIT);

  /* should have little copyright herald message ? */
  AU_DISABLE_PASSWORDS ();
  db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY);
  db_login ("DBA", NULL);

  if (db_restart (arg->command_name, TRUE, database_name) != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      goto error_exit;
    }

  (void) db_set_isolation (TRAN_READ_COMMITTED);

  lock_dump (outfp, is_contention);
  db_shutdown ();

  if (outfp != stdout)
    {
      fclose (outfp);
    }

  return EXIT_SUCCESS;

print_lock_usage:
  fprintf (stderr, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_LOCKDB, LOCKDB_MSG_USAGE),
       basename (arg->argv0));
  util_log_write_errid (MSGCAT_UTIL_GENERIC_INVALID_ARGUMENT);

error_exit:
  if (outfp != stdout && outfp != NULL)
    {
      fclose (outfp);
    }
  return EXIT_FAILURE;
#else /* CS_MODE */
  fprintf (stderr, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_LOCKDB, LOCKDB_MSG_NOT_IN_STANDALONE),
       basename (arg->argv0));
  return EXIT_FAILURE;
#endif /* !CS_MODE */
}

/*
 * isvalid_transaction() - test if transaction is valid
 *   return: non-zero if valid transaction
 *   tran(in)
 */
static int
isvalid_transaction (const ONE_TRAN_INFO * tran)
{
  int valid;

  valid = (tran != NULL && tran->tran_index != -1 && tran->tran_index != tm_Tran_index);

  return valid;
}

/*
 * doesmatch_transaction() - test if matching transaction
 *   return: non-zero if the information matches this transaction
 *   tran(in)
 *   tran_index_list(in)
 *   index_list_size(in)
 *   user_name(in)
 *   hostname(in)
 *   progname(in)
 */
static bool
doesmatch_transaction (const ONE_TRAN_INFO * tran, int *tran_index_list, int index_list_size, const char *username,
               const char *hostname, const char *progname, const char *sql_id)
{
  int i;

  if (!isvalid_transaction (tran))
    {
      return false;
    }

  if ((username != NULL && strcmp (tran->login_name, username) == 0)
      || (hostname != NULL && strcmp (tran->host_name, hostname) == 0)
      || (progname != NULL && strcmp (tran->program_name, progname) == 0)
      || (sql_id != NULL && tran->query_exec_info.sql_id != NULL && strcmp (tran->query_exec_info.sql_id, sql_id) == 0))
    {
      return true;
    }

  for (i = 0; i < index_list_size; i++)
    {
      if (tran->tran_index == tran_index_list[i])
    {
      return true;
    }
    }

  return false;
}

/*
 * dump_trantb() - Displays information about all the currently
 *                 active transactions
 *   return: none
 *   info(in) :
 *   dump_level(in) :
 */
static void
dump_trantb (TRANS_INFO * info, TRANDUMP_LEVEL dump_level, bool full_sqltext)
{
  int i;
  int num_valid = 0;
  MSGCAT_TRANLIST_MSG header = TRANLIST_MSG_SUMMARY_HEADER;
  MSGCAT_TRANLIST_MSG underscore = TRANLIST_MSG_SUMMARY_UNDERSCORE;

  if (dump_level == TRANDUMP_FULL_INFO)
    {
      header = TRANLIST_MSG_FULL_INFO_HEADER;
      underscore = TRANLIST_MSG_FULL_INFO_UNDERSCORE;
    }
  else if (dump_level == TRANDUMP_QUERY_INFO)
    {
      header = TRANLIST_MSG_QUERY_INFO_HEADER;
      underscore = TRANLIST_MSG_QUERY_INFO_UNDERSCORE;
    }

  if (info != NULL && info->num_trans > 0)
    {
      /*
       * remember that we have to print the messages one at a time, mts_
       * reuses the message buffer on each call.
       */
      for (i = 0; i < info->num_trans; i++)
    {
      /*
       * Display transactions in transaction table that seems to be valid
       */
      if (isvalid_transaction (&info->tran[i]))
        {
          if (num_valid == 0)
        {
          /* Dump table header */
          fprintf (stdout, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_TRANLIST, header));
          fprintf (stdout, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_TRANLIST, underscore));
        }

          num_valid++;
          print_tran_entry (&info->tran[i], dump_level, full_sqltext);
        }
    }
    }

  if (num_valid > 0)
    {
      fprintf (stdout, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_TRANLIST, underscore));
    }
  else
    {
      fprintf (stdout,
           msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_TRANLIST, TRANLIST_MSG_NONE_TABLE_ENTRIES));
    }

  if (info != NULL && (dump_level == TRANDUMP_QUERY_INFO || dump_level == TRANDUMP_FULL_INFO))
    {
      int j;

      fprintf (stdout, "\n");
      /* print query string info */
      for (i = 0; i < info->num_trans; i++)
    {
      if (isvalid_transaction (&info->tran[i]) && !XASL_ID_IS_NULL (&info->tran[i].query_exec_info.xasl_id))
        {
          fprintf (stdout, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_TRANLIST, TRANLIST_MSG_SQL_ID),
               info->tran[i].query_exec_info.sql_id);
          fprintf (stdout, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_TRANLIST, TRANLIST_MSG_TRAN_INDEX),
               info->tran[i].tran_index);

          for (j = i + 1; j < info->num_trans; j++)
        {
          if (isvalid_transaction (&info->tran[j])
              && XASL_ID_EQ (&info->tran[i].query_exec_info.xasl_id, &info->tran[j].query_exec_info.xasl_id))
            {
              /* same query */
              fprintf (stdout, ", %d", info->tran[j].tran_index);
              /* reset xasl to skip in next search */
              XASL_ID_SET_NULL (&info->tran[j].query_exec_info.xasl_id);
            }
        }
          fprintf (stdout, "\n");

          /* print query statement */
          fprintf (stdout, "%s\n\n", info->tran[i].query_exec_info.query_stmt);
        }
    }
    }
}

/*
 * kill_transactions() - kill transaction(s)
 *   return: number of killed transactions
 *   info(in/out)
 *   tran_index(in)
 *   username(in)
 *   hostname(in)
 *   progname(in)
 *   verify(in)
 *
 * Note: Kill one or several transactions identified only one of the
 *       above parameters. If the verification flag is set, the user is
 *       prompted for verification wheheter or not to kill the
 *       transaction(s).
 *
 *       if tran_index_list != NULL && != ""
 *         kill transactions in the tran_index comma list.
 *       else if username != NULL && != ""
 *         kill all transactions associated with given user.
 *       else if hostname != NULL && != ""
 *         kill all transactions associated with given host.
 *       else if progname != NULL && != ""
 *         kill all transactions associated with given program.
 *       else
 *         error.
 *
 *    If verify is set, the transactions are only killed after prompting
 *    for verification.
 */
static int
kill_transactions (TRANS_INFO * info, int *tran_index_list, int list_size, const char *username, const char *hostname,
           const char *progname, const char *sql_id, bool verify)
{
  int i, ok;
  int nkills = 0, nfailures = 0;
  int ch;
  MSGCAT_TRANLIST_MSG header = TRANLIST_MSG_SUMMARY_HEADER;
  MSGCAT_TRANLIST_MSG underscore = TRANLIST_MSG_SUMMARY_UNDERSCORE;
  TRANDUMP_LEVEL dump_level = TRANDUMP_SUMMARY;

  if (sql_id != NULL)
    {
      /* print --query-exec-info table format */
      header = TRANLIST_MSG_QUERY_INFO_HEADER;
      underscore = TRANLIST_MSG_QUERY_INFO_UNDERSCORE;
      dump_level = TRANDUMP_QUERY_INFO;
    }

  /* see if we have anything do do */
  for (i = 0; i < info->num_trans; i++)
    {
      if (doesmatch_transaction (&info->tran[i], tran_index_list, list_size, username, hostname, progname, sql_id))
    {
      break;
    }
    }

  if (i >= info->num_trans)
    {
      /*
       * There is not matches
       */
      PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_KILLTRAN, KILLTRAN_MSG_NO_MATCHES));
    }
  else
    {
      if (!verify)
    {
      ok = 1;
    }
      else
    {
      ok = 0;
      /*
       * display the transactin identifiers that we are about to kill
       */
      fprintf (stdout, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_KILLTRAN, KILLTRAN_MSG_READY_TO_KILL));

      fprintf (stdout, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_TRANLIST, header));
      fprintf (stdout, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_TRANLIST, underscore));

      for (i = 0; i < info->num_trans; i++)
        {
          if (doesmatch_transaction (&info->tran[i], tran_index_list, list_size, username, hostname, progname,
                     sql_id))
        {
          print_tran_entry (&info->tran[i], dump_level, false);
        }
        }
      fprintf (stdout, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_TRANLIST, underscore));

      fprintf (stdout, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_KILLTRAN, KILLTRAN_MSG_VERIFY));
      fflush (stdout);

      ch = getc (stdin);
      if (ch == 'Y' || ch == 'y')
        {
          ok = 1;
        }
    }

      if (ok)
    {
      for (i = 0; i < info->num_trans; i++)
        {
          if (doesmatch_transaction (&info->tran[i], tran_index_list, list_size, username, hostname, progname,
                     sql_id))
        {
          fprintf (stdout,
               msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_KILLTRAN, KILLTRAN_MSG_KILLING),
               info->tran[i].tran_index);
          if (thread_kill_tran_index (info->tran[i].tran_index, info->tran[i].db_user, info->tran[i].host_name,
                          info->tran[i].process_id) == NO_ERROR)
            {
              info->tran[i].tran_index = -1;    /* Gone */
              nkills++;
            }
          else
            {
              /*
               * Fail to kill the transaction
               */
              if (nfailures == 0)
            {
              fprintf (stdout, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_KILLTRAN,
                               KILLTRAN_MSG_KILL_FAILED));
              fprintf (stdout, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_TRANLIST, header));
              fprintf (stdout, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_TRANLIST, underscore));
            }

              print_tran_entry (&info->tran[i], dump_level, false);

              if (er_errid () != NO_ERROR)
            {
              PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
            }
              else  /* probably it is the case of timeout */
            {
              PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_KILLTRAN,
                                 KILLTRAN_MSG_KILL_TIMEOUT));
            }
              nfailures++;
            }
        }
        }

      if (nfailures > 0)
        {
          fprintf (stdout, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_TRANLIST, underscore));
        }
    }
    }

  return nkills;
}

/*
 * print_tran_entry()
 *   return: NO_ERROR
 *   tran_info(in) :
 *   include_query_info(in) :
 */
static int
print_tran_entry (const ONE_TRAN_INFO * tran_info, TRANDUMP_LEVEL dump_level, bool full_sqltext)
{
  char *buf = NULL;
  char *query_buf;
  char tmp_query_buf[32];

  if (tran_info == NULL)
    {
      assert_release (0);
      return ER_FAILED;
    }

  assert_release (dump_level <= TRANDUMP_FULL_INFO);

  if (dump_level == TRANDUMP_FULL_INFO || dump_level == TRANDUMP_QUERY_INFO)
    {
      buf = tran_info->query_exec_info.wait_for_tran_index_string;

      if (tran_info->query_exec_info.query_stmt != NULL)
    {
      /* print 31 string */
      if (full_sqltext == true)
        {
          query_buf = tran_info->query_exec_info.query_stmt;
        }
      else
        {
          strncpy (tmp_query_buf, tran_info->query_exec_info.query_stmt, 32);
          tmp_query_buf[31] = '\0';
          query_buf = tmp_query_buf;
        }
    }
    }

  if (dump_level == TRANDUMP_FULL_INFO)
    {
      fprintf (stdout, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_TRANLIST, TRANLIST_MSG_FULL_INFO_ENTRY),
           tran_info->tran_index, tran_get_tranlist_state_name (tran_info->state), tran_info->db_user,
           tran_info->host_name, tran_info->process_id, tran_info->program_name,
           tran_info->query_exec_info.query_time, tran_info->query_exec_info.tran_time, (buf == NULL ? "-1" : buf),
           ((tran_info->query_exec_info.sql_id) ? tran_info->query_exec_info.sql_id : "*** empty ***"),
           ((tran_info->query_exec_info.query_stmt) ? query_buf : " "));
    }
  else if (dump_level == TRANDUMP_QUERY_INFO)
    {
      fprintf (stdout, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_TRANLIST, TRANLIST_MSG_QUERY_INFO_ENTRY),
           tran_info->tran_index, tran_get_tranlist_state_name (tran_info->state),
           tran_info->process_id, tran_info->program_name, tran_info->query_exec_info.query_time,
           tran_info->query_exec_info.tran_time, (buf == NULL ? "-1" : buf),
           ((tran_info->query_exec_info.sql_id) ? tran_info->query_exec_info.sql_id : "*** empty ***"),
           ((tran_info->query_exec_info.query_stmt) ? query_buf : " "));
    }
  else
    {
      fprintf (stdout, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_TRANLIST, TRANLIST_MSG_SUMMARY_ENTRY),
           tran_info->tran_index, tran_get_tranlist_state_name (tran_info->state), tran_info->db_user,
           tran_info->host_name, tran_info->process_id, tran_info->program_name);
    }

  return NO_ERROR;
}


/*
 * tranlist() -
 *   return: EXIT_SUCCESS/EXIT_FAILURE
 */
int
tranlist (UTIL_FUNCTION_ARG * arg)
{
#if defined (CS_MODE)
  UTIL_ARG_MAP *arg_map = arg->arg_map;
  char er_msg_file[PATH_MAX];
  const char *database_name;
#if defined(NEED_PRIVILEGE_PASSWORD)
  const char *username;
  const char *password;
#endif
  char *passbuf = NULL;
  TRANS_INFO *info = NULL;
  int error;
  bool is_summary, include_query_info, full_sqltext = false;
  TRANDUMP_LEVEL dump_level = TRANDUMP_FULL_INFO;

  if (utility_get_option_string_table_size (arg_map) != 1)
    {
      goto print_tranlist_usage;
    }

  database_name = utility_get_option_string_value (arg_map, OPTION_STRING_TABLE, 0);
  if (database_name == NULL)
    {
      goto print_tranlist_usage;
    }

#if defined(NEED_PRIVILEGE_PASSWORD)
  username = utility_get_option_string_value (arg_map, TRANLIST_USER_S, 0);
  password = utility_get_option_string_value (arg_map, TRANLIST_PASSWORD_S, 0);
#endif
  is_summary = utility_get_option_bool_value (arg_map, TRANLIST_SUMMARY_S);
  tranlist_Sort_column = utility_get_option_int_value (arg_map, TRANLIST_SORT_KEY_S);
  tranlist_Sort_desc = utility_get_option_bool_value (arg_map, TRANLIST_REVERSE_S);
  full_sqltext = utility_get_option_bool_value (arg_map, TRANLIST_FULL_SQL_S);

#if defined(NEED_PRIVILEGE_PASSWORD)
  if (username == NULL)
    {
      /* default : DBA user */
      username = "DBA";
    }
#endif

  if (check_database_name (database_name) != NO_ERROR)
    {
      goto error_exit;
    }

  if (tranlist_Sort_column > 10 || tranlist_Sort_column < 0 || (is_summary && tranlist_Sort_column > 5))
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_TRANLIST,
                         TRANLIST_MSG_INVALID_SORT_KEY), tranlist_Sort_column);
      goto error_exit;
    }

  /* error message log file */
  snprintf (er_msg_file, sizeof (er_msg_file) - 1, "%s_%s.err", database_name, arg->command_name);
  er_init (er_msg_file, ER_NEVER_EXIT);

#if defined(NEED_PRIVILEGE_PASSWORD)
  error = db_restart_ex (arg->command_name, database_name, username, password, NULL, DB_CLIENT_TYPE_ADMIN_UTILITY);
  if (error != NO_ERROR)
    {
      char msg_buf[64];

      if (error == ER_AU_INVALID_PASSWORD && password == NULL)
    {
      /*
       * prompt for a valid password and try again, need a reusable
       * password prompter so we can use getpass() on platforms that
       * support it.
       */
      snprintf (msg_buf, 64,
            msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_TRANLIST, TRANLIST_MSG_USER_PASSWORD),
            username);

      passbuf = getpass (msg_buf);

      if (passbuf[0] == '\0')
        {
          passbuf = (char *) NULL;
        }
      password = passbuf;

      error =
        db_restart_ex (arg->command_name, database_name, username, password, NULL, DB_CLIENT_TYPE_ADMIN_UTILITY);
    }

      if (error != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      goto error_exit;
    }
    }

  if (!au_is_dba_group_member (Au_user))
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_TRANLIST, TRANLIST_MSG_NOT_DBA_USER),
                 username);
      db_shutdown ();
      goto error_exit;
    }
#else
  AU_DISABLE_PASSWORDS ();
  db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY);
  if (db_login ("DBA", NULL) || db_restart (arg->command_name, TRUE, database_name))
    {
      PRINT_AND_LOG_ERR_MSG ("%s: %s. \n\n", arg->command_name, db_error_string (3));
      goto error_exit;
    }
#endif

  /*
   * Get the current state of transaction table information. All the
   * transaction kills are going to be based on this information. The
   * transaction information may be changed back in the server if there
   * are new transactions starting and finishing. We need to do this way
   * since verification is required at this level, and we cannot freeze the
   * state of the server ()transaction table).
   */
  include_query_info = !is_summary;

  info = logtb_get_trans_info (include_query_info);
  if (info == NULL)
    {
      util_log_write_errstr ("%s\n", db_error_string (3));
      db_shutdown ();
      goto error_exit;
    }

  if (is_summary)
    {
      dump_level = TRANDUMP_SUMMARY;
    }

  if (tranlist_Sort_column > 0 || tranlist_Sort_desc == true)
    {
      qsort ((void *) info->tran, info->num_trans, sizeof (ONE_TRAN_INFO), tranlist_cmp_f);
    }

  (void) dump_trantb (info, dump_level, full_sqltext);

  if (info)
    {
      logtb_free_trans_info (info);
    }

  (void) db_shutdown ();
  return EXIT_SUCCESS;

print_tranlist_usage:
  fprintf (stderr, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_TRANLIST, TRANLIST_MSG_USAGE),
       basename (arg->argv0));
  util_log_write_errid (MSGCAT_UTIL_GENERIC_INVALID_ARGUMENT);

error_exit:
  return EXIT_FAILURE;
#else /* CS_MODE */
  PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_TRANLIST,
                     TRANLIST_MSG_NOT_IN_STANDALONE), basename (arg->argv0));
  return EXIT_FAILURE;
#endif /* !CS_MODE */
}

/*
 * killtran() - killtran main routine
 *   return: EXIT_SUCCESS/EXIT_FAILURE
 */
int
killtran (UTIL_FUNCTION_ARG * arg)
{
#if defined (CS_MODE)
  UTIL_ARG_MAP *arg_map = arg->arg_map;
  char er_msg_file[PATH_MAX];
  const char *database_name;
  const char *kill_tran_index;
  const char *kill_progname;
  const char *kill_user;
  const char *kill_host;
  const char *kill_sql_id;
  const char *dba_password;
  bool dump_trantab_flag;
  bool force = true;
  int isbatch;
  char *passbuf = NULL;
  TRANS_INFO *info = NULL;
  int error;
  bool include_query_exec_info;
  int tran_index_list[MAX_KILLTRAN_INDEX_LIST_NUM];
  int list_size = 0;
  int value;
  char delimiter = ',';
  const char *ptr;
  char *tmp;

  if (utility_get_option_string_table_size (arg_map) != 1)
    {
      goto print_killtran_usage;
    }

  database_name = utility_get_option_string_value (arg_map, OPTION_STRING_TABLE, 0);
  if (database_name == NULL)
    {
      goto print_killtran_usage;
    }

  kill_tran_index = utility_get_option_string_value (arg_map, KILLTRAN_KILL_TRANSACTION_INDEX_S, 0);
  kill_user = utility_get_option_string_value (arg_map, KILLTRAN_KILL_USER_NAME_S, 0);
  kill_host = utility_get_option_string_value (arg_map, KILLTRAN_KILL_HOST_NAME_S, 0);
  kill_progname = utility_get_option_string_value (arg_map, KILLTRAN_KILL_PROGRAM_NAME_S, 0);
  kill_sql_id = utility_get_option_string_value (arg_map, KILLTRAN_KILL_SQL_ID_S, 0);

  force = utility_get_option_bool_value (arg_map, KILLTRAN_FORCE_S);
  dba_password = utility_get_option_string_value (arg_map, KILLTRAN_DBA_PASSWORD_S, 0);
  dump_trantab_flag = utility_get_option_bool_value (arg_map, KILLTRAN_DISPLAY_INFORMATION_S);

  include_query_exec_info = utility_get_option_bool_value (arg_map, KILLTRAN_DISPLAY_QUERY_INFO_S);

  if (check_database_name (database_name))
    {
      goto error_exit;
    }

  isbatch = 0;
  if (kill_tran_index != NULL && strlen (kill_tran_index) != 0)
    {
      isbatch++;
    }
  if (kill_user != NULL && strlen (kill_user) != 0)
    {
      isbatch++;
    }
  if (kill_host != NULL && strlen (kill_host) != 0)
    {
      isbatch++;
    }
  if (kill_progname != NULL && strlen (kill_progname) != 0)
    {
      isbatch++;
    }
  if (kill_sql_id != NULL && strlen (kill_sql_id) != 0)
    {
      isbatch++;
    }

  if (isbatch > 1)
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_KILLTRAN, KILLTRAN_MSG_MANY_ARGS));
      goto error_exit;
    }

  /* error message log file */
  snprintf (er_msg_file, sizeof (er_msg_file) - 1, "%s_%s.err", database_name, arg->command_name);
  er_init (er_msg_file, ER_NEVER_EXIT);

  /* disable password, if don't use kill option */
  if (isbatch == 0)
    {
      if (dba_password != NULL)
    {
      goto print_killtran_usage;
    }
      AU_DISABLE_PASSWORDS ();
    }

  db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY);

  if (db_login ("DBA", dba_password) != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      goto error_exit;
    }

  /* first try to restart with the password given (possibly none) */
  error = db_restart (arg->command_name, TRUE, database_name);
  if (error)
    {
      if (error == ER_AU_INVALID_PASSWORD && (dba_password == NULL || strlen (dba_password) == 0))
    {
      /*
       * prompt for a valid password and try again, need a reusable
       * password prompter so we can use getpass() on platforms that
       * support it.
       */

      /* get password interactively if interactive mode */
      passbuf = getpass (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_KILLTRAN,
                         KILLTRAN_MSG_DBA_PASSWORD));
      if (passbuf[0] == '\0')   /* to fit into db_login protocol */
        {
          passbuf = (char *) NULL;
        }
      dba_password = passbuf;
      if (db_login ("DBA", dba_password) != NO_ERROR)
        {
          PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
          goto error_exit;
        }
      else
        {
          error = db_restart (arg->command_name, TRUE, database_name);
        }
    }

      if (error)
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      goto error_exit;
    }
    }

  /*
   * Get the current state of transaction table information. All the
   * transaction kills are going to be based on this information. The
   * transaction information may be changed back in the server if there
   * are new transactions starting and finishing. We need to do this way
   * since verification is required at this level, and we cannot freeze the
   * state of the server ()transaction table).
   */

  info = logtb_get_trans_info (include_query_exec_info || kill_sql_id);
  if (info == NULL)
    {
      util_log_write_errstr ("%s\n", db_error_string (3));
      db_shutdown ();
      goto error_exit;
    }

  if (dump_trantab_flag || include_query_exec_info
      || ((kill_tran_index == NULL || strlen (kill_tran_index) == 0) && (kill_user == NULL || strlen (kill_user) == 0)
      && (kill_host == NULL || strlen (kill_host) == 0) && (kill_progname == NULL || strlen (kill_progname) == 0)
      && (kill_sql_id == NULL || strlen (kill_sql_id) == 0)))
    {
      TRANDUMP_LEVEL dump_level;

      dump_level = (include_query_exec_info) ? TRANDUMP_QUERY_INFO : TRANDUMP_SUMMARY;
      dump_trantb (info, dump_level, false);
    }
  else
    {
      if (kill_tran_index != NULL && strlen (kill_tran_index) > 0)
    {
      int result;

      ptr = kill_tran_index;

      tmp = (char *) strchr (ptr, delimiter);
      while (*ptr != '\0' && tmp)
        {
          if (list_size >= MAX_KILLTRAN_INDEX_LIST_NUM)
        {
          break;
        }

          *tmp = '\0';
          result = parse_int (&value, ptr, 10);
          if (result != 0 || value <= 0)
        {
          PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_KILLTRAN,
                             KILLTRAN_MSG_INVALID_TRANINDEX), ptr);
          if (info)
            {
              logtb_free_trans_info (info);
            }
          db_shutdown ();
          goto error_exit;
        }

          tran_index_list[list_size++] = value;
          ptr = tmp + 1;
          tmp = (char *) strchr (ptr, delimiter);
        }

      result = parse_int (&value, ptr, 10);
      if (result != 0 || value <= 0)
        {
          PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_KILLTRAN,
                             KILLTRAN_MSG_INVALID_TRANINDEX), ptr);
          if (info)
        {
          logtb_free_trans_info (info);
        }
          db_shutdown ();
          goto error_exit;
        }

      if (list_size < MAX_KILLTRAN_INDEX_LIST_NUM)
        {
          tran_index_list[list_size++] = value;
        }
    }

      /* some piece of transaction identifier was entered, try to use it */
      if (kill_transactions (info, tran_index_list, list_size, kill_user, kill_host, kill_progname, kill_sql_id, !force)
      <= 0)
    {
      if (info)
        {
          logtb_free_trans_info (info);
        }
      db_shutdown ();
      goto error_exit;
    }
    }

  if (info)
    {
      logtb_free_trans_info (info);
    }

  (void) db_shutdown ();
  return EXIT_SUCCESS;

print_killtran_usage:
  fprintf (stderr, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_KILLTRAN, KILLTRAN_MSG_USAGE),
       basename (arg->argv0));
  util_log_write_errid (MSGCAT_UTIL_GENERIC_INVALID_ARGUMENT);

error_exit:
  return EXIT_FAILURE;
#else /* CS_MODE */
  PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_KILLTRAN,
                     KILLTRAN_MSG_NOT_IN_STANDALONE), basename (arg->argv0));
  return EXIT_FAILURE;
#endif /* !CS_MODE */
}

/*
 * plandump() - plandump main routine
 *   return: EXIT_SUCCESS/EXIT_FAILURE
 */
int
plandump (UTIL_FUNCTION_ARG * arg)
{
#if defined (CS_MODE)
  UTIL_ARG_MAP *arg_map = arg->arg_map;
  char er_msg_file[PATH_MAX];
  const char *database_name;
  const char *output_file = NULL;
  char *sha1 = NULL;
  bool drop_flag = false;
  FILE *outfp = NULL;

  database_name = utility_get_option_string_value (arg_map, OPTION_STRING_TABLE, 0);
  if (database_name == NULL)
    {
      goto print_plandump_usage;
    }

  drop_flag = utility_get_option_bool_value (arg_map, PLANDUMP_DROP_S);
  output_file = utility_get_option_string_value (arg_map, PLANDUMP_OUTPUT_FILE_S, 0);
  sha1 = utility_get_option_string_value (arg_map, PLANDUMP_SHA1_S, 0);

  if (utility_get_option_string_table_size (arg_map) != 1)
    {
      goto print_plandump_usage;
    }

  if (output_file == NULL)
    {
      outfp = stdout;
    }
  else
    {
      outfp = fopen (output_file, "w");
      if (outfp == NULL)
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_PLANDUMP,
                         PLANDUMP_MSG_BAD_OUTPUT), output_file);
      goto error_exit;
    }
    }

  if (check_database_name (database_name))
    {
      goto error_exit;
    }

  /* error message log file */
  snprintf (er_msg_file, sizeof (er_msg_file) - 1, "%s_%s.err", database_name, arg->command_name);
  er_init (er_msg_file, ER_NEVER_EXIT);

  /* should have little copyright herald message ? */
  AU_DISABLE_PASSWORDS ();
  db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY);
  db_login ("DBA", NULL);

  if (db_restart (arg->command_name, TRUE, database_name) != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      goto error_exit;
    }

  if (sha1 != NULL)
    {
      if (qmgr_drop_query_plans_by_sha1 (sha1) != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      db_shutdown ();
      goto error_exit;
    }
    }
  else if (drop_flag)
    {
      if (qmgr_drop_all_query_plans () != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      db_shutdown ();
      goto error_exit;
    }
    }
  qmgr_dump_query_plans (outfp);
  db_shutdown ();

  if (outfp != stdout)
    {
      fclose (outfp);
    }

  return EXIT_SUCCESS;

print_plandump_usage:
  fprintf (stderr, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_PLANDUMP, PLANDUMP_MSG_USAGE),
       basename (arg->argv0));
  util_log_write_errid (MSGCAT_UTIL_GENERIC_INVALID_ARGUMENT);

error_exit:
  if (outfp != stdout && outfp != NULL)
    {
      fclose (outfp);
    }
  return EXIT_FAILURE;
#else /* CS_MODE */
  fprintf (stderr, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_PLANDUMP, PLANDUMP_MSG_NOT_IN_STANDALONE),
       basename (arg->argv0));
  return EXIT_FAILURE;
#endif /* !CS_MODE */
}

/*
 * paramdump() - paramdump main routine
 *   return: EXIT_SUCCESS/EXIT_FAILURE
 */
int
paramdump (UTIL_FUNCTION_ARG * arg)
{
  UTIL_ARG_MAP *arg_map = arg->arg_map;
  char er_msg_file[PATH_MAX];
  const char *database_name;
  const char *output_file = NULL;
  bool both_flag = false;
  bool ha_only_flag = false;
  bool exclude_ha_flag = false;
  bool for_cm_flag = false;
  const char *hexa_string;
  FILE *outfp = NULL;
  unsigned int added_in_flags, out_flags, dump_flags;

  if (utility_get_option_string_table_size (arg_map) != 1)
    {
      goto print_dumpparam_usage;
    }

  database_name = utility_get_option_string_value (arg_map, OPTION_STRING_TABLE, 0);
  if (database_name == NULL)
    {
      goto print_dumpparam_usage;
    }

  output_file = utility_get_option_string_value (arg_map, PARAMDUMP_OUTPUT_FILE_S, 0);
  both_flag = utility_get_option_bool_value (arg_map, PARAMDUMP_BOTH_S);
  ha_only_flag = utility_get_option_bool_value (arg_map, PARAMDUMP_HA_ONLY_S);
  exclude_ha_flag = utility_get_option_bool_value (arg_map, PARAMDUMP_EXCLUDE_HA_S);

  /* --dump-flag is hidden option intended for developers or technical supoort */
  hexa_string = utility_get_option_string_value (arg_map, PARAMDUMP_DUMP_FLAG_S, 0);

  /* --for-cm is hidden option to maintain compatibility with cubrid manager */
  for_cm_flag = utility_get_option_bool_value (arg_map, PARAMDUMP_FOR_CM_S);

  if (ha_only_flag && exclude_ha_flag)
    {
      fprintf (stderr, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_PARAMDUMP, PARAMDUMP_MSG_BAD_OPTION));
      goto print_dumpparam_usage;
    }

  if (output_file == NULL)
    {
      outfp = stdout;
    }
  else
    {
      outfp = fopen (output_file, "w");
      if (outfp == NULL)
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_PARAMDUMP,
                         PARAMDUMP_MSG_BAD_OUTPUT), output_file);
      goto error_exit;
    }
    }

  if (check_database_name (database_name))
    {
      goto error_exit;
    }

  /* error message log file */
  snprintf (er_msg_file, sizeof (er_msg_file) - 1, "%s_%s.err", database_name, arg->command_name);
  er_init (er_msg_file, ER_NEVER_EXIT);

  added_in_flags = PRM_EMPTY_FLAG;
  out_flags = PRM_HIDDEN;

  /* ignore another options and print old style, when using --for-cm (that is, for_cm_flag is true.)  */
  if (for_cm_flag == false)
    {
      if (ha_only_flag)
    {
      added_in_flags |= PRM_FOR_HA;
    }
      else if (exclude_ha_flag)
    {
      out_flags |= PRM_FOR_HA;
    }

      if (hexa_string != NULL)
    {
      dump_flags = (unsigned int) strtoul (hexa_string, NULL, 16);
      added_in_flags |= dump_flags;
      out_flags &= ~dump_flags;
    }
    }

  /* should have little copyright herald message ? */
  AU_DISABLE_PASSWORDS ();
  db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY);
  db_login ("DBA", NULL);

  if (db_restart (arg->command_name, TRUE, database_name) != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      goto error_exit;
    }

  if (for_cm_flag)
    {
#if defined(SA_MODE)
      fprintf (outfp,
           msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_PARAMDUMP, PARAMDUMP_MSG_STANDALONE_PARAMETER));
      sysprm_dump_parameters (outfp, ' ', PRM_FOR_CLIENT | PRM_FOR_SERVER, PRM_OR_CONDITION, out_flags,
                  PRM_OR_CONDITION, true);
#else
      if (both_flag)
    {
      /* dump client's parameters */
      fprintf (outfp,
           msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_PARAMDUMP, PARAMDUMP_MSG_CLIENT_PARAMETER));
      sysprm_dump_parameters (outfp, 'C', PRM_FOR_CLIENT | PRM_FOR_SERVER, PRM_OR_CONDITION, out_flags,
                  PRM_OR_CONDITION, true);
      fprintf (outfp, "\n");
    }

      /* dump server's parameters */
      fprintf (outfp, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_PARAMDUMP, PARAMDUMP_MSG_SERVER_PARAMETER),
           database_name);
      sysprm_dump_server_parameters (outfp, PRM_FOR_SERVER | PRM_FOR_SERVER, PRM_OR_CONDITION, out_flags,
                     PRM_OR_CONDITION, true);
#endif
    }
  else
    {

      /* dump client's parameters */
      fprintf (outfp, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_PARAMDUMP, PARAMDUMP_MSG_CLIENT_PARAMETER));
      sysprm_dump_parameters (outfp, 'C', PRM_FOR_CLIENT | added_in_flags, PRM_AND_CONDITION, out_flags,
                  PRM_OR_CONDITION, false);
      fprintf (outfp, "\n");

      /* dump server's parameters */
      fprintf (outfp, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_PARAMDUMP, PARAMDUMP_MSG_SERVER_PARAMETER),
           database_name);
      sysprm_dump_server_parameters (outfp, PRM_FOR_SERVER | added_in_flags, PRM_AND_CONDITION, out_flags,
                     PRM_OR_CONDITION, false);
    }

  db_shutdown ();

  if (outfp != stdout)
    {
      fclose (outfp);
    }

  return EXIT_SUCCESS;

print_dumpparam_usage:
  fprintf (stderr, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_PARAMDUMP, PARAMDUMP_MSG_USAGE),
       basename (arg->argv0));
  util_log_write_errid (MSGCAT_UTIL_GENERIC_INVALID_ARGUMENT);

error_exit:
  if (outfp != stdout && outfp != NULL)
    {
      fclose (outfp);
    }
  return EXIT_FAILURE;
}

static void
print_timestamp (FILE * outfp)
{
  time_t tloc;
  struct tm tmloc;
  char str[80];

  tloc = time (NULL);
  utility_localtime (&tloc, &tmloc);
  strftime (str, 80, "%a %B %d %H:%M:%S %Z %Y", &tmloc);
  fprintf (outfp, "\n\t%s\n", str);
}

/*
 * statdump() - statdump main routine
 *   return: EXIT_SUCCESS/EXIT_FAILURE
 */
int
statdump (UTIL_FUNCTION_ARG * arg)
{
#if defined (CS_MODE)
  UTIL_ARG_MAP *arg_map = arg->arg_map;
  char er_msg_file[PATH_MAX];
  const char *database_name;
  const char *output_file = NULL;
  int interval;
  bool cumulative;
  const char *substr;
  FILE *outfp = NULL;

  if (utility_get_option_string_table_size (arg_map) != 1)
    {
      goto print_statdump_usage;
    }

  database_name = utility_get_option_string_value (arg_map, OPTION_STRING_TABLE, 0);
  if (database_name == NULL)
    {
      goto print_statdump_usage;
    }

  output_file = utility_get_option_string_value (arg_map, STATDUMP_OUTPUT_FILE_S, 0);
  interval = utility_get_option_int_value (arg_map, STATDUMP_INTERVAL_S);
  if (interval < 0)
    {
      goto print_statdump_usage;
    }
  cumulative = utility_get_option_bool_value (arg_map, STATDUMP_CUMULATIVE_S);
  substr = utility_get_option_string_value (arg_map, STATDUMP_SUBSTR_S, 0);

  if (interval == 0)
    {
      cumulative = true;
    }

  if (output_file == NULL)
    {
      outfp = stdout;
    }
  else
    {
      outfp = fopen (output_file, "w");
      if (outfp == NULL)
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_STATDUMP,
                         STATDUMP_MSG_BAD_OUTPUT), output_file);
      goto error_exit;
    }
    }

  if (check_database_name (database_name))
    {
      goto error_exit;
    }

  /* error message log file */
  snprintf (er_msg_file, sizeof (er_msg_file) - 1, "%s_%s.err", database_name, arg->command_name);
  er_init (er_msg_file, ER_NEVER_EXIT);

  /* should have little copyright herald message ? */
  AU_DISABLE_PASSWORDS ();
  db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY);
  db_login ("DBA", NULL);

  if (db_restart (arg->command_name, TRUE, database_name) != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      goto error_exit;
    }

  if (histo_start (true) != NO_ERROR)
    {
      goto error_exit;
    }

  if (interval > 0)
    {
      is_Sigint_caught = false;
#if defined(WINDOWS)
      SetConsoleCtrlHandler ((PHANDLER_ROUTINE) intr_handler, TRUE);
#else
      os_set_signal_handler (SIGINT, intr_handler);
#endif
    }

  do
    {
      print_timestamp (outfp);
      if (histo_print_global_stats (outfp, cumulative, substr) != NO_ERROR)
    {
      histo_stop ();
      goto error_exit;
    }
      fflush (outfp);
      sleep (interval);
    }
  while (interval > 0 && !is_Sigint_caught);

  histo_stop ();

  db_shutdown ();

  if (outfp != stdout)
    {
      fclose (outfp);
    }

  return EXIT_SUCCESS;

print_statdump_usage:
  fprintf (stderr, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_STATDUMP, STATDUMP_MSG_USAGE),
       basename (arg->argv0));
  util_log_write_errid (MSGCAT_UTIL_GENERIC_INVALID_ARGUMENT);

error_exit:
  if (outfp != stdout && outfp != NULL)
    {
      fclose (outfp);
    }
  return EXIT_FAILURE;
#else /* CS_MODE */
  PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_STATDUMP,
                     STATDUMP_MSG_NOT_IN_STANDALONE), basename (arg->argv0));

  return EXIT_FAILURE;
#endif /* !CS_MODE */
}

#if defined (ENABLE_UNUSED_FUNCTION)
/* check ha_mode is turned on in the server */
static int
check_server_ha_mode (void)
{
  char prm_buf[LINE_MAX], *prm_val;

  strcpy (prm_buf, prm_get_name (PRM_ID_HA_MODE));
  if (db_get_system_parameters (prm_buf, LINE_MAX - 1) != NO_ERROR)
    {
      return ER_FAILED;
    }
  prm_val = strchr (prm_buf, '=');
  if (prm_val == NULL)
    {
      return ER_FAILED;
    }
  if (strcmp (prm_val + 1, "y") != 0)
    {
      return ER_FAILED;
    }
  return NO_ERROR;
}
#endif /* ENABLE_UNUSED_FUNCTION */

/*
 * changemode() - changemode main routine
 *   return: EXIT_SUCCESS/EXIT_FAILURE
 *
 * TODO: this is really confusing. changemode utility actually changes HA state and not HA mode. They are two different
 *       things.
 */
int
changemode (UTIL_FUNCTION_ARG * arg)
{
#if defined (WINDOWS)
  PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_CHANGEMODE,
                     CHANGEMODE_MSG_HA_NOT_SUPPORT), basename (arg->argv0));

  return EXIT_FAILURE;
#else /* WINDOWS */
#if defined (CS_MODE)
  UTIL_ARG_MAP *arg_map = arg->arg_map;
  char er_msg_file[PATH_MAX];
  const char *database_name;
  char *mode_name;
  int error;
  HA_SERVER_STATE ha_state = HA_SERVER_STATE_NA;
  bool force;
  int timeout;

  if (utility_get_option_string_table_size (arg_map) != 1)
    {
      goto print_changemode_usage;
    }

  database_name = utility_get_option_string_value (arg_map, OPTION_STRING_TABLE, 0);
  if (database_name == NULL)
    {
      goto print_changemode_usage;
    }

  mode_name = utility_get_option_string_value (arg_map, CHANGEMODE_MODE_S, 0);
  force = utility_get_option_bool_value (arg_map, CHANGEMODE_FORCE_S);
  timeout = utility_get_option_int_value (arg_map, CHANGEMODE_TIMEOUT_S);

  if (timeout == -1)
    {
      timeout = HA_CHANGE_MODE_DEFAULT_TIMEOUT_IN_SECS;
    }

  if (check_database_name (database_name))
    {
      goto error_exit;
    }

  /* check mode_name option argument */
  if (mode_name != NULL)
    {
      int keyval = -1;
      if (changemode_keyword (&keyval, &mode_name) != NO_ERROR)
    {
      if (sscanf (mode_name, "%d", &keyval) != 1)
        {
          PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_CHANGEMODE,
                             CHANGEMODE_MSG_BAD_MODE), mode_name);
          goto error_exit;
        }
    }
      ha_state = (HA_SERVER_STATE) keyval;
      if (!(ha_state == HA_SERVER_STATE_ACTIVE || ha_state == HA_SERVER_STATE_STANDBY
        || ha_state == HA_SERVER_STATE_MAINTENANCE))
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_CHANGEMODE,
                         CHANGEMODE_MSG_BAD_MODE), mode_name);
      goto error_exit;
    }
    }

  /* error message log file */
  snprintf (er_msg_file, sizeof (er_msg_file) - 1, "%s_%s.err", database_name, arg->command_name);
  er_init (er_msg_file, ER_NEVER_EXIT);

  AU_DISABLE_PASSWORDS ();
  db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY);
  if (db_login ("DBA", NULL) != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      goto error_exit;
    }
  error = db_restart (arg->command_name, TRUE, database_name);
  if (error != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      goto error_exit;
    }

  if (HA_DISABLED ())
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_CHANGEMODE,
                         CHANGEMODE_MSG_NOT_HA_MODE));
      goto error_exit;
    }

  if (mode_name == NULL)
    {
      /* display the value of current ha_state */
      ha_state = boot_change_ha_mode (HA_SERVER_STATE_NA, false, timeout);
    }
  else
    {
      /* change server's HA state */
      ha_state = boot_change_ha_mode (ha_state, force, timeout);
    }
  if (ha_state != HA_SERVER_STATE_NA)
    {
      int keyval = (int) ha_state;
      mode_name = NULL;
      if (changemode_keyword (&keyval, &mode_name) != NO_ERROR)
    {
      fprintf (stderr, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_CHANGEMODE, CHANGEMODE_MSG_BAD_MODE),
           (mode_name ? mode_name : "unknown"));
    }
      else
    {
      fprintf (stdout,
           msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_CHANGEMODE, CHANGEMODE_MSG_SERVER_MODE),
           database_name, mode_name);
    }
      ha_state = (HA_SERVER_STATE) keyval;
    }
  else
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      goto error_exit;
    }

  (void) db_shutdown ();
  return EXIT_SUCCESS;

print_changemode_usage:
  fprintf (stderr, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_CHANGEMODE, CHANGEMODE_MSG_USAGE),
       basename (arg->argv0));
  util_log_write_errid (MSGCAT_UTIL_GENERIC_INVALID_ARGUMENT);

error_exit:
  return EXIT_FAILURE;
#else /* CS_MODE */
  PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_CHANGEMODE,
                     CHANGEMODE_MSG_NOT_IN_STANDALONE), basename (arg->argv0));
  return EXIT_FAILURE;
#endif /* !CS_MODE */
#endif /* !WINDOWS */
}

#if defined (CS_MODE) && !defined(WINDOWS)
/*
 * sigusr1_signal_handler () - wake the monitor thread on SIGUSR1
 *   return: none
 *   sig_no(in): signal number
 *
 * The actual dump uses fprintf-heavy routines, so keep the signal handler
 * async-signal-safe and delegate work to the monitor thread through a pipe.
 */
static void
sigusr1_signal_handler (int sig_no)
{
  int saved_errno = errno;
  int fd = (int) sigusr1_pipe_write_fd;

  if (sig_no == SIGUSR1 && fd != -1)
    {
      char wakeup = 1;

      (void) write (fd, &wakeup, sizeof (wakeup));
    }

  errno = saved_errno;
}

/*
 * sigusr1_dump () - dump information for copylogdb/applylogdb
 *   return: none
 *   util_index(in): utility index
 *   out(in): dump output stream
 */
static void
sigusr1_dump (int util_index, FILE * out)
{
  switch (util_index)
    {
    case COPYLOGDB:
      logwr_dump_logwr_gl (out);
      break;
    case APPLYLOGDB:
      la_dump_la_info (out);
      break;
    default:
      break;
    }
}

/*
 * Thread function that waits for SIGUSR1 requests and dumps information
 * depending on which utility (COPYLOGDB or APPLYLOGDB) is running.
 */
static void *
sigusr1_monitor_thread (void *arg)
{
  int util_index = (int) (intptr_t) arg;
  FILE *out = sigusr1_dump_outfp != NULL ? sigusr1_dump_outfp : stdout;

  while (sigusr1_running)
    {
      char buffer[64];
      ssize_t nread = read (sigusr1_pipe_fds[0], buffer, sizeof (buffer));

      if (nread > 0)
    {
      if (!sigusr1_running)
        {
          break;
        }

      sigusr1_dump (util_index, out);
      fflush (out);
    }
      else if (nread == -1)
    {
      if (errno == EINTR)
        {
          continue;
        }

      break;
    }
    }

  return NULL;
}

/*
 * sigusr1_save_stdout () - keep the original stdout as the diagnostic dump target
 *   return: none
 *
 * Note: copylogdb/applylogdb redirect stdout to /dev/null in NDEBUG builds.
 * Save the descriptor before that redirection so SIGUSR1 diagnostics still go
 * to the caller-visible stdout requested by CBRD-26062.
 */
static void
sigusr1_save_stdout (void)
{
  if (sigusr1_saved_stdout_fd == -1)
    {
      sigusr1_saved_stdout_fd = dup (STDOUT_FILENO);
    }
}

/*
 * sigusr1_close_dump_output () - close diagnostic output descriptors
 *   return: none
 */
static void
sigusr1_close_dump_output (void)
{
  if (sigusr1_dump_outfp != NULL)
    {
      fclose (sigusr1_dump_outfp);
      sigusr1_dump_outfp = NULL;
    }

  if (sigusr1_saved_stdout_fd != -1)
    {
      close (sigusr1_saved_stdout_fd);
      sigusr1_saved_stdout_fd = -1;
    }
}

/*
 * sigusr1_close_pipe () - close the monitor wakeup pipe
 *   return: none
 */
static void
sigusr1_close_pipe (void)
{
  sigusr1_pipe_write_fd = -1;

  if (sigusr1_pipe_fds[0] != -1)
    {
      close (sigusr1_pipe_fds[0]);
      sigusr1_pipe_fds[0] = -1;
    }

  if (sigusr1_pipe_fds[1] != -1)
    {
      close (sigusr1_pipe_fds[1]);
      sigusr1_pipe_fds[1] = -1;
    }
}

/*
 * sigusr1_create_pipe () - create the monitor wakeup pipe
 *   return: NO_ERROR or error code
 */
static int
sigusr1_create_pipe (void)
{
  int flags;

  if (pipe (sigusr1_pipe_fds) != 0)
    {
      er_log_debug (ARG_FILE_LINE, "failed to create SIGUSR1 monitor pipe: %d\n", errno);
      return ER_FAILED;
    }

  flags = fcntl (sigusr1_pipe_fds[1], F_GETFL, 0);
  if (flags == -1 || fcntl (sigusr1_pipe_fds[1], F_SETFL, flags | O_NONBLOCK) == -1)
    {
      er_log_debug (ARG_FILE_LINE, "failed to set SIGUSR1 monitor pipe nonblocking: %d\n", errno);
      sigusr1_close_pipe ();
      return ER_FAILED;
    }

  sigusr1_pipe_write_fd = sigusr1_pipe_fds[1];
  return NO_ERROR;
}

/*
 * sigusr1_install_signal_handler () - install the SIGUSR1 wakeup handler
 *   return: NO_ERROR or error code
 */
static int
sigusr1_install_signal_handler (void)
{
  struct sigaction action;

  sigemptyset (&action.sa_mask);
  action.sa_handler = sigusr1_signal_handler;
  action.sa_flags = SA_RESTART;

  if (sigaction (SIGUSR1, &action, &sigusr1_old_action) != 0)
    {
      er_log_debug (ARG_FILE_LINE, "failed to install SIGUSR1 handler: %d\n", errno);
      return ER_FAILED;
    }

  sigusr1_old_action_saved = true;
  return NO_ERROR;
}

/*
 * sigusr1_restore_signal_handler () - restore previous SIGUSR1 disposition
 *   return: none
 */
static void
sigusr1_restore_signal_handler (void)
{
  if (sigusr1_old_action_saved)
    {
      (void) sigaction (SIGUSR1, &sigusr1_old_action, NULL);
      sigusr1_old_action_saved = false;
    }
}

/*
 * Start the SIGUSR1 monitor thread.
 * Installs an async-signal-safe handler that wakes a joinable monitor
 * thread to print diagnostics.
 */
static void
start_sigusr1_monitor (int util_index)
{
  int error;

  if (sigusr1_started)
    {
      return;
    }

  sigusr1_save_stdout ();
  if (sigusr1_saved_stdout_fd != -1)
    {
      int dump_fd = dup (sigusr1_saved_stdout_fd);
      if (dump_fd != -1)
    {
      sigusr1_dump_outfp = fdopen (dump_fd, "a");
      if (sigusr1_dump_outfp == NULL)
        {
          close (dump_fd);
        }
      else
        {
          setvbuf (sigusr1_dump_outfp, NULL, _IOLBF, 0);
        }
    }
    }

  if (sigusr1_create_pipe () != NO_ERROR)
    {
      sigusr1_close_dump_output ();
      return;
    }

  if (sigusr1_install_signal_handler () != NO_ERROR)
    {
      sigusr1_close_pipe ();
      sigusr1_close_dump_output ();
      return;
    }

  /* Set running flag and create the monitor thread (joinable) */
  sigusr1_running = true;
  error = pthread_create (&sigusr1_tid, NULL, sigusr1_monitor_thread, (void *) (intptr_t) util_index);
  if (error != 0)
    {
      er_log_debug (ARG_FILE_LINE, "failed to create SIGUSR1 monitor thread: %d\n", error);
      sigusr1_running = false;
      sigusr1_restore_signal_handler ();
      sigusr1_close_pipe ();
      sigusr1_close_dump_output ();
      return;
    }

  sigusr1_started = true;
}

/*
 * Stop the SIGUSR1 monitor thread.
 * Clears the running flag, wakes the monitor through the pipe, and then joins
 * the thread to clean up.
 */
static void
stop_sigusr1_monitor (void)
{
  if (!sigusr1_started)
    {
      sigusr1_running = false;
      sigusr1_restore_signal_handler ();
      sigusr1_close_pipe ();
      sigusr1_close_dump_output ();
      return;
    }

  /* Clear the running flag so thread will exit on next wakeup */
  sigusr1_running = false;

  /* Wake the monitor thread from read(). */
  if (sigusr1_pipe_fds[1] != -1)
    {
      char wakeup = 1;

      (void) write (sigusr1_pipe_fds[1], &wakeup, sizeof (wakeup));
    }

  /* Wait for the monitor thread to terminate and reclaim resources */
  (void) pthread_join (sigusr1_tid, NULL);

  sigusr1_started = false;
  sigusr1_restore_signal_handler ();
  sigusr1_close_pipe ();
  sigusr1_close_dump_output ();
}
#endif /* CS_MODE && !WINDOWS */

/*
 * copylogdb() - copylogdb main routine
 *   return: EXIT_SUCCESS/EXIT_FAILURE
 */
int
copylogdb (UTIL_FUNCTION_ARG * arg)
{
#if defined (WINDOWS)
  PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_COPYLOGDB, COPYLOGDB_MSG_HA_NOT_SUPPORT),
             basename (arg->argv0));
  return EXIT_FAILURE;
#else /* WINDOWS */
#if defined (CS_MODE)
  UTIL_ARG_MAP *arg_map = arg->arg_map;
  char er_msg_file[PATH_MAX];
  const char *database_name;
  const char *log_path;
  char *mode_name;
  int mode = -1;
  int error = NO_ERROR;
  int retried = 0, sleep_nsecs = 1;
  bool need_er_reinit = false;
  unsigned long num_db_restarted = 0;
#if !defined(WINDOWS)
  char *binary_name;
  char executable_path[PATH_MAX];
#endif
  INT64 start_pageid = 0;

  if (utility_get_option_string_table_size (arg_map) != 1)
    {
      goto print_copylog_usage;
    }

  database_name = utility_get_option_string_value (arg_map, OPTION_STRING_TABLE, 0);
  if (database_name == NULL)
    {
      goto print_copylog_usage;
    }

  log_path = utility_get_option_string_value (arg_map, COPYLOG_LOG_PATH_S, 0);
  mode_name = utility_get_option_string_value (arg_map, COPYLOG_MODE_S, 0);

  if (check_database_name (database_name))
    {
      goto error_exit;
    }
  if (log_path == NULL)
    {
      goto print_copylog_usage;
    }
  /* check mode_name option argument */
  if (mode_name != NULL)
    {
      if (copylogdb_keyword (&mode, &mode_name) != NO_ERROR)
    {
      if (sscanf (mode_name, "%d", &mode) != 1)
        {
          PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_COPYLOGDB,
                             COPYLOGDB_MSG_BAD_MODE), mode_name);
          goto error_exit;
        }
    }
      if (!(mode >= LOGWR_MODE_ASYNC && mode <= LOGWR_MODE_SYNC))
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_COPYLOGDB,
                         COPYLOGDB_MSG_BAD_MODE), mode_name);
      goto error_exit;
    }
    }
  else
    {
      mode = LOGWR_MODE_SYNC;
    }

  /* 'SEMISYNC' is treated as 'SYNC'. */
  if (mode == LOGWR_MODE_SEMISYNC)
    {
      mode = LOGWR_MODE_SYNC;
    }

  start_pageid = utility_get_option_bigint_value (arg_map, COPYLOG_START_PAGEID_S);

  sigusr1_save_stdout ();

#if defined(NDEBUG)
  util_redirect_stdout_to_null ();
#endif

  /* error message log file */
  snprintf (er_msg_file, sizeof (er_msg_file) - 1, "%s_%s.err", database_name, arg->command_name);
  er_init (er_msg_file, ER_NEVER_EXIT);

#if !defined (WINDOWS)
  os_set_signal_handler (SIGABRT, crash_handler);
  os_set_signal_handler (SIGILL, crash_handler);
  os_set_signal_handler (SIGFPE, crash_handler);
  os_set_signal_handler (SIGBUS, crash_handler);
  os_set_signal_handler (SIGSEGV, crash_handler);
  os_set_signal_handler (SIGSYS, crash_handler);
#endif

  start_sigusr1_monitor (COPYLOGDB);
  AU_DISABLE_PASSWORDS ();
  db_set_client_type (DB_CLIENT_TYPE_LOG_COPIER);
  if (db_login ("DBA", NULL) != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      goto error_exit;
    }
#if !defined(WINDOWS)
  /* save executable path */
  binary_name = basename (arg->argv0);
  (void) envvar_bindir_file (executable_path, PATH_MAX, binary_name);

  hb_set_exec_path (executable_path);
  hb_set_argv (arg->argv);

  /* initialize system parameters */
  if (sysprm_load_and_init (database_name, NULL, SYSPRM_LOAD_ALL) != NO_ERROR)
    {
      error = ER_FAILED;
      goto error_exit;
    }

  /*
   * Force error log file system parameter as copylogdb;
   * during a retry loop, `db_restart` will reset the error file name as :
   * er_init (prm_get_string_value (PRM_ID_ER_LOG_FILE), ... ) 
   */
  sysprm_set_force (PRM_ID_ER_LOG_FILE, er_msg_file);

  if (start_pageid < NULL_PAGEID && !HA_DISABLED ())
    {
      error = hb_process_init (database_name, log_path, HB_PTYPE_COPYLOGDB);
      if (error != NO_ERROR)
    {
      er_log_debug (ARG_FILE_LINE, "cannot connect to cub_master for heartbeat. \n");
      if (er_errid () != NO_ERROR)
        {
          util_log_write_errstr ("%s\n", db_error_string (3));
        }

      stop_sigusr1_monitor ();
      return EXIT_FAILURE;
    }
      er_set_ignore_uninit (true);
    }
#endif

retry:
  AU_DISABLE_PASSWORDS ();
  db_set_client_type (DB_CLIENT_TYPE_LOG_COPIER);
  if (db_login ("DBA", NULL) != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      goto error_exit;
    }

  error = db_restart (arg->command_name, TRUE, database_name);
  if (error != NO_ERROR)
    {
      if (retried % 10 == 0)
    {
      fprintf (stderr, "%s\n", db_error_string (3));
    }
      goto error_exit;
    }
  num_db_restarted += 1;

  if (need_er_reinit)
    {
      er_init (er_msg_file, ER_NEVER_EXIT);
      need_er_reinit = false;
    }

  /* initialize system parameters */
  if (sysprm_load_and_init (database_name, NULL, SYSPRM_LOAD_ALL) != NO_ERROR)
    {
      (void) db_shutdown ();

      error = ER_FAILED;
      goto error_exit;
    }

  /* PRM_LOG_BACKGROUND_ARCHIVING is always true in CUBRID HA */
  sysprm_set_to_default (PRM_ID_LOG_BACKGROUND_ARCHIVING, true);

  error = logwr_copy_log_file (database_name, log_path, mode, start_pageid);
  if (error != NO_ERROR)
    {
      fprintf (stderr, "%s\n", db_error_string (3));
      (void) db_shutdown ();
      goto error_exit;
    }

  (void) db_shutdown ();
  stop_sigusr1_monitor ();
  return EXIT_SUCCESS;

print_copylog_usage:
  fprintf (stderr, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_COPYLOGDB, COPYLOGDB_MSG_USAGE),
       basename (arg->argv0));
  util_log_write_errid (MSGCAT_UTIL_GENERIC_INVALID_ARGUMENT);

  stop_sigusr1_monitor ();
  return EXIT_FAILURE;

error_exit:
#if !defined(WINDOWS)
  if (hb_Proc_shutdown)
    {
      stop_sigusr1_monitor ();
      return EXIT_SUCCESS;
    }
#endif

  if (!logwr_force_shutdown ()
      && (ER_IS_SERVER_DOWN_ERROR (error)
      || error == ERR_CSS_TCP_CANNOT_CONNECT_TO_MASTER || error == ERR_CSS_TCP_CONNECT_TIMEDOUT))
    {
      (void) sleep (sleep_nsecs);
      /* sleep 1, 2, 4, 8, etc; don't wait for more than 1/2 min */
      if (num_db_restarted > 0)
    {
      sleep_nsecs *= 2;
      if (sleep_nsecs > 30)
        {
          sleep_nsecs = 1;
        }
    }

      need_er_reinit = true;
      ++retried;

      er_init (er_msg_file, ER_NEVER_EXIT);
      goto retry;
    }

  stop_sigusr1_monitor ();
  return EXIT_FAILURE;
#else /* CS_MODE */
  PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_COPYLOGDB,
                     COPYLOGDB_MSG_NOT_IN_STANDALONE), basename (arg->argv0));
  return EXIT_FAILURE;
#endif /* !CS_MODE */
#endif /* !WINDOWS */
}

/*
 * applylogdb() - applylogdb main routine
 *   return: EXIT_SUCCESS/EXIT_FAILURE
 */
int
applylogdb (UTIL_FUNCTION_ARG * arg)
{
#if defined (WINDOWS)
  PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_APPLYLOGDB,
                     APPLYLOGDB_MSG_HA_NOT_SUPPORT), basename (arg->argv0));

  return EXIT_FAILURE;
#else /* WINDOWS */
#if defined (CS_MODE)
  UTIL_ARG_MAP *arg_map = arg->arg_map;
  char er_msg_file[PATH_MAX];
  const char *database_name = NULL;
  const char *log_path = NULL;
  char log_path_buf[PATH_MAX];
  char *log_path_base;
  int max_mem_size = 0;
  int error = NO_ERROR;
  int retried = 0, sleep_nsecs = 1;
  bool need_er_reinit = false;
  char *replica_time_bound_str;
#if !defined(WINDOWS)
  char *binary_name;
  char executable_path[PATH_MAX];
#endif

  if (utility_get_option_string_table_size (arg_map) != 1)
    {
      goto print_applylog_usage;
    }

  database_name = utility_get_option_string_value (arg_map, OPTION_STRING_TABLE, 0);
  if (database_name == NULL)
    {
      goto print_applylog_usage;
    }

  log_path = utility_get_option_string_value (arg_map, APPLYLOG_LOG_PATH_S, 0);
  max_mem_size = utility_get_option_int_value (arg_map, APPLYLOG_MAX_MEM_SIZE_S);

  if (check_database_name (database_name))
    {
      goto error_exit;
    }
  if (log_path != NULL)
    {
      log_path = realpath (log_path, log_path_buf);
    }
  if (log_path == NULL)
    {
      goto print_applylog_usage;
    }

  sigusr1_save_stdout ();

#if defined(NDEBUG)
  util_redirect_stdout_to_null ();
#endif

  /* error message log file */
  log_path_base = strdup (log_path);
  snprintf (er_msg_file, sizeof (er_msg_file) - 1, "%s_%s_%s.err", database_name, arg->command_name,
        basename (log_path_base));
  free (log_path_base);
  er_init (er_msg_file, ER_NEVER_EXIT);

#if !defined (WINDOWS)
  os_set_signal_handler (SIGABRT, crash_handler);
  os_set_signal_handler (SIGILL, crash_handler);
  os_set_signal_handler (SIGFPE, crash_handler);
  os_set_signal_handler (SIGBUS, crash_handler);
  os_set_signal_handler (SIGSEGV, crash_handler);
  os_set_signal_handler (SIGSYS, crash_handler);
#endif
  start_sigusr1_monitor (APPLYLOGDB);

  AU_DISABLE_PASSWORDS ();
  db_set_client_type (DB_CLIENT_TYPE_LOG_APPLIER);
  if (db_login ("DBA", NULL) != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      goto error_exit;
    }

#if !defined(WINDOWS)
  /* save executable path */
  binary_name = basename (arg->argv0);
  (void) envvar_bindir_file (executable_path, PATH_MAX, binary_name);

  hb_set_exec_path (executable_path);
  hb_set_argv (arg->argv);

  /* initialize system parameters */
  if (sysprm_load_and_init (database_name, NULL, SYSPRM_LOAD_ALL) != NO_ERROR)
    {
      util_log_write_errid (MSGCAT_UTIL_GENERIC_SERVICE_PROPERTY_FAIL);
      error = ER_FAILED;
      goto error_exit;
    }

  if (!HA_DISABLED ())
    {
      /* initialize heartbeat */
      error = hb_process_init (database_name, log_path, HB_PTYPE_APPLYLOGDB);
      if (error != NO_ERROR)
    {
      er_log_debug (ARG_FILE_LINE, "Cannot connect to cub_master for heartbeat. \n");
      if (er_errid () != NO_ERROR)
        {
          util_log_write_errstr ("%s\n", db_error_string (3));
        }

      stop_sigusr1_monitor ();
      return EXIT_FAILURE;
    }
      er_set_ignore_uninit (true);
    }

  if (HA_GET_MODE () == HA_MODE_REPLICA)
    {
      replica_time_bound_str = prm_get_string_value (PRM_ID_HA_REPLICA_TIME_BOUND);
      if (replica_time_bound_str != NULL)
    {
      if (util_str_to_time_since_epoch (replica_time_bound_str) == 0)
        {
          PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_GENERIC,
                             MSGCAT_UTIL_GENERIC_INVALID_PARAMETER),
                     prm_get_name (PRM_ID_HA_REPLICA_TIME_BOUND),
                     "(the correct format: YYYY-MM-DD hh:mm:ss)");

          stop_sigusr1_monitor ();
          return EXIT_FAILURE;
        }
    }
    }
#endif

retry:
  AU_DISABLE_PASSWORDS ();
  db_set_client_type (DB_CLIENT_TYPE_LOG_APPLIER);
  if (db_login ("DBA", NULL) != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      goto error_exit;
    }

  error = db_restart (arg->command_name, TRUE, database_name);
  if (error != NO_ERROR)
    {
      fprintf (stderr, "%s\n", db_error_string (3));
      goto error_exit;
    }

  /* applylogdb should not fire trigger action */
  db_disable_trigger ();

  if (need_er_reinit)
    {
      er_init (er_msg_file, ER_NEVER_EXIT);
      need_er_reinit = false;
    }

  /* set lock timeout to infinite */
  db_set_lock_timeout (-1);

  /* initialize system parameters */
  if (sysprm_load_and_init (database_name, NULL, SYSPRM_LOAD_ALL) != NO_ERROR)
    {
      (void) db_shutdown ();

      error = ER_FAILED;
      goto error_exit;
    }

  if (HA_DISABLED ())
    {
      fprintf (stderr, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_APPLYLOGDB, APPLYLOGDB_MSG_NOT_HA_MODE));
      (void) db_shutdown ();
      goto error_exit;
    }

  error = la_apply_log_file (database_name, log_path, max_mem_size);
  if (error != NO_ERROR)
    {
      fprintf (stderr, "%s\n", db_error_string (3));
      (void) db_shutdown ();
      goto error_exit;
    }

  (void) db_shutdown ();
  stop_sigusr1_monitor ();
  return EXIT_SUCCESS;

print_applylog_usage:
  fprintf (stderr, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_APPLYLOGDB, APPLYLOGDB_MSG_USAGE),
       basename (arg->argv0));
  util_log_write_errid (MSGCAT_UTIL_GENERIC_INVALID_ARGUMENT);

error_exit:
#if !defined(WINDOWS)
  if (hb_Proc_shutdown)
    {
      stop_sigusr1_monitor ();
      return EXIT_SUCCESS;
    }
#endif

  if (!la_force_shutdown ()
      && (ER_IS_SERVER_DOWN_ERROR (error)
      || error == ERR_CSS_TCP_CANNOT_CONNECT_TO_MASTER
      || error == ER_NET_SERVER_COMM_ERROR || error == ER_LC_PARTIALLY_FAILED_TO_FLUSH))
    {
      (void) sleep (sleep_nsecs);
      /* sleep 1, 2, 4, 8, etc; don't wait for more than 10 sec */
      if ((sleep_nsecs *= 2) > 10)
    {
      sleep_nsecs = 1;
    }
      need_er_reinit = true;
      ++retried;
      goto retry;
    }

  stop_sigusr1_monitor ();
  return EXIT_FAILURE;
#else /* CS_MODE */
  PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_APPLYLOGDB,
                     APPLYLOGDB_MSG_NOT_IN_STANDALONE), basename (arg->argv0));

error_exit:
  return EXIT_FAILURE;
#endif /* !CS_MODE */
#endif /* !WINDOWS */
}

/*
 * sig_interrupt() -
 *   return: none
 *   sig_no(in)
 */
static void
backupdb_sig_interrupt_handler (int sig_no)
{
  db_set_interrupt (1);
}

STATIC_INLINE char *
spacedb_get_size_str (char *buf, UINT64 num_pages, T_SPACEDB_SIZE_UNIT size_unit)
{
#define UNIT_STR(un) (((un) == SPACEDB_SIZE_UNIT_MBYTES) ? 'M' : ((un) == SPACEDB_SIZE_UNIT_GBYTES) ? 'G' : 'T')
  int pgsize, i;
  double size;

  assert (buf);

  if (size_unit == SPACEDB_SIZE_UNIT_PAGE)
    {
      sprintf (buf, "%13llu", (long long unsigned int) num_pages);
    }
  else
    {
      pgsize = IO_PAGESIZE / 1024;
      size = pgsize * ((double) num_pages);

      if (size_unit == SPACEDB_SIZE_UNIT_HUMAN_READABLE)
    {
      for (i = SPACEDB_SIZE_UNIT_MBYTES; i <= SPACEDB_SIZE_UNIT_TBYTES; i++)
        {
          size /= 1024;

          if (size < 1024)
        {
          break;
        }
        }
      sprintf (buf, "%9.1f %c", size, UNIT_STR (i));
    }
      else
    {
      for (i = size_unit; i > (int) SPACEDB_SIZE_UNIT_PAGE; i--)
        {
          size /= 1024;
        }
      sprintf (buf, "%9.1f %c", size, UNIT_STR (size_unit));
    }
    }

  return buf;
#undef UNIT_STR
}

/*
 * applyinfo() - ApplyInfo main routine
 *   return: EXIT_SUCCESS/EXIT_FAILURE
 */
int
applyinfo (UTIL_FUNCTION_ARG * arg)
{
#if defined (WINDOWS)
  PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_APPLYINFO, APPLYINFO_MSG_HA_NOT_SUPPORT),
             basename (arg->argv0));

  return EXIT_FAILURE;
#else /* WINDOWS */
#if defined (CS_MODE)
  UTIL_ARG_MAP *arg_map = arg->arg_map;
  char er_msg_file[PATH_MAX];
  const char *database_name;
  const char *master_node_name;
  char local_database_name[CUB_MAXHOSTNAMELEN];
  char master_database_name[CUB_MAXHOSTNAMELEN];
  bool check_applied_info, check_applied_info_temp, check_copied_info, check_copied_info_temp;
  bool check_master_info, check_master_info_temp, check_replica_info;
  bool verbose;
  const char *log_path;
  char log_path_buf[PATH_MAX];
  int error = NO_ERROR;
  INT64 pageid = 0;
  int interval;
  float process_rate = 0.0f;
  char *replica_time_bound_str;
  /* log lsa to calculate the estimated delay */
  LOG_LSA master_eof_lsa, applied_final_lsa;
  LOG_LSA copied_append_lsa, copied_eof_lsa;
  LOG_LSA initial_copied_append_lsa, initial_applied_final_lsa;
  time_t start_time, cur_time;

  start_time = time (NULL);

  LSA_SET_NULL (&master_eof_lsa);
  LSA_SET_NULL (&applied_final_lsa);
  LSA_SET_NULL (&copied_append_lsa);
  LSA_SET_NULL (&copied_eof_lsa);
  LSA_SET_NULL (&initial_copied_append_lsa);
  LSA_SET_NULL (&initial_applied_final_lsa);

  if (utility_get_option_string_table_size (arg_map) != 1)
    {
      goto print_applyinfo_usage;
    }

  check_applied_info_temp = check_applied_info = check_copied_info_temp = check_copied_info = false;
  check_replica_info = check_master_info_temp = check_master_info = false;

  database_name = utility_get_option_string_value (arg_map, OPTION_STRING_TABLE, 0);
  if (database_name == NULL)
    {
      goto print_applyinfo_usage;
    }

  /* initialize system parameters */
  if (sysprm_load_and_init (database_name, NULL, SYSPRM_LOAD_ALL) != NO_ERROR)
    {
      util_log_write_errid (MSGCAT_UTIL_GENERIC_SERVICE_PROPERTY_FAIL);
      return EXIT_FAILURE;
    }

  master_node_name = utility_get_option_string_value (arg_map, APPLYINFO_REMOTE_NAME_S, 0);
  if (master_node_name != NULL)
    {
      check_master_info_temp = check_master_info = true;
    }

  check_applied_info_temp = check_applied_info = utility_get_option_bool_value (arg_map, APPLYINFO_APPLIED_INFO_S);
  log_path = utility_get_option_string_value (arg_map, APPLYINFO_COPIED_LOG_PATH_S, 0);
  if (log_path != NULL)
    {
      check_copied_info_temp = check_copied_info = true;
    }

  if (!check_copied_info && !check_master_info)
    {
      goto print_applyinfo_usage;
    }

  if (!check_copied_info && check_applied_info)
    {
      goto print_applyinfo_usage;
    }

  check_replica_info = (HA_GET_MODE () == HA_MODE_REPLICA);
  pageid = utility_get_option_bigint_value (arg_map, APPLYINFO_PAGE_S);
  verbose = utility_get_option_bool_value (arg_map, APPLYINFO_VERBOSE_S);

  interval = utility_get_option_int_value (arg_map, APPLYINFO_INTERVAL_S);

  if (interval < 0)
    {
      goto print_applyinfo_usage;
    }

  if (check_replica_info)
    {
      replica_time_bound_str = prm_get_string_value (PRM_ID_HA_REPLICA_TIME_BOUND);
      if (replica_time_bound_str != NULL)
    {
      if (util_str_to_time_since_epoch (replica_time_bound_str) == 0)
        {
          PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_GENERIC,
                             MSGCAT_UTIL_GENERIC_INVALID_PARAMETER),
                     prm_get_name (PRM_ID_HA_REPLICA_TIME_BOUND),
                     "(the correct format: YYYY-MM-DD hh:mm:ss)");
          return EXIT_FAILURE;
        }
    }
    }

  /* error message log file */
  sprintf (er_msg_file, "%s_%s.err", database_name, arg->command_name);
  er_init (er_msg_file, ER_NEVER_EXIT);

  is_Sigint_caught = false;
#if defined(WINDOWS)
  SetConsoleCtrlHandler ((PHANDLER_ROUTINE) intr_handler, TRUE);
#else
  os_set_signal_handler (SIGINT, intr_handler);
#endif

  do
    {
      memset (local_database_name, 0x00, CUB_MAXHOSTNAMELEN);
      strcpy (local_database_name, database_name);
      strcat (local_database_name, "@localhost");

      if (check_applied_info_temp)
    {
      db_clear_host_connected ();

      printf ("\n *** Applied Info. *** \n");
      if (check_database_name (local_database_name))
        {
          goto check_applied_info_end;
        }

      AU_DISABLE_PASSWORDS ();
      db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY);

      error = db_login ("DBA", NULL);
      if (error != NO_ERROR)
        {
          goto check_applied_info_end;
        }

      error = db_restart (arg->command_name, TRUE, local_database_name);
      if (error != NO_ERROR)
        {
          goto check_applied_info_end;
        }

      if (HA_DISABLED ())
        {
          check_applied_info_temp = false;
          PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_APPLYINFO,
                             APPLYINFO_MSG_NOT_HA_MODE));
          goto check_applied_info_end;
        }

      error = la_get_applied_log_info (database_name, log_path, check_replica_info, verbose, &applied_final_lsa);
      if (error != NO_ERROR)
        {
          check_applied_info_temp = false;
          error = NO_ERROR;
        }
    }

    check_applied_info_end:

      if (error != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      check_applied_info_temp = false;
      error = NO_ERROR;
    }

      if (check_copied_info_temp)
    {
      error =
        la_get_copied_log_info (database_name, log_path, pageid, verbose, &copied_eof_lsa, &copied_append_lsa);
      if (error != NO_ERROR)
        {
          check_copied_info_temp = false;
          error = NO_ERROR;
        }
    }

      if (BOOT_IS_CLIENT_RESTARTED ())
    {
      (void) db_shutdown ();
    }

      if (check_master_info_temp)
    {
      printf ("\n ***  Active Info. *** \n");
      memset (master_database_name, 0x00, CUB_MAXHOSTNAMELEN);
      strcpy (master_database_name, database_name);
      strcat (master_database_name, "@");
      strcat (master_database_name, master_node_name);

      db_clear_host_connected ();

      if (check_database_name (master_database_name))
        {
          goto check_master_info_end;
        }

      AU_DISABLE_PASSWORDS ();
      db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY);

      if (db_login ("DBA", NULL) != NO_ERROR)
        {
          goto check_master_info_end;
        }

      error = db_restart (arg->command_name, TRUE, master_database_name);
      if (error != NO_ERROR)
        {
          goto check_master_info_end;
        }

      error = logwr_copy_log_header_check (master_database_name, verbose, &master_eof_lsa);
      if (error != NO_ERROR)
        {
          goto check_master_info_end;
        }

    }

    check_master_info_end:
      if (error != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      check_master_info_temp = false;
      error = NO_ERROR;
    }

      if (BOOT_IS_CLIENT_RESTARTED ())
    {
      (void) db_shutdown ();
    }

      /* print delay info */
      cur_time = time (NULL);
      if (check_copied_info_temp && check_master_info_temp)
    {
      if (!LSA_ISNULL (&initial_copied_append_lsa))
        {
          process_rate =
        (float) (copied_append_lsa.pageid - initial_copied_append_lsa.pageid) / (cur_time - start_time);
        }
      else
        {
          initial_copied_append_lsa = copied_append_lsa;
          process_rate = 0.0f;
        }

      printf ("\n *** Delay in Copying Active Log *** \n");
      la_print_delay_info (copied_append_lsa, master_eof_lsa, process_rate);
    }

      if (check_applied_info_temp)
    {
      if (!LSA_ISNULL (&initial_applied_final_lsa))
        {
          process_rate =
        (float) (applied_final_lsa.pageid - initial_applied_final_lsa.pageid) / (cur_time - start_time);
        }
      else
        {
          initial_applied_final_lsa = applied_final_lsa;
          process_rate = 0.0f;
        }

      printf ("\n *** Delay in Applying Copied Log *** \n");
      la_print_delay_info (applied_final_lsa, copied_eof_lsa, process_rate);
    }

      check_copied_info_temp = check_copied_info;
      check_applied_info_temp = check_applied_info;
      check_master_info_temp = check_master_info;

      sleep (interval);
    }
  while (interval > 0 && !is_Sigint_caught);

  return EXIT_SUCCESS;

print_applyinfo_usage:
  fprintf (stderr, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_APPLYINFO, APPLYINFO_MSG_USAGE),
       basename (arg->argv0));
  util_log_write_errid (MSGCAT_UTIL_GENERIC_INVALID_ARGUMENT);

  return EXIT_FAILURE;
#else /* CS_MODE */
  fprintf (stderr, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_APPLYINFO, APPLYINFO_MSG_NOT_IN_STANDALONE),
       basename (arg->argv0));
  return EXIT_FAILURE;
#endif /* !CS_MODE */
#endif /* !WINDOWS */
}

/*
 * intr_handler() - Interrupt handler for utility
 *   return: none
 *   sig_no(in)
 */
#if defined(WINDOWS)
static BOOL WINAPI
#else
static void
#endif
intr_handler (int sig_no)
{
  is_Sigint_caught = true;

#if defined(WINDOWS)
  if (sig_no == CTRL_C_EVENT)
    {
      return TRUE;
    }

  return FALSE;
#endif /* WINDOWS */
}

/*
 * crash_handler() - print call stack for occurring crash
 *    return: none
 *    sig_no(in)
 */
static void
crash_handler (int sig_no)
{
  if (os_set_signal_handler (sig_no, SIG_DFL) == SIG_ERR)
    {
      return;
    }

  er_print_crash_callstack (sig_no);
}

/*
 * tranlist_cmp_f() - qsort compare function used in tranlist().
 *   return:
 */
static int
tranlist_cmp_f (const void *p1, const void *p2)
{
  int ret;
  SORT_COLUMN_TYPE column_type;
  const ONE_TRAN_INFO *info1, *info2;
  const char *str_key1 = NULL, *str_key2 = NULL;
  double number_key1 = 0, number_key2 = 0;

  info1 = (ONE_TRAN_INFO *) p1;
  info2 = (ONE_TRAN_INFO *) p2;

  switch (tranlist_Sort_column)
    {
    case 0:
    case 1:
      number_key1 = info1->tran_index;
      number_key2 = info2->tran_index;
      column_type = SORT_COLUMN_TYPE_INT;
      break;
    case 2:
      str_key1 = info1->db_user;
      str_key2 = info2->db_user;
      column_type = SORT_COLUMN_TYPE_STR;
      break;
    case 3:
      str_key1 = info1->host_name;
      str_key2 = info2->host_name;
      column_type = SORT_COLUMN_TYPE_STR;
      break;
    case 4:
      number_key1 = info1->process_id;
      number_key2 = info2->process_id;
      column_type = SORT_COLUMN_TYPE_INT;
      break;
    case 5:
      str_key1 = info1->program_name;
      str_key2 = info2->program_name;
      column_type = SORT_COLUMN_TYPE_STR;
      break;
    case 6:
      number_key1 = info1->query_exec_info.query_time;
      number_key2 = info2->query_exec_info.query_time;
      column_type = SORT_COLUMN_TYPE_FLOAT;
      break;
    case 7:
      number_key1 = info1->query_exec_info.tran_time;
      number_key2 = info2->query_exec_info.tran_time;
      column_type = SORT_COLUMN_TYPE_FLOAT;
      break;
    case 8:
      str_key1 = info1->query_exec_info.wait_for_tran_index_string;
      str_key2 = info2->query_exec_info.wait_for_tran_index_string;
      column_type = SORT_COLUMN_TYPE_STR;
      break;
    case 9:
      str_key1 = info1->query_exec_info.sql_id;
      str_key2 = info2->query_exec_info.sql_id;
      column_type = SORT_COLUMN_TYPE_STR;
      break;
    case 10:
      str_key1 = info1->query_exec_info.query_stmt;
      str_key2 = info2->query_exec_info.query_stmt;
      column_type = SORT_COLUMN_TYPE_STR;
      break;
    default:
      assert (0);
      return 0;
    }

  switch (column_type)
    {
    case SORT_COLUMN_TYPE_INT:
    case SORT_COLUMN_TYPE_FLOAT:
      {
    if (number_key1 == number_key2)
      {
        ret = 0;
      }
    else if (number_key1 > number_key2)
      {
        ret = 1;
      }
    else
      {
        ret = -1;
      }
      }
      break;
    case SORT_COLUMN_TYPE_STR:
      {
    if (str_key1 == NULL && str_key2 == NULL)
      {
        ret = 0;
      }
    else if (str_key1 == NULL && str_key2 != NULL)
      {
        ret = -1;
      }
    else if (str_key1 != NULL && str_key2 == NULL)
      {
        ret = 1;
      }
    else
      {
        ret = strcmp (str_key1, str_key2);
      }
      }
      break;
    default:
      assert (0);
      ret = 0;
    }

  if (tranlist_Sort_desc == true)
    {
      ret *= (-1);
    }

  return ret;
}

/*
 * vacuumdb() - vacuumdb main routine
 *   return: EXIT_SUCCESS/EXIT_FAILURE
 */
int
vacuumdb (UTIL_FUNCTION_ARG * arg)
{
  UTIL_ARG_MAP *arg_map = arg->arg_map;
  char er_msg_file[PATH_MAX];
  const char *database_name, *output_file = NULL;
  bool dump_flag;
  FILE *outfp = NULL;

  if (utility_get_option_string_table_size (arg_map) < 1)
    {
      goto print_check_usage;
    }

  database_name = utility_get_option_string_value (arg_map, OPTION_STRING_TABLE, 0);
  if (database_name == NULL)
    {
      goto print_check_usage;
    }

  if (check_database_name (database_name))
    {
      goto error_exit;
    }

  dump_flag = utility_get_option_bool_value (arg_map, VACUUM_DUMP_S);

  if (dump_flag)
    {
      output_file = utility_get_option_string_value (arg_map, VACUUM_OUTPUT_FILE_S, 0);
      if (output_file == NULL)
    {
      outfp = stdout;
    }
      else
    {
      outfp = fopen (output_file, "w");
      if (outfp == NULL)
        {
          PRINT_AND_LOG_ERR_MSG (msgcat_message
                     (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_VACUUMDB, VACUUMDB_MSG_BAD_OUTPUT),
                     output_file);
          goto error_exit;
        }
    }
    }

#if defined(SA_MODE)
  /* error message log file */
  snprintf (er_msg_file, sizeof (er_msg_file) - 1, "%s_%s.err", database_name, arg->command_name);
  er_init (er_msg_file, ER_NEVER_EXIT);

  AU_DISABLE_PASSWORDS ();
  if (dump_flag)
    {
      db_set_client_type (DB_CLIENT_TYPE_SKIP_VACUUM_ADMIN_CSQL);
    }
  else
    {
      sysprm_set_force (PRM_ID_DISABLE_VACUUM, "no");
      db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY);
    }
  db_login ("DBA", NULL);
  if (db_restart (arg->command_name, TRUE, database_name) == NO_ERROR)
    {
      (void) db_set_isolation (TRAN_READ_COMMITTED);

      if (dump_flag)
    {
      vacuum_dump (outfp);

      if (outfp != stdout)
        {
          fclose (outfp);
        }
    }
      else
    {
      if (cvacuum () != NO_ERROR)
        {
          const char *tmpname;

          if ((tmpname = er_get_msglog_filename ()) == NULL)
        {
          tmpname = "/dev/null";
        }
          PRINT_AND_LOG_ERR_MSG (msgcat_message
                     (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_VACUUMDB, VACUUMDB_MSG_FAILED), tmpname);

          util_log_write_errstr ("%s\n", db_error_string (3));
          db_shutdown ();
          goto error_exit;
        }
    }
      db_shutdown ();
    }
  else
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      goto error_exit;
    }

  return EXIT_SUCCESS;
#else
  if (dump_flag)
    {
      /* error message log file */
      snprintf (er_msg_file, sizeof (er_msg_file) - 1, "%s_%s.err", database_name, arg->command_name);
      er_init (er_msg_file, ER_NEVER_EXIT);

      AU_DISABLE_PASSWORDS ();
      db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY);
      db_login ("DBA", NULL);

      if (db_restart (arg->command_name, TRUE, database_name) != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      goto error_exit;
    }

      (void) db_set_isolation (TRAN_READ_COMMITTED);

      vacuum_dump (outfp);
      db_shutdown ();

      if (outfp != stdout)
    {
      fclose (outfp);
    }
    }
  else
    {
      fprintf (stderr,
           msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_VACUUMDB,
                   VACUUMDB_MSG_CLIENT_SERVER_NOT_AVAILABLE), basename (arg->argv0));
      util_log_write_errid (MSGCAT_UTIL_GENERIC_INVALID_ARGUMENT);
    }

  return EXIT_SUCCESS;
#endif
print_check_usage:
  fprintf (stderr, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_VACUUMDB, VACUUMDB_MSG_USAGE),
       basename (arg->argv0));
  util_log_write_errid (MSGCAT_UTIL_GENERIC_INVALID_ARGUMENT);

error_exit:

  return EXIT_FAILURE;
}

/*
 * tde() - tde main routine
 *   return: EXIT_SUCCESS/EXIT_FAILURE
 */
int
tde (UTIL_FUNCTION_ARG * arg)
{
  UTIL_ARG_MAP *arg_map = arg->arg_map;
  char er_msg_file[PATH_MAX];
  char mk_path[PATH_MAX] = { 0, };
  const char *database_name;
  const char *dba_password;
  char *passbuf;
  int error = NO_ERROR;
  int vdes = NULL_VOLDES;
  bool gen_op;
  bool show_op;
  bool print_val;
  int change_op_idx;
  int delete_op_idx;
  int op_cnt = 0;

  if (utility_get_option_string_table_size (arg_map) != 1)
    {
      goto print_tde_usage;
    }

  database_name = utility_get_option_string_value (arg_map, OPTION_STRING_TABLE, 0);
  if (database_name == NULL)
    {
      goto print_tde_usage;
    }

  gen_op = utility_get_option_bool_value (arg_map, TDE_GENERATE_KEY_S);
  show_op = utility_get_option_bool_value (arg_map, TDE_SHOW_KEYS_S);
  change_op_idx = utility_get_option_int_value (arg_map, TDE_CHANGE_KEY_S);
  delete_op_idx = utility_get_option_int_value (arg_map, TDE_DELETE_KEY_S);

  print_val = utility_get_option_bool_value (arg_map, TDE_PRINT_KEY_VALUE_S);
  dba_password = utility_get_option_string_value (arg_map, TDE_DBA_PASSWORD_S, 0);

  if (gen_op)
    {
      op_cnt++;
    }
  if (show_op)
    {
      op_cnt++;
    }
  if (change_op_idx != -1)
    {
      op_cnt++;
    }
  if (delete_op_idx != -1)
    {
      op_cnt++;
    }

  if (op_cnt != 1)
    {
      /* Only one and at least one operation has to be given */
      /* -c -1 -d -1 -n is now allowed, but it's trivial */
      goto print_tde_usage;
    }

  /* Checking input range, -1 means not the operation case */
  if (change_op_idx < -1)
    {
      goto print_tde_usage;
    }
  if (delete_op_idx < -1)
    {
      goto print_tde_usage;
    }

  /* extra validation */
  if (check_database_name (database_name))
    {
      goto error_exit;
    }

  /* error message log file */
  snprintf (er_msg_file, sizeof (er_msg_file) - 1, "%s_%s.err", database_name, arg->command_name);
  er_init (er_msg_file, ER_NEVER_EXIT);

  db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY);
  if (db_login ("DBA", dba_password) != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      goto error_exit;
    }

  /* first try to restart with the password given (possibly none) */
  error = db_restart (arg->command_name, TRUE, database_name);
  if (error)
    {
      if (error == ER_AU_INVALID_PASSWORD && (dba_password == NULL || strlen (dba_password) == 0))
    {
      /*
       * prompt for a valid password and try again, need a reusable
       * password prompter so we can use getpass() on platforms that
       * support it.
       */

      /* get password interactively if interactive mode */
      passbuf = getpass (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_TDE, TDE_MSG_DBA_PASSWORD));
      if (passbuf[0] == '\0')   /* to fit into db_login protocol */
        {
          passbuf = (char *) NULL;
        }
      dba_password = passbuf;
      if (db_login ("DBA", dba_password) != NO_ERROR)
        {
          PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
          goto error_exit;
        }
      else
        {
          error = db_restart (arg->command_name, TRUE, database_name);
        }
    }

      if (error)
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      goto error_exit;
    }
    }

  if (tde_get_mk_file_path (mk_path) != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      db_shutdown ();
      goto error_exit;
    }

  printf ("Key File: %s\n", mk_path);

  /* 
   * The file lock here is necessary to provide exclusiveness with backupdb in the current design.
   */
  vdes = fileio_mount (NULL, database_name, mk_path, LOG_DBTDE_KEYS_VOLID, 1, false);
  if (vdes == NULL_VOLDES)
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      db_shutdown ();
      goto error_exit;
    }
  /* 
   * There is no need to call fileio_dismount() for 'vdes' later in this function
   * because it is dismounted in db_shutdown() 
   * */

  printf ("\n");
  if (gen_op)
    {
      unsigned char master_key[TDE_MASTER_KEY_LENGTH];
      int mk_index = -1;
      time_t created_time;
      char ctime_buf[CTIME_MAX];

      if (tde_create_mk (master_key, &created_time) != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("FAILURE: %s\n", db_error_string (3));
      db_shutdown ();
      goto error_exit;
    }
      if (tde_add_mk (vdes, master_key, created_time, &mk_index) != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("FAILURE: %s\n", db_error_string (3));
      db_shutdown ();
      goto error_exit;
    }
      ctime_r (&created_time, ctime_buf);
      printf ("SUCCESS: ");
      printf (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_TDE, TDE_MSG_MK_GENERATED), mk_index, ctime_buf);
      if (print_val)
    {
      printf ("Key: ");
      tde_print_mk (master_key);
      printf ("\n");
    }
    }
  else if (show_op)
    {
      int mk_index;
      time_t created_time, set_time;
      char ctime_buf1[CTIME_MAX];
      char ctime_buf2[CTIME_MAX];

      printf ("The current key set on %s:\n", database_name);
      if (tde_get_mk_info (&mk_index, &created_time, &set_time) == NO_ERROR)
    {
      ctime_r (&created_time, ctime_buf1);
      ctime_r (&set_time, ctime_buf2);

      printf ("Key Index: %d\n", mk_index);
      printf ("Created on %s", ctime_buf1);
      printf ("Set     on %s", ctime_buf2);
    }
      else
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_TDE, TDE_MSG_NO_SET_MK_INFO));
    }
      printf ("\n");
      if (tde_dump_mks (vdes, print_val) != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      db_shutdown ();
      goto error_exit;
    }
    }
  else if (change_op_idx != -1)
    {
      int prev_mk_idx;
      time_t created_time, set_time;

      if (tde_get_mk_info (&prev_mk_idx, &created_time, &set_time) != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("FAILURE: %s\n", db_error_string (3));
      db_shutdown ();
      goto error_exit;
    }

      printf (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_TDE, TDE_MSG_MK_CHANGING), prev_mk_idx,
          change_op_idx);
      /* no need to check if the previous key exists or not. It is going to be checked on changing on server */
      if (tde_change_mk_on_server (change_op_idx) != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("FAILURE: %s\n", db_error_string (3));
      db_shutdown ();
      goto error_exit;
    }

      if (db_commit_transaction () != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("FAILURE: %s\n", db_error_string (3));
      db_shutdown ();
      goto error_exit;
    }

      printf ("SUCCESS: ");
      printf (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_TDE, TDE_MSG_MK_CHANGED), prev_mk_idx,
          change_op_idx);
    }
  else if (delete_op_idx != -1)
    {
      int mk_index;
      time_t created_time, set_time;

      if (tde_get_mk_info (&mk_index, &created_time, &set_time) != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("FAILURE: %s\n", db_error_string (3));
      db_shutdown ();
      goto error_exit;
    }
      if (mk_index == delete_op_idx)
    {
      PRINT_AND_LOG_ERR_MSG ("FAILURE: %s",
                 msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_TDE,
                         TDE_MSG_MK_SET_ON_DATABASE_DELETE));
      db_shutdown ();
      goto error_exit;
    }
      if (tde_delete_mk (vdes, delete_op_idx) != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("FAILURE: %s\n", db_error_string (3));
      db_shutdown ();
      goto error_exit;
    }
      printf ("SUCCESS: ");
      printf (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_TDE, TDE_MSG_MK_DELETED), delete_op_idx);
    }

  db_shutdown ();

  return EXIT_SUCCESS;

print_tde_usage:
  fprintf (stderr, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_TDE, TDE_MSG_USAGE), basename (arg->argv0));
  util_log_write_errid (MSGCAT_UTIL_GENERIC_INVALID_ARGUMENT);
error_exit:
  return EXIT_FAILURE;
}

static void
clean_stdin ()
{
  int c;

  /* consumes all the values in the input buffer */
  do
    {
      c = getchar ();
    }
  while (c != '\n' && c != EOF);
}

static time_t
parse_date_string_to_time (char *date_string)
{
  assert (date_string != NULL);

  time_t result = 0;
  struct tm time_data = { };

  if (sscanf
      (date_string, "%d-%d-%d:%d:%d:%d", &time_data.tm_mday, &time_data.tm_mon, &time_data.tm_year, &time_data.tm_hour,
       &time_data.tm_min, &time_data.tm_sec) != 6)
    {
      return 0;
    }

  if (time_data.tm_mday < 1 || time_data.tm_mday > 31
      || time_data.tm_mon < 1 || time_data.tm_mon > 12
      || time_data.tm_year < 1900
      || time_data.tm_hour < 0 || time_data.tm_hour > 23
      || time_data.tm_min < 0 || time_data.tm_min > 59 || time_data.tm_sec < 0 || time_data.tm_sec > 59)
    {
      return 0;
    }

  time_data.tm_mon -= 1;
  time_data.tm_year -= 1900;
  time_data.tm_isdst = -1;

  result = mktime (&time_data);

  return result < 0 ? 0 : result;
}

int
flashback (UTIL_FUNCTION_ARG * arg)
{
#if defined (CS_MODE)
  UTIL_ARG_MAP *arg_map = arg->arg_map;
  char er_msg_file[PATH_MAX];

  const char *database_name = NULL;
  int num_tables = 0;
  dynamic_array *darray = NULL;
  int i = 0;
  char table_name_buf[SM_MAX_IDENTIFIER_LENGTH];
  char *table_name = NULL;

  char *invalid_class = NULL;
  int invalid_class_idx = 0;

  time_t invalid_time = 0;

  OID *oid_list = NULL;

  const char *output_file = NULL;
  FILE *outfp = NULL;
  char *user = NULL;
  const char *dba_password = NULL;

  char *start_date = NULL;
  char *end_date = NULL;
  time_t start_time = 0;
  time_t end_time = 0;

  bool is_detail = false;
  bool is_oldest = false;

  char *passbuf = NULL;
  int error = NO_ERROR;

  int trid = 0;

  int num_item = 5;
  char *loginfo_list = NULL;

  FLASHBACK_SUMMARY_INFO_MAP summary_info;
  FLASHBACK_SUMMARY_INFO *summary_entry = NULL;

  bool need_shutdown = false;

  LOG_LSA start_lsa = LSA_INITIALIZER;
  LOG_LSA end_lsa = LSA_INITIALIZER;

  int timeout = 0;

  time_t current_time = time (NULL);

  num_tables = utility_get_option_string_table_size (arg_map) - 1;
  if (num_tables < 1)
    {
      goto print_flashback_usage;
    }

  database_name = utility_get_option_string_value (arg_map, OPTION_STRING_TABLE, 0);
  if (database_name == NULL)
    {
      goto print_flashback_usage;
    }

  if (check_database_name (database_name))
    {
      goto error_exit;
    }

  output_file = utility_get_option_string_value (arg_map, FLASHBACK_OUTPUT_S, 0);
  user = utility_get_option_string_value (arg_map, FLASHBACK_USER_S, 0);
  dba_password = utility_get_option_string_value (arg_map, FLASHBACK_DBA_PASSWORD_S, 0);
  start_date = utility_get_option_string_value (arg_map, FLASHBACK_START_DATE_S, 0);
  end_date = utility_get_option_string_value (arg_map, FLASHBACK_END_DATE_S, 0);
  is_detail = utility_get_option_bool_value (arg_map, FLASHBACK_DETAIL_S);
  is_oldest = utility_get_option_bool_value (arg_map, FLASHBACK_OLDEST_S);

  /* create table list */
  /* class existence and classoid will be found at server side. if is checked at utility side, it needs addtional access to the server through locator */
  darray = da_create (num_tables, SM_MAX_IDENTIFIER_LENGTH);
  if (darray == NULL)
    {
      util_log_write_errid (MSGCAT_UTIL_GENERIC_NO_MEM);
      goto error_exit;
    }

  /* start date check */
  if (start_date != NULL && strlen (start_date) > 0)
    {
      start_time = parse_date_string_to_time (start_date);
      if (start_time == 0)
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message
                 (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_FLASHBACK, FLASHBACK_MSG_INVALID_DATE_FORMAT));
      goto error_exit;
    }
    }

  /* end date check */
  if (end_date != NULL && strlen (end_date) > 0)
    {
      end_time = parse_date_string_to_time (end_date);
      if (end_time == 0)
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message
                 (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_FLASHBACK, FLASHBACK_MSG_INVALID_DATE_FORMAT));
      goto error_exit;
    }
    }

  /* start time and end time setting.
   * 1. 10 minutes before end time, if only end time is specified
   * 2. 10 minutes after start time, if only start time is specified
   * 3. if no time is specified, then get current execution time for end time */

  if (start_time == 0 && end_time != 0)
    {
      start_time = end_time - 600;
    }
  else if (start_time != 0 && end_time == 0)
    {
      end_time = start_time + 600;
    }
  else if (start_time == 0 && end_time == 0)
    {
      end_time = time (NULL);
      start_time = end_time - 600;
    }

  /* 1. start time < end time
   * 2. start time is required to be set after db_creation time (server side check)
   * 3. start time, and end time are required to be set within the log volume range (server side check) */
  if (start_time >= end_time)
    {
      char sdate_buf[20];
      char edate_buf[20];

      if (start_date == NULL)
    {
      strftime (sdate_buf, 20, "%d-%m-%Y:%H:%M:%S", localtime (&start_time));
      start_date = sdate_buf;
    }

      if (end_date == NULL)
    {
      strftime (edate_buf, 20, "%d-%m-%Y:%H:%M:%S", localtime (&end_time));
      end_date = edate_buf;
    }

      PRINT_AND_LOG_ERR_MSG (msgcat_message
                 (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_FLASHBACK, FLASHBACK_MSG_INVALID_DATE_RANGE),
                 start_date, end_date);
      goto error_exit;
    }

  /* output file check */
  if (output_file == NULL)
    {
      outfp = stdout;
    }
  else
    {
      outfp = fopen (output_file, "w");
      if (outfp == NULL)
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message
                 (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_FLASHBACK, FLASHBACK_MSG_BAD_OUTPUT),
                 output_file);

      goto error_exit;
    }
    }

  /* error message log file */
  snprintf (er_msg_file, sizeof (er_msg_file) - 1, "%s_%s.err", database_name, arg->command_name);
  er_init (er_msg_file, ER_NEVER_EXIT);

  db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY);
  if (db_login ("DBA", dba_password) != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      goto error_exit;
    }

  /* first try to restart with the password given (possibly none) */
  error = db_restart (arg->command_name, TRUE, database_name);
  if (error)
    {
      if (error == ER_AU_INVALID_PASSWORD && (dba_password == NULL || strlen (dba_password) == 0))
    {
      /*
       * prompt for a valid password and try again, need a reusable
       * password prompter so we can use getpass() on platforms that
       * support it.
       */

      /* get password interactively if interactive mode */
      passbuf =
        getpass (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_FLASHBACK, FLASHBACK_MSG_DBA_PASSWORD));
      if (passbuf[0] == '\0')   /* to fit into db_login protocol */
        {
          passbuf = (char *) NULL;
        }
      dba_password = passbuf;
      if (db_login ("DBA", dba_password) != NO_ERROR)
        {
          PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
          goto error_exit;
        }
      else
        {
          error = db_restart (arg->command_name, TRUE, database_name);
        }
    }

      if (error)
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      goto error_exit;
    }
    }

  need_shutdown = true;

  if (!prm_get_integer_value (PRM_ID_SUPPLEMENTAL_LOG))
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message
                 (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_FLASHBACK, FLASHBACK_MSG_NO_SUPPLEMENTAL_LOG));
      goto error_exit;
    }

  for (i = 0; i < num_tables; i++)
    {
      table_name = utility_get_option_string_value (arg_map, OPTION_STRING_TABLE, i + 1);

      if (sm_check_system_class_by_name (table_name))
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message
                 (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_FLASHBACK,
                  FLASHBACK_MSG_SYSTEM_CLASS_NOT_SUPPORTED), table_name);

      goto error_exit;
    }

      if (utility_check_class_name (table_name) != NO_ERROR)
    {
      goto error_exit;
    }

      strncpy_bufsize (table_name_buf, table_name);

      if (da_add (darray, table_name_buf) != NO_ERROR)
    {
      util_log_write_errid (MSGCAT_UTIL_GENERIC_NO_MEM);
      goto error_exit;
    }
    }

  oid_list = (OID *) malloc (sizeof (OID) * num_tables);
  if (oid_list == NULL)
    {
      util_log_write_errid (MSGCAT_UTIL_GENERIC_NO_MEM);
      goto error_exit;
    }

  error =
    flashback_get_and_show_summary (darray, user, start_time, end_time, &summary_info, &oid_list, &invalid_class,
                    &invalid_time);
  if (error != NO_ERROR)
    {
      /* print error message */
      switch (error)
    {
    case ER_FLASHBACK_INVALID_TIME:
      {
        char db_creation_time[20];
        char current_time_buf[20];

        strftime (db_creation_time, 20, "%d-%m-%Y:%H:%M:%S", localtime (&invalid_time));
        strftime (current_time_buf, 20, "%d-%m-%Y:%H:%M:%S", localtime (&current_time));

        PRINT_AND_LOG_ERR_MSG (msgcat_message
                   (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_FLASHBACK, FLASHBACK_MSG_INVALID_TIME),
                   current_time_buf, db_creation_time);
        break;
      }
    case ER_FLASHBACK_INVALID_CLASS:
      PRINT_AND_LOG_ERR_MSG (msgcat_message
                 (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_FLASHBACK, FLASHBACK_MSG_TABLE_NOT_EXIST),
                 invalid_class);
      free_and_init (invalid_class);

      break;
    case ER_FLASHBACK_EXCEED_MAX_NUM_TRAN_TO_SUMMARY:
      PRINT_AND_LOG_ERR_MSG (msgcat_message
                 (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_FLASHBACK, FLASHBACK_MSG_TOO_MANY_TRANSACTION));
      break;
    case ER_FLASHBACK_DUPLICATED_REQUEST:
      PRINT_AND_LOG_ERR_MSG (msgcat_message
                 (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_FLASHBACK, FLASHBACK_MSG_DUPLICATED_REQUEST));

    default:
      break;
    }

      goto error_exit;
    }

  if (summary_info.empty ())
    {
      goto error_exit;
    }

  timeout = prm_get_integer_value (PRM_ID_FLASHBACK_TIMEOUT);

  while (summary_entry == NULL)
    {
      POLL_FD input_fd = { STDIN_FILENO, POLLIN | POLLPRI, 0 };

      printf ("Enter transaction id (press -1 to quit): ");
      fflush (stdout);

      if (poll (&input_fd, 1, timeout * 1000))
    {
      if (scanf ("%d", &trid) != 1)
        {
          /* When non integer value is input, the input buffer must be flushed. */
          clean_stdin ();

          continue;
        }
    }
      else
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message
                 (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_FLASHBACK, FLASHBACK_MSG_TIMEOUT), timeout);

      goto error_exit;
    }

      if (trid == -1)
    {
      goto error_exit;
    }

      FLASHBACK_FIND_SUMMARY_ENTRY (trid, summary_info, summary_entry);
      if (summary_entry == NULL)
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message
                 (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_FLASHBACK, FLASHBACK_MSG_INVALID_TRANSACTION),
                 trid);
    }

      printf ("\n");
    }

  start_lsa = summary_entry->start_lsa;
  end_lsa = summary_entry->end_lsa;
  user = summary_entry->user;

  do
    {
      error =
    flashback_get_loginfo (trid, user, oid_list, num_tables, &start_lsa, &end_lsa, &num_item, is_oldest,
                   &loginfo_list, &invalid_class_idx);
      if (error != NO_ERROR)
    {
      switch (error)
        {
        case ER_FLASHBACK_SCHEMA_CHANGED:
          {
        char classname[SM_MAX_IDENTIFIER_LENGTH];
        da_get (darray, invalid_class_idx, classname);

        PRINT_AND_LOG_ERR_MSG (msgcat_message
                       (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_FLASHBACK,
                    FLASHBACK_MSG_TABLE_SCHEMA_CHANGED), classname);
        break;
          }
        case ER_FLASHBACK_LOG_NOT_EXIST:
          PRINT_AND_LOG_ERR_MSG (msgcat_message
                     (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_FLASHBACK,
                      FLASHBACK_MSG_LOG_VOLUME_NOT_EXIST));
          break;
        default:
          break;
        }

      goto error_exit;
    }

      error = flashback_print_loginfo (loginfo_list, num_item, darray, oid_list, is_detail, outfp);
      if (error != NO_ERROR)
    {
      goto error_exit;
    }

    }
  while (!LSA_ISNULL (&start_lsa) && !LSA_ISNULL (&end_lsa) && LSA_LT (&start_lsa, &end_lsa));

  db_shutdown ();

  da_destroy (darray);

  free_and_init (oid_list);

  if (loginfo_list != NULL)
    {
      free_and_init (loginfo_list);
    }

  return EXIT_SUCCESS;

print_flashback_usage:
  fprintf (stderr, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_FLASHBACK, FLASHBACK_MSG_USAGE),
       basename (arg->argv0));
  util_log_write_errid (MSGCAT_UTIL_GENERIC_INVALID_ARGUMENT);
error_exit:

  if (need_shutdown)
    {
      db_shutdown ();
    }

  if (darray != NULL)
    {
      da_destroy (darray);
    }

  if (oid_list != NULL)
    {
      free_and_init (oid_list);
    }

  if (loginfo_list != NULL)
    {
      free_and_init (loginfo_list);
    }

  return EXIT_FAILURE;

#else /* CS_MODE */
  fprintf (stderr, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_FLASHBACK, FLASHBACK_MSG_NOT_IN_STANDALONE),
       basename (arg->argv0));
  return EXIT_FAILURE;
#endif /* !CS_MODE */

}

int
memmon (UTIL_FUNCTION_ARG * arg)
{
#if defined(CS_MODE)
  UTIL_ARG_MAP *arg_map = arg->arg_map;
  char er_msg_file[PATH_MAX];
  const char *database_name;
  bool need_shutdown = false;
  const char *outfile_name;
  bool disable_force = false;
  FILE *outfile_fp = NULL;
  int error_code = NO_ERROR;
  MMON_SERVER_INFO server_info;

  outfile_name = utility_get_option_string_value (arg_map, MEMMON_OUTPUT_S, 0);
  disable_force = utility_get_option_bool_value (arg_map, MEMMON_DISABLE_FORCE_S);

  database_name = utility_get_option_string_value (arg_map, OPTION_STRING_TABLE, 0);
  if (database_name == NULL)
    {
      goto print_memmon_usage;
    }

  if (check_database_name (database_name))
    {
      goto error_exit;
    }

  if (outfile_name && disable_force)
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message
                 (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_MEMMON,
                  MEMMON_MSG_CANNOT_USE_DISABLE_FORCE_WITH_OTHER_OPTION));
      goto error_exit;
    }

  if (outfile_name)
    {
      outfile_fp = fopen (outfile_name, "w+");
      if (outfile_fp == NULL)
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message
                 (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_MEMMON, MEMMON_MSG_CANNOT_OPEN_OUTPUT_FILE),
                 outfile_name);
      goto error_exit;
    }
    }
  else
    {
      outfile_fp = stdout;
    }

  /* error message log file */
  snprintf (er_msg_file, sizeof (er_msg_file) - 1, "%s_%s.err", database_name, arg->command_name);
  er_init (er_msg_file, ER_NEVER_EXIT);

  AU_DISABLE_PASSWORDS ();  /* disable authorization for this operation */
  db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY);
  db_login ("DBA", NULL);

  if (db_restart (arg->command_name, TRUE, database_name))
    {
      PRINT_AND_LOG_ERR_MSG ("%s: %s. \n\n", arg->command_name, db_error_string (3));
      goto error_exit;
    }
  need_shutdown = true;

  if (!prm_get_bool_value (PRM_ID_ENABLE_MEMORY_MONITORING))
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_MEMMON, MEMMON_MSG_NOT_SUPPORTED));
      goto error_exit;
    }

  if (disable_force)
    {
      error_code = mmon_disable_force ();
      if (error_code != NO_ERROR)
    {
      switch (error_code)
        {
        case ER_INTERFACE_NOT_SUPPORTED_OPERATION:
          PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_MEMMON,
                             MEMMON_MSG_NOT_SUPPORTED_OS));
          break;
        default:
          break;
        }
      goto error_exit;
    }
      fprintf (stdout, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_MEMMON, MEMMON_MSG_DISABLE_SUCCESS));
      goto success_exit;
    }

  /* execute phase */
  error_code = mmon_get_server_info (server_info);
  if (error_code != NO_ERROR)
    {
      switch (error_code)
    {
    case ER_FAILED:
      PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_MEMMON,
                         MEMMON_MSG_MEMORY_MONITOR_IS_DISABLED));
      break;
    case ER_INTERFACE_NOT_SUPPORTED_OPERATION:
      PRINT_AND_LOG_ERR_MSG (msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_MEMMON,
                         MEMMON_MSG_NOT_SUPPORTED_OS));
      break;
    default:
      break;
    }
      goto error_exit;
    }

  mmon_print_server_info (server_info, outfile_fp);

success_exit:
  fclose (outfile_fp);

  db_shutdown ();

  return EXIT_SUCCESS;

print_memmon_usage:
  fprintf (stderr, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_MEMMON, MEMMON_MSG_USAGE),
       basename (arg->argv0));
  util_log_write_errid (MSGCAT_UTIL_GENERIC_INVALID_ARGUMENT);

error_exit:
  if (need_shutdown)
    {
      db_shutdown ();
    }

  if (outfile_fp)
    {
      fclose (outfile_fp);
    }

  return EXIT_FAILURE;
#else /* CS_MODE */
  fprintf (stderr, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_MEMMON, MEMMON_MSG_NOT_IN_STANDALONE),
       basename (arg->argv0));
  return EXIT_FAILURE;
#endif /* !CS_MODE */
}

/*
 * cleanfiledb() - cleanfiledb main routine
 *   return: EXIT_SUCCESS/EXIT_FAILURE
 */
int
cleanfiledb (UTIL_FUNCTION_ARG * arg)
{
  UTIL_ARG_MAP *arg_map = arg->arg_map;
  char er_msg_file[PATH_MAX];
  const char *db_name;
#if !defined(NDEBUG)
  const char *target_vfid_str = NULL;
#endif
  const char *output_file = NULL;
  FILE *outfp = NULL;
  bool is_dump_file_list;
  bool is_clean_invalid_file;

  db_name = utility_get_option_string_value (arg_map, OPTION_STRING_TABLE, 0);
  if (db_name == NULL)
    {
      goto print_cleanfiledb_usage;
    }

  output_file = utility_get_option_string_value (arg_map, CLEANFILEDB_OUTPUT_FILE_S, 0);
  if (output_file == NULL)
    {
      outfp = stdout;
    }
  else
    {
      outfp = fopen (output_file, "w");
      if (outfp == NULL)
    {
      PRINT_AND_LOG_ERR_MSG (msgcat_message
                 (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_CLEANFILEDB, CLEANFILEDB_MSG_BAD_OUTPUT),
                 output_file);
      goto error_exit;
    }
    }

  is_dump_file_list = utility_get_option_bool_value (arg_map, CLEANFILEDB_DUMP_FILE_LIST_S);
  is_clean_invalid_file = utility_get_option_bool_value (arg_map, CLEANFILEDB_CLEAN_INVALID_FILE_S);
#if !defined(NDEBUG)
  /*
   * INFO: Hidden option for debugging.
   * Usage: -t, --clean-target-file=VFID
   * Format: "fileid|volid" (e.g., "123|1")
   */
  target_vfid_str = utility_get_option_string_value (arg_map, CLEANFILEDB_DELETE_TARGET_FILE_S, 0);
#endif

  if (check_database_name (db_name))
    {
      goto error_exit;
    }

  /* error message log file */
  snprintf (er_msg_file, sizeof (er_msg_file) - 1, "%s_%s.err", db_name, arg->command_name);
  er_init (er_msg_file, ER_NEVER_EXIT);

  AU_DISABLE_PASSWORDS ();

  db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY);

  db_login ("DBA", NULL);

  if (db_restart (arg->command_name, TRUE, db_name) != NO_ERROR)
    {
      PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
      goto error_exit;
    }

  // Execute with default settings (no command-line options provided)
  if (!is_dump_file_list && !is_clean_invalid_file
#if !defined(NDEBUG)
      && target_vfid_str == NULL
#endif
    )
    {
      (void) file_dump_file_list (outfp, true);

      fflush (outfp);
    }
  else
    {
      if (is_dump_file_list)
    {
      (void) file_dump_file_list (outfp, false);

      fflush (outfp);
    }

      if (is_clean_invalid_file)
    {
      int heap = 0, heap_ovf = 0, btree = 0, btree_ovf = 0;
      int total;

      if (file_clean_invalid_file (&heap, &heap_ovf, &btree, &btree_ovf) != NO_ERROR)
        {
          PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
          db_shutdown ();
          goto error_exit;
        }

      total = heap + heap_ovf + btree + btree_ovf;

      fprintf (outfp,
           msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_CLEANFILEDB, CLEANFILEDB_MSG_CLEAN_SUMMARY),
           db_name, heap, heap_ovf, btree, btree_ovf, total);

      fflush (outfp);
    }
#if !defined(NDEBUG)
      else if (target_vfid_str != NULL)
    {
      (void) file_delete_target_file (target_vfid_str);
    }
#endif
    }

  db_shutdown ();

  if (output_file != NULL && outfp != NULL && outfp != stdout)
    {
      fclose (outfp);
    }

  return EXIT_SUCCESS;

print_cleanfiledb_usage:
  fprintf (stderr, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_CLEANFILEDB, CLEANFILEDB_MSG_USAGE),
       basename (arg->argv0));
  util_log_write_errid (MSGCAT_UTIL_GENERIC_INVALID_ARGUMENT);

error_exit:
  if (output_file != NULL && outfp != NULL && outfp != stdout)
    {
      fclose (outfp);
    }

  return EXIT_FAILURE;
}