[OSSCA] 과제 #4 echo 함수 만들기
과제 내용
1. echo와 동일한 echo{아이디}로 echoCommand 추가
1-1 commands.def 에 새 명령어 등록
1-2 새 명령어가 호출할 command 함수 구현
1-3 서버 시작 시 command table에 등록 클라이언트 요청 시 lookup 후 c->cmd->proc(c) 에서 실행2. ossca-2026-valkey에 PR을 보내기
3. 전체 과정 블로깅
commands.def 에 각 명령어가 MAKE_CMD() 형태로 들어있다.
1
{MAKE_CMD("name", function, arity, flags,ACL, keys/args)}
- name: 클라이언트가 호출할 때 사용하는 명령어 문자열
소스 코드 상에서는 소문자로 정의, 클라이언트가 대문자로 호출하더라도 구분 없이 매칭 - function: 해당 명령어가 호출되었을 때 실제로 실행될 함수 포인터
보통 void commandName(client *c)의 형태. 예) echo -> echoCommand - arity: 명령어에 전달될 수 있는 인자의 개수를 정의
양수일 경우, 인자의 개수가 정확히 n개이어야 한다.
음수을 경우, 인자의 개수가 최소 n개 이상이어야 한다. - flags: 해당 명령어가 시스템에 어떤 영향을 주는지 비트 플래그로 설정
CMD_WRITE: 데이터를 변경하는 명령어 (Read-only 복제본에서 실행 불가).
CMD_READONLY: 데이터를 읽기만 하는 명령어.
CMD_ADMIN: 서버 설정 변경 등 관리자 권한이 필요한 명령어.
CMD_NOSCRIPT: Lua 스크립트 내에서 실행을 금지할 때 사용. - ACL: 명령어가 어떤 카테고리에 속하는지 정의
@read, @write, @slow, @fast, @string, @list 등
echo로 확인해보면 아래와 같이 나눌 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
MAKE_CMD(
"echo","Returns the given string.","O(1)","1.0.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,ECHO_History,0,ECHO_Tips,0,
echoCommand,
2,
CMD_LOADING|CMD_STALE|CMD_FAST,
ACL_CATEGORY_CONNECTION|ACL_CATEGORY_FAST,
NULL,
ECHO_Keyspecs,0,
NULL,
1
),
.args = ECHO_Args
},
그리고 server.c에는 아래와 같이 echoCommand 함수가 구현되어 있다.
echoJihoon 구현
1-1 commands.def에 새 명령어 등록
기존 echo를 그대로 복사하기엔 변화가 있어야 알아보기도 쉬우니 jihoon이 포함된다면 hello! + String의 형태로 만들어보자
1
2
3
4
5
6
7
8
9
10
11
12
/* ossca assignment 4 */
{
MAKE_CMD(
"echoJihoon","Returns 'hello!' + string if it contains 'jihoon', otherwise returns the given string.",
"O(N)","1.0.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,ECHO_History,0,ECHO_Tips,0,
echoJihoonCommand,
2,
CMD_LOADING|CMD_STALE|CMD_FAST,
ACL_CATEGORY_CONNECTION|ACL_CATEGORY_FAST,
NULL,ECHO_Keyspecs,0,NULL,1
),
.args=ECHO_Args},
1-2 새 명령어가 호출할 command 함수 구현
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/* ossca assignment 4 */
void echoJihoonCommand(client *c) {
robj *o = c->argv[1];
robj *decoded = getDecodedObject(o);
char *payload = (char*)objectGetVal(decoded);
if (payload && strcasestr(payload, "jihoon") != NULL) {
sds response = sdsnew("hello! ");
response = sdscat(response, payload);
addReplyBulkSds(c, response);
} else {
addReplyBulk(c, o);
}
decrRefCount(decoded);
}
*robj: redis object
*sdsnew: 새로운 동적 문자열 메모리 할당
c -> argv[0] : ECHOJIHOON
c -> argv[1] : MESSAGE
문자열에서 대소문자 상관없이 jihoon을 찾으면 해당 위치를 반환하는 strcasestr을 사용하여 if문을 작성했다.
sds를 사용하면 메모리 공간이 부족할때 자동으로 크기를 늘린다고 한다.
1-3 서버 시작 시 command table에 등록 클라이언트 요청 시 lookup 후 c->cmd->proc(c) 에서 실행
commands.def 파일에 구문 추가 진행
server.h 파일에 함수 선언
성공!








