最近、Mroongaの開発をしている児玉です。
Mroongaを開発する中で特定のオブジェクトの中身をデバッグしたい状況になりました。
そんな時に、便利なのがGroongaのオブジェクトの状態を標準出力に表示するgrn_p()
です。
しかし、grn_p()
を使ってターミナル上にオブジェクトの状態を表示しようとしたところ、
うまく表示されませんでした。どうやら標準出力が別の場所に向けられているようです。
今回この問題を解決し、grn_p()
で快適にMroongaをデバッグできるようになったので、
その方法を紹介します!
この記事が、Mroongaのデバッグをしたい方の参考になれば幸いです。 MroongaはMySQLやMariaDBと組み合わせて利用できますが、今回はMariaDBを例に説明します。 (Mroongaに限らず、標準出力先がどこか分からずに困っている方にも役立つかもしれません。)
結論
grn_p()
の出力は、MariaDBの標準出力に出力されます。ただ、デフォルトの設定では、標準出力先はターミナルではなく、
ログファイルに設定されています。そのため、grn_p()
の結果を見るには、MariaDBの標準出力先を特定し、
そこで出力内容を確認する必要があります。
言葉だけでは分かりづらいと思うので、実際に標準出力先を特定し、grn_p()
の結果を見るまでを紹介します。
Mroongaのデバッグでgrn_p()
を利用するまでの具体的な手順
MariaDBの標準出力先を特定する
MariaDBの標準出力先を調べるため、MariaDBが動いているPID(プロセスID)を確認します。
$ ps -C mariadbd -o pid=
2633009
上の結果からMariaDBは、PID2633009
で動いていることがわかります。
そのプロセスのファイルディスクリプターを確認し、標準出力がどこに出力されているかを確認します。
$ ls -la /proc/2633009/fd/
...
lr-x------ 1 otegami otegami 64 10月 31 17:49 0 -> /dev/null
l-wx------ 1 otegami otegami 64 10月 31 17:49 1 -> /dev/shm/var_auto_jCdT/log/mysqld.1.err
標準出力に利用されるファイルディスクリプターは、1
になります。
上の結果から、今回のケースでは/dev/shm/var_auto_jCdT/log/mysqld.1.err
が標準出力先になっているのが分かります。
これで、grn_p()
の出力先がわかったので実際にデバッグしながら出力結果をみていきます。
標準出力先のログファイルを監視する
デバッグ時の出力を確認するために、標準出力先のファイルを監視します。
そうすることで、grn_p()
のログを確認できます。実際にgrn_p()
のログを監視する方法をみていきます。
別のターミナルで、標準出力先である/dev/shm/var_auto_jCdT/log/mysqld.1.err
ファイルを監視します。
$ tail -f /dev/shm/var_auto_jCdT/log/mysqld.1.err
これで、grn_p()
の出力がこのログファイルに書き込まれたときに、リアルタイムで確認できます。
GDBを起動する
次のコマンドを実行して、実際にGDBを起動しデバッグの準備をします。
今回は、mysql-test/mroonga/storage/column/set/t/16_with_index.test
のテストを例に、
GDBを使ってMariaDBのプロセスにアタッチしデバッグを行います。詳細な手順については、デバッグ方法のドキュメントをご参照ください。
$ ../mroonga/test/run-sql-test.sh --manual-gdb ../mroonga/mysql-test/mroonga/storage/column/set/t/16_with_index.test
...
To start gdb for mysqld.1, type in another window:
gdb -x /home/otegami/work/cpp/mariadb-11.4.3.build/mysql-test/var/tmp/gdbinit.mysqld.1 /home/otegami/work/cpp/mariadb-11.4.3.build/sql/mariadbd
ログにあるように別のターミナルで、最後の行のコマンドを実行してGDBを起動してください。
$ gdb -x /home/otegami/work/cpp/mariadb-11.4.3.build/mysql-test/var/tmp/gdbinit.mysqld.1 /home/otegami/work/cpp/mariadb-11.4.3.build/sql/mariadbd
ここまででGDBを起動して、MariaDBのプロセスにアタッチできました。 次は実際に、GDBでブレイクポイントを設定してデバッグします。
ブレイクポイントを設定し、grn_p()
を使用する
デバッグしたい関数にブレイクポイントを設定し、そこで処理を中断してデバッグします。
今回は、ha_mroonga::storage_index_read_map()
関数の処理にブレイクポイントを設定して、
デバッグをしていくのを例としてみていきます。今回は詳しいGDBの使い方に関しては割愛します。
(gdb) b ha_mroonga::storage_index_read_map
ブレイクポイントを設定したら実際にデバッグをしたいプログラムを実行します。
(gdb) run
ブレークポイントで停止したら、grn_p()
を使ってオブジェクトの内容を出力します。
たとえば、grn_table
の状態を確認したいときは、grn_p()
で次のように確認できます。
(gdb) p grn_p(ctx, grn_table)
$4 = void
これで標準出力にgrn_table
のオブジェクトの状態が出力されます。
実際に、標準出力先であるファイルを監視していたターミナルを確認します。
$ tail -f /dev/shm/var_auto_xBE6/log/mysqld.1.err
...
#<table:no_key items value:(nil) size:3 columns:[colors, name] ids:[1, 2, 3] subrec:none>
grn_table
のオブジェクトの情報が表示されていますね。
このような形でMroongaでは、grn_p()
を利用して簡単にデバッグができます。
ここで1つ気をつけるべきポイントを紹介します。 場合によっては、標準出力先であるファイルを監視していたターミナルを確認しても何も表示されないことがあります。 この原因は、表示する内容がバッファーに溜まった状態になっているためです。 なので、バッファーの内容を出力してあげることで解決できます。 では、実際にどのようにバッファーに溜まった出力内容を表示するばよいのかを説明します。
バッファーに溜まったgrn_p()
の出力内容を出力する
標準出力の内容をfflush()
を利用してフラッシュしてあげることで、バッファーに溜まった内容を出力できます。
(gdb) p fflush(stdout)
実際に実行後に、標準出力先のファイルを監視していたターミナルを確認すると、次のように出力されていることを確認できます。
$ tail -f /dev/shm/var_auto_xBE6/log/mysqld.1.err
...
#<table:no_key items value:(nil) size:3 columns:[colors, name] ids:[1, 2, 3] subrec:none>
まとめ
grn_p()
を使ってMroongaのデバッグを行う流れを紹介しました。
これでサクサクとデバッグができるようになったのではないでしょうか?
Mroongaのデバッグに限らず、標準出力先がわからず困っている場合やデバッグ情報が表示されずに困っている場合にも、 役立つ内容になっているのではないでしょうか。
もし、Mroongaを利用してMySQLやMariaDBで全文検索を実現したい方や、開発でお困りのことがありましたら、 ぜひお気軽にお問い合わせください。
私たちは、MroongaやGroongaに関する技術支援やコンサルティングサービスを提供しています。 皆さまの課題解決のお手伝いができれば幸いです。