콘텐츠로 이동

(KO) CUBRID cub_master 프로세스 — 데몬 lifecycle, 연결 레지스트리, 요청 디스패치, 자동 재시작 server monitor

서비스-레지스트리 데몬 은 host 별 “여기서 어떤 데이터베이스 서버가 어떤 포트로 어떤 인자로 돌고 있는가” 의 맵을 소유하는 long-lived 프로세스이다. 다중 서버 엔진은 모두 하나씩 필요로 한다 — 클라이언트가 미리 per-server 포트를 알지 않은 채로 데이터 베이스 mydb 의 위치를 무언가에게 물어야 한다는 점이다. 디자인 선택이 두 축으로 나뉜다:

  1. Host 별 vs cluster 별. Host 별 (PostgreSQL 의 postmaster 는 cluster 별이지만 실제로는 host 별; MySQL 은 systemd 에 의존; Oracle 은 cluster 단위로 CRS 와 host 별로 lsnrctl)이 레지 스트리를 추적하는 프로세스와 같은 host 에 둔다. Cluster 별 (새 엔진의 etcd-backed 레지스트리)은 host 실패에 살아남지만 네트워크 의존성을 더한다는 뜻이다. CUBRID 는 host 별을 고른다 — 모든 CUBRID 설치가 host 별로 한 cub_master 를 돌리고, 클라 이언트가 잘 알려진 포트로 연결해서 실제 cub_server 포트를 발견한다.

  2. 프로세스 supervision 범위. 단순한 레지스트리는 X 가 어디? 에만 답하고 외부 supervisor (systemd, monit, runit)가 재시작을 처리하게 한다. Supervising 레지스트리는 PID 도 추적하고 비정상 exit 에 re-fork 한다는 점이다. CUBRID 의 master 는 기본은 단순 레지스트리지만 auto_restart_server 옵트인 모드를 가진다 — server_monitor C++ 서브시스템을 활성화한다. cub_master 에 임베드된 작은 프로세스 supervisor 로, 커널이 자식을 예기치 않게 reap 하면 기록된 argv 에서 cub_server 를 re-exec 한다.

cub_master 바이너리는 따라서 한 진입점에 묶인 세 가지이다 — (a) commdb / cubrid commdb 의 status / shutdown 쿼리를 처리 하는 요청 서버, (b) 클라이언트와 cub_server 인스턴스 사이를 중개하는 연결 레지스트리, (c) 옵션으로 서버 인스턴스 자체에 대한 프로세스 supervisor. HA-replication 서브시스템 (cubrid-heartbeat.md)이 이 셋 위에 얹힌다는 점이다.

엔진Host 별 데몬프로세스 supervision클라이언트 발견
PostgreSQLdata 디렉토리당 postmaster; 클라이언트 연결당 한 Postgres backendpostmaster 가 크래시에 backend 를 re-exec; PANIC 시 cluster 단위 재시작클라이언트가 postmaster 포트 (5432)에 직접 연결
MySQLdata 디렉토리당 mysqld; thread-per-connectionsystemd / mysql.server 스크립트가 mysqld 재시작; in-process supervision 없음mysqld 에 직접 TCP/UDS 연결 (3306 / socket file)
Oraclehost 별 lsnrctl (Listener)가 연결을 받아 적절한 Oracle 인스턴스로 중개; clustered Oracle 에는 OHASD/CRSDOHASD/CRSD 가 실패 시 Oracle 인스턴스 재시작클라이언트가 listener (1521)에 연결; listener 가 적절한 인스턴스로 forward
MongoDB노드당 mongod; sharded cluster 에는 mongos 가 routersystemd; replica set primary 가 election 으로 failover 처리mongod 에 직접 연결 (또는 sharded 에는 mongos 로)
CUBRIDhost 당 cub_master; 클라이언트와 cub_server 사이를 중개옵션 in-process server_monitor (auto_restart_server 로 활성화); master_heartbeat.c 를 통한 HA failover (별도 문서)클라이언트가 cub_master (기본 1523)에 연결, per-database cub_server 포트를 받고, 그 포트에 직접 연결

CUBRID 의 listener (cub_master)는 정신적으로 Oracle 의 lsnrctl 에 가장 가깝다 — host 별 introduction broker. 차별점은 옵션 in-process supervisor 이다 — 대부분의 엔진은 재시작을 systemd/ init 에 위임하지만, CUBRID 의 master 는 설정되면 서버 lifecycle 을 직접 소유할 수 있다는 점이다.

cub_mastermain (master.c:1207)이 다음 시퀀스를 돌린다는 점이다:

// master.c::main (의역)
utility_initialize (); // 메시지 카탈로그
util_config_ret = master_util_config_startup (
(argc > 1) ? argv[1] : NULL, &port_id); // $CUBRID/conf/cubrid.conf 읽기
GETHOSTNAME (hostname, ...); // 에러 로그 파일명용
er_init (errlog, ER_NEVER_EXIT); // <hostname>_master.err
if (__gv_cvar.css_does_master_exist (port_id)) // 중복 master 검사
goto cleanup; // bail out — 이미 master 가 있음
msgcat_final (); // fork 전에 카탈로그 닫기
er_final (ER_ALL_FINAL);
if (envvar_get ("NO_DAEMON") == NULL)
css_daemon_start (); // background 로 fork
utility_initialize (); // 자식에서 카탈로그 다시 열기
er_init (errlog, ER_NEVER_EXIT);
time (&css_Start_time); // status 용 시작 시간 기록
if (css_master_init (port_id, css_Master_socket_fd) != NO_ERROR)
goto cleanup; // 소켓 bind / 시그널 setup 실패
if (envvar_get ("NO_DAEMON") != NULL)
os_set_signal_handler (SIGINT, css_master_cleanup);
if (!HA_DISABLED ())
hb_master_init (); // cubrid-heartbeat.md 참조
auto_Restart_server = prm_get_bool_value (PRM_ID_AUTO_RESTART_SERVER);
if (auto_Restart_server)
master_Server_monitor.reset (new server_monitor ());
conn = __gv_cvar.css_make_conn (css_Master_socket_fd[0]);
css_add_request_to_socket_queue (conn, false, NULL,
css_Master_socket_fd[0], READ_WRITE, 0,
&css_Master_socket_anchor);
/* ... IPv6 / UDS 용 둘째 소켓 fd 추가 ... */
/* ... 메인 select 루프 ... */

흐름에 관찰 가능한 여섯 단계가 있다는 점이다:

  1. Config + 중복 감지. master_util_config_startupmaster_shm_id 와 listening 포트를 위해 cubrid.conf 를 읽는다. css_does_master_exist 가 포트를 probe — 다른 master 가 이미 listening 하면 새 인스턴스는 시작을 거절한다.
  2. 에러-로그 init. 에러는 $CUBRID/log/<hostname>_master.err 에 들어간다. fork 전에 한다 — pre-fork 와 post-fork 코드 둘 다 에러를 만날 수 있기 때문이다.
  3. Daemonisation. css_daemon_start 가 controlling terminal 에서 detach 하는 표준 double-fork 를 한다. NO_DAEMON 환경 변수가 이를 건너뛴다 — foreground 디버깅과 이미 PID 1 을 하는 container init system 에 사용된다.
  4. Master 소켓 setup. css_master_init 이 listening 소켓들 (IPv4 한 개, IPv6 / UDS 한 개)을 bind 하고, SIGCHLD / SIGINT / SIGTERM 핸들러를 설치하고, css_Master_socket_anchor (모든 active 연결의 doubly-linked list — select() set)를 seed 한다.
  5. 옵션 HA bootstrap. cubrid.confha_mode = on 이면 hb_master_init 이 heartbeat 서브시스템 (cubrid-heartbeat.md 에서 다룸)을 init 한다 — heartbeat 별 연결 타입과 worker thread 를 추가한다는 뜻이다.
  6. 옵션 server monitor. auto_restart_server = on 이면 server_monitor C++ 객체 (아래 기술)를 인스턴스화. 크래시된 cub_server 인스턴스를 re-exec 하는 in-process supervisor 다.

init 후 master 가 css_Master_socket_anchor 안의 모든 연결을 multiplex 하는 select() 루프에 들어간다는 점이다. 각 socket-queue 항목이 어떤 종류의 연결인지를 식별하는 name 필드를 가진다:

  • Listening 소켓 (IPv4, IPv6/UDS) — 새 클라이언트 accept.
  • 등록된 cub_server 연결 — cub_server 가 부팅하고 자기를 master 에 등록할 때 (master 가 들어오는 클라이언트를 그것으로 중개할 수 있도록) 수립된다. 연결 이름은 데이터베이스 이름 (또는 HA 의 경우 <dbname>@<hostname>).
  • HA-server / HA-copylog / HA-applylog 연결 — 복제-프로세스 liveness 추적을 위해 heartbeat 서브시스템이 열어둔다. 이름 prefix 로 식별된다 (IS_MASTER_CONN_NAME_HA_SERVER, IS_MASTER_CONN_NAME_HA_COPYLOG, IS_MASTER_CONN_NAME_HA_APPLYLOG).
  • Driver / commdb / management-tool 연결 — status 또는 shutdown 을 묻는 짧은-수명 클라이언트 요청 (commdb, cubrid commdb, cubrid manager 웹 도구).
  • 클라이언트 introduction — 데이터베이스를 찾기 위해 연결 하는 클라이언트. master 가 cub_server 의 포트를 답하고 클라 이언트가 직접 다시 연결한다는 점이다. introduction 연결 자체는 그 다음 닫힌다.

select 루프의 매 iteration:

  1. accept-pending listening 소켓을 css_process_master_request 로 drain (anchor 에서 다시 arm 하기도 한다).
  2. 데이터가 ready 인 각 연결마다 요청을 읽고 오피코드로 디스패치.
  3. 닫힌 연결 (peer EOF)를, anchor 에서 제거하고 per-connection 상태를 free. 닫힌 연결이 등록된 cub_server 였다면 그리고 auto_restart_server 가 켜져 있으면, server monitor 에 REVIVE_SERVER job 을 enqueue.

요청 디스패치 (process_master_request)

섹션 제목: “요청 디스패치 (process_master_request)”

오피코드 디스패치는 master_request.c:1947 에 산다. 세 패밀리:

// master_request.c — 요청 디스패치 (의역)
switch (request) {
// Status 패밀리
case GET_START_TIME: css_process_start_time_info (...); break;
case GET_SHUTDOWN_TIME: css_process_shutdown_time_info (...); break;
case GET_SERVER_COUNT: css_process_server_count_info (...); break;
case GET_REQUEST_COUNT: css_process_request_count_info (...); break;
case GET_SERVER_LIST: css_process_server_list_info (...); break;
case GET_ALL_COUNT: css_process_all_count_info (...); break;
case GET_ALL_LIST: css_process_all_list_info (...); break;
case GET_SERVER_HA_MODE: css_process_get_server_ha_mode (...); break;
case GET_SERVER_STATE: /* ... */; break;
// Shutdown 패밀리
case KILL_SLAVE_SERVER: css_process_kill_slave (...); break;
case KILL_MASTER_SERVER: css_process_kill_master (); break;
case KILL_SERVER_IMMEDIATE: css_process_kill_immediate (...); break;
case START_SHUTDOWN: css_process_start_shutdown (...); break;
// HA 패밀리 (ha_mode = on 일 때)
case GET_HA_PING_HOST_INFO: css_process_ha_ping_host_info (...); break;
case GET_HA_NODE_LIST: css_process_ha_node_list_info (..., false); break;
case GET_HA_NODE_LIST_VERBOSE: css_process_ha_node_list_info (..., true); break;
case GET_HA_PROCESS_LIST: css_process_ha_process_list_info (..., false); break;
case GET_HA_PROCESS_LIST_VERBOSE: css_process_ha_process_list_info (..., true); break;
case GET_HA_ADMIN_INFO: css_process_ha_admin_info (...); break;
case KILL_ALL_HA_PROCESS: css_process_kill_all_ha_process (...); break;
case DEREGISTER_HA_PROCESS_BY_PID: css_process_deregister_ha_process_by_pid (...); break;
case DEREGISTER_HA_PROCESS_BY_ARGS: css_process_deregister_ha_process_by_args (...); break;
case START_HA_UTIL_PROCESS: css_process_start_ha_util_process (...); break;
}

각 핸들러가 요청 패킷에서 인자를 읽고, 동작을 수행하고 (보통 css_Master_socket_anchor 를 walk 하면서 per-connection name 필드를 검사), 같은 연결로 응답을 다시 쓴다는 뜻이다.

Status 패밀리는 commdb -P / commdb -O / cubrid service status / cubrid server status / cubrid heartbeat status 가 묻는 것에 답한다. Shutdown 패밀리는 commdb -S / commdb -A / cubrid server stop 이 보내는 것이다. HA 패밀리는 cubrid heartbeat … 가 보내는 것이고, heartbeat 서브시스템에 대한 공개 인터페이스이다.

여러 핸들러 — css_process_kill_slave, css_process_kill_immediate, css_process_start_shutdown_by_name, css_process_get_server_ha_mode, css_process_shutdown_reviving_server — 가 css_Master_socket_anchor 를 walk 하면서 name 이 target 서버 이름과 매칭되고 그리고 HA-replication 연결이 아닌 (!IS_MASTER_CONN_NAME_HA_SERVER 등) 항목을 찾는다. 반복되는 가드가 같은 anchor list 를 공유하지만 다른 프로세스를 나타내는 heartbeat-internal 연결을 걸러낸다는 점이다 — 이를 제외하지 않으면 shutdown 명령이 잘못된 프로세스를 target 으로 한다.

이것이 IS_MASTER_CONN_NAME_* 매크로가 master_request.c 에서 그토록 자주 등장하는 cross-cutting 이유다 — 모든 per-server 동작이 데이터베이스 X 의 cub_server 연결 을 “데이터베이스 X 의 HA-copylog/applylog 연결” 과 disambiguate 해야 한다는 뜻이다. 둘 다 데이터베이스 이름을 공유한다.

auto_restart_server = on 일 때 master 가 server_monitor (master_server_monitor.hpp 에 선언)를 인스턴스화한다는 점이다:

class server_monitor {
public:
enum class job_type {
REGISTER_SERVER = 0, // 새 cub_server 가 연결됨 — PID + argv 기록
UNREGISTER_SERVER = 1, // cub_server 가 깨끗하게 deregister — entry 제거
REVIVE_SERVER = 2, // cub_server 연결이 예기치 않게 죽음 — re-fork
CONFIRM_REVIVE_SERVER = 3, // re-fork 후 새 서버가 정말 떴는지 검사
SHUTDOWN_SERVER = 4, // 명시적 shutdown 요청 — revive 없이 entry 제거
JOB_MAX
};
void produce_job (job_type, int pid, const std::string &exec_path,
const std::string &args, const std::string &server_name);
private:
std::unordered_map <std::string, server_entry> m_server_entry_map;
std::unique_ptr<std::thread> m_monitoring_thread;
std::queue<job> m_job_queue;
std::mutex m_server_monitor_mutex;
std::condition_variable m_monitor_cv_consumer;
void server_monitor_thread_worker (); // m_job_queue 의 consumer 루프
};
class server_entry {
int m_pid;
std::string m_exec_path;
std::unique_ptr<char *[]> m_argv; // re-exec 용 저장
volatile bool m_need_revive;
std::chrono::steady_clock::time_point m_last_revived_time;
};

supervisor 는 한 consumer thread 를 가진 producer-consumer 큐 다. produce_job 이 다양한 이벤트가 일어났을 때 master 의 select- 루프 thread 에서 호출된다는 점이다:

  • REGISTER_SERVER — 새 cub_server 연결이 anchor 에 나타나 자기를 식별; master 가 PID, exec 경로, args, 서버 이름을 m_server_entry_map 에 기록.
  • UNREGISTER_SERVERcub_server 가 깨끗하게 disconnect (예: commdb -S 를 통한 정상 shutdown); revive 없이 entry 제거.
  • REVIVE_SERVER — 사전 unregister 없이 cub_server 연결이 죽음; entry 의 m_need_revivetrue 로 설정.
  • CONFIRM_REVIVE_SERVER — revive fork 후 master 가 새 프로세스가 정말 timeout 안에 새 연결을 열었는지 검증하는 confirm job 을 enqueue.
  • SHUTDOWN_SERVER — 명시적 shutdown; entry 제거; auto_restart_server 가 켜져 있어도 revive 없음.

Consumer thread (server_monitor_thread_worker)가 m_monitor_cv_consumer 에서 job 을 기다리며 block 하고 직렬로 처리한다 — 등록과 revival 이 race 할 수 없다 (m_server_entry_map 과 큐 주변의 lock 을 공유하기 때문이다).

try_revive_server 가 실제 fork 지점이다 — 저장된 argv 와 함께 <exec_path>fork 하고 execv 하고, 새 PID 를 기존 서버-이름 entry 에 기록하고, m_last_revived_time 을 업데이트해 flapping 서버를 rate-limit 할 수 있다 (현재 코드에서 rate-limiting 정책 자체는 엄격하지 않다 — m_last_revived_time 이 기록되지만 consumer 가 다음 revive 전에 읽지는 않는다는 점이다).

auto_restart_server 가 이 supervisor 를 활성화하는 유일한 조건이다 — 그것 없이는 master_Server_monitor 가 null unique_ptr 이고 master 가 자식 서버를 추적하거나 재시작하지 않는다. (production 에서 HA 를 쓰는 운영자는 거의 항상 auto_restart_server = on 을 설정한다 — heartbeat failover 가 크래시된 서버가 돌아온다고 가정 하기 때문이다. HA-disabled standalone 배포에서 운영자의 선택은 외부 supervisor 가 있는지에 달려 있다.)

master_util.cmaster_util.h — 작은 도우미

섹션 제목: “master_util.c 와 master_util.h — 작은 도우미”

부팅 동안 사용되는 세 가지 utility 도우미:

  • master_util_config_startup (config_path, &port_id)cubrid.conf 의 master section 을 읽음; 파일이 없거나 파싱 안 되면 false 반환. main 의 argv[1] 이 config-파일 경로 override 로 전달된다 (드물게 사용; 기본은 $CUBRID/conf/cubrid.conf).
  • master_util_wait_proc_terminatecss_process_kill_immediate 가 SIGTERM 된 자식이 정말 죽은 후 requester 에게 완료를 보고 하기 전에 기다리는 데 사용.
  • master_util_get_eof_message — 예기치 않게 떨어진 연결에 대한 end-of-stream 메시지 형식화.

이들은 의도적으로 작다 — master_util.c 는 ~90 줄, 자체로 실질 모듈은 아니다.

Master shutdown 은 세 곳에서 시작될 수 있다는 점이다:

  1. commdb -S <db> — 한 cub_server kill (KILL_SLAVE_SERVER / KILL_SERVER_IMMEDIATE); master 가 자식에 SIGTERM, 기다림, entry 제거. master 자체는 shutdown 하지 않는다.
  2. commdb -A — 등록된 모든 cub_server kill. 각각이 차례로 kill; master 는 동작 유지.
  3. master 용 commdb (KILL_MASTER_SERVER, 또는 cubrid service stop) — css_process_kill_master 가 master shutdown 을 시작 — server monitor 의 thread 를 깨끗하게 종료, 등록된 모든 cub_server 에 shutdown 전송, listening 소켓 닫음, exit.

css_master_cleanupNO_DAEMON (foreground 디버그) 모드에 설치된 SIGINT/SIGTERM 핸들러이다 — KILL_MASTER_SERVER 와 같은 shutdown 시퀀스를 돌린다.

심볼역할
main진입; config; 중복 master 검사; daemonise; 소켓과 시그널 init; 옵션 HA + server-monitor 인스턴스화; select 루프 진입
css_master_initlistening 소켓 (IPv4 + IPv6/UDS) setup, SIGCHLD/SIGINT/SIGTERM 설치, 연결 anchor seed
css_daemon_start표준 double-fork daemonisation; setsid, stdio 를 /dev/null 로 redirect
css_master_errorstderr<hostname>_master.err 둘 다로 가는 master-specific 에러 printer
css_master_cleanupforeground 모드의 SIGINT 핸들러; shutdown 시퀀스 실행
css_Master_socket_fd[]두 listening 파일 디스크립터
css_Master_socket_anchorselect 루프가 iterate 하는 연결 anchor (doubly-linked list)
css_Start_timeGET_START_TIME 응답을 위해 부팅에 기록
auto_Restart_serverPRM_ID_AUTO_RESTART_SERVER 의 bool 미러; master_Server_monitor 인스턴스화 게이트
심볼역할
process_master_requesttop-level 오피코드 switch (라인 1947); status, shutdown, HA 패밀리
css_process_start_time_info / _shutdown_time_infoGET_START_TIME / GET_SHUTDOWN_TIME
css_process_server_count_info / _server_list_infoGET_SERVER_COUNT / GET_SERVER_LIST — commdb -P
css_process_all_count_info / _all_list_infoGET_ALL_COUNT / GET_ALL_LIST — commdb -O 용 (서버 + broker + pl)
css_process_request_count_infomaster 자체 요청 카운터 — 진단용
css_process_kill_slave / _kill_immediate / _kill_mastershutdown 핸들러
css_process_start_shutdown / _start_shutdown_by_name / _shutdown / _stop_shutdown두 단계 shutdown 조정
css_process_shutdown_reviving_server현재 revive 중인 서버에 대한 특수 shutdown 경로 (server_monitor 와의 race 회피)
css_process_get_server_ha_modeGET_SERVER_HA_MODE — HA 로직이 사용
css_process_register_ha_process / _deregister_ha_process / _change_ha_modeHA-process lifecycle (heartbeat 서브시스템 ↔ master)
css_process_ha_ping_host_info / _ha_node_list_info / _ha_admin_infoHA-info-query 핸들러
css_process_get_eof짧은-수명 probe 연결을 위한 generic EOF responder

Server monitor (master_server_monitor.{cpp,hpp})

섹션 제목: “Server monitor (master_server_monitor.{cpp,hpp})”
심볼역할
server_monitor (class)supervisor; m_server_entry_map, m_job_queue, consumer thread 소유
server_monitor::produce_jobmaster select 루프에서 호출되는 producer 진입점
server_monitor::server_monitor_thread_workerconsumer 루프; job 을 가져와 디스패치
server_monitor::register_server_entry / remove_server_entry / revive_server / try_revive_server / check_server_revived / shutdown_serverper-job 핸들러
server_entry (inner class)등록된 cub_server 당 하나; PID + exec 경로 + 저장된 argv + revive timestamp
master_Server_monitor (전역 unique_ptr)싱글톤 인스턴스; auto_restart_server 가 아닌 한 nullptr
auto_Restart_server (전역 bool)sysparam 의 미러

부팅 / shutdown 도우미 (master_util.c)

섹션 제목: “부팅 / shutdown 도우미 (master_util.c)”
심볼역할
master_util_config_startupcubrid.conf 읽기; 포트 ID 와 유효성 반환
master_util_wait_proc_terminate자식에 SIGTERM 보낸 후 사용되는 waitpid wrapper
master_util_get_eof_messageEOF 메시지 formatter
심볼경로
master.c::mainsrc/executables/master.c:1207
css_master_initsrc/executables/master.c:259
process_master_request (요청 switch)src/executables/master_request.c:1947
css_process_start_time_infosrc/executables/master_request.c:166
css_process_server_list_infosrc/executables/master_request.c:286
css_process_all_list_infosrc/executables/master_request.c:386
css_process_kill_slavesrc/executables/master_request.c:498
css_process_kill_immediatesrc/executables/master_request.c:579
css_process_start_shutdown_by_namesrc/executables/master_request.c:615
css_process_kill_mastersrc/executables/master_request.c:686
css_process_register_ha_processsrc/executables/master_request.c:913
css_process_change_ha_modesrc/executables/master_request.c:956
server_monitor (class)src/executables/master_server_monitor.hpp:38
server_monitor::job_type (enum)src/executables/master_server_monitor.hpp:43

심볼 이름이 정규 anchor 이고, 라인 번호는 updated: 날짜에 스코프된 힌트이다.

  • HA-replication 과 master 가 분리되어 있다. 이 문서는 master 의 데몬 모양과 요청 디스패치를 다룬다. HA-replication 서브 시스템 (master_heartbeat.c, ~7300 줄)은 같은 select 루프 위에 얹히고 IS_MASTER_CONN_NAME_HA_* prefix 로 식별되는 추가 연결 타입을 사용한다. heartbeat 의미, peer-discovery, failover 는 cubrid-heartbeat.md 에 산다는 뜻이다.
  • Server monitor 와 heartbeat 가 독립적이다. C++ server_monitor (이 문서)는 host 별 프로세스 supervision 이다. Heartbeat 는 cluster 별 replication-state 조정이다. 설정으로 한쪽만 활성화 가능하다 (HA on, auto_restart_server off — heartbeat 가 복제 상태를 추적하지만 크래시된 서버는 재시작하지 않는다; HA off, auto_restart_server on — single-host with crash-restart). 둘 다 on 이 일반적인 HA production setup 이다.
  • Connection-anchor 이름 disambiguation. master_request.c 의 모든 per-server 요청 핸들러가 anchor walk 에서 IS_MASTER_CONN_NAME_HA_* prefix 를 거른다. 패턴이 소스에서 8 번 이상 반복된다. cub_server 연결에 동작하는 새 요청 핸들러 를 추가하면서 이 필터를 잊으면 조용히 HA-internal 연결을 target 한다 — 코드 리뷰에서 표시할 가치가 있는 흔한 버그 모양.
  • auto_restart_server 활성화는 master startup 에서 one-shot 이다. 런타임에 sysparam 을 토글해도 server monitor 가 켜지 거나 꺼지지 않는다 — master 를 재시작해야 한다는 뜻이다. 의도 적이다 — supervisor 의 상태 (m_server_entry_map)가 유용하려 면 부팅부터 일관된 등록 history 가 필요하다.
  • 명시적 shutdown 과 revive 의 race. css_process_shutdown_reviving_server 가 존재하는 이유는 정확히, 운영자가 server_monitor 가 같은 서버를 re-fork 하는 도중에 commdb -S <db> 를 발사할 수 있기 때문이다. 핸들러가 try_revive_server 가 실제로 fork 하기 전에 검사하는 sentinel 을 설정한다 — shutdown 이 먼저 도착했으면 revive 가 cancel 된다.
  • m_last_revived_time 가 기록되지만 강제되지 않는다. server_entry 가 각 revive 시도의 timestamp 를 기록하지만, consumer 가 현재 flapping 서버를 rate-limit 하는 데 쓰지 않는다. 재시작 후 몇 초 안에 panic 하는 버기 cub_server 가 빡빡한 loop 에서 revive 된다 — 알려진 갭이고 flapping 감지는 외부 모니터링에 맡긴다는 점이다.
  • 중복-master 검사가 포트별이지 config 별이 아니다. css_does_master_exist (port_id) 는 포트가 사용 중인지만 검사 한다. 다른 cubrid.conf 를 읽지만 같은 포트가 할당된 두 cub_master 인스턴스는 충돌하고, 다른 포트의 두 인스턴스는 둘 다 돌면서 서로의 존재를 모른다.
  • 컨테이너화된 배포. double-fork daemonisation 이 컨테이너 init system (Docker init=tini, init container 가 있는 Kubernetes pod) 안에서는 불필요하다. NO_DAEMON 환경 변수가 fork 를 건너 뛰지만 다른 데몬 동작 (시그널 처리, 에러 로그 경로)는 변경 하지 않는다는 뜻이다. 완전히 container-aware 모드는 또한 로그 를 stdout/stderr 로 redirect 하고 <hostname>_master.err 파일 을 쓰지 않을 것이다.
  • Server monitor flapping 정책. 위에 적은 대로, revive 에 rate limiting 없음. 문서화된 정책은: hard ceiling 이 있는 exponential backoff (예: 5 분에 max 5 revive, 그 다음 deregister 하고 운영자 개입 요구).
  • 요청 오피코드 인증. 요청 오피코드에 인증 없음 — master 의 포트에 연결할 수 있는 누구나 KILL_MASTER_SERVER 를 발사할 수 있다는 점이다. Production 배포는 네트워크 수준 firewalling 에 의존한다 (master 포트가 보통 노출되지 않는다). 일급 auth 메커니즘은 문서화되지 않았다.
  • HA 상세. 이 문서는 HA 를 의도적으로 connection-registry 수준에 머문다. HA-info-query 의미 (GET_HA_NODE_LIST, GET_HA_PROCESS_LIST 등)의 완전한 그림은 여기가 아니라 cubrid-heartbeat.md 에 속한다.
  • src/executables/master.c — 데몬 진입, init, select 루프, 소켓 anchor 관리, 시그널 핸들러
  • src/executables/master_request.c — 오피코드 디스패처와 per-opcode 핸들러
  • src/executables/master_request.h — 오피코드 enum, IS_MASTER_CONN_NAME_* 매크로, 핸들러 prototype
  • src/executables/master_server_monitor.{cpp,hpp} — producer- consumer job 큐를 가진 C++ 프로세스 supervisor
  • src/executables/master_util.{c,h} — config reader 와 작은 프로세스 도우미
  • src/executables/AGENTS.md — agent 가이드
  • 인접 문서: cubrid-heartbeat.md (같은 데몬 위에 얹힌 HA-replication 서브시스템 — master_heartbeat.c 와 이 문서에서 cross-ref 된 HA-info-query 핸들러를 다룬다), cubrid-broker.md (broker 는 별도 데몬이지만 commdb -O 가 master 로 도달한다), cubrid-cub-admin.md (통합 admin CLI; cubrid service 패밀리가 master 를 fork 하고 cubrid commdb verb 가 master 의 요청 핸들러 대부분이 서비스하는 것이다), cubrid-overview-server-architecture.md (4-프로세스 모델 안에서의 master 위치)