自分の始末は自分で付ける,すべて自己責任

オブジェクトのノーマルな終了手続きとアノーマルな終了手続きを切り分けるためにblackflagというフラグを導入しているが,最終的には廃止して,状況に関わりなくいつでもどこでも単にdeleteを実行するだけで整合的な終了措置を実現できるのではないかと思う.なぜなら,blackflagは親オブジェクト側でdataCountDownを実行した,つまりオブジェクトのデストラクタではdataCountDownを実行しなくてよいということを伝達するだけのものになっているからだ.

フラグを廃止しオブジェクトのデストラクタでつねにdataCountDownを実行するようにしても動作には変わりはない.ノーマルな終了処理とアノーマルな終了処理が実質的に同一の操作になる.これでオブジェクトの親は親であることに責任を持たなくてもよいということになった.逆に言えば,自分自身の始末を付けるのは自分であり,すべて自己責任ということにもなる…オブジェクトの世界は意外にシンプルでわかり易い.(いや,人の世界では元々そうだ.親に先立つのはノーマルではないとみなされている…)

このようなこと(秩序立った終末期処理)を可能としているのは,やはりZTシステムで採用している「(双方向)接続」という関係の存在ではないだろうか?「(単方向)参照」しか存在しない世界でこのようなことができるだろうか?不可能ではないかもしれないが,おそらく「接続」と似た機構がどこかで必要になってくるような気がする…

BUG20-12-02 01-34-26.ZELを開いて,孤立した#251 noduleを削除してUNDOSYSTEM::CommnadEndで(unode->create < 0 && !unode->address->Deleted() && !unode->address->checkcid(‘P’))というエラーが出た

CommnadEndが呼び出されるときにはすでにdeleteは実行されているのだから,Deletedになっていないというのはかなりおかしい.⇒ゴミ箱に入っているのは確かだが…Nringから移動したという形跡がない.⇒VAIOにインストールされているバージョンではこのような現象は起きていない.VAIOにインストールされているのはV2.2.0.016 R2020-11-02だ.⇒とんでもないミスを冒していた.~noduleをdisoposingがONという理由でパスしていた.完全な間違いだ.

同上の操作を行って,UNDOSYSTEMの出口のTOPOLOGY:topologicalSorting→ChecWasterCountでカウントが合っていない waste + Nodecount() – (NEWOBJECTCNT – REUSECOUNT)はつねにゼロでなくてはならないところ,差分1が生じている

9994 = waste=23 + Nodecount=9971
9993 = NEWOBJECTCNT=129753 – REUSECOUNT=119760

NEWOBJECTCNTとREUSECOUNTの数字はおそらく間違いないので,waste+Nodecountの方に誤りがあるのではないか?ダブって数えている可能性がある.削除されたオブジェクトがゴミ箱に入っていることは確かなので,Nringのカウントが間違っているか,ないしリング上に残っているのだろう.⇒ゴミ箱への移動とNringからの切断が同時に行われていればまず,このようなことは起きないはずなのだが…

ゴミ箱への投棄TRASHCAN::DumpWasteはnodule::operator deleteで実行される.Nringからの削除はsetNringのコマンドNRING_DELETEないし,NRING_DISCONNECTで実施される.NRING_DELETEではオブジェクトのDELETEDをONに設定するがまだコンタクトは切れていない.NRING_DISCONNECTでリングからの切断が実行される.しかし,これが実行されるのはIfDuplicatedという特殊なケースだけだ.⇒いや,違う.NRING_DELETEのケース文ではブレイクしないで下に続くNRING_DISCONNECTを実行している.

setNring(NRING_DELETE)はnodule::operator deleteでDumpWasteの直前に実施されている.条件はShadowedではないこととDELETEDがゼロ以下であることだ.削除されたカードはUNDOで保全されてShadowedとなっているため,Nringから切断されていない.コメントでは「UNDOで保全されたShadow付きノードもゴミ箱に入れる@20170825」としている.このコメントは「UNDOで保全されたShadow付きノードはNringとゴミ箱にダブル登録される」と解釈されるが,これはChecWasterCountの指針と合致しない.

2017年のログが残っているだろうか?「2017-08-25 UNDOで保全されたオブジェクトをゴミ箱の管理下に置く」という記事があった.これは決定事項であり,「仕様」と考えるしかなさそうだ.「UNDOで保全されたオブジェクト」とは一般には削除されたオブジェクトであり,それがゴミ箱に移動するというのは妥当であるとしても,Nringとの重複というのはかなり問題だ.ゴミ箱の中のオブジェクトはリサイクルの対象となるが,Shadowedオブジェクトは除外されているようなので,その点で誤動作することはないとしても,あまり感心した状態ではない.

いまここではUNDOシステムの細部まで踏み込みたくはないし,UNDO自体はとりあえず問題なく動作しているように思われるのでUNDOシステムをいじることはしたくないが,カウントは一致するようにしておかなくてはならない.NringにはNRING_INVALIDATEという操作があるが,「DELETE=NRING_INVALIDATEであることとShadowを持つことは必ずしも一致しない」とあるので,単純にこれだけを除外すればよいということにはならない.ゴミ箱に入っているという属性はないので,チェックするとすればIsInTrashCanを実行しなくてはならない.

ここでは暫定的にNringのnodecountをカウントするときに,NRING_INVALIDATEでかつShadowedであるものを除外するとしてみよう.⇒NRING_INVALIDATEはコマンドでDELETEには(通常の削除されたオブジェクトと同様)負値が入る.NRING_INVALIDATE→ Nring上でDELETEが負という状態と一致する.実質的にはこれはShadowedと一致しているはずだ.NRING_INVALIDATEはカード合併時にも適用されているが,その後すぐに削除されるので状態としては維持されていない.いや,まだおかしいことがある.

NODEREFLISTが11個もダブル登録されている.⇒これはおそらく,IsInTrashCanの誤動作だ.いや,誤動作ではない.削除されたカードに付帯してゴミ箱に移動しているためだ.ゴミ箱はCIDごとのリストになっているので,付帯オブジェクトはゴミとしてはカウントされないから,重複にはならない.⇒nodule::IsOntheListという関数を新設して直列リスト上のノードだけを拾うようにした.⇒nodecountではなく,activeringを使えば数字は一致する.今日のところは取り敢えず,これで逃げておくことにしよう.

上記サンプルを起動→終了してCloseFamilyBaseのとき,~TRIBEBOXでdatacountが負になった 障害ノードは系列枠#8478.DATALIST::findにcheckdatacountを仕掛けたところ,TRIBELISTではひどいデータカウントの不一致が発生していることが分かった.他のリストでは起きていないので,何かTRIBELISTに限った事情があるように思われる.DATALISTでdatacountをprivateにしてみよう.datacountを取り出すsizeという関数があるが,リストなのでlenとリネームした.datacountを直接操作している関数がいくつかある.

  1. NLIST::put
  2. nlist::put
  3. PAIRBOX::MoveSamePoint
  4. PAIRBOX::ChannelChange
  5. PAIRLIST::puttail
  6. PAIRLIST::takeout
  7. PAIRLIST::cutout
  8. NAMEBOX::makePairBox
  9. NLIST::insert

datacount→len()に書き換えた箇所は58箇所.TRIBELISTはNLISTの派生クラスなのでこれらが関係しているとすれば,上の(1)putかないし(9)のinsert,あるいはその両方と考えられるが,これらの関数でカウントダウンが起きる可能性はない… 暫定的にdataCountというdatacountの参照※を返す関数を作っておこう.⇒LISTがDATALISTのfriendクラスになっていた.⇒datacountが負になる原因が分かった.dataCountDownが重複して呼び出されていた.最初は~TRIBEBOX,ついで~noduleからも掛かってくる.これはblackflagがONになっていないためだ.dataCountDownの中でONにすることで解消した.

※ここで言う『参照』とZTシステムで常用している「参照」では意味が異なる.ZTで「参照」というときにはつねにオブジェクトを指すポインタ(メモリ上のオブジェクトのアドレス)を意味している.「リンク」という語もこの意味で用いられる.これに対しC++言語で言う『参照』はオブジェクトの実体を示すものとして定義され,『参照』を別の変数に代入すると,そこには元のオブジェクトの複製が格納される.また,『参照』を返す関数をオブジェクトの実体そのものとして操作できる.

▲同上サンプルを起動→終了してPAIRLIST::checkdatacountでデータ数不一致が発生する.⇒多分これは擬似的なものだと思う.PAIRLIST::Removeの中で起きているので,リストには削除対象ノードが含まれているためではないか?いや,数字はその逆だ.datacountつまり,論理値が3でリスト上の実カウントが2になっている.これはおかしい.PAIRLISTの処理は多少込み入っているので,先にロジックを整理してしまった方がよいのではないか?

コメントを残す

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

CAPTCHA