Apply FileOps using CRDT table handles opened once for the full pass. This is a specialized fast path for insert-only workloads such as large initial file adds. More complex edit patterns fall back to the generic `apply_file_ops`.
(
txn: &mut WriteTxn<'_>,
change_id: NodeId,
file_ops: &[FileOps],
)
| 182 | /// initial file adds. More complex edit patterns fall back to the generic |
| 183 | /// `apply_file_ops`. |
| 184 | pub fn apply_file_ops_batched( |
| 185 | txn: &mut WriteTxn<'_>, |
| 186 | change_id: NodeId, |
| 187 | file_ops: &[FileOps], |
| 188 | ) -> PristineResult<ApplyFileOpsStats> { |
| 189 | if !can_batch_apply_file_ops(file_ops) { |
| 190 | return apply_file_ops(txn, change_id, file_ops); |
| 191 | } |
| 192 | |
| 193 | let mut stats = ApplyFileOpsStats::new(); |
| 194 | let mut trunk_creates = Vec::with_capacity(file_ops.len()); |
| 195 | |
| 196 | for ops in file_ops { |
| 197 | let trunk_create = match ops.trunk_op() { |
| 198 | Some(TrunkOp::Create { encoding, .. }) => { |
| 199 | let inode = match txn.get_inode(ops.path())? { |
| 200 | Some(i) => i, |
| 201 | None => txn.alloc_inode()?, |
| 202 | }; |
| 203 | Some(SerializedTrunk { |
| 204 | inode, |
| 205 | state: TrunkState::Alive, |
| 206 | encoding: encoding_to_u8(encoding.as_ref()), |
| 207 | path: ops.path().to_string(), |
| 208 | }) |
| 209 | } |
| 210 | _ => None, |
| 211 | }; |
| 212 | trunk_creates.push(trunk_create); |
| 213 | } |
| 214 | |
| 215 | let mut trunks_table = txn.txn.open_table(TRUNKS)?; |
| 216 | let mut inode_trunk_table = txn.txn.open_table(INODE_TRUNK)?; |
| 217 | let mut path_trunk_table = txn.txn.open_table(PATH_TRUNK)?; |
| 218 | let mut branches_table = txn.txn.open_table(BRANCHES)?; |
| 219 | let mut trunk_branches_table = txn.txn.open_multimap_table(TRUNK_BRANCHES)?; |
| 220 | let mut branch_after_table = txn.txn.open_table(BRANCH_AFTER)?; |
| 221 | let mut leaves_table = txn.txn.open_table(LEAVES)?; |
| 222 | let mut branch_leaves_table = txn.txn.open_multimap_table(BRANCH_LEAVES)?; |
| 223 | let mut branch_vertex_table = txn.txn.open_table(BRANCH_VERTEX)?; |
| 224 | let mut vertex_branch_table = txn.txn.open_table(VERTEX_BRANCH)?; |
| 225 | |
| 226 | let mut next_leaf_idx = 0u32; |
| 227 | for (ops, trunk_create) in file_ops.iter().zip(trunk_creates.iter()) { |
| 228 | // Resolve TrunkId placeholder — same logic as apply_single_file_ops. |
| 229 | let raw_trunk_id = ops.trunk_id(); |
| 230 | let trunk_id = if raw_trunk_id.change_id().is_root() { |
| 231 | TrunkId::new(change_id, raw_trunk_id.file_idx()) |
| 232 | } else { |
| 233 | raw_trunk_id |
| 234 | }; |
| 235 | let trunk_key = encode_trunk_id(&trunk_id); |
| 236 | |
| 237 | if let Some(serialized) = trunk_create { |
| 238 | let trunk_value = encode_trunk_value(serialized); |
| 239 | trunks_table.insert(&trunk_key, trunk_value.as_slice())?; |
| 240 | inode_trunk_table.insert(serialized.inode.get(), &trunk_key)?; |
| 241 | path_trunk_table.insert(ops.path(), &trunk_key)?; |
no test coverage detected