Subscribed unsubscribe Subscribe Subscribe

Redisのソースコードをちょっと読んでみようという試み(1)

C言語Hello world以上のものを読むのは初めてだった。とりあえず実装の詳細は飛ばして、
サーバー立ち上げる -> クライアントから繋がる -> コマンドが実行される -> 書き込まれる までの関数の呼ばれる流れだけを追ってみた。
大分意図的に端折ってるし、意図せず抜けてたり間違ってたりすると思うから、間にうけないほうが良さそう

Doxygenというので、ドキュメントっぽいのを生成して、それも時々見てた。全然関係ないけどdoxygengui付きのオプション付けてbrewでビルドしようとしたけど、依存しているQtのビルドに時間がかかって、そのうえGUI(doxywizard)のバイナリ出来てなかった感じがして損した感じがした。

しょうがないからDoxyfile色々いじってやった。https://gist.github.com/ToQoz/5057612 途中関数のコールグラフみたいなのが出てきてる感じになったけど、色々いじってたら出てこなくなった気がする。

main
  initServer
    acceptTcpHandler(acceptUnixHandler)
      anetTcpAccept
        anetGenericAccept
          accept
                                   # クライアントから繋がれました~~~
      acceptCommonHandler
        createClient               # redisClient作って返す(この後こいつが色々持つ、コマンドとか)
          readQueryFromClient      # clientからのqueryの長さとかチェックしたりする
            processInputBuffer     # request typeとか決定したり(決まって無い時), そのチェックしたり
              processCommand       # lookupCommandでコマンド探してcallで実行する
                lookupCommand      # 実行するコマンドを探しす
                call               # コマンドを実行してる(redisClient c->cmd->proc())
                                   # procはredisCommandTableで, コマンドごとに登録されていて、
                                   # それが実行される. ↓こんな感じ

  struct redisCommand redisCommandTable[] = {
    {"get",getCommand,2,"r",0,NULL,1,1,1,0,0},
    {"set",setCommand,3,"wm",0,noPreloadGetKeys,1,1,1,0,0},

例えばsetコマンドだと、procは

# src/t_string.c
void setCommand(redisClient *c) {
  c->argv[2] = tryObjectEncoding(c->argv[2]);
  setGenericCommand(c,0,c->argv[1],c->argv[2],NULL,0);
}

という感じで, valueをエンコードして, setGenericCommandに client, nx(謎), key, value, expire, unit(謎) を渡している.

流れはこんな感じ。

setCommand          # 値をエンコードとか
  tryObjectEncoding # エンコードしようとしてる
  setGenericCommand # expireチェックとか
    setKey          # 実際にキーに値をセット(この関数の中より下見てない, dbAdd or dbOverrideで書き込まれてるっぽい)

とにかくredisClientというやつが, コマンドの情報とか色々持っていて、そいつに対して値をセットしたり色々しながら 最終的にそいつが持ってる情報から実行するみたいな感じだった。とりあえずメモを残そうと思って残したけど、次読もうとするのいつになるか分からない。