UNDOに関していくつか重要な修正を行った

UNDOに関していくつか重要な修正を行った.①UndoNumberを設置する,②ShadowチェーンからUNDOノードを検出する,③UNDOのShadowをfreeblock化など.①はUNDOノードの重複を避けるために,コマンド発行ごとにインクリメントされる値で,保全対象のオブジェクトにはこの値が格納され,すでに格納済であるか否かを判断する材料とする.②は従来方式ではコマンドに連結されたUNDOノードリングをスキャンしていたのを,オブジェクトのShadowチェーンを直接操作する方式に変更した.この方がスキャンの範囲を狭めることができる.③は②を実現するために必要となった措置で,これまではヒープから直接切り出していたバックアップイメージ領域をfreeblockのオブジェクトとして管理できるようにするものである.

昨日のログではこれらの修正後,ある程度改善されたとしているが,実質的にはまったく変化していない.つまり,依然としてUNDOノードの増殖は続いている.これに対処するために,UNDOノードリング上に同じタイプで完全に同内容のイメージが存在するためには,リングに追加しないようにしたところ,一昨日の障害が再発してしまった.

▲UNDOBASE::UndoProcess→ TOPOLOGY::RebuildCardList→ NAMESORT::NameSort→ NAMESORT::SortNameSub→ compnode のコールバックでcard2の参照番号が0になっている.⇒この障害は,2022-04-23に初発したもので,「オブジェクトのコピーにUndoNumberを格納していたことが誤動作の原因」として廃止しているが,その後の修正で,オブジェクトのコピーの前にUndoNumberを設定しているので,シャドーにもそれがコピーされている.

前回はこの障害をカードテーブル上のカードの参照番号がゼロとなるタイミングをSWOで追いかけて突き止めているので,試してみよう.⇒UNDOSYSTEM::RestoreShadowで完全に白紙のシャドーがリストアされている.このUNDOのノードのSSNは#614867.どこでこのノードが生成されたかを見る必要がある.このノードはCARDLINK#2246のバックアップだ.CARDLINK#2246はカード番号@479の「479」というカードで,カード削除の対象カードだ.

UNDOチェーンには#2246のバックアップは「削除」コマンド分しか残っていない.BackupPointDataでは保全されているので,上書きされてしまったのではないだろうか?⇒UNDOBASE::SetUndoListの修正にミスがあった.ただしこれを訂正後,COUPLING::TopologicalSort→ TOPOLOGY::SortAncestorTableで「先祖ノード数がゼロ」という別の障害が出てきた.カードテーブルには分散しているが,カードは入っている.maxrecn=361でtablesizeは8192,基準ノードは@23だ.

senzosu=1となっているが,Senzolist配列には何も入っていない.TOPOLOGY::SortAncestorTableで先祖リストを生成している.⇒カードテーブルにアクセスできていない.getmaxrecnが返す値がカードテーブルの範囲をカバーしていない.⇒BASETABLE::getmaxrenはmin(maxrefnum, tablesize)を返しているが,テーブルはmaxrefnumよりも拡がっている.⇒暫定的にtablesizeを返すようにした.むしろ最大レコード番号を返せるようにした方がよいのだが… ⇒これで収まるかと思われたが,まだ(max < 1)が起きる.

▲極小反例 361.zelでカード@479を単点削除した後のUndo出口→ 系統並び替え→ TribeDecomposition→ SortAncestorTableで(max < 1) で停止する.基準ノードは@479.これは,UNDOがよく機能していないことを示すものではないか?対象ノードの親がQに入っていないため離脱している.Qへの登録はTOPOLOGY::InitializeDecompositionとTOPOLOGY::GetkinshipDegreeで実行されている.InitializeDecompositionはTOPOLOGY::TribeDecompositionで実行される.TOPOLOGY::TribeDecompositionはTOPOLOGY::FilteringKinshipから呼び出される.FilteringKinshipはTribeDecompositionに先行する.

@479の親は#1841@35で,InitializeDecompositionではQに登録されている.⇒@ 35はQに入っている.先祖ノードであることも確認されている.問題は優先ノードが一致しないという点だ.これは,InitializeDecompositionではやっていない.⇒少し混乱している.Undo後の系統並び替えの基準ノードは@23で,先祖ノードは@35だ.@479を削除した後,Undoしているのだから,元の原木に戻っているはずだ.それが,実際は@479を削除して4系列に分解したままの状態になっているということだろう.おそらく,@479の事前バックアップデータが上書きされてしまっているのだろう.つまり,事後データは別途保存されなくてはならないというところが崩れているのだろう.⇒UNDONODEクラスにUNDOTYPE undotypeを新設し,createを廃止して,SetUndoListの引数のcopymodeと統合してundotypeに吸収した.UNDOTYPE は「SetUndoListのノード生成時の動作種別」で,以下のように類別される.

  1. UNDO_DEL = -2, オブジェクトの削除コマンド
  2. UNDO_NEW,         オブジェクトの新規生成コマンド
  3. UNDO_NORMAL,   オブジェクトが保全されている場合は上書きしない
  4. UNDO_COPY,        オブジェクトが保全されている場合は上書きする
  5. UNDO_MAKE,        つねにUNDOノードを新規生成する

この修正によって動作はかなり改善されたが,まだ時間経過とともにUNDOノードが増殖するという傾向は残っている.以前は等比級数的に増加していたところが,等差級数的に近くなっている.現行論理では,一つのオブジェクトに対して,undotypeが同じUNDOノードは生成されないようになっているから,オブジェクト1個につき,最大でも5個以上のリングにはならないはずなのだが…また,1個につき上限が5個で,かつ毎回Undoしているのだから,単調増加することはあり得ないように思われるのだが…少しランニングさせて様子を見ることにしよう.やはり,各回につき10個くらいづつ増加している…

どうも,UNDOBASE::CommandEndでコマンドオブジェクトを一つ追加しているというのが敗因であるように思われる.このコマンドは完全にダミーの役割しか果たしていないのだが,これがあると,UndoとRedoの状態の管理がかなりシンプルなものになるという理由から導入されたものだ.しかし,これを廃止するということは本質的な改善にはならないのではないか?というのは,この位置にはリングノードはまったく追加されていないからだ.

コマンドを実行するときには,最初に現在のUndo位置のコマンドリングを完全に削除してからコマンドの実行に入る.従って,つねに白紙状態から実行に移ることになる.これならリングノードの増殖が起こる余地はないと考えられるのだが…もし,それで差し支えないのなら,現行論理のまま,UNDOの現在位置の一つ前の位置まで戻して,そこをクリーンアップすればよいのではないか?いや,むしろ,CommandEndで書き込みしている部分を前方に移動すべきなのではないか?

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA