Redisのソースコードをちょっと読んでみようという試み(1)
C言語でHello world以上のものを読むのは初めてだった。とりあえず実装の詳細は飛ばして、
サーバー立ち上げる -> クライアントから繋がる -> コマンドが実行される -> 書き込まれる までの関数の呼ばれる流れだけを追ってみた。
大分意図的に端折ってるし、意図せず抜けてたり間違ってたりすると思うから、間にうけないほうが良さそう
Doxygenというので、ドキュメントっぽいのを生成して、それも時々見てた。全然関係ないけどdoxygenをgui付きのオプション付けて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というやつが, コマンドの情報とか色々持っていて、そいつに対して値をセットしたり色々しながら 最終的にそいつが持ってる情報から実行するみたいな感じだった。とりあえずメモを残そうと思って残したけど、次読もうとするのいつになるか分からない。