コピーオンライトオブジェクトグラフトランザクション

THotPDF は、トランザクション開始時にドキュメントを複製することなく、ロード済みまたは組み立てられた間接オブジェクトグラフにネストしたセーブポイントを提供します

トランザクションのライフサイクル

PDF.BeginGraphTransaction('metadata edit');
try
  Info.AddStringValue('Producer', 'HotPDF');
  PDF.CommitGraphTransaction;
except
  PDF.RollbackGraphTransaction;
  raise;
end;

BeginGraphTransaction は現在の間接ルートをインデックス化し、変更オブザーバーをインストールしますが、スナップショットは作成しません。そのフレームで既存の間接ルートへの最初の書き込みが 1 つのスナップショットを作成し、同じルートへの後続の書き込みはそれを再利用します

CommitGraphTransaction は現在のグラフを保持し、グラフを複製せずにスナップショットを破棄または転送します。RollbackGraphTransaction はルートオブジェクトをその場で復元し、セーブポイントの後に追加されたオブジェクトを削除し、オブジェクト番号の割り当てを復元します

ネストしたトランザクションは独立したセーブポイントです。内側のロールバックは内側のエントリ状態に戻り、内側のコミットは後で発生する外側のロールバックのために十分な履歴を保持します

自動および明示的な書き込み準備

THPDFDictionaryObject.AddValue、ReplaceValue、DeleteValue、THPDFArrayObject.AddObject と SetIndexedItem、THPDFStreamObject.Length の変更は、囲んでいる間接ルートに自動的に通知します

公開スカラーフィールドと生ストリームバイトは代入を傍受できません。Value を代入する前、公開オブジェクトフラグを変更する前、グラフポインタを置き換える前、または THPDFStreamObject.Stream を通じて書き込む前に PrepareLoadedObjectForWrite を呼び出してください

PDF.BeginGraphTransaction('raw stream edit');
try
  PDF.PrepareLoadedObjectForWrite(StreamObject);
  StreamObject.Stream.Size:= 0;
  StreamObject.Stream.WriteBuffer(Bytes[0], Length(Bytes));
  StreamObject.Length:= Length(Bytes);
  PDF.CommitGraphTransaction;
except
  PDF.RollbackGraphTransaction;
  raise;
end;

メモリとパフォーマンス

スナップショットのメモリは、ドキュメント全体のサイズではなく、触れられた間接ルートとともに成長します。大きなストリームペイロードは、GraphTransactionMemoryThreshold(デフォルト 16 MiB)を超えると所有する一時ファイルにスピルオーバーします

ロールバックは、保存された辞書エントリ、配列項目、ストリームストレージを既存のルートに戻して入れ替えるため、2 回目のディープコピーを回避します。ルートポインタは安定したままですが、直接子孫へのポインタはロールバック後に再取得する必要があります

GetGraphTransactionStatistics は、Active、ネスト Depth、SnapshotCount、AddedObjectCount、常駐およびスピルしたスナップショットバイト、ピーク常駐スナップショットバイトを返します

THPDFBeforeMutationEvent は、コンテナとライフサイクルの変更を囲んでいる間接ルートスナップショットにルーティングするために使用される低レベルオブザーバーシグネチャです

スコープ

トランザクションは、間接オブジェクトグラフ、ライフサイクル状態、追加されたルート、オブジェクト番号の割り当てをカバーします。呼び出し元が所有するポインタ、ロード済みページの順序配列、レンダリングキャッシュ、その他のファサード側状態はジャーナル化されません

トランザクションがアクティブな間、GetLoadedIndirectObjects 内の既存エントリを削除、並べ替え、置き換えしないでください。グラフコンテナメソッドを使用し、ロールバック後に直接子孫を再取得してください