写时复制对象图事务

THotPDF 为已加载或组装的间接对象图提供嵌套保存点,而无需在事务开始时克隆文档

事务生命周期

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

BeginGraphTransaction 索引当前间接根并安装变更观察器,但不创建快照;该帧中对现有间接根的第一次写入创建一个快照,后续对同一根的写入复用它

CommitGraphTransaction 保留当前图并丢弃或转移快照而不克隆它;RollbackGraphTransaction 原地恢复根对象,移除保存点后追加的对象,并恢复对象编号分配

回滚会在恢复对象之前使已加载表单关系缓存失效,因此后续的字段查找会基于恢复后的图重建,而不是保留对已移除字段或 widget 的引用

嵌套事务是独立保存点;内部回滚返回到内部入口状态,而内部提交保留足够的历史供稍后的外部回滚使用

自动和显式写入准备

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

回滚将保存的字典条目、数组项和流存储交换回现有根,避免第二次深拷贝;根指针保持稳定,但回滚后必须重新获取直接后代的指针

GetGraphTransactionStatistics 返回 Active、嵌套 Depth、SnapshotCount、AddedObjectCount、常驻和溢出快照字节,以及峰值常驻快照字节

THPDFBeforeMutationEvent 是用于将容器和生命周期变更路由到封闭间接根快照的低级观察器签名

范围

事务覆盖间接对象图、生命周期状态、追加的根和对象编号分配;调用方拥有的指针、已加载页面排序数组、渲染缓存和其他外观侧状态不会被记录

事务活动期间不要移除、重新排序或替换 GetLoadedIndirectObjects 中的现有条目;使用图容器方法并在回滚后重新获取直接后代