制御された解体(controlled demolition)のポイントが大体つかめた

制御された解体(controlled demolition)のポイントが大体つかめた.病院のベッドであるいは自宅で近親者に囲まれて最後の時を迎えるのがノーマルな死であるとすれば,事故死や自殺,孤独死などはアノーマルな死と言える.このような意味でオブジェクトのアノーマルな削除に対処するというのが制御された解体の目的である.

削除されたオブジェクトはメモリから消去(ないしゴミ箱に移動)される前に必ずそのデストラクタが呼び出されるので,知人・関係者に死亡通知を送りつけることができる.その時点で知人・関係者とのコンタクトが取れなくなっている場合には何もできないが,知人・関係者がすでに他界しているのであれば(できないことは)問題にはならない.

関係者側では死亡通知を受理した時点で事後処理を実施する.この方式なら関係者が関わりを持たない場所でアノーマリィに削除された場合にも対処することができるので,システムの一貫性・データの整合性を保つことがこれまでよりはるかに容易なものになる.PAIRLIST→ PAIRBOXとEDGELIST→ SIMPLEEDGEの関係に限定してテスト的に実装しているが,まだエラーが残っている.

アプリ終了でEraseTreeView→~TRIBEBOX→… SIMPLEGRAPH:TakeRemainSansyoを実行中にLIST::nextでエラーが検出される

TakeRemainSansyoのループで最初にNODELISTを処理した時点でデータ不整合が発生している.対象グラフはTOPOLOGYのgraph3(系列木グラフ生成用枝グラフ)だ.識別し易いようにgraph3をリネームしてTribeTreeGraphとしておこう.このグラフの節点は系列枠だ.⇒確かにNODELIST::Removeを実行しただけでEDGELISTに影響が及んでいる.不思議だ…節点が削除されるとそれを参照している枝にも影響が出るということのようだが… EDGELISTはNODELIST要素を参照しているので,その参照がクリアされることは確かだが… NODELIST::Removeが実行されると,EDGELISTの要素は23個から16個に減少する.つまり,7個削減されている.事後のdatacountとtoplistの値は正しいが,bottomlistの値がtoplistと同じになっている.

グラフの枝の両端点のいずれかが削除されるとその枝も削除されるようになっているが,どこでやっているのかはよくわからない.いずれにしても,この操作で不整合が発生していることは間違いない.節点の削除を実施するグラフの関数は2つある.releaseとReleaseだ.前者は節点が参照するオブジェクトが削除されたとき,後者は節点そのものが削除されたときの操作だが,いずれも枝の両端点のうちいずれかが削除されたときには,枝を枝リストから削除するようになっている.しかし,枝の削除を実行するSIMPLEGRAPH::removeでSIMPLEEDGE::removeの前後をチェックしているが,不整合は検知されていない.

TakeRemainSansyoの入口でトリガーを掛けても,SIMPLEGRAPH:remove(SIMPLEEDGE*)実行では停止しない.⇒TakeRemainSansyoは再帰的に実行されている!再帰から戻ったときに値が戻ってしまうのではないか?というか,いまのblackflagのプロトコルは再帰実行されることを予定していない.また難問が出てきた… 現行方式では delete → Dispose → dataCountDown → 事後処理のフローは直列かつ即時・排他的に実行されることを予定している.blackflagを関数のローカル変数に置くことができれば再帰実行に対処することは難しくないが,delete の実行と dataCountDown は独立の別関数でまったく非同期に実行されるため,クラスのメンバ変数とするしかない.つまり,現行方式ではこの問題には原理的に対処できない.

ではどうすればよいか?こうなれば豚のトレーサビリティシステムのように個体に識別子を付けて履歴管理するしかない.いや,個体識別子はもちろん付いている.豚の全頭履歴管理を行うというのは確かにすごいと思うが,プログラム的には比較的単純なデータベースがあれば済む.多重な関係ネットワークを持つオブジェクトの終末管理にはあまり向いていない.いずれにしても個体にマークを付けるしかないことは明らかだ.マーク名はblakflagとして,それをどこに置けばよいか?拡張性を考えれば,noduleクラスメンバとするのが適切だろう.noduleは基底クラスNODULEから直接派生する唯一のクラスであり,オブジェクト全数管理のためのNリングシステムとリサイクルシステムおよびUNDOシステムを備えた応用システム構築用の基本クラスだ.オプションではあるが,完全参照リスト管理も持っている.これに終末期管理のための制御された解体機能が備われば,ほぼ万全と言えるのではないか?

死亡通知同期用フラグとしてnodule::blackflagを設置すれば,dataCountDownによる死亡通知は不要になるのだろうか?いや,ならない.養豚場から盗まれた豚がどこかで密殺された場合,これがなければ終末処理ができない.今日はまだ修正は1件も入っていないので,このまま続けよう.⇒フラグではなく,deleteの実行者のリンクを直接書き込んでおくというのはどうだろう?こうすれば,いちいちデスノートの宛て先を探しまくる必要はなくなる.そのアドレス宛てにデスノートを送るだけでよい.デスノートは定型文なのでそれぞれのクラスで用意する.DeathNoteという仮想関数を一つnoduleに作っておいてもよいのではないか?nodule::nodule *executerとしてみよう.この変数はオブジェクトのライフタイムで一度しか使われないのだから,operator new で初期化しておけばよいだろう.

いや,少し違うのではないか?dataCountDownは密殺された豚の死亡通知を管理者に届ける仕組みだ.dataCountDownを管理者に送れるということは管理者とのコンタクトが切れていないという証明であり,管理者がexecuterに署名したところで何の意味もない.密殺者は署名できないし,適切な終末処理を持っていないのだから,署名しても意味がない.やはり,blackflagを使うしかないと思う.

blackflagとexecuterを併用することは可能だが,そこまでする必要もないだろう.まだ障害が残っている.

今度はTRIBELISTのCleanSansyo中にbottomlistに関するエラーが出た LIST::nextで検出されている.TRIBELIST自体の不調だ ⇒ CleanSansyoの入口ですでに不正規になっている.これを防止するには,TRIBELIST自体にCDD(Controlled Demolition)を導入するしかない.⇒ダメだ.効果がない.⇒dataCountDown自身でエラーを作っている.⇒対処した.

▲COUPLING::CloseFamilyBaseが過剰に呼び出されている ファイルをオープンしていないときはNOPリターンでよい ⇒ 未了

▲COUPLING::EraseFamilyTreeにモードを設け,アプリ終了時には「EraseFamilyTreeで削除しない@20201120」で保留したブロックを強制削除する ⇒ 保留

▲アプリ終了の出口近くで,残留したLIST派生クラスのインスタンス64個のうち1個でデータ数不一致が発生している #34GENELISTでデータ数13のところゼロになっている

GENELIST#34を追跡するようなSWO(SearchWrongObject)を仕掛けて,完全参照リスト管理から「参照元ノードリスト不記載」エラーが出た ⇒ SWOがクリティカルゾーンに入って再帰が起きているためだ.escapeで回避するようにして止まった.

▲リストアクセス関数のLIST::topなどを実行するとcurnodへの書き込みが発生する topやnextなどのルーチンは副作用がないことを予定しているので,このような動作は望ましくない 実際問題としてcurnodはほとんどまったく使われていないと考えられるので廃止してよいのではないか? ⇒ 一度バックアップを取ってから廃止手続きを進めることにしよう.LIST::insertはcurnodを参照する動作になっている.かなり疑問の多い論理なので後で精査することにする.

probeではアイドリング時のカウントアップを避けるため,DRAWSTAGEフェーズではScoutとscountを更新しないようにした ⇒ これはかなり重要なポイントだ.これでようやく,トラッキングの完全再現性が保証されるようになった.

▲アプリ終了→…EraseTreeViewでGENEBOXを削除して被参照カウントの残留が出た GENELIST#34→GENEBOX#15223が残っている

コメントを残す

メールアドレスが公開されることはありません。

CAPTCHA