제가 공부한 내용을 정리하는 블로그입니다.
아직 많이 부족하고 배울게 너무나도 많습니다. 틀린내용이 있으면 언제나 가감없이 말씀해주시면 감사하겠습니다😁

이번 과제는 지난 과제 3이였던 echo 명령을 개선하는 과제이다.

이번 힌트는 sds 구조체 분석이다. 

과제 3 세팅

먼저 이전 과제 3번을 세팅하면

이전 과제에서는 직접 command.def 파일에 정의했다면 json 파일을 통해 정의하는 방법으로 진행하겠다.

src/commands 아래에 echo2.json 파일을 다음과 같이 생성한다. document와 함께 def 파일을 정의하기 위해 redis에서는 다음과 같이 json으로 빌드 시에 def 파일에 정의할 수 있도록 하였다.

{
    "ECHO2": {
        "summary": "Returns the given string.",
        "complexity": "O(1)",
        "group": "connection",
        "since": "1.0.0",
        "arity": 2,
        "function": "echo2Command",
        "command_flags": [
            "LOADING",
            "STALE",
            "FAST"
        ],
        "acl_categories": [
            "CONNECTION"
        ],
        "reply_schema": {
            "description": "The given string adding string echo2",
            "type": "string"
        },
        "arguments": [
            {
                "name": "message",
                "type": "string"
            }
        ]
    }
}

그 이후 utils/ 폴더의 generate-command-json.pygenerate-command-code.py 를 실행하면 command.def 파일에 정의가 된다.

command.def

이후 이제 server.h와 server.c에서 echo2Command를 정의한다.

server.h
server.c

가 되면 과제 3은 완료가 되었다!

과제 4


함수 실행 flow

먼저 함수 실행 flow를 분석해보면

다음과 같다. 간략하게 설명하면

  • connGetPrivateData: client 객체를 생성
  • ProcessInputBuffer: protocol에 따라 Inline으로 실행할 지 Multibulk로 실행할 지 판단.
  • lookupCommand: 지금 실행하는 함수를 Map에서 조회. 실행하는 함수 이름을 key로.
  • call: 함수를 실행.

이다.

구조체 분석

함수를 다음과 같이 구성하고 echo2 123을 실행해보면 shell에 *2\r\n$5\r\necho2\r\n$3\r\n123\r\n이 출력된다.

그래서 나는 querybuf를 변경하면 될 것이라 생각했고, querybufclient 구조체의 멤버이므로 client는 다음과 같이 이루어져 있었다.

server.h에 정의되어 있는 client 구조체

sds 구조체(Simple Dynamic String)

querybuf는 sds 구조체로 이루어져 있어 해당 sds 구조체를 보면 다음과 같다.

sds.h

단순히 문자열을 sds라고 칭한 것인데, 조금 더 분석해보자면

  • 문자열을 단순히 char*만 사용하면 문자열의 길이를 확인할 때 항상 저장된 메모리의 크기를 확인해야 하기에 성능 상의 문제점이 발생할 수 있음.
    • sdshdr 구조체를 사용함으로써, 저장된 문자열의 길이를 확인하는데 O(1)의 조회가 됨.
  • 실제로 데이터가 저장되는 부분은 char*로 저장되어 있는 sds.
  • 새로운 문자열을 생성하려면 sdsnewLen함수를 이용.

과제 수행

echo2Command 이후 addReplyBulk를 분석하면 다음과 같다. 

틀릴 확률이 높지만 파악한대로 설명을 이어나가면

  • addReplyBulkLen: 명령어의 길이를 파악
  • addReply: 실제 argu 값을 반환
  • addReplyProto: 마무리 작업.

을 한다고 파악이 되었다. 예를 들어 echo2 123이면 

  • addReplyBulkLen: 123의 길이인 3을 파악하고
  • addReply: 123이라는 값을 반환하고
  • addReplyproto: 명령어를 종료.

한다고 생각했다. 따라서 상위 함수인 addReplyBulk에 client 객체에 querybuf만 변화시켜주면 된다고 생각했는데 되질 않았다.

강의를 듣고 수정해보도록 하겠다.

💡 참고
redis sds관련: https://djlee118.tistory.com/109

 

+ Recent posts