SlideShare ist ein Scribd-Unternehmen logo
1 von 25
Downloaden Sie, um offline zu lesen
riak-erlang-client
                                2012/12/11 @nobu_k




Thursday, December 13, 12
自己紹介
                    • 久保田展行(@nobu_k)

                    • Preferred Infrastructure(PFI, ピーFI)

                            • Architect: Sedue, Bazil
                    • DB, Distributed Systems, C++
                    • Erlang素人

                            • Riakのコードを読みながら勉強したい
                    •       IIDX




Thursday, December 13, 12
読むもの

                    • riak-erlang-client
                    • +周辺のコード

                            • riak_pb (pb=Protocol Buffers)
                            • riak_kv
                             • リクエストを処理してる部分


Thursday, December 13, 12
riak-erlang-client



Thursday, December 13, 12
概要


                    • Erlang用のクライアント

                    • ソースコード

                            • git://github.com/basho/riak-erlang-
                              client.git



Thursday, December 13, 12
使い方
                > {ok, Pid} = riakc_pb_socket:start_link(Address, Port).
                {ok,<0.34.0>}
                > riakc_pb_socket:ping(Pid).
                pong


                    • https://github.com/basho/riak-erlang-
                      client
                            • githubのREADMEがわかりやすい

                    • Portはconfigのriak_api/pb_portの値

                    • 返値のPidをriakc_pb_socketに渡す感じで

Thursday, December 13, 12
本日のターゲット


                    • riakc_obj.erl
                            • 値

                    • riakc_pb_socket.erl
                            • API



Thursday, December 13, 12
riakc_obj.erl



Thursday, December 13, 12
riak_obj.erl
                > Object = riakc_obj:new(<<"groceries">>, <<"mine">>,
                                         <<"eggs & bacon">>).
                {riakc_obj,<<"groceries">>,<<"mine">>,undefined,
                 [],undefined,<<"eggs & bacon">>}



                    • Riakに保存される値の情報

                    • riakc_obj:new(Bucket, Key, Value).
                            • getで取得する値もこれ


Thursday, December 13, 12
中身
                            -type   bucket() :: binary().
                            -type   key() :: binary() | 'undefined'.
                            -type   vclock() :: binary().
                            -type   metadata() :: dict().
                            -type   content_type() :: string().
                            -type   value() :: binary().
                            -type   contents() :: [{metadata(), value()}].


                            -record(riakc_obj, {
                                      bucket :: bucket(),
                                      key :: key(),
                                      vclock :: vclock(),
                                      contents :: contents(),
                                      updatemetadata :: dict(),
                                      updatevalue :: value()
                                     }).




Thursday, December 13, 12
関数とか


                    • recordの中身に対する操作がほとんど

                    • ところで
                            dict:store(?MD_CTYPE, CT, M1)


                            ?MD_CTYPEの頭に付いてる?はなに?

                            追記:マクロと教えて頂きました!

Thursday, December 13, 12
set系の関数はどこ?
                    • contentなどをセットする関数はない

                    • 代わりにupdateがある

                            • 今の値と更新後の値を別扱い

                            • newに渡した値はupdateに入る

                            • putするとupdateの値が保存される

                             • Riakから元のcontentsは消える

Thursday, December 13, 12
なんでcontentsは配列?
                    • コンフリクトしたときのため

                    • riakc_obj:value_count(Obj).
                    • riakc_obj:get_values(Obj).
                    • コンフリクト除去

                            • updateに適切な値を入れる

                            • 値を選択 or 適切にマージ

Thursday, December 13, 12
riakc_pb_socket.erl



Thursday, December 13, 12
riakc_pb_socket.erl
                    • RPC(?)の部分

                    • 読む順序

                            • 通信っぽい部分

                            • CRUD関係

                            • list系

                            • mapredはMasahitoさんから解説がありそう

                    • 後は実際にコードを読みながら・・・

Thursday, December 13, 12
全体的なメモ1

                    • ***_optionsの書き方が綺麗

                            • リスト+中身のパターンマッチングで再帰

                    • rpb***req
                            • riak_pbのriak_kv.protoを参照

                    • コードの40%がテスト

                            • Riakが起動してることが前提?

Thursday, December 13, 12
全体的なメモ2


                    • 基本はgen_server:call

                            • 値の入ったタプルを投げてるだけ

                            • {req, #pbなrecord, Timeout}




Thursday, December 13, 12
get/putの疑問点

                    • encode
                            • putではencodeした値を送っている

                            • getは受け取った値をそのまま返す

                                • どこかでdecodeされてる?
                    •       そもそもgen_server:callを理解してなかった

                            •   後述しますがhandle_infoの中でレスポンスを処理してます




Thursday, December 13, 12
get: サーバ側の処理
                    • リクエストの処理場所が分からない

                            • rpb***reqを処理してるとこを探す

                            • →riak_kv/riak_kv_pb_object.erl
                            • processのgetreqを処理してるやつ

                    • 中でriak:local_clientのgetを呼んでる

                            • が、今は追わなくてよさそう

Thursday, December 13, 12
get: riak_objectの処理
                    • local_clientが返した値の処理を追う

                            • riakc_objじゃなくてriak_object

                    • riak_pb_kv_codec:encode_contents
                            • 値を返す前にPBにエンコードしてる

                            • やっぱりclientでデコードが必要!?

                    • put側の処理も見てみる
                    •       TODO: vclockに対してなんかやってるのも気になる・・・



Thursday, December 13, 12
put: ちょっと寄り道
                    • clientがエンコードした値の処理され方

                            • riak_kv_pb_object.erl
                            • process putreqの中

                              • update_rpbcontentで値を取り出す

                              • ここでは明示的にデコードしてる

                  %% Update riak_object with the pbcontent provided
                  update_rpbcontent(O0, RpbContent) ->
                      {MetaData, Value} =
                          riak_pb_kv_codec:decode_content(RpbContent),
                      O1 = riak_object:update_metadata(O0, MetaData),
                        •
                      riak_object:update_value(O1, Value).

Thursday, December 13, 12
get: process_response
                    • clientに戻る

                    • decode_contentsを呼んでるとこ発見

                            • handle_info からの process_response
                            •   (再)そもそもgen_server:callを理解してなかった
               process_response(#request{msg = #rpbgetreq{bucket = Bucket, key = Key}},
                                #rpbgetresp{content = RpbContents, vclock = Vclock},
                                State) ->
                   Contents = riak_pb_kv_codec:decode_contents(RpbContents),
                   {reply, {ok, riakc_obj:new_obj(Bucket, Key, Vclock, Contents)},
                    State};




Thursday, December 13, 12
list_keys
                    • 中身はstream_list_keysとwait

                    • strean_list_keys
                            • キーをreceiveしまくる戦法

                            • 対応するのはriak_kv_pb_bucket.erl

                            • riak_clientのstream_list_keysを呼び出し

                             • 中身はまさかのmapred!?

Thursday, December 13, 12
まとめ



Thursday, December 13, 12
まとめ
                    •       riak-erlang-client
                            •   Protocol Buffersを使ってる

                            •   riak_kv/src/riak_kv_pb_{bucket,object}.erlに対応

                    •       すごいエロ本(Learn You Some Erlang for Great Good!)は神

                            •   分からないところを調べながらやってました!

                            •   翻訳した@ymotongpooさんも神

                    •       TODO
                            •   vclockまわり

                            •   サーバ側のリクエスト処理部をもうちょっと追いたい


Thursday, December 13, 12

Weitere ähnliche Inhalte

Was ist angesagt?

UnityのLambda API を Dynamo DB APIっぽく使う
UnityのLambda API を Dynamo DB APIっぽく使うUnityのLambda API を Dynamo DB APIっぽく使う
UnityのLambda API を Dynamo DB APIっぽく使うKinose Tomohito
 
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 3.2.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 3.2.0対応)NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 3.2.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 3.2.0対応)fisuda
 
ラムダと invokedynamic の蜜月
ラムダと invokedynamic の蜜月ラムダと invokedynamic の蜜月
ラムダと invokedynamic の蜜月Taku Miyakawa
 
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 1.13.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 1.13.0対応)NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 1.13.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 1.13.0対応)fisuda
 
なぜリアクティブは重要か #ScalaMatsuri
なぜリアクティブは重要か #ScalaMatsuriなぜリアクティブは重要か #ScalaMatsuri
なぜリアクティブは重要か #ScalaMatsuriYuta Okamoto
 
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 1.14.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 1.14.0対応)NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 1.14.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 1.14.0対応)fisuda
 
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 3.1.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 3.1.0対応)NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 3.1.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 3.1.0対応)fisuda
 
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 2.0.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 2.0.0対応)NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 2.0.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 2.0.0対応)fisuda
 
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 1.15.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 1.15.0対応)NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 1.15.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 1.15.0対応)fisuda
 
Shibuya.lisp #28: 仮題: R について
Shibuya.lisp #28: 仮題: R についてShibuya.lisp #28: 仮題: R について
Shibuya.lisp #28: 仮題: R についてtnoda
 

Was ist angesagt? (11)

UnityのLambda API を Dynamo DB APIっぽく使う
UnityのLambda API を Dynamo DB APIっぽく使うUnityのLambda API を Dynamo DB APIっぽく使う
UnityのLambda API を Dynamo DB APIっぽく使う
 
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 3.2.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 3.2.0対応)NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 3.2.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 3.2.0対応)
 
MySQL de NoSQL Fukuoka
MySQL de NoSQL FukuokaMySQL de NoSQL Fukuoka
MySQL de NoSQL Fukuoka
 
ラムダと invokedynamic の蜜月
ラムダと invokedynamic の蜜月ラムダと invokedynamic の蜜月
ラムダと invokedynamic の蜜月
 
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 1.13.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 1.13.0対応)NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 1.13.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 1.13.0対応)
 
なぜリアクティブは重要か #ScalaMatsuri
なぜリアクティブは重要か #ScalaMatsuriなぜリアクティブは重要か #ScalaMatsuri
なぜリアクティブは重要か #ScalaMatsuri
 
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 1.14.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 1.14.0対応)NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 1.14.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 1.14.0対応)
 
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 3.1.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 3.1.0対応)NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 3.1.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 3.1.0対応)
 
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 2.0.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 2.0.0対応)NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 2.0.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 2.0.0対応)
 
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 1.15.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 1.15.0対応)NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 1.15.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 1.15.0対応)
 
Shibuya.lisp #28: 仮題: R について
Shibuya.lisp #28: 仮題: R についてShibuya.lisp #28: 仮題: R について
Shibuya.lisp #28: 仮題: R について
 

Ähnlich wie Riak Source Code Reading #2: Erlang Client

Web Operations and Perl kansai.pm#14
Web Operations and Perl kansai.pm#14Web Operations and Perl kansai.pm#14
Web Operations and Perl kansai.pm#14Masahiro Nagano
 
第8回KPF発表資料
第8回KPF発表資料第8回KPF発表資料
第8回KPF発表資料cryks
 
Web技術勉強会 第25回
Web技術勉強会 第25回Web技術勉強会 第25回
Web技術勉強会 第25回龍一 田中
 
tcpdump & xtrabackup @ MySQL Casual Talks #1
tcpdump & xtrabackup @ MySQL Casual Talks #1tcpdump & xtrabackup @ MySQL Casual Talks #1
tcpdump & xtrabackup @ MySQL Casual Talks #1Ryosuke IWANAGA
 
Kai = (Dynamo + memcache API) / Erlang
Kai = (Dynamo + memcache API) / ErlangKai = (Dynamo + memcache API) / Erlang
Kai = (Dynamo + memcache API) / ErlangTakeru INOUE
 
RestKitの紹介 - Webサービスのクライアント実装補助フレームワーク -
RestKitの紹介 - Webサービスのクライアント実装補助フレームワーク -RestKitの紹介 - Webサービスのクライアント実装補助フレームワーク -
RestKitの紹介 - Webサービスのクライアント実装補助フレームワーク -次朗 永島
 
fluentd を利用した大規模ウェブサービスのロギング
fluentd を利用した大規模ウェブサービスのロギングfluentd を利用した大規模ウェブサービスのロギング
fluentd を利用した大規模ウェブサービスのロギングYuichi Tateno
 
Ruby で扱う LDAP のススメ
Ruby で扱う LDAP のススメRuby で扱う LDAP のススメ
Ruby で扱う LDAP のススメKazuaki Takase
 
~knitr+pandocではじめる~『R MarkdownでReproducible Research』
~knitr+pandocではじめる~『R MarkdownでReproducible Research』~knitr+pandocではじめる~『R MarkdownでReproducible Research』
~knitr+pandocではじめる~『R MarkdownでReproducible Research』Nagi Teramo
 
Learning spaerk chapter03
Learning spaerk chapter03Learning spaerk chapter03
Learning spaerk chapter03Akimitsu Takagi
 
HashiCorpのNomadを使ったコンテナのスケジューリング手法
HashiCorpのNomadを使ったコンテナのスケジューリング手法HashiCorpのNomadを使ったコンテナのスケジューリング手法
HashiCorpのNomadを使ったコンテナのスケジューリング手法Masahito Zembutsu
 
Cookpad 17 day Tech internship 2017 言語処理系入門 Rubyをコンパイルしよう
Cookpad 17 day Tech internship 2017 言語処理系入門 RubyをコンパイルしようCookpad 17 day Tech internship 2017 言語処理系入門 Rubyをコンパイルしよう
Cookpad 17 day Tech internship 2017 言語処理系入門 RubyをコンパイルしようKoichi Sasada
 
Integral - New O/R Mapper for Common Lisp
Integral - New O/R Mapper for Common LispIntegral - New O/R Mapper for Common Lisp
Integral - New O/R Mapper for Common Lispfukamachi
 
20130626 kawasaki.rb NKT77
20130626 kawasaki.rb NKT7720130626 kawasaki.rb NKT77
20130626 kawasaki.rb NKT77nkt77
 
Javaはどのように動くのか~スライドでわかるJVMの仕組み
Javaはどのように動くのか~スライドでわかるJVMの仕組みJavaはどのように動くのか~スライドでわかるJVMの仕組み
Javaはどのように動くのか~スライドでわかるJVMの仕組みChihiro Ito
 
AWS Black Belt Online Seminar 2017 Amazon DynamoDB
AWS Black Belt Online Seminar 2017 Amazon DynamoDB AWS Black Belt Online Seminar 2017 Amazon DynamoDB
AWS Black Belt Online Seminar 2017 Amazon DynamoDB Amazon Web Services Japan
 

Ähnlich wie Riak Source Code Reading #2: Erlang Client (20)

Web Operations and Perl kansai.pm#14
Web Operations and Perl kansai.pm#14Web Operations and Perl kansai.pm#14
Web Operations and Perl kansai.pm#14
 
第8回KPF発表資料
第8回KPF発表資料第8回KPF発表資料
第8回KPF発表資料
 
Web技術勉強会 第25回
Web技術勉強会 第25回Web技術勉強会 第25回
Web技術勉強会 第25回
 
tcpdump & xtrabackup @ MySQL Casual Talks #1
tcpdump & xtrabackup @ MySQL Casual Talks #1tcpdump & xtrabackup @ MySQL Casual Talks #1
tcpdump & xtrabackup @ MySQL Casual Talks #1
 
Kai = (Dynamo + memcache API) / Erlang
Kai = (Dynamo + memcache API) / ErlangKai = (Dynamo + memcache API) / Erlang
Kai = (Dynamo + memcache API) / Erlang
 
RestKitの紹介 - Webサービスのクライアント実装補助フレームワーク -
RestKitの紹介 - Webサービスのクライアント実装補助フレームワーク -RestKitの紹介 - Webサービスのクライアント実装補助フレームワーク -
RestKitの紹介 - Webサービスのクライアント実装補助フレームワーク -
 
fluentd を利用した大規模ウェブサービスのロギング
fluentd を利用した大規模ウェブサービスのロギングfluentd を利用した大規模ウェブサービスのロギング
fluentd を利用した大規模ウェブサービスのロギング
 
Ruby で扱う LDAP のススメ
Ruby で扱う LDAP のススメRuby で扱う LDAP のススメ
Ruby で扱う LDAP のススメ
 
Riakmeetup2forupload
Riakmeetup2foruploadRiakmeetup2forupload
Riakmeetup2forupload
 
OSC2012 OSC.DB Hadoop
OSC2012 OSC.DB HadoopOSC2012 OSC.DB Hadoop
OSC2012 OSC.DB Hadoop
 
~knitr+pandocではじめる~『R MarkdownでReproducible Research』
~knitr+pandocではじめる~『R MarkdownでReproducible Research』~knitr+pandocではじめる~『R MarkdownでReproducible Research』
~knitr+pandocではじめる~『R MarkdownでReproducible Research』
 
Learning spaerk chapter03
Learning spaerk chapter03Learning spaerk chapter03
Learning spaerk chapter03
 
HashiCorpのNomadを使ったコンテナのスケジューリング手法
HashiCorpのNomadを使ったコンテナのスケジューリング手法HashiCorpのNomadを使ったコンテナのスケジューリング手法
HashiCorpのNomadを使ったコンテナのスケジューリング手法
 
Cookpad 17 day Tech internship 2017 言語処理系入門 Rubyをコンパイルしよう
Cookpad 17 day Tech internship 2017 言語処理系入門 RubyをコンパイルしようCookpad 17 day Tech internship 2017 言語処理系入門 Rubyをコンパイルしよう
Cookpad 17 day Tech internship 2017 言語処理系入門 Rubyをコンパイルしよう
 
activerecord-turntable
activerecord-turntableactiverecord-turntable
activerecord-turntable
 
Integral - New O/R Mapper for Common Lisp
Integral - New O/R Mapper for Common LispIntegral - New O/R Mapper for Common Lisp
Integral - New O/R Mapper for Common Lisp
 
20130626 kawasaki.rb NKT77
20130626 kawasaki.rb NKT7720130626 kawasaki.rb NKT77
20130626 kawasaki.rb NKT77
 
Javaはどのように動くのか~スライドでわかるJVMの仕組み
Javaはどのように動くのか~スライドでわかるJVMの仕組みJavaはどのように動くのか~スライドでわかるJVMの仕組み
Javaはどのように動くのか~スライドでわかるJVMの仕組み
 
AWS Black Belt Online Seminar 2017 Amazon DynamoDB
AWS Black Belt Online Seminar 2017 Amazon DynamoDB AWS Black Belt Online Seminar 2017 Amazon DynamoDB
AWS Black Belt Online Seminar 2017 Amazon DynamoDB
 
MongoDB2.2の新機能
MongoDB2.2の新機能MongoDB2.2の新機能
MongoDB2.2の新機能
 

Mehr von nobu_k

Elasticsearchと機械学習を実際に連携させる
Elasticsearchと機械学習を実際に連携させるElasticsearchと機械学習を実際に連携させる
Elasticsearchと機械学習を実際に連携させるnobu_k
 
機械学習を利用したちょっとリッチな検索
機械学習を利用したちょっとリッチな検索機械学習を利用したちょっとリッチな検索
機械学習を利用したちょっとリッチな検索nobu_k
 
4th PFI System reading
4th PFI System reading4th PFI System reading
4th PFI System readingnobu_k
 
Goraft and InfluxDB
Goraft and InfluxDBGoraft and InfluxDB
Goraft and InfluxDBnobu_k
 
Transactional Information Systems入門
Transactional Information Systems入門Transactional Information Systems入門
Transactional Information Systems入門nobu_k
 
Suffix Array@Solr勉強会
Suffix Array@Solr勉強会Suffix Array@Solr勉強会
Suffix Array@Solr勉強会nobu_k
 
第一回MongoDBソースコードリーディング
第一回MongoDBソースコードリーディング第一回MongoDBソースコードリーディング
第一回MongoDBソースコードリーディングnobu_k
 

Mehr von nobu_k (8)

Elasticsearchと機械学習を実際に連携させる
Elasticsearchと機械学習を実際に連携させるElasticsearchと機械学習を実際に連携させる
Elasticsearchと機械学習を実際に連携させる
 
機械学習を利用したちょっとリッチな検索
機械学習を利用したちょっとリッチな検索機械学習を利用したちょっとリッチな検索
機械学習を利用したちょっとリッチな検索
 
4th PFI System reading
4th PFI System reading4th PFI System reading
4th PFI System reading
 
Goraft and InfluxDB
Goraft and InfluxDBGoraft and InfluxDB
Goraft and InfluxDB
 
Transactional Information Systems入門
Transactional Information Systems入門Transactional Information Systems入門
Transactional Information Systems入門
 
Paxos
PaxosPaxos
Paxos
 
Suffix Array@Solr勉強会
Suffix Array@Solr勉強会Suffix Array@Solr勉強会
Suffix Array@Solr勉強会
 
第一回MongoDBソースコードリーディング
第一回MongoDBソースコードリーディング第一回MongoDBソースコードリーディング
第一回MongoDBソースコードリーディング
 

Riak Source Code Reading #2: Erlang Client

  • 1. riak-erlang-client 2012/12/11 @nobu_k Thursday, December 13, 12
  • 2. 自己紹介 • 久保田展行(@nobu_k) • Preferred Infrastructure(PFI, ピーFI) • Architect: Sedue, Bazil • DB, Distributed Systems, C++ • Erlang素人 • Riakのコードを読みながら勉強したい • IIDX Thursday, December 13, 12
  • 3. 読むもの • riak-erlang-client • +周辺のコード • riak_pb (pb=Protocol Buffers) • riak_kv • リクエストを処理してる部分 Thursday, December 13, 12
  • 5. 概要 • Erlang用のクライアント • ソースコード • git://github.com/basho/riak-erlang- client.git Thursday, December 13, 12
  • 6. 使い方 > {ok, Pid} = riakc_pb_socket:start_link(Address, Port). {ok,<0.34.0>} > riakc_pb_socket:ping(Pid). pong • https://github.com/basho/riak-erlang- client • githubのREADMEがわかりやすい • Portはconfigのriak_api/pb_portの値 • 返値のPidをriakc_pb_socketに渡す感じで Thursday, December 13, 12
  • 7. 本日のターゲット • riakc_obj.erl • 値 • riakc_pb_socket.erl • API Thursday, December 13, 12
  • 9. riak_obj.erl > Object = riakc_obj:new(<<"groceries">>, <<"mine">>, <<"eggs & bacon">>). {riakc_obj,<<"groceries">>,<<"mine">>,undefined, [],undefined,<<"eggs & bacon">>} • Riakに保存される値の情報 • riakc_obj:new(Bucket, Key, Value). • getで取得する値もこれ Thursday, December 13, 12
  • 10. 中身 -type bucket() :: binary(). -type key() :: binary() | 'undefined'. -type vclock() :: binary(). -type metadata() :: dict(). -type content_type() :: string(). -type value() :: binary(). -type contents() :: [{metadata(), value()}]. -record(riakc_obj, { bucket :: bucket(), key :: key(), vclock :: vclock(), contents :: contents(), updatemetadata :: dict(), updatevalue :: value() }). Thursday, December 13, 12
  • 11. 関数とか • recordの中身に対する操作がほとんど • ところで dict:store(?MD_CTYPE, CT, M1) ?MD_CTYPEの頭に付いてる?はなに? 追記:マクロと教えて頂きました! Thursday, December 13, 12
  • 12. set系の関数はどこ? • contentなどをセットする関数はない • 代わりにupdateがある • 今の値と更新後の値を別扱い • newに渡した値はupdateに入る • putするとupdateの値が保存される • Riakから元のcontentsは消える Thursday, December 13, 12
  • 13. なんでcontentsは配列? • コンフリクトしたときのため • riakc_obj:value_count(Obj). • riakc_obj:get_values(Obj). • コンフリクト除去 • updateに適切な値を入れる • 値を選択 or 適切にマージ Thursday, December 13, 12
  • 15. riakc_pb_socket.erl • RPC(?)の部分 • 読む順序 • 通信っぽい部分 • CRUD関係 • list系 • mapredはMasahitoさんから解説がありそう • 後は実際にコードを読みながら・・・ Thursday, December 13, 12
  • 16. 全体的なメモ1 • ***_optionsの書き方が綺麗 • リスト+中身のパターンマッチングで再帰 • rpb***req • riak_pbのriak_kv.protoを参照 • コードの40%がテスト • Riakが起動してることが前提? Thursday, December 13, 12
  • 17. 全体的なメモ2 • 基本はgen_server:call • 値の入ったタプルを投げてるだけ • {req, #pbなrecord, Timeout} Thursday, December 13, 12
  • 18. get/putの疑問点 • encode • putではencodeした値を送っている • getは受け取った値をそのまま返す • どこかでdecodeされてる? • そもそもgen_server:callを理解してなかった • 後述しますがhandle_infoの中でレスポンスを処理してます Thursday, December 13, 12
  • 19. get: サーバ側の処理 • リクエストの処理場所が分からない • rpb***reqを処理してるとこを探す • →riak_kv/riak_kv_pb_object.erl • processのgetreqを処理してるやつ • 中でriak:local_clientのgetを呼んでる • が、今は追わなくてよさそう Thursday, December 13, 12
  • 20. get: riak_objectの処理 • local_clientが返した値の処理を追う • riakc_objじゃなくてriak_object • riak_pb_kv_codec:encode_contents • 値を返す前にPBにエンコードしてる • やっぱりclientでデコードが必要!? • put側の処理も見てみる • TODO: vclockに対してなんかやってるのも気になる・・・ Thursday, December 13, 12
  • 21. put: ちょっと寄り道 • clientがエンコードした値の処理され方 • riak_kv_pb_object.erl • process putreqの中 • update_rpbcontentで値を取り出す • ここでは明示的にデコードしてる %% Update riak_object with the pbcontent provided update_rpbcontent(O0, RpbContent) -> {MetaData, Value} = riak_pb_kv_codec:decode_content(RpbContent), O1 = riak_object:update_metadata(O0, MetaData), • riak_object:update_value(O1, Value). Thursday, December 13, 12
  • 22. get: process_response • clientに戻る • decode_contentsを呼んでるとこ発見 • handle_info からの process_response • (再)そもそもgen_server:callを理解してなかった process_response(#request{msg = #rpbgetreq{bucket = Bucket, key = Key}}, #rpbgetresp{content = RpbContents, vclock = Vclock}, State) -> Contents = riak_pb_kv_codec:decode_contents(RpbContents), {reply, {ok, riakc_obj:new_obj(Bucket, Key, Vclock, Contents)}, State}; Thursday, December 13, 12
  • 23. list_keys • 中身はstream_list_keysとwait • strean_list_keys • キーをreceiveしまくる戦法 • 対応するのはriak_kv_pb_bucket.erl • riak_clientのstream_list_keysを呼び出し • 中身はまさかのmapred!? Thursday, December 13, 12
  • 25. まとめ • riak-erlang-client • Protocol Buffersを使ってる • riak_kv/src/riak_kv_pb_{bucket,object}.erlに対応 • すごいエロ本(Learn You Some Erlang for Great Good!)は神 • 分からないところを調べながらやってました! • 翻訳した@ymotongpooさんも神 • TODO • vclockまわり • サーバ側のリクエスト処理部をもうちょっと追いたい Thursday, December 13, 12