diff --git a/docs/internal/epock_file_handling.md b/docs/internal/epock_file_handling.md deleted file mode 100644 index 9f4c6f2..0000000 --- a/docs/internal/epock_file_handling.md +++ /dev/null @@ -1,126 +0,0 @@ -# Epoch Fileに関する修正 - -## 問題点 - -現在のEpochファイルには、以下の2つの問題がある。 - -1. ローテーション時にEpochファイルもローテーションされるが、ローテーションされたEpochファイルを削除する機能が存在しないため、ファイルが増え続ける。 -2. ローテーションを行わないと、Epochファイルのサイズが単純に増え続けるので、以下の問題が生じる。 - * ディスク容量を無駄に消費する。 - * ファイルサイズの巨大化による性能劣化 - * ファイルサイズの制限により動かんくなる(おそらく現実的には発生しなし) - - -## 修正方針 - - -### ローテーションされたEpochファイルを増やさないための修正 - -* コンパクション時には、Epochファイルのローテーションが不要にもかかわらずローテーションを行っているので、これをやめる。 -* Epochの追記時に、Epochファイルのサイズが一定サイズを超えた場合に、Epochファイルの切り詰めを行う。 - * 以下のロジックでEpochファイルの着る詰めを行う - * テンポラリファイルを作成する。 - * テンポラリファイルにEpochを書き込む - * テンポラリファイルと、Epochファイルをrename2を使用してアトミックに入れ替える。 - * テンポラリファイル(=もとのEpochファイル)を削除する。 - * この操作は、クリティカルセクション内で行い、他のEpocファイルに関する操作が干渉しないようにする。 - - -### ローテーションされたEpochファイルを削除するための修正 - -* コンパクション時にEpochファイルのローテーションをやめたので、Epochファイルのローテーションが行われるのは、 - バックアップのためのローテーション時のみになる。 -* ローテーションされたEpochファイルはバックアップ終了後に削除可能だが、 現状バックアップ終了を検知する手段がない。 -* 現段階ではローテーションされたEpochファイルを削除する機能は実装せず、バックアップ後のクリーニング機能実装時に併せて実装する。 - * バックアップ時のクリーニング機能 - * バックアップ時に、またはバックアップ語に当該バックアップがあれば不要になるローテーション済みファイルを削除する機能。 - -## 現状のEpochの仕様 - -### 起動時 - -* epoch_id_type dblog_scan::last_durable_epoch_in_dir()で、epochを決定している。 -* この関数の処理内容 - * main_epoch_file: ローテーションしていないepochファイルが存在しない場合はエラー(=>異常終了) - * ログディレクトリが空の場合は異常終了していはいけない。このようなケースでは、関数が呼ばれる前にディレクトリが初期化されEpochファイルが存在すろちう前提なのだろう。 - * main_epoch_fileからepochが取り出し、その値を返す。 - * main_pepch_fileからepochを取り出せなかった場合、全てのローテーション済みのepoch_fileから、epochを取り出し、最大のepochを適用する。 - * epochファイルからpeochの取り出しは、last_durable_epoch()を使用している。 -* last_durable_epoch()の処理内容。 - * epochファイルを順に呼んでいき、最後のエントリのEpoch IDを返す。 - * marker_durable以外のエントリがある場合エラー - * エントリがない場合は、空のEpoch IDを返す。 - * => 戻り値は、Optional - -### Epcohファイル更新時 - -datastore::update_min_epoch_id()で、 -epoch_idを決定して、epochファイルにエントリを追加している - - - -### Epochファイルのローテーション - -* datastore::rotate_epoch_file()で行われている。 - * 現行のEpochファイルをリネームして、ローテンション済みファイルにする。 - * リネームしたファイルをdatastoreが管理するファイルのリストに追加する。 - * 新しいEpochファイルを作成する。 - -### 現状のEpochの問題点と対応方針 -* ローテーション時のリネームから新規Epochファイルの作成までの間にプロセスが落ちると、Epochファイルが存在しない状態になる。 - * 新規Epochファイルの作成失敗時も同じ状態になる。 - * この状態で次回起動時に、Epochファイルが存在しないことが理由で起動に失敗し、手作業でEpochファイルを復旧しない限り、起動しなくなる。 -* 単に起動時にEpochファイルが存在シない場合は、ローテーションされたEpochファイルを参照するようにすればよさそうだが、Epochファイルの存在有無を、正しいログディレクトリが存在するかの確認のためにも使用しているので、単純な方法ではNG。 - -* 対応方針1 - * 一時的にEpochファイルが存在しない状態を許容する。 - * 起動時にEpochファイルが存在しない場合も、Epochファイルが空の場合と同様に、ローテションされたファイルからDurabe Epochを取得する。 - * Epochファイルの存在を、正しいログディレクトリが指定されたことの確認に使用せず、別の方法で確認する。 - * マニフェストファイルをこの用途に使用する。 - * ついでにマニフェストファイルにFlockをかけて、道立ログディレクトリを使用したTsurugiの二重起動防止や、Tsurugi起動中にtglogutilでログを修正することの防止にも使用する。 - - -## Epochファイル更新時のepoch_idの決定ロジック - -datastore::update_min_epoch_id()の処理だが、コードを読んでも -何をしているのかわからないので、関連する変数がどのように扱われているのかを調べる。 - -関連する変数とは - -* datastore::update_min_epoch_id()のローカル変数 - * upper_limit - * よくわからない - * max_finished_epoch - * よくわからない - * old_epoch_id - * 関数実行中のある瞬間のepoch_id_recorded_の値 - * to_be_epoch - * Epochファイルに書き込むべきepoch_id、ただしこの値がold_epoch_id未満の場合は、Epochファイルに書き込まない。 - * 永続化処理の後、upper_limitが代入され処理が行われる~~が、何をしているのか分からない。~~ - * 特定の条件を満たすときにinformed_epoch_を、upper_limitに設定し、persistent_callback_を呼び出している。 - * uppper_limitの値をto_be_epochに設定しているのは、informed_epoch_に設定すべき値という意味であり、前の方の処理では、永続化する値という意味だと思われる。2つの値は必ずしも一致しない。 - * old_epoch_id - * 関数実行中のある瞬間のepoch_id_informed_の値 - -* datasotreクラスのフィールド - * epoch_id_switched_ - * 最後のdatastore::switch_epoch()呼び出しの引数で指定されたepoch_idの値 - * 起動時には、datastore::create_snapshot()で値が設定される。 - * snapshot作成時に戻り値として返されるepoch_idを設定する。 - * 具体的にどのような値が設定されるかは未調査。 - * epoch_id_recorded_ - * epochファイルに書き込んだ値? - * epoch_id_informed_ - * persistent_callback_で通知したepoch_idの値 - -* log_channelクラスのフィールド - * current_epoch_id_ - * セッション開始時に、epoch_id_switched_の値がセットされる。 - * セッション修了時にクリアされる(UINT64_MAX) - * latest_ession_epoch_id_ - * セッション開始時に、epoch_id_switched_の値がセットされる。 - * current_epoch_id_と異なりセッションが終了しても保持される - - - - diff --git a/docs/internal/epock_handling.md b/docs/internal/epock_handling.md deleted file mode 100644 index 9763cfe..0000000 --- a/docs/internal/epock_handling.md +++ /dev/null @@ -1,88 +0,0 @@ -# LimestoneのEpoch処理のまとめ - - -## LimestoneのEpoch処理の要件 - -* Epochに関するLimestoneのAPIは以下の3つ(※1) - * datastore::switch_epoch(epoch_id_type new_epoch_id) - * 指定のEpochに切り替える。 - * log_channel::begin_session() - * ログチャネルのセッションを開始する。 - * 当該セッションのEpochは、直近のswitch_epoch()で指定されたEpochになる。 - * log_channel::end_session() - * ログチャネルのセッションを終了する。 - * ログ出力用のストリームをflush, syncしクローズする。 - -* 上記3メソッドは任意のタイミングで呼び出される。呼び出しがオーバーラップすることもありえる。 - * ただし、同一のログチャネルのbegin_session()とend_session()はオーバラップすることはない。 - -* limestoneはEpoch終了時に、Epochファイルの更新と、persistent_callback_の呼び出しを行う。 - * 次の条件が満たされるとき、当該Epochが終了したとみなす。 - * datastore::switch_epoch()により、当該Epochより新しいEpochに切り替えられた。 - * 当該Epochのセッションが全て終了した。 - -※1 この他に、persistent_callbackに関するAPIがある。 - -## LimestoneのEpoch処理の概要 - -### Epochの状態を管理する変数 - -以下のatomic変数で、Epochの状態を管理している。各atomic変数の参照、更新時に -mutxなどによる排他制御や同期は行われていない。 - -* data_store::epoch_id_switched_ - * 最後のdatastore::switch_epoch()呼び出しの引数で指定されたepoch_idの値 -* data_sotre::epoch_id_recorded_ - * 最後にepochファイルに書き込んだepoch_idの値 -* data_store::epoch_id_informed_ - * persistent_callback_で通知したepoch_idの値 -* log_channel::current_epoch_id_ - * セッション開始時に、epoch_id_switched_の値がセットされる。 - * セッション修了時にクリアされ、UINT64_MAXがセットされる。 -* log_channel::finished_epoch_id_ - * セッション修了時に、current_epoch_id_の値がセットされる。 - -※ この他に、コンパクション処理で以下の変数を使用しているが、本ドキュメントの議論の範囲では使用していないので、本ドキュメントのスコープ外とする。 - -* log_channel::latest_session_epoch_id_ - * セッション開始時に、epoch_id_switched_の値がセットされる。 - * current_epoch_id_と異なりセッションが終了しても保持される - -### datastore::update_min_epoch_id()の処理内容 - -datastore::switch_epoch()呼び出し時と、log_channel::end_session()呼び出し時に、datastore::update_min_epoch_id()が呼び出される。この中で必要に応じで、epochファイルの更新と、persistent_callback_の呼び出しが行われる。 - -#### upper_limit の決定 - -* アクティブなlog_channelが1つもない場合 - * epoch_id_switched_ - 1 -* アクティブなlog_channelがある場合 - * アクティブなlog_channelの中で最小のcurrent_epoch_id_ - 1 -* epochがこの値より大きくなってはいけないという意図だと思う。 - -#### max_finished_epochの決定 - -* 各log_channelの中で最大のfinished_epoch_id_をmax_finished_epochに設定する。 - -#### epochファイルの更新 - -* to_be_epochの決定 - * switch_epochから呼ばれたとき - * uppper_limtとmax_finished_epochの小さい方の値をセットする - * アクティブなセッションがない場合はuppper_limtがUINT64_MAX - 1なので、max_finished_epochがセットされる。 - * log_channel::end_session()から呼ばれたとき - * uppper_limtにto_be_epochをセットする。 -* epoch_id_recorded_がto_be_epoch以上の場合、epochファイルの更新は行わない。そうでない場合は、epoch_id_recorded_ を更新し to_be_epoch の値をセットする。 - * この処理は、epoch_id_recorded_.compare_exchange_strong()を使用して行う。 - * 他のスレッドによりepoch_id_recorded_が更新された場合は、他のスレッドにより更新された値とto_be_epochの値を比較し、to_be_epochの方が小さい場合、epochファイルの更新処理を行わない。 -* epochファイルの更新 - * epoch_id_recorded_の値をepochファイルに書き込む。 - -#### persistent_callback_ の呼び出し - -* to_be_epochの決定 - * uppper_limtをto_be_epochに設定する。 -* epoch_id_informed_がto_be_epoch以上の場合、persistent_callback_の呼び出しは行わない。そうでない場合は、epoch_id_informed_を更新し、to_be_epochの値をセットする。 - * この処理は、epoch_id_informed_.compare_exchange_strong()を使用して行う。 - * 他のスレッドにより、epoch_id_informed_が更新された場合は、他のスレッドにより更新された値とto_be_epochの値を比較し、to_be_epochの方が小さい場合、persistent_callback_の呼び出しを行わない。 -