PARTIALNAME::MakePartialListを廃止

PARTIALNAME::MakePartialListは現在使われていないようなので,廃止しておこう.さて,リンクテーブルとlookupの同期に関してかなり深刻な問題が発生している.部分図リストのレコード数がlookupで数えた場合とPDBで数えた場合で一致しないという現象だ.lookupがゼロ発進に対し,PDBは1発進になっているという違いがある.ただし,lookupのレコード番号と言うときは,1発進の数として扱っているはずだ.確かにどこかで躓きそうな感じはする.

まず,テーブルのサイズを確認しておこう.lookupはlongtableのインスタンスで,MAXPDBというサイズのlong配列を保持している.lookupはゼロ発進だから,これで問題ない.PDBはどうか?CARDTABLEはBASETABLEの派生クラスで,MAXPDBサイズのCARDLINK*配列だ.BASETABLEはARRAYという配列クラスの派生クラスで,ARRAYは指定したサイズのスロットを持つオブジェクトだ.

確かに,これはまずいような気がする.BASETABLEはtablesizeというメンバー変数を持っているが,ここには,オブジェクト生成時の配列サイズ,つまりMAXPDBが入っている.現行ではgetmaxrecnはtablesizeを返すようになっている.⇒まず,BASETABLE::tablesizeをprivateに指定して外部から隠蔽してみよう.その上でアクセス関数gettablesizeを追加して,tablesize-1を返すようにしてみる.念のため,tablesize→ tablesize2にリネームしてクラス内部での参照もチェックしておこう.⇒NODECLASS *newlinkから参照されていた.getmaxrecn,doClean, getnod, emptyrecn からもアクセスされている.

一般には,getmaxrecnまでのレコードは許容されているが,refnum >= gettablesize()でtablesize-1を返すとおかしくなるところも出てくる.たとえば,refnum >= gettablesize()をエラーとみなしているところなど…TableSizeOverなども同様の仕様になっている.その逆に,CARDTABLE::makelinkなどではrecn <= tablesizeならば適法としている.⇒まだ,見直しは完了していないが,ざっくり修正して通るかと思ったが,TOPOLOGY::MakeActiveListで起きているエラーはまだ止まらない.デバッグするしかないのだろうか?

2023/01/09のリストに戻ってみよう.登録レコード数:recordcount→ recordCount, 最大レコード番号: maxrecord→ getmaxrecn, _maxrecn としているが,テーブルサイズを押さえている関数は予定されていない.現行のgetmaxrecnはtablesizeを返しているので,実質それに該当しているのだが,maxrecordはテーブルサイズではなく,現に登録されている有効なレコード番号中の最大のものという位置付けだ.tableSizeでもよいような気はするが,最大レコードというところを強調したい.上の修正でgettablesizeに相当する関数だ.中を取って,getTablesizeとしてみよう.この関数はtablesize-1を返すことにする.現行のgettablesizeを置き換えるものだ.この関数を使っているところで,使われ方が正しいかどうかを点検してみよう.

getTablesizeはレコード番号の取れる最大値を意味している.⇒TableSizeOverという関数名は状態を示す関数としては適切ではないので,LinkTableFullに変更する.LinkTableFullはmaxrecordではなく,recordcountがtableSizeと等しくなることを意味する.⇒すでにそういう実装になっている.

カードの肩書に文字を書き込んで登録して,TOPOLOGY:MakeActiveListで(treeview->validcard != ActiveList->count)のエラーになる.TREEVIEWの側の値が間違っているものと思われる.TREEVIEW::validcardは「有効なカード数(基準カードと親族関係にあるカード数)」で多分これは画面上のカード数と一致するはずだ.この値は,①SetKinship,②validcardnum,③ExtractPartialCardのいずれかの方法で決定される.今の場合は③に該当する.⇒validcardnumはTOPOLOGYのメンバー変数,SetKinshipはTOPOLOGY:FilteringKinshipの中で,「親族範囲を確定する」ために実行される.

どうも,カードの登録更新で部分図ノードが増加してしまっているようだ.このサンプルには現在部分図が3つ登録されているが,そのうちの2番目の「3077直系血族図278点」がデフォルトになっている.編集対象のカードはこれら3つの部分図のすべてに登録されているので,部分図の登録に変化があるというのはおかしいのだが…

PartialListのカウントは278のままで変化していない.partialflagというのはCARDLINKの固有情報であり,Undo/Redoは実行されていないのだから,誤って上書きされることも考え辛い.partialflagにTRUEを設定している箇所は7箇所ある.ファイルオープン時には,InitLinkTable→ PartialLoad で既定の部分図が読み込まれる.

カードの登録でmakenewcardが掛かってくる.なぜだろう?アプリから送付されたCarddataのRefnumが空欄になっている!Personalには入っている.これはかなり由々しき事態だ.MyCardというのは,アプリに常設されているカード情報の格納域だ.MyCardはGetNewCardでロードされているはずだが…OpenFileProc→ GetNewCardでは入ってくる.mCARDDATA::Putで転記されていない!

どうもこの関数の中で例外が発生しているようだ.この関数では例外が発生することを想定していないので,voidになっている.例外をトラップしたところでGCERROR_CARDDATAPUTをスローするようにしたが,何も応答はない.この関数を呼び出しているmZelkova:mSendCardでキャッチして,GCERROR_SENDCARDで復帰している.SendCarDataにはエラー処理は入っているが,ごく一部のエラー以外は処理されていない.ERR_CARDTABLEOVERとERR_MARGTABLEOVERでは黙って復帰する.ERR_NOMEMORYの場合はアプリ終了する.

それ以外では戻り値の上位ビットを取って,その部分がSAMENAMEEXISTの場合には,黙って新規カードを作成する.これは「本人氏名と同じときは黙って新規カードを生成する」というルールによる.この仕掛けはあまり感心できない.SAMENAMEEXIST As Integer = &HFFFF0000なので,ほとんどのエラーコードと合致してしまう.NAMERECURRENCE As Integer = &HEFEF0000はなんとか識別できるのではないか?SAMENAMEEXISTのコードをFEFE0000に変えておこう.いや,これはすでに使われているので,F8F80000とする.

これで「本人氏名と同じ」とは衝突しないようになったが,どう処理すればよいか?当面,公式リリースはないと見込まれるから,エラーパネルを出して異常終了でよいのではないか?⇒異常終了ではなく,ノーマル終了とした.これで一応例外が発生していることだけは検出できるようになった.あまりユーザフレンドリでないパネルだが…

image

戻り値を持っている関数はエラーリターンできるが,void関数ではエラートラップに落ちたことはコンソールへのダンプでしか知ることができない.ほとんど見落とされてしまうので,void関数では例外をスローするようにしておこう.⇒16箇所のトラップにthrow文を入れた.

さて,問題は,mCARDDATA::Putでなぜ例外が発生しているのかという理由だ.理由ははっきりしていて,(carddata->Refnum != refnum)のときには例外をスローするという論理になっているためだ.「参照番号の改変」とされる事象だが,

いや,その前に別のエラーが発生してしまった.「本人の氏名データがありません」というエラーが起きている.

image

MakeNewCard→ Myself.Getで-5007というエラーが返っている.参照番号は3079.-5007というのはGCERROR_GETPERSONALだ.⇒修正ミスがあった.catchの{}の外にthrow文を置いてしまっていた.

例外をスローしているのは以下の一文だ.

if (carddata->Refnum != refnum) throw “mCARDDATA::Put 参照番号の改変”;

しかし,これはかなり奇妙だ.mZelkova::mSendCardでは,引数で渡されたmCARDDATA^ mycard… 以下のデータをDLL側に送付するものであり,CARDDATA card… 以下のオブジェクトはアプリ側のデータをDLL向けに変換するための受け皿として用意された関数内オブジェクトであり,まったく空の状態になっているはずだから,carddata->Refnum と refnumが一致するようなことは起こり得ないと考えられるのだが… 「参照番号の改変」という文字列はここにしか現れない.⇒この文をコメントアウトしてエラーなしで動作するようになった.

「改変」という文字列は,2019/08/13に一箇所出てくるだけだ.もちろん,「参照番号の改変」とはまったく別の文脈だ.サイトにアップロードされていない以前のログを探せば何か手がかりになる情報を見つけられる可能性はあるが,今のところ,全文検索ができていないので,それもできない.もしかすると,以前はCARDDATAを関数内ではなく,静的領域に置いていた可能性はあるかもしれない.そうなっていれば,一致することはあり得るように思われるが…

さて,どこまで進んでいたのか?わからなくなってしまった.エラーはすでに解消しているが,不良の原因となった,「新規カードの生成」で起きる不具合について,原因と対策を考えておかなくてはならない.部分図モードのときに新規生成されたカードは自動的にその部分図に属するようになるというのが仕様だったような気がするので,部分図のメンバーが増加すること自体は正当だが,あちこちで不整合が発生するというのは問題だ.どんな事象が起きていたのか?

カード情報を更新しようとして,新規カードが生成されたという事象だ.不良の原因ははっきりしている.lookupテーブルが更新されていないためだ.いまのところ,ファイルオープン時に一度生成されただけで,それ以外の処理は何一つ組み込まれていないのだから当然だ.カードの生成と削除に同期してlookupを時点処理するというのが現在の方針であり,その手続きを実装しなくてはならない.

lookupではレコード番号は必ずしも連続した並びにはなっていない.場合によっては,順序が逆転していることすらあり得るし,また,そのような場合でも正しく操作できなくてはならない.逆に言えば,もし,それが可能ならレコードの追加・削除ではテーブル全体の詰め合わせや並び替えをやらなくてもよいということになる.系統並び替えにはテーブルソートが入っていたはずだから,そのような処理はそこに任せてよいはずだ.従って,lookupの保守はかなり簡単なもので済むはずだ.

いや,maxrecordというのは仮に中間に空きがあったとしても,テーブル上では必ず末尾に来なくてはならないのではないか?⇒これは解釈の問題ではないかと思う.maxrecordが有効レコードの末尾であるということは,その(リンクテーブル上の)レコード番号の最大値であるということを意味する.定義としては,これで十分なのではないだろうか?カード追加・削除時のlookup更新手続きを書いてみよう.

  1. 新規カードが追加された場合には,そのレコード番号をlookupの末尾に追加し,lookup.countを+1する
  2. 既存カードの削除では,lookup上のそのカードのセルを空欄とする.

つまり,lookupのサイズは単調に増加するものとする.⇒しかし,どこかで整序する必要があるのではないか?これは結局,MakingLookUpを実行するということに他ならない.おそらく,CommandEndとUndoProcessの出口でやっておけば十分なのではないかと思われるが,もし,RebuildCardListでlookupを参照しているとすれば,その前に実行する必要があるかもしれない.⇒MakingLookUpを実行する必要はない.系統並び替え時にはつねにテーブル並び替えを実施している.テーブル並び替えとはlookupの整列に他ならない.

コメントを残す

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

CAPTCHA