English | 한국어
Core 스펙 목차 | 이전: 공개 계약 관리 | 다음: Message
Context¶
이 장이 정의하는 것 — Context가 무엇을 소유하고, 어떻게 만들고 설정하며 안전하게 종료하는지의 공개 C ABI 계약.
1. Context 개요¶
zlink의 Context는 I/O 처리 thread와 socket을 담는 최상위 container다. 모든 application은 다른 zlink API를 쓰기 전에 Context를 하나 이상 만들어야 하고, 모든 socket은 반드시 어떤 Context에 속한다.
이 문서는 Context를 만들고, 옵션으로 설정하고, 안전하게 종료하는 계약을 정의한다. 대상 독자는 이 계약을 C API와 각 언어 binding으로 옮기는 개발자다.
관련 계약의 소유 문서는 다음과 같다.
| 관련 계약 | 정의하는 문서 |
|---|---|
| Auto HWM budget 계산·admission과 관련 함수 | Auto HWM |
| socket 생성·옵션·송수신 | Socket 공통 |
| message lifecycle와 ownership | Message |
2. Context가 소유하는 것¶
Context는 다음을 소유한다.
- I/O thread pool — 네트워크 송수신을 실제로 처리하는 I/O thread 집합이다. thread 개수, 스케줄링 우선순위와 CPU affinity를 Context 옵션으로 정한다.
- socket container — 이 Context로 만든 모든 socket의 상위다. 동시에 열 수 있는 socket 수의 상한도 Context 옵션이다.
- 공유 설정 — thread 이름, 최대 message 크기, 그리고 socket queue의 크기를 자동으로 정하는 Auto HWM 정책처럼 context 전체에 적용하는 값이다.
Context는 thread-safe하다. 여러 thread가 같은 Context 핸들을 동시에 공유하고 옵션을 조회·설정할 수 있다.
3. 수명과 종료¶
Context의 수명은 만들기 → 사용 → 종료 신호 → 자원 해제 순으로 진행한다.
- 만들기 —
zlink_ctx_new가 기본 옵션 값으로 Context를 만든다. - 종료 신호 —
zlink_ctx_shutdown은 이 Context에 속한 socket의 모든 blocking 작업이 즉시ETERM으로 풀리도록 신호만 보낸다. 자원은 해제하지 않는 non-blocking 호출이다. 이렇게 풀린zlink_recv는ZLINK_RECV_TERMINATED를 반환하고 receive output을 바꾸지 않는다. 풀린zlink_send는ZLINK_SUBMIT_TERMINATED를 반환하고 다른 submit 실패와 같이 모든 입력 슬롯을 소비해 빈 initialized 상태로 두며 completion ID0을 돌려준다. - 자원 해제 —
zlink_ctx_term이 Context를 파괴한다. 이 호출은 Context 안에서 만든 모든 socket이 닫힐 때까지 blocking될 수 있다. 각 Context는 정확히 한 번만 term한다.
여러 thread가 socket을 사용하는 중이라면 term 전에 shutdown을 먼저 호출해 deadlock을 피한다.
shutdown 없이 term만 호출하면 socket이 닫히기를 기다리며 멈출 수 있기 때문이다.
ZLINK_CTX_OPT_BLOCKY를 0으로 설정하면 이후 생성하는 socket의 기본 LINGER가 0이 되어,
socket이 전달하지 못한 message를 기다리지 않고 닫히므로 term이 빨리 반환된다. term 자체는 이
옵션과 무관하게 내부 정리가 끝날 때까지 기다린다.
%%{init: {'sequence': {'actorFontSize': '18px', 'messageFontSize': '18px', 'noteFontSize': '18px', 'boxMargin': 8, 'width': 140}, 'themeVariables': {'fontSize': '18px'}}}%%
sequenceDiagram
participant App as Application
participant Ctx as Context
participant S as Socket들
App->>Ctx: zlink_ctx_new()
Note over Ctx: I/O thread pool 생성
App->>S: socket 생성·사용
App->>Ctx: zlink_ctx_shutdown() (non-blocking)
Ctx-->>S: 모든 blocking 작업 즉시 ETERM
App->>S: 각 socket close
App->>Ctx: zlink_ctx_term()
Note over Ctx: 모든 socket 닫힐 때까지 대기 후 파괴
4. 옵션¶
각 option의 값, 타입, 접근 API, 초기값과 적용 시점은 다음과 같다. 표의 set/get은
zlink_ctx_set/zlink_ctx_get, set_data/get_data는 같은 이름의 data API를 뜻한다.
Option (ZLINK_ 접두사) |
값·Type·접근 | 초기값 또는 read-only 값 | 적용 시점 |
|---|---|---|---|
IO_THREADS |
1; int, set/get |
4 |
설정값은 즉시 조회되며 runtime이 처음 시작될 때 pool 크기로 고정됨 |
MAX_SOCKETS |
2; int, set/get |
4095를 poller limit에 맞춰 줄인 값 |
설정값은 즉시 조회되며 runtime이 처음 시작될 때 slot capacity로 고정됨 |
SOCKET_LIMIT |
3; int, get-only |
65535를 poller limit에 맞춰 줄인 값 |
항상 현재 platform hard limit을 반환함 |
THREAD_PRIORITY |
22; int, set/get |
-1 |
설정 뒤 시작하는 I/O thread에 적용됨 |
THREAD_SCHED_POLICY |
4; int, set/get |
-1 |
설정 뒤 시작하는 I/O thread에 적용됨 |
MSG_T_SIZE |
6; int, get-only |
sizeof(zlink_msg_t)인 64 |
compile-time ABI 크기를 반환함 |
THREAD_AFFINITY_CPU_ADD |
7; int, set-only |
빈 CPU 집합 | CPU를 즉시 집합에 추가하고 이후 시작하는 I/O thread에 적용함 |
THREAD_AFFINITY_CPU_REMOVE |
8; int, set-only |
빈 CPU 집합 | CPU를 즉시 집합에서 제거하고 이후 시작하는 I/O thread에 적용함 |
THREAD_NAME_PREFIX |
9; byte string, set_data/get_data |
길이 0 |
설정 뒤 시작하는 I/O thread의 이름에 적용함 |
CTX_OPT_BLOCKY |
10; int, set/get |
1 |
설정 뒤 만드는 socket의 기본 LINGER에 적용함 |
CTX_OPT_AUTO_HWM_ENABLE |
12; int, set/get |
1 |
저장한 뒤 기존 socket을 포함한 재계산을 예약함 |
CTX_OPT_AUTO_HWM_RECALC_DEBOUNCE_MS |
14; int, set/get |
3000 ms |
저장한 debounce로 재계산을 예약함 |
CTX_OPT_AUTO_HWM_PROFILE |
17; int, set/get |
BALANCED |
저장한 뒤 기존 socket을 포함한 재계산을 예약함 |
CTX_OPT_AUTO_HWM_MEMORY_LIMIT_BYTES |
19; uint64_t, set_data/get_data |
0 |
저장한 뒤 기존 socket을 포함한 재계산을 예약함 |
CTX_OPT_AUTO_HWM_RUNTIME_MEMORY_LIMIT_BYTES |
20; uint64_t, set_data/get_data |
0 |
저장한 뒤 기존 socket을 포함한 재계산을 예약함 |
CTX_OPT_AUTO_HWM_CORE_BUDGET_BYTES |
21; uint64_t, set_data/get_data |
0 |
저장한 뒤 기존 socket을 포함한 재계산을 예약함 |
typedef enum zlink_auto_hwm_profile_t
{
ZLINK_AUTO_HWM_PROFILE_COMPACT = 0, // memory 비율이 가장 작다 — 메모리를 아껴야 할 때
ZLINK_AUTO_HWM_PROFILE_LOW_LATENCY = 1, // queue를 짧게 유지해 지연을 줄인다
ZLINK_AUTO_HWM_PROFILE_BALANCED = 2, // 기본값. memory와 처리량을 절충한다
ZLINK_AUTO_HWM_PROFILE_THROUGHPUT = 3 // memory 비율이 가장 크다 — 대용량 처리가 우선일 때
} zlink_auto_hwm_profile_t;
각 profile의 정확한 memory 비율, 고정 cap과 역할별 하한·상한은 Auto HWM §2가 소유한다.
Auto HWM byte 옵션 세 개(MEMORY_LIMIT_BYTES, RUNTIME_MEMORY_LIMIT_BYTES,
CORE_BUDGET_BYTES)가 어떤 budget을 계산하고 어떻게 admission에 쓰이는지는
Auto HWM이 소유한다.
4.1 기본값¶
#define ZLINK_IO_THREADS_DFLT 4 // 기본 I/O thread 수
#define ZLINK_MAX_SOCKETS_DFLT 4095 // 기본 최대 socket 수
#define ZLINK_THREAD_PRIORITY_DFLT -1 // 기본 우선순위 (OS 기본값)
#define ZLINK_THREAD_SCHED_POLICY_DFLT -1 // 기본 스케줄링 정책 (OS 기본값)
#define ZLINK_CTX_AUTO_HWM_ENABLE_DFLT 1 // 자동 HWM 기본 활성 (끄거나 수동 HWM 미설정 시 balanced)
#define ZLINK_CTX_AUTO_HWM_RECALC_DEBOUNCE_MS_DFLT 3000 // 재계산 기본 debounce (ms)
#define ZLINK_CTX_AUTO_HWM_PROFILE_DFLT ZLINK_AUTO_HWM_PROFILE_BALANCED // 기본 profile
#define ZLINK_CTX_AUTO_HWM_MEMORY_LIMIT_BYTES_DFLT ((uint64_t) 0) // 명시적 limit 미설정
#define ZLINK_CTX_AUTO_HWM_RUNTIME_MEMORY_LIMIT_BYTES_DFLT ((uint64_t) 0) // runtime hint 없음
#define ZLINK_CTX_AUTO_HWM_CORE_BUDGET_BYTES_DFLT ((uint64_t) 0) // 수동 Core budget 미설정
SNDBUF / RCVBUF 기본값은 -1이다. 이 값은 zlink가 OS socket buffer
크기를 직접 정하지 않고 OS 기본값과 TCP 자동 조정에 맡긴다는 뜻이다.
auto-HWM profile은 이 값을 자동으로 바꾸지 않는다.
5. 함수¶
zlink_ctx_new¶
새 zlink context를 생성한다.
기본 옵션 값으로 새 context를 할당하고 초기화한다. Context는 I/O thread pool을
관리하며 socket 생성의 기반이 된다. 모든 socket은 context와 연결되어야 한다.
Context가 더 이상 필요하지 않으면 zlink_ctx_term으로 해제한다.
반환값: 성공 시 context 핸들, 실패 시 NULL (errno가 설정됨).
스레드 안전성: 모든 스레드에서 안전하게 호출할 수 있다. 반환된 context 핸들은 thread 간에 공유할 수 있다.
참고: zlink_ctx_term, zlink_ctx_set
zlink_ctx_term¶
Context를 종료하고 관련된 모든 자원을 해제한다.
Context를 파괴한다. 이 호출은 context 내에서 생성된 모든 socket이 닫힐 때까지
blocking될 수 있다. Context에 속한 socket의 blocking 작업은 zlink_ctx_shutdown이
호출되거나 모든 socket이 닫힌 후 ETERM을 반환한다. 각 context는 정확히
한 번만 종료해야 한다.
반환값: 성공 시 ZLINK_CLOSE_OK, 실패 시 zlink_close_result_t 값. zlink_errno()는 진단용 내부 errno를 그대로 유지한다.
에러:
- EFAULT -- 유효하지 않은 context 핸들.
- EINTR -- signal에 의해 종료가 중단됨; 재시도할 수 있다.
스레드 안전성: 모든 스레드에서 안전하게 호출할 수 있지만, context당 정확히 한 번만 호출해야 한다. 이 호출이 반환된 후에는 context 핸들을 사용하지 않는다.
참고: zlink_ctx_new, zlink_ctx_shutdown
zlink_ctx_shutdown¶
Context를 즉시 종료한다.
이 context에 속한 socket의 모든 blocking 작업이 ETERM과 함께 즉시 반환되도록
신호를 보낸다. 이것은 종료를 시작하지만 자원을 해제하지 않는 non-blocking
호출이다. 최종 정리를 위해 이후에 zlink_ctx_term을 호출해야 한다.
term 전에 shutdown을 호출하면 여러 thread에서 socket을 사용할 때 deadlock을
방지할 수 있다.
반환값: 성공 시 ZLINK_CLOSE_OK, 실패 시 zlink_close_result_t 값. zlink_errno()는 진단용 내부 errno를 그대로 유지한다.
에러:
- EFAULT -- 유효하지 않은 context 핸들.
스레드 안전성: 모든 스레드에서 안전하게 호출할 수 있다.
참고: zlink_ctx_term
zlink_ctx_set¶
Context 옵션을 설정한다.
ZLINK_EXPORT zlink_config_result_t zlink_ctx_set(void *context_, zlink_ctx_option_t option_, int optval_);
socket이 생성되기 전 또는 후에 context를 구성한다. 유효한 옵션 이름과 의미는 §4 옵션
목록을 참조한다. 단, ZLINK_IO_THREADS와 ZLINK_MAX_SOCKETS는 설정 자체는 언제든
성공하고 조회에도 반영되지만, 실제 I/O thread pool과 socket 슬롯 용량은 context runtime이
처음 시작될 때의 값으로 한 번 고정되며 그 후에 값을 바꿔도 런타임 용량은 바뀌지 않는다.
runtime은 첫 socket 생성에서 시작되지만, 그 전에 양수 debounce로 Auto HWM 재계산이
예약되는 등 control runtime이 먼저 요청되면 그 시점에 시작된다.
ZLINK_CTX_OPT_AUTO_HWM_ENABLE은 이미 만들어진 socket에도 적용된다 — 변경은 자동
재계산을 예약하며(기본 debounce 3000 ms), 그 전에 새 계획이 필요하면
zlink_ctx_auto_hwm_recalculate를 호출한다. 아직 수동 SNDHWM / RCVHWM 값을 주지
않은 socket만 자동 정책으로 다시 계산한다. 값을 0으로 바꾸면 현재 pipe에 마지막으로 적용한 HWM을
유지하고 이후 자동 재계산에서 제외하며 snapshot의 planning-active flag를 지운다.
ZLINK_CTX_OPT_AUTO_HWM_PROFILE은 다음 자동 HWM 계산에서 쓰는 profile을
바꾸며, runtime 중에도 안전하게 조정할 수 있다. Profile은 memory 비율과
역할별 byte 하한·상한을 선택한다. SNDBUF / RCVBUF 기본값은 -1이며,
auto-HWM profile은 이 값을 자동으로 바꾸지 않는다. 세 Auto HWM byte 옵션은
zlink_ctx_set으로 설정할 수 없고 EINVAL로 실패한다. (계약은 Auto HWM 참조)
반환값: 성공 시 ZLINK_CONFIG_OK, 실패 시 zlink_config_result_t 값. zlink_errno()는 진단용 내부 errno를 그대로 유지한다.
에러:
- EINVAL -- 알 수 없는 옵션 또는 유효하지 않은 값.
- EFAULT -- 유효하지 않은 context 핸들 (ZLINK_CONFIG_INVALID_HANDLE).
스레드 안전성: 모든 스레드에서 안전하게 호출할 수 있다.
참고: zlink_ctx_set_data, zlink_ctx_get
zlink_ctx_set_data¶
byte 버퍼로 context 옵션을 설정한다.
ZLINK_EXPORT zlink_config_result_t zlink_ctx_set_data(void *context_,
zlink_ctx_option_t option_,
const void *optval_,
size_t optvallen_);
세 Auto HWM byte 옵션은 정확히 sizeof(uint64_t) byte를 받는다. 값 0은
unlimited가 아니라 해당 입력을 설정하지 않았다는 뜻이다. 다른 크기와 위 enum에 없는
context 옵션 값은 ZLINK_CONFIG_INVALID_ARGUMENT로 실패한다. 유효한 값을 설정하면
값을 저장한 뒤 Auto HWM 재계산을 예약한다. 새 budget이 현재 수동 HWM과 자동 하한을 함께
수용하지 못해도 setter는 성공하며, planner는 자동 하한을 낮추지 않고 budget snapshot에
ZLINK_AUTO_HWM_BUDGET_FLAG_INSUFFICIENT를 설정한다. (계약은
Auto HWM 참조)
ZLINK_THREAD_NAME_PREFIX에는 null 종료 문자열을 optval_로 전달하고
strlen(prefix) + 1을 optvallen_으로 전달한다. 접두사는 platform thread
이름 제한에 맞춰 최대 16바이트(optvallen_ <= 16)로 제한된다.
반환값: 성공 시 ZLINK_CONFIG_OK, 실패 시 zlink_config_result_t 값. zlink_errno()는 진단용 내부 errno를 그대로 유지한다.
에러:
- EINVAL -- 알 수 없는 옵션 또는 유효하지 않은 값.
- EFAULT -- 유효하지 않은 context 핸들 (ZLINK_CONFIG_INVALID_HANDLE).
스레드 안전성: 모든 스레드에서 안전하게 호출할 수 있다.
참고: zlink_ctx_set, zlink_ctx_get_data, zlink_ctx_get
zlink_ctx_get_data¶
호출자가 제공한 저장 공간으로 context 옵션을 조회한다.
ZLINK_EXPORT zlink_config_result_t zlink_ctx_get_data(void *context_,
zlink_ctx_option_t option_,
void *optval_,
size_t *optvallen_);
세 Auto HWM byte 옵션에는 uint64_t output buffer가 필요하고, 호출할 때
*optvallen_이 정확히 sizeof(uint64_t)여야 한다. 더 큰 임시 buffer나 4-byte
크기를 포함해 그 밖의 크기는 값을 잘라 쓰거나 일부만 채우지 않고
ZLINK_CONFIG_INVALID_ARGUMENT와 errno == EINVAL로 실패한다. 이때 필요한
크기인 sizeof(uint64_t)를 *optvallen_에 기록한다. 성공해도 같은 크기를
유지한다.
ZLINK_THREAD_NAME_PREFIX도 이 함수로 조회한다. *optvallen_에는 output buffer의 용량을
전달한다. 용량이 저장된 prefix 길이보다 작으면 필요한 길이를 *optvallen_에 기록하고
ZLINK_CONFIG_INVALID_ARGUMENT와 EINVAL로 실패한다. 충분하면 prefix byte를 복사하고
*optvallen_을 복사한 길이로 갱신한다.
반환값: 성공 시 ZLINK_CONFIG_OK, 실패 시 zlink_config_result_t 값.
zlink_errno()는 진단용 내부 errno를 그대로 유지한다.
에러:
- EINVAL -- 알 수 없는 option, 잘못된 output 크기 또는 NULL output pointer (ZLINK_CONFIG_INVALID_ARGUMENT).
- EFAULT -- 유효하지 않은 context handle (ZLINK_CONFIG_INVALID_HANDLE).
스레드 안전성: 모든 스레드에서 안전하게 호출할 수 있다.
참고: zlink_ctx_set_data, zlink_ctx_get
zlink_ctx_get¶
Context 옵션을 조회한다.
ZLINK_EXPORT int zlink_ctx_get(void *context_, zlink_ctx_option_t option_, zlink_config_result_t *error_out_);
Context 옵션의 현재 값을 가져온다. ZLINK_SOCKET_LIMIT 및 ZLINK_MSG_T_SIZE
같은 읽기 전용 옵션을 포함하여 언제든지 context 구성을 검사하는 데 사용할 수
있다. 실패 시 *error_out_에 설정 결과(zlink_config_result_t)가
기록되고, 성공 시 옵션 값이 기본 반환값으로 반환된다. error_out_은 선택
사항이다 — NULL을 전달하면 실패 시 결과 코드는 기록되지 않고 -1 반환과
errno 설정만 관찰된다.
반환값: 성공 시 옵션 값, 실패 시 -1이며 *error_out_에
zlink_config_result_t가 기록된다. zlink_errno()는 진단용 내부 errno를
그대로 유지한다.
에러:
- EINVAL -- 알 수 없는 옵션.
- EFAULT -- 유효하지 않은 context 핸들; *error_out_에 ZLINK_CONFIG_INVALID_HANDLE이 기록된다.
스레드 안전성: 모든 스레드에서 안전하게 호출할 수 있다.
참고: zlink_ctx_set, zlink_ctx_get_data
6. 구현 및 contract test 검증 요구¶
공개 표면(zlink_ctx_* 함수, 옵션 set·get, 반환값·errno)만으로 다음을 확인한다. 각 항목은
unit test 하나로 이어진다.
수명
- zlink_ctx_new는 성공 시 non-NULL 핸들을, 실패 시 NULL과 설정된 errno를 반환한다.
- zlink_ctx_shutdown을 호출하면 그 context에 속한 socket의 blocking 작업이 즉시 ETERM으로 반환된다.
- zlink_ctx_term은 context당 한 번 성공하고, 그 안의 모든 socket이 닫힐 때까지 blocking될 수 있다.
- 유효하지 않은 context 핸들로 zlink_ctx_term·zlink_ctx_shutdown을 호출하면 EFAULT다.
- signal로 zlink_ctx_term이 중단되면 EINTR이며 재시도할 수 있다.
옵션
- zlink_ctx_set에 알 수 없는 옵션이나 유효하지 않은 값을 주면 EINVAL, 유효하지 않은 핸들이면 EFAULT(ZLINK_CONFIG_INVALID_HANDLE)다.
- ZLINK_THREAD_PRIORITY는 고유 값 22로 설정·조회하고 ZLINK_SOCKET_LIMIT 값 3의 읽기 전용 계약에 영향을 주지 않는다.
- 세 Auto HWM byte 옵션을 zlink_ctx_set으로 설정하려 하면 EINVAL이다(설정은 zlink_ctx_set_data만 허용).
- Auto HWM byte 옵션을 zlink_ctx_get_data로 정확히 sizeof(uint64_t)가 아닌 크기로 조회하면 EINVAL이고 필요한 크기를 *optvallen_에 기록한다.
- enum에 없는 context 옵션 값을 zlink_ctx_set_data로 쓰면 ZLINK_CONFIG_INVALID_ARGUMENT다.
- ZLINK_THREAD_NAME_PREFIX를 zlink_ctx_get_data로 저장된 prefix 길이보다 작은 용량으로 조회하면 EINVAL이고 필요한 길이를 *optvallen_에 기록한다.
스레드 안전성
- 모든 zlink_ctx_* 함수는 여러 thread에서 동시에 호출해도 안전하다. zlink_ctx_term만 context당 한 번으로 제한한다.
Auto HWM budget과 admission의 검증은 Auto HWM가 소유한다.