要約

  • RFC 3018は、分散したnodeを128-bit address spaceで結び、VMにremote read、write、memory allocation、object operation、JUMP、CALLを与えた。
  • transactionは全命令を一度に実行するか、まったく実行しないかを決めた。しかし実行後の取消しは規定せず、control transferのように取消不能な命令があると明記した。

受信側には完成したtransactionがある。まだ実行はされていない。ここなら選択肢は二つあった。EXEC_TRで走らせるか、CANCEL_TRで捨てるか。

問題は、その選択が済んだ後だった。

命令群の中に遠隔CALLがあれば、新しいcontrol flowは別のnodeで仕事を始める。memoryを書き換え、object procedureを呼び、別のsystemへ作用するかもしれない。元のchainを消しても、その出来事は消えない。

RFC 3018はこの限界を隠していない。実行後のtransaction cancellationは規定されない。必要ならVM levelで実現すべきであり、control transferのようにcancelできない命令もある、と本文は述べる。

2000年12月のExperimental RFC、Unified Memory Space Protocol Specificationは、networkを単なるmessage交換路より深く抽象化しようとした。applicationはnetwork primitiveを知らず、128-bit addressを使う。VMがその命令をUMSP commandへ変換し、遠隔nodeのmemoryやcodeへ届ける。

距離はAPIから見えなくなった。しかし障害の距離は残った。

一つのaddressは一つの管理主体ではなかった

UMSPの計算modelはjob、task、thread of controlの三層である。jobは分散application、各nodeの表現がtask、その中で動く単位がthreadだった。Job Control Point(JCP)がtaskの開始と終了を追い、global identifierを割り当てた。

ただしJCPがすべてを管理したわけではない。local memoryはVMの責任であり、protocolはjob memoryを制御しない。user threadも追跡しない。taskが終了したとき、そのtaskを指すpointerを無効にするのもVMだった。

16-octetのaddressはnetwork、node、local memoryを一つの表現にまとめた。それは命名の統合であって、clock、journal、rollback authorityの統合ではない。ある遠隔addressへcontrol transferすると、そのnodeに新しいthreadが生まれる。一方で連続したcode segmentは複数nodeにまたがれない。

つまり、pointerは境界を越えられても、保管責任と実行環境は境界を持ち続けた。

命令の範囲は広い。即時read/write、allocation/free、comparison、synchronization、JUMP、CALL、code移動、objectの生成・削除・procedure実行が含まれる。誤ったmessageが単に拒否されるとは限らない。遠隔のresourceやcontrol flowそのものが変わり得た。

transactionは転送、待機、解放を分けていた

UMSPはchainを使って命令を束ねた。sequenceは依存順序を表し、途中が失敗すれば残りをcancelする。transactionは互いに無関係な命令も含められるが、全体を一度に実行するか、どれも実行しない。

最初に必要なのは完全な転送である。buffering方法を決めるためtransaction lengthは事前に分からなければならない。先頭は_BEGIN_TR、末尾は_END_CHAINで示される。

完成後の挙動はflagで変わった。TRR=1なら末尾を受け取ると直ちに実行する。TRR=0なら別のEXEC_TRを待つ。実行前のchainはCANCEL_TRで削除できるが、削除した命令の復元はない。

TREはtime-outや異常終了に意味を与えた。完成済みで未実行のtransactionについて、TRE=1ならlifetime満了やemergency session endで実行しなければならない。TRE=0ならcancelする。lifetimeは全命令受信後から数え、ゼロなら制限なしだった。

そのため「connectionが切れた」という一文だけでは状態を決められない。途中までしか届かなかったのか。完成して待機していたのか。すでに明示的に解放されたのか。異常終了規則が実行を発火させたのか。

少なくとも、chainのidentityとordered digest、complete-buffer receipt、releaseまたはcancelの原因、各命令のexecution resultを別々に残す必要がある。

atomicなのは入口であり、世界の逆再生ではない

databaseのtransactionを知る読者は、「全部かゼロ」という表現からrollbackを連想しやすい。しかしRFC 3018が定義した境界は、命令群を実行に入れるかどうかである。

遠隔writeは他のthreadにすぐ読まれるかもしれない。FREEは別の場所に残ったpointerを無効にする。codeを移して走らせれば、新しい作用主体が生まれる。object procedureはtransaction外のsystemへmessageを送れる。JUMPやCALLで生まれたcontrol flowは、元chainの寿命を越えて動ける。

したがって、命令群が完全にatomicに開始しても、結果に一般的な逆命令があるとは限らない。

memoryを確保し、codeを配置し、そこへjumpするtransactionを考える。三命令が一体として始まることは保証できる。だが新threadが外部へ通知した後で、元のtransactionを消しても通知は戻らない。

execution前に扱うのがcancellation、execution後に必要なのがapplication固有のcompensationである。protocolはoperation codeだけから、現実の副作用に対する正しい補償を生成できない。

EXEC_TR receiptも同じである。それは特定chainへの実行命令を示す。全VM actionの完了、外部effectの一回性、business goalの達成までは示さない。

TCP ACKはVMの完了通知ではない

UMSPは信頼できるdata exchangeにTCPを必須とし、acknowledgement不要のdataにUDPを許した。RFC 793のTCPはordered reliable octet streamを提供し、loss、duplicate、damage、reorderingに対処する。RFC 768のUDPはより薄いdatagram contractである。

TCPのreceiptは重要だが、application executionのreceiptではない。受信TCPがoctetを受けたことから、UMSP validation、正しいchainへの格納、正しいauthorityによるrelease、期待したmemory versionでの実行までは導けない。

RFC 1831のONC RPCは、遠隔実行の不確実性を別の角度から示す。TCP上でreplyを受ければ、そのmodelではprocedure executionを推論できる。しかしreplyがなければ、未実行とは言えない。serverは実行後にconnectionを失った可能性がある。remote callはlocal callと異なり、failure、side effect、performance、authenticationを明示的に扱う必要がある。

UMSPは遠隔操作をCPU instructionに近く見せた。interfaceが近いほど、観測証拠まで近いと錯覚しやすい。

JCPは中心だったが、全知ではなかった

JCPはjobにglobal identityを与え、taskの開始と終了を追跡した。集中user identificationやattack protectionにも利用できるとされた。

しかしVMのmemoryとpointerはJCPの直接管理外である。remote threadが外部effectを生み、実行後reply前に障害が起きれば、JCPのlifecycle recordだけでは結果を確定できない。node reload後には旧session segmentを識別する必要もあった。

task終了はlifecycle fact、writeの永続化はmemory fact、外部actionの一回性はapplication factである。job completionも、この三つを一つにする証明ではない。

securityは初期仕様の外に置かれた

Security Considerationsは、initial complexityを下げるためsafety questionを本文の機能に含めなかった、と明記する。その後に並ぶのはfuture extensionへのrecommendationである。

TCP/IPのprotection、special-processing chainによるintegrity controlやencryption、extension headerでのauthentication parameterが提案された。二nodeとJCPの間で複数の認証組合せも想定した。man-in-the-middle対策では三経路が重ならないことを利用し、同じgatewayを通ると効果が落ちるとも認めた。

またJUMPとCALLをdenial-of-serviceの原因として挙げ、resource判断をVMに委ねた。serverからclientへactive codeをloadする構成はclientにとって最も危険で、client codeをserverで動かす構成はserver側の防御強化が必要とした。

これらはrisk inventoryであって、完成したsecurity protocolではない。algorithm、key、authorization、replay defense、revocation、auditは具体化されていない。

後年のRFC 3552は、Internet attackerがchannel上のpacketをread、remove、change、injectできるというthreat modelを示す。これを2000年の文書へ遡及適用するべきではない。ただし、route separationと未定義extensionだけでsecurity completionを主張できない理由はよく見える。

Experimentalは運用実績を意味しない

RFC 2026によればExperimentalはstandards track外であり、Internet Standardではない。researchやdevelopment workの記録として公開され得る。RFC 2119はrequirement word、RFC 2234はABNFを提供した。

これらの資料から分かるのはdesignである。UMSPの実装、deployment、interoperability、incident、adoptionを証明する資料ではない。

歴史的価値は、強いabstractionの限界を仕様自身が露出させた点にある。一つのaddress spaceでもcustodyは複数だった。complete transferでもreleaseは別だった。atomic executionでもeffectはreversibleとは限らなかった。jobが終わっても、現実の目的は観測を要した。

Lu HengのRunning-Code Primacyは、instruction definitionとrunning outcomeを分けるlensになる。Reality Layersはencoded chain、buffer、release、execution、resultを別々の層として扱う。Minimum Initial Specificationは薄いcoreの価値を認めつつ、security、compensation、observationの欠落を明示するよう促す。

これは後から使う分析lensであり、RFC authorの意図を代弁するものではない。

transactionは一括で走り出せた。その後の世界を一括で巻き戻すことはできなかった。

Sources