ニマイガイとマキガイをカード合併した図

UNDOシステムを搭載していないZT BASIC版で源氏物語全系譜6.1.ZELの全体図を#235 常陸介の前の北の方で開き,浮舟の母の配偶者欄で「常陸介」→「7777常陸介」のように変更して「登録」すると,系統並び替え中TOPOLOGY::MakeActiveListでエラーが発生する.treeview->validcardとActiveList->countのカウントが一致していない.「7777常陸介」という新しいカードが生成されているので,有効なカード数は318から1増えて319になっているはずだが,ActiveList->countは318のままになっている.treeview->validcardはSetKinshipから得ているが,TOPOLOGY::validcardnumとも同期している.validcardnumはTOPOLOGY::HideNameboxでカウントされている.

ActiveListはTOPOLOGY::MakeActiveListで生成されているが,ここではPDB()->lookup->tableを使ってカードにアクセスしている.lookup->countが318のままになっている.CARDTABLE::makelinkでは以前はMakingLookUpを実行していたが,@2018-02-1に 廃止された.同様に廃止された箇所が2箇所ある.MakingLookUpはルックアップテーブルを1から作り直す関数で,カードテーブルへのリンクの挿入と削除に際しては実行される必要がある.UNDOBASE:UndoProcessとCommandEndではつねにMakingLookUpが実行される.

MakingLookUpでテーブルの作り直しをしているのなら,個別にメンテナンスするより,系統並び替えで一度だけ更新するというのが早いのではないか?そうすれば,1箇所だけで済むようになるはずだ.それでもよいとは思われるが,現状を追認して,CARDTABLEとMARGTABLEのmakelink,FAMILYTREE::callSendCardで復活させることにする.削除の場合も必要になると思われるが,CARDTABLE:deletelinkの末尾で実行しているdecmaxrecnでMakingLookUpを実行するようにしたら,却ってエラーが出るようになってしまった.

image

これはVB側で出しているエラーだ.UpdateMaxCardはステータスバーを更新するための関数で,Z.RecordCountとZ.ActiveCountを比較している.Z.ActiveCountはおそらくActiveListのカウントに対応するものと思われるが,更新されていないため319になっている.Z.RecordCountはmaxRecordCountで取得された値で,lookupテーブルのカウントが入っている.MakingLookUpを実行しないようにすると,エラーは発生しないが,ステータスバーのカード数は319/319のまま更新されていない.つまり,誤った数字が表示されている.

問題は2つある.①MakingLookUpの実行後,Z.RecordCountとZ.ActiveCountで不一致が生じる,②系統並び替えを実行してActiveCountが更新されてもUpdateMaxCardが実行されない(ステータスバーが更新されない)⇒lookupテーブルはActiveListや部分図リスト構築のために使われているので,系統並び替えで一度だけ更新するというのでよいのではないか?まず,この修正を入れてみたい.バックアップを取ってからやることにしよう.

同上サンプルで常陸介を含む十数点のカードを選択→ 常陸介を削除で被参照カウントの残留が発生した.参照カウントが4残留している.参照はすべてMARGBOX[22]で「所属系列の先祖ノード人名リンクへの参照」が入っている.常陸介を単独削除しても同様事象が発生する.CARDLINK::DisposeではTRIBEBOX::CleanSansyoで先祖ノードからの参照をクリーンアップしているはずなのだが… これらの結婚枠はおそらくなんらかの事情で系列移籍が実行されたものではないかと思われる.所属系列の先祖と結婚枠が保持する先祖リンクが一致しない.

MARGBOX::CheckMargBoxChangedでこのような先祖リンクは積極的に解除するようにした.また,TRIBEBOX::CheckTribeでは「結婚リンクの先祖不在」を無視するようにした.実際,大半の結婚枠の先祖リンクは空になっている.⇒「7777常陸介」のカードが追加されたとき,一覧表が更新されていない.やはり,「系統並び替えで一度だけ更新」というのはダメのようだ.コマンド実行に対応するVB側の動作は「コマンド処理」のスコープで実行されなくてはならない.系統並び替えはそれと非同期に実行されるものなので,タイミング的に遅れてしまう.

元の論理に戻して,CARDTABLE::deletelinkとMARGTABLE:deletelinkでそれぞれMakingLookUpを実行するようにした.「UpdateMaxCard 不正なカード数」エラーが発生する件に関しては,maxcount < Z.ActiveCount に付け加えて Z.mSpanTreeNode() = 0 を見るようにした.これでエラーは回避できるようになった.

カード合併時には記録ページのマージが実行される.UNDOをサポートしていないシステムでこの辺りがどのような動作になっているのかが気になるところだ.⇒UNDOがサポートされていないシステムでは削除されたオブジェクトが復活するということはあり得ないから,特に何の問題も起きないと考えられる.2021年2月27日 のログではUNDOの問題が起きているが,この版の素性が問題だ.

UNDOをテストしているのだから,UNDOは実装されていたはずだが,ゴミ箱は外してあったのではないだろうか?多分,DEFINEUNDOSYSTEMだけがオンになっていたはずだ.ゴミ箱がなくても基本的にUNDOは動作する.Shadow付きのオブジェクトは削除されないからだ.しかし,写真や記録ページのようなfreeblockオブジェクトは削除されているはずだ.だとすれば明らかにUNDO/REDOで不具合が起きても不思議はない.まず,反例を確保する必要がある.

逆にZT Basicでは写真や記録ページをサポートしないという仕様も考えられるのだが… それも少しわびしい気持ちがする…

DEFINEUNDOSYSTEMをオン,それ以外のZT BASICでサポートされない(ゴミ箱を含む)機能をすべてオフにした版で軟体動物3.zelの動作を見てみたが,やはりUNDO/REDOはできない.ゴミ箱がある場合には,freeblockオブジェクトはゴミ箱に残っているので,それを参照するオブジェクトが復活した場合にも問題なく動作するが,メモリから完全にパージされてしまえばそれもできなくなる.しかし,ゴミ箱に入っているオブジェクトはリサイクルに回る可能性があるから,運が悪ければ同じようなエラーが起きる可能性はあると考えなくてはならない.

従って,UNDOをサポートしている場合には,ゴミ箱のあるなしに関わらず,freeblockオブジェクトをパージしないようにする必要があると考えられる.ゴミ箱に入らない場合にはフロート状態のオブジェクトとしてNリングに連結されるはずだ.freeblockオブジェクトにはカード記録ページやカード写真イメージの他に,データベースの作業域その他に用いるバッファ類やタイトル情報などがある.

多分タイトル情報はUNDOの対象になっていないはずだから,保護しなくてはならないfreeblockオブジェクトはMM_NOTEPAGEとMM_CARDIMAGEだけではないかと思われる.まず,これらのオブジェクトをパージしないという仕掛けを作ってみよう.⇒うまく行ったようだ.下図は,ニマイガイとマキガイをカード合併した図だ.

image

ニマイガイの下にマキガイの類が混載状態になっている.記録ページも両方のページを合体したものになっている.この動作はゴミ箱のあるなしに関わりなく,どちらでも動作するものになっている.これで一昨日出ていたバグは解決しているのではないかと思う.ま,まずい.UNDO/REDOの動作は確認したつもりだが,UNDOで戻ろうとしてエラーになった.ニマイガイの方はUNDOで戻ると記録ページも復元されているが,マキガイの方は写真も記録も消えてしまう.オブジェクト本体は残っているので,その限りではUNDOにはなっているが…

image

ビットマップはやや難しいところがあるので,記録ページのRTFの方を追いかけてみよう.⇒CARDLINK.CARDBASE.bitmapinfoとnotepageは空になっている..cBitmapには値は残っているがパージされた状態になっている.まず,ゴミ箱付きのときの動作を確認してみよう.UNDOはうまく行ったが,REDOがおかしい.処理の途中でバックアップタイマーの割り込みが入って,作業域のためのメモリ要求が出されて記録ページが使われそうになっている.

このオブジェクトのsnumは131だが,NODULE.sizeが179603240というとんでもない数字になっている.その他の部分は概ねまともなので,どこかで書き込みが発生している可能性がある.というか,ここで例外が発生しているので,このアドレス自体すでにパージされている可能性がある.再起動して,バックアップタイマーを止め,ファイルをクローズしようとしてTRASHCAN::throwCanで停止した.

delete wasteで例外が発生している.NODULE.sizeは215179560という値になっている.このオブジェクトのsnumは232だ.⇒クリーンビルドで作り直したら動作するようになった.しかし,2回目のUNDOでまた引っかかった.freeblock::_delmem_でdelete mblockを実行しようとして例外が発生した.やはり,sizeに大きな数が書き込まれている.CARDBASEのデストラクタではcBitmapをdeleteし,bitmapinfoとnotepageをfreeblock::_delmem_している.

これでは写真や記録を復元することなどできないのではないだろうか?むしろ,これまで動いていたとすればその方が不思議という感じもする… 古いバージョンでは~CARDBASEでビットマップの破棄などをやっていなかったのではないだろうか?⇒~CARDBASEを無動作で抜けるようにして動作するようになった.

コメントを残す

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

CAPTCHA