-
Notifications
You must be signed in to change notification settings - Fork 55
expiretime 동작 방식
-
ASCII 문자열 형태의 exptime 수신
-
해당 exptime 문자열을
long
(64bit 정수형)타입으로 읽은 후int32_t
(부호가 있는 32bit 정수형)으로 형변환-
long
을 더 작은 크기의int32_t
로 변환 → 상위 32bit의 데이터가 손실됨 (invalid data)클라이언트가
long
을 사용하여 32bit 정수형을 초과하는 값을 전송하면, 제대로 된 동작이 불가. -
서버에서 이를 처리하는 코드(
safe_strtol
)bool safe_strtol(const char *str, int32_t *out) { assert(out != NULL); errno = 0; *out = 0; char *endptr; long l = strtol(str, &endptr, 10); // ASCII 문자열을 long 형태로 변환 if (errno == ERANGE) return false; if (isspace(*endptr) || (*endptr == '\0' && endptr != str)) { *out = l; // long 형태로 변환된 값을 int32_t 변수에 다시 넣음 return true; } return false; }
-
-
int32_t
타입의 exptime을 언제 만료되어야 하는지에 대한 상대적인 값으로 변환 후 캐시에 저장-
캐시 서버는 아래의 두 가지 시간 변수를 설정
- 구동 시간 :
process_started
- 자료형 : time_t (
long
) - 서버가 구동 시작한 시점의 unix 시간 저장
- 자료형 : time_t (
- 현재 시간 :
current_time
- 자료형 : rel_time_t (
uint32_t
) - 서버가 구동 후부터 현재까지 흐른 시간(초) 을 보관
- libevent의 timer event 이용하여 매 1초마다 현재의 unix 시간에서
process_started
뺀 값을 저장
- 자료형 : rel_time_t (
- 구동 시간 :
-
위의 두 변수를 통해 아래의 방식으로 exptime을 상대값으로 변환하여 저장
-
exptime > 30days (클라이언트가 unix 시간 형태의 exptime을 설정한 경우)
-
입력받은 exptime에서
process_started
뺀 값을 저장 -
example :
클라이언트가 전송한 exptime = 1577805000
서버의
process_started
= 1577804300→ 캐시에 저장되는 exptime = 700 (1577805000 - 1577804300)
-
-
exptime ≤ 30days (클라이언트가 몇 초 후에 만료될 지의 exptime을 설정한 경우)
-
입력받은 exptime에서
current_time
합한 값을 저장 -
example :
클라이언트가 전송한 exptime = 600
서버의
current_time
= 100→ 캐시에 저장되는 exptime = 700 (600 + 100)
-
-
-
두 경우 모두 서버 기준으로 만료되는 시간이 계산되며, 부호없는 32bit 정수형(
uint32_t
)으로 저장-
캐시에 저장하는 값이 unix 시간 자체가 아닌 서버 구동 시간에 따른 상대적인 값
→ 32bit unix 시간에서 생기는 2038년 문제에 영향을 받지 않음
-
서버 구동 시간(
process_started
)보다uint32_t
의 최대값인 4294967295초(약 136년)보다 큰 값의 시간이 아니라면 캐시에 저장되는 자료형은uint32_t
를 사용해도 문제가 없음
-
-
서버에서 이를 처리하는 코드(
realtime
)static rel_time_t realtime(const time_t exptime) { if (exptime == 0) return 0; if (exptime < 0) { #ifdef ENABLE_STICKY_ITEM if (exptime == -1) return (rel_time_t)(-1); #endif return (rel_time_t)1; } if (exptime > REALTIME_MAXDELTA) { // 30일을 초과할 때 if (exptime <= process_started) return (rel_time_t)1; // 입력받은 exptime(unix time)에서 서버가 구동 시작한 값을 뺌. return (rel_time_t)(exptime - process_started); } else { // 30일 이하일 때 // 입력받은 exptime에서 서버가 구동 이후 현재까지 흐른 시간을 더함. return (rel_time_t)(exptime + current_time); } }
-
- 클라이언트로부터 값을 전달받는 변수의 자료형은 64bit 정수형으로 변경 필요
- 캐시에 저장되는 자료형은 32bit 정수형을 그대로 사용해도 무방
- invalid item 검사 :
current_time (현재 시간)
이 cache item에 저장된 exptime을 초과했는지 여부에 따라 판별 -
getattr
명령 : 저장된 exptime에서 다시current_time
을 빼서 앞으로 몇 초 후에 만료가 되는지 출력-
서버에서 이를 처리하는 코드(
human_readable_time
)static rel_time_t human_readable_time(const rel_time_t exptime) { if (exptime == 0) { return exptime; #ifdef ENABLE_STICKY_ITEM } else if (exptime == (rel_time_t)-1) { return exptime; #endif } else { if (exptime <= current_time) { return (rel_time_t)-2; } else { return exptime - current_time; } } }
-
- 서버에서 사용하는 프로그래밍 언어는 C → 정수 자료형에 대하여 부호 유무 결정이 가능
- 클라이언트에서 사용하는 프로그래밍 언어는 Java, C++ → Java는 무조건 부호가 있는 정수 자료형만 가능
- 서버의 시간 계산은
uint32_t
로 부호가 없기에 Java의int
와 호환이 안될 가능성이 있음. - 예를 들어, 계산 결과가 2147483648초(약 68년)를 초과할 때, Java에서는 음수로 인식되어 잘못된 연산을 가져올 수 있음
- 서버의 시간 계산은
→ Java 클라이언트에서 서버와 송수신하는 시간 관련 변수들의 자료형을 모두 Long 타입으로 변경이 필요함.