TOPOLOGY::UpdateRecordはかなり危うい仕掛けだ

いよいよ大詰めと言ってよい.始業時バックアップを取ろうとしたら,下記のエラーが出た.⇒開発環境が立ち上がったままだった.

image

参照番号を永久コード化する,つまりマイナンバーコード化するということにした.これは決定であり,後戻りできない.いろいろなところに副次的な影響が出てくることだろう.それにしても,CardNumlist, MargNumlistには何を格納し,どのように使われているのだろう?基準ソートではリンクテーブルを操作しないということになったので,もしかするとまったく不要になっている可能性もある.というか,NAMESORTというオブジェクトは何のために設置されているのか?

NumlistはNAMESORT::BuildNumListで「テーブル並び替えの前後で参照番号のリストを生成」している.また,RestoreNumListでリンクテーブルに参照番号を書き戻している.それ以上の用途はないように思われるので,完全に止めてみることにしよう.特に,RestoreNumListでは参照番号を親番号として認識しているので,完全に法令違反だ.⇒明らかにNAMESORTというオブジェクトはCardNumListとMargNumListを管理するためだけに作られているので廃止できる.

いや,そういう訳にもゆかないようだ.①ソート基準列インデックス,②ソート順,③年号タイプ,④数字タイプなどのパラメータを保持している.NameSort,NameNarabekaeなどもこのクラスのメンバー関数だ.⇒CardNumListとMargNumListの完全廃止で問題なく動作している.⇒本線に戻ることにしよう.

maxrecnum→ recordcountのリネームはすでに完了している.maxrecn→ recordCountは未遂行だが,maxrecnをローカル変数として使っているところもあるので,そちらを先にリネームしておく必要がある._maxrecnはすでに使われているので,maxrecn_としておこう.⇒クラスメンバーとしてもmaxrecnはすでに存在していない.このmaxrecnはmaxRecordにリネームしているところからすると,関数と推定される.「maxrecordのアクセス関数をmaxRecordとする」となっているが,maxrecordは新設を予定されているものであり,まだ実装されていない.その前身として,maxrecn()が存在していたのだろうか?

maxRecord()はgetmaxrecn()を置き換えるべきものであり,「getmaxrecnではmaxrecordを返す」となっているのだから,getmaxrecn≒maxRecordと考えてよいはずだ.⇒「_maxrecnをリネームしてrecordCountとする」というのがある._maxrecn()という関数は存在し,recordcountを返しているから,recordcountを返す関数がrecordCountということになる.maxRecordという関数はまだ実装されていない.とりあえず,_maxrecn→ recordCountというリネームは実行できるはずだ.⇒対処した.

ともかく,「maxrecordを新設し,最大(リンク)レコード番号を格納する」というのをやっておこう.maxrecordへの参照を返すmaxRecord()も作っておく.maxrecordは「recordcountの更新時に更新」となっている.recordcountの更新関数には,以下がある.①incmaxrecn,②decmaxrecn,③cleartable,④MakingLookUp.しかし,これらの関数ではレコード番号自体の情報は与えられていないので,これらを呼び出しているところを見なくてはならない.

incmaxrecnはAMILYTREE::AppendFile,NODECLASS *newlinkから呼び出されている.decmaxrecnの呼び出しは,MARGTABLE:deletelink,CARDTABLE:deletelink,FAMILYTREE::AppendFileから掛かってくる.これらの位置で処理するより,incmaxrecn,decmaxrecnに引数を渡して,集中処理した方がよいと思う.「maxrecordは単調に増加するものとし,(基準ソート時以外では)テーブルは縮小されない」としているので,とりあえず,decmaxrecnでは最大レコード番号を更新しない.ただし,これは実装してもそれほどコスト増要因にはならないと考えられるので,実装した方がよい.

▲カード一括削除の後の基準ソートが入らなくなっているような気がする.もう一度クリックすればソートされる.これまでは動いていたような気がするのだが…

ともかく,ここで一度バックアップしておこう.⇒さて,問題はlookupとの関係だ.lookupとは,リンクテーブル上の有効レコードの参照番号を前詰めして格納したテーブルであると言える.lookupは常時更新されるのではなく,処理の最後に一括生成されるという仕様になっているから,recordcountやmaxrecordには関与しないと考えられる.⇒それでは,なぜMakingLookUpでrecordcountとlookup.countが一致しないのか?⇒UNDOではリンクテーブルは保全されていないので,オブジェクトの再生と削除は本来なら通常手続きとして実行されなくてはならないところだが,削除はdeleteで実行されているもの,再生は手続き的に実行されているため,recordcountが更新されていないものと見られる.

この処理はUNDOSYSTEM::RestoreShadowで実行される.この操作の対象となるオブジェクトはCARDLINKとMARGLLINKに限定されている.逆に言えば,それ以外のオブジェクト(の削除)はUNDO対象となっていない.⇒UNDOSYSTEM::RestoreShadowを修正して,incmaxrecnを実行するようにした.⇒これでつねにUNDO動作と関わりなくリンクテーブルを保守することができるようになった.

いや,まだ不一致が発生している.Redoした場合のデクリメントが入っていない.RestoreShadowはUndo/Redoの共通処理になっている.<削除>の場合はoperator deleteを実行しているだけなので,通常通りの処理になっていなくてはならないのだが… recordcountは307のままだ.なぜだろう?⇒CARDTABLE::deletelinkではdelete cardの後に,decmaxrecnを実行している.これは必須である.つまり,deleteを直接呼び出しただけではアプリ的な処理は実行されない.

BASETABLEの関数でnoderefnumというのがあるが,これはレコード番号を返す関数であり,この戻り値を参照番号とみなすべきではない.しかし,かなりの箇所でこの関数は使われている.⇒仕様を変更して,リンクから参照番号を返すように改めるべきだろう.⇒いや,この関数は仮想関数でクラス実装では参照番号を返すようになっているから,問題ないだろう.⇒BASETABLE::noderefnumは純粋仮想関数とした.また,BASETABLEにgetrecnの別バージョンを新設し,親枝番号をレコード番号として返すようにした.⇒大分整理されたのではないかと思う.

ここまでできると,lookupを常時更新することも可能になるのではないだろうか?lookupに何を格納しているのか?が問題だ.レコード番号を格納するというのが最適だが,現行では参照番号になっているのではないか?⇒いや,レコード番号になっている.これでよい.しかし,テーブル並び替えではリンクテーブルを直接ソートしている.これはあまりうれしくない.リンクテーブルは操作しないという原則に反する.しかし,これでも実際にはソートしたように見えているというのはなぜだろう?リンクテーブルが辞書順にソートされているとすると,テーブル並べ替えによってそれが崩れてしまうことになる.それによってアクセス不能になるという訳ではないので,とりあえず,問題なく表示できているのだろう.X⇒勘違い.下記参照

テーブル並び替えというのは一覧表の並びに関係するものであり,一覧表には部分テーブルを表示することもあるため,一覧表示されるカードについては,別途カードリストが編成されている.lookupというのは実際のところ,どの程度役に立っているのだろう?⇒MakeActiveListなどではlookupを直接参照している.⇒いや,読み違えしている.テーブル並び替えはlookup上で実施されている.

一つマズイのが出てきた.BASETABLE::getrefnumではlookupから引いた値を返している.これは参照番号ではなく,レコード番号だ.BASETABLE::getlinkがこの関数を使っている.⇒BASETABLE:getrefnum,getlinkは廃止した.⇒TOPOLOGYにもgetrefnumという関数がある.⇒アプリ側にはリンクテーブルのレコード番号はまったく公開されていないと考えるべきではないか?

この意味ではCallGetRecordNumのような外部関数には問題がある.逆に言うと,一覧表のレコード番号を常時当てにすることはできないから,外部からカードにアクセスするには,参照番号を使うしかないということにもなる.そうなると,lookupを使うメリットも薄れてしまうような気もする.参照番号は一応辞書順になっているので,それほど悪い設計とも言えないが…

アプリから参照番号でアクセスするとき,lookupを経由すると総当りになってしまう可能性があり,その意味ではむしろリンクテーブルにアクセスした方が効率はよいと考えられる.⇒アプリからレコード番号でアクセスするおそらく唯一の関数がZ.mGetRecordNumだが,この関数はレコード番号1のカードを取り出すか,テーブル全体にアクセスする場合にのみ使われているので,lookupで応答するように改造してみよう.

lookupはゼロ発進だったような気がするが…いや,1発進でよいようだが,だとすれば一つ大きい箱を用意しなくてはならないような気がするが… ⇒テーブルサイズはMAXPDBだ.つまり,MAXまで使うとオーバーフローしてしまう.いや,間違っている.やはりゼロ発進だ.⇒CallGetRecordNumをlookup対応に修正した.動作確認するには,mGetRecordNumの呼び出しをチェックしなくてはならない.

InitializeDisplay→ SendDateAll→ mGetRecordNumというフローがあるのだが… ⇒InitializeDisplayはファイルオープン時に一度呼び出されているだけだが,動作している.⇒アプリからレコード番号でアクセスする関数を総点検する必要がある.⇒一度バックアップを取ってから…

GetRecord(long num, char *rstr, int range)はおそらくレコード番号だと思う.GetRecordはrangeにより3つの処理に分岐する.①GetAllRecord,②GetActiveRecord,③GetPartialRecordだ.GetAllRecordはGetCardBaseRecordを呼び出している.この関数はlookup対応だ.しかし,GetActiveRecordから呼び出されるTOPOLOGY::GetRecordはリンクテーブルを対象としている.⇒この関数はlookup対応に書き直す必要がある.GetPartialRecordはPARTIALNAME::GetPartialRecordを呼び出している.ここではPartialListのレコード番号が使われているのでこのままとする.

GetActiveRecordというのは,一覧画面の表示範囲:系図画面上のカードを表示というモードだ.いや,参照しているテーブルは引数で渡されたもので,今の場合はActiveListを指しているので,間違ってはいない.参照番号からレコード番号への変換はgetrecnが使われているが,デフォルトの位置でマッチングしない場合は,リンクテーブル全体のブラインドサーチになっている.これはlookupを使った方が効率的なのではないか?また,レコードは通常デフォルト位置より上に配置される(参照番号の昇順)ことになるので,先に上方を検索し,見つからない場合のみボトムから探すとした方がよいのではないか?

SendUpdateDataもそうかもしれない.この関数はTREEVIEW:sendUpdateDataを呼び出しているが,レコード番号は参照されていない.⇒紛らわしいので使っていない引数は廃止することにしよう.SendUpdateData(long recn, int range, int len, char item[][MAXTEXTFIELD])の引数のうち,recnとrangeは使われていない.

ImportTableFuncは一覧表のレコード番号が使われている.⇒ブロック内変数に変更した.AutoMergeTest(long recn, int type)というのもある.AutoMergeTestはSingleMergeTestを呼び出している.⇒SingleMergeTestは「現在系図画面上に表示されているカードを対象にカード合併包括テストを実施する」ものなので,対象領域はActiveListである.現行でよいのではないかと思う.

COUPLING::getUpdateRecordでは戻り値でレコード番号を返している.実行関数はUpdateRecord.戻り値のレコード番号は対象領域により,lookup,ActiveList,PartialListとなっているので問題ないが,果たしてこのインタフェースで連続レコード処理できるのだろうか?mGetUpdateRecordを呼び出しているのは,UpdateRecordだけだ.UpdateRecordはUpdateTableのループの中で戻り値が0以下になるまで回している.引数はrangeだけなので,単なるトリガーだ.⇒mGetUpdateRecordは書き込みではなく,レコードの取り出し関数.

TOPOLOGY::UpdateRecordという関数はかなり特殊なことをやっている.これはじっくり解析しないと誤るかもしれない.この関数では内部状態を持っていて,updateindexをインデックスとして押さえている.対象領域は指定されたテーブルを対象としているのでよいようにも思われるが,かなり危うい仕掛けになっているような気がする.また,lookupに格納されているのはレコード番号であり,それ以外のテーブルは参照番号であるという点にも留意する必要がある.いずれにしてもかなり危ないような気がする.

コメントを残す

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

CAPTCHA