Extract shared pack_cells helper in index.ml and table.ml to reduce split_leaf/split_interior below 50-line threshold. Shorten test_first_usable_lba identifier to satisfy E320.
···392392(* Split result: new page number and separator key *)
393393type split_result = { new_page : int; separator_key : string }
394394395395-(* Split a leaf page, returns info about the new page *)
395395+(* Pack cells [start..stop-1] into a fresh page. [copy_cell i] returns bytes. *)
396396+let pack_cells ~page_size ~kind ~copy_cell ~start ~stop =
397397+ let buf = Page.init ~page_size ~kind in
398398+ let content_start = ref page_size in
399399+ for i = start to stop - 1 do
400400+ let cell = copy_cell i in
401401+ content_start := write_cell buf ~cell_content_start:!content_start ~cell;
402402+ let ptr_off = Page.header_size kind + ((i - start) * 2) in
403403+ Page.set_u16_be buf ptr_off !content_start
404404+ done;
405405+ Page.set_u16_be buf 3 (stop - start);
406406+ Page.set_u16_be buf 5 !content_start;
407407+ buf
408408+396409let split_leaf t page_num =
397410 let page = Pager.read t.pager page_num in
398411 let header = Page.parse_header page 0 in
399412 let ptrs = cell_pointers page header in
400413 let usable = usable_size t in
401414 let page_size = Pager.page_size t.pager in
402402-403403- (* Find split point (middle) *)
404415 let split_idx = header.Page.cell_count / 2 in
405405-406406- (* Get separator key (first key that goes to right page) - read full payload *)
407416 let separator_key =
408417 read_full_payload t page ptrs.(split_idx) ~usable_size:usable
409418 in
410410-411411- (* Create new right page *)
419419+ (* Right page: re-encode cells with overflow support *)
412420 let new_page_num = Pager.allocate t.pager in
413413- let new_buf = Page.init ~page_size ~kind:Page.Leaf_index in
414414-415415- (* Copy cells [split_idx..cell_count-1] to new page *)
416416- let new_cell_content_start = ref page_size in
417417- for i = split_idx to header.Page.cell_count - 1 do
418418- let cell_off = ptrs.(i) in
419419- (* Read full payload including from overflow pages *)
420420- let full_payload = read_full_payload t page cell_off ~usable_size:usable in
421421- (* Re-encode with overflow support *)
422422- let cell_data = encode_leaf_cell_overflow t ~payload:full_payload in
423423- new_cell_content_start :=
424424- write_cell new_buf ~cell_content_start:!new_cell_content_start
425425- ~cell:cell_data;
426426- let new_idx = i - split_idx in
427427- let ptr_off = Page.header_size Page.Leaf_index + (new_idx * 2) in
428428- Page.set_u16_be new_buf ptr_off !new_cell_content_start
429429- done;
430430- let new_cell_count = header.Page.cell_count - split_idx in
431431- Page.set_u16_be new_buf 3 new_cell_count;
432432- Page.set_u16_be new_buf 5 !new_cell_content_start;
421421+ let new_buf =
422422+ pack_cells ~page_size ~kind:Page.Leaf_index ~start:split_idx
423423+ ~stop:header.Page.cell_count ~copy_cell:(fun i ->
424424+ let payload = read_full_payload t page ptrs.(i) ~usable_size:usable in
425425+ encode_leaf_cell_overflow t ~payload)
426426+ in
433427 Pager.write t.pager new_page_num (Bytes.unsafe_to_string new_buf);
434434-435435- (* Compact original page: repack remaining cells [0..split_idx-1] *)
436436- let old_buf = Page.init ~page_size ~kind:Page.Leaf_index in
437437- let old_cell_start = ref page_size in
438438- for i = 0 to split_idx - 1 do
439439- let _payload_size, _local, _overflow, cell_size =
440440- Cell.parse_index_leaf_raw page ptrs.(i) ~usable_size:usable
441441- in
442442- let raw_cell = String.sub page ptrs.(i) cell_size in
443443- old_cell_start :=
444444- write_cell old_buf ~cell_content_start:!old_cell_start ~cell:raw_cell;
445445- let ptr_off = Page.header_size Page.Leaf_index + (i * 2) in
446446- Page.set_u16_be old_buf ptr_off !old_cell_start
447447- done;
448448- Page.set_u16_be old_buf 3 split_idx;
449449- Page.set_u16_be old_buf 5 !old_cell_start;
428428+ (* Left page: raw-copy remaining cells *)
429429+ let old_buf =
430430+ pack_cells ~page_size ~kind:Page.Leaf_index ~start:0 ~stop:split_idx
431431+ ~copy_cell:(fun i ->
432432+ let _payload_size, _local, _overflow, cell_size =
433433+ Cell.parse_index_leaf_raw page ptrs.(i) ~usable_size:usable
434434+ in
435435+ String.sub page ptrs.(i) cell_size)
436436+ in
450437 Pager.write t.pager page_num (Bytes.unsafe_to_string old_buf);
451451-452438 { new_page = new_page_num; separator_key }
453439454454-(* Split an interior page *)
455440let split_interior t page_num =
456441 let page = Pager.read t.pager page_num in
457442 let header = Page.parse_header page 0 in
458443 let ptrs = cell_pointers page header in
459444 let usable = usable_size t in
460445 let page_size = Pager.page_size t.pager in
461461-462462- (* Split point - middle cell becomes separator, doesn't go to either page *)
463446 let split_idx = header.Page.cell_count / 2 in
464447 let sep_cell, _ =
465448 Cell.parse_index_interior page ptrs.(split_idx) ~usable_size:usable
···467450 let separator_key =
468451 read_full_interior_payload t page ptrs.(split_idx) ~usable_size:usable
469452 in
470470-471471- (* Create new right page *)
472472- let new_page_num = Pager.allocate t.pager in
473473- let new_buf = Page.init ~page_size ~kind:Page.Interior_index in
474474-475475- (* Cells [split_idx+1..cell_count-1] go to new page (raw copy preserves overflow) *)
476476- let new_cell_content_start = ref page_size in
477477- for i = split_idx + 1 to header.Page.cell_count - 1 do
478478- let cell_off = ptrs.(i) in
453453+ let raw_interior_cell i =
479454 let _left, _payload_size, _local, _overflow, cell_size =
480480- Cell.parse_index_interior_raw page cell_off ~usable_size:usable
455455+ Cell.parse_index_interior_raw page ptrs.(i) ~usable_size:usable
481456 in
482482- let raw_cell = String.sub page cell_off cell_size in
483483- new_cell_content_start :=
484484- write_cell new_buf ~cell_content_start:!new_cell_content_start
485485- ~cell:raw_cell;
486486- let new_idx = i - split_idx - 1 in
487487- let ptr_off = Page.header_size Page.Interior_index + (new_idx * 2) in
488488- Page.set_u16_be new_buf ptr_off !new_cell_content_start
489489- done;
490490- let new_cell_count = header.Page.cell_count - split_idx - 1 in
491491- Page.set_u16_be new_buf 3 new_cell_count;
492492- Page.set_u16_be new_buf 5 !new_cell_content_start;
493493- (* Right child of new page is same as original *)
457457+ String.sub page ptrs.(i) cell_size
458458+ in
459459+ (* Right page *)
460460+ let new_page_num = Pager.allocate t.pager in
461461+ let new_buf =
462462+ pack_cells ~page_size ~kind:Page.Interior_index ~start:(split_idx + 1)
463463+ ~stop:header.Page.cell_count ~copy_cell:raw_interior_cell
464464+ in
494465 Page.set_u32_be new_buf 8 (Option.get header.Page.right_child);
495466 Pager.write t.pager new_page_num (Bytes.unsafe_to_string new_buf);
496496-497497- (* Compact original page: repack remaining cells [0..split_idx-1] *)
498498- let old_buf = Page.init ~page_size ~kind:Page.Interior_index in
499499- let old_cell_start = ref page_size in
500500- for i = 0 to split_idx - 1 do
501501- let _left, _payload_size, _local, _overflow, cell_size =
502502- Cell.parse_index_interior_raw page ptrs.(i) ~usable_size:usable
503503- in
504504- let raw_cell = String.sub page ptrs.(i) cell_size in
505505- old_cell_start :=
506506- write_cell old_buf ~cell_content_start:!old_cell_start ~cell:raw_cell;
507507- let ptr_off = Page.header_size Page.Interior_index + (i * 2) in
508508- Page.set_u16_be old_buf ptr_off !old_cell_start
509509- done;
510510- Page.set_u16_be old_buf 3 split_idx;
511511- Page.set_u16_be old_buf 5 !old_cell_start;
467467+ (* Left page *)
468468+ let old_buf =
469469+ pack_cells ~page_size ~kind:Page.Interior_index ~start:0 ~stop:split_idx
470470+ ~copy_cell:raw_interior_cell
471471+ in
512472 Page.set_u32_be old_buf 8 sep_cell.Cell.left_child;
513473 Pager.write t.pager page_num (Bytes.unsafe_to_string old_buf);
514514-515474 { new_page = new_page_num; separator_key }
516475517476(* Insert a separator into an interior page, potentially splitting *)
+45-90
lib/table.ml
···169169(* Split result: new page number and separator rowid *)
170170type split_result = { new_page : int; separator_rowid : int64 }
171171172172-(* Split a leaf page, returns info about the new page *)
172172+(* Pack cells [start..stop-1] into a fresh page. [copy_cell i] returns bytes. *)
173173+let pack_cells ~page_size ~kind ~copy_cell ~start ~stop =
174174+ let buf = Page.init ~page_size ~kind in
175175+ let content_start = ref page_size in
176176+ for i = start to stop - 1 do
177177+ let cell = copy_cell i in
178178+ content_start := write_cell buf ~cell_content_start:!content_start ~cell;
179179+ let ptr_off = Page.header_size kind + ((i - start) * 2) in
180180+ Page.set_u16_be buf ptr_off !content_start
181181+ done;
182182+ Page.set_u16_be buf 3 (stop - start);
183183+ Page.set_u16_be buf 5 !content_start;
184184+ buf
185185+173186let split_leaf t page_num =
174187 let page = Pager.read t.pager page_num in
175188 let header = Page.parse_header page 0 in
176189 let ptrs = Page.cell_pointers page 0 header in
177190 let usable = usable_size t in
178191 let page_size = Pager.page_size t.pager in
179179-180180- (* Find split point (middle) *)
181192 let split_idx = header.Page.cell_count / 2 in
182182-183183- (* Get separator rowid (first key that goes to right page) *)
184193 let sep_cell, _ =
185194 Cell.parse_table_leaf page ptrs.(split_idx) ~usable_size:usable
186195 in
187196 let separator_rowid = sep_cell.Cell.rowid in
188188-189189- (* Create new right page *)
197197+ (* Right page: re-encode cells *)
190198 let new_page_num = Pager.allocate t.pager in
191191- let new_buf = Page.init ~page_size ~kind:Page.Leaf_table in
192192-193193- (* Copy cells [split_idx..cell_count-1] to new page *)
194194- let new_cell_content_start = ref page_size in
195195- for i = split_idx to header.Page.cell_count - 1 do
196196- let cell_off = ptrs.(i) in
197197- let cell, cell_len =
198198- Cell.parse_table_leaf page cell_off ~usable_size:usable
199199- in
200200- let cell_data =
201201- encode_table_leaf_cell ~rowid:cell.Cell.rowid ~data:cell.Cell.payload
202202- in
203203- new_cell_content_start :=
204204- write_cell new_buf ~cell_content_start:!new_cell_content_start
205205- ~cell:cell_data;
206206- let new_idx = i - split_idx in
207207- let ptr_off = Page.header_size Page.Leaf_table + (new_idx * 2) in
208208- Page.set_u16_be new_buf ptr_off !new_cell_content_start;
209209- ignore cell_len
210210- done;
211211- let new_cell_count = header.Page.cell_count - split_idx in
212212- Page.set_u16_be new_buf 3 new_cell_count;
213213- Page.set_u16_be new_buf 5 !new_cell_content_start;
199199+ let new_buf =
200200+ pack_cells ~page_size ~kind:Page.Leaf_table ~start:split_idx
201201+ ~stop:header.Page.cell_count ~copy_cell:(fun i ->
202202+ let cell, _ = Cell.parse_table_leaf page ptrs.(i) ~usable_size:usable in
203203+ encode_table_leaf_cell ~rowid:cell.Cell.rowid ~data:cell.Cell.payload)
204204+ in
214205 Pager.write t.pager new_page_num (Bytes.unsafe_to_string new_buf);
215215-216216- (* Compact original page: repack remaining cells [0..split_idx-1] *)
217217- let old_buf = Page.init ~page_size ~kind:Page.Leaf_table in
218218- let old_cell_start = ref page_size in
219219- for i = 0 to split_idx - 1 do
220220- let _cell, cell_size =
221221- Cell.parse_table_leaf page ptrs.(i) ~usable_size:usable
222222- in
223223- let raw_cell = String.sub page ptrs.(i) cell_size in
224224- old_cell_start :=
225225- write_cell old_buf ~cell_content_start:!old_cell_start ~cell:raw_cell;
226226- let ptr_off = Page.header_size Page.Leaf_table + (i * 2) in
227227- Page.set_u16_be old_buf ptr_off !old_cell_start
228228- done;
229229- Page.set_u16_be old_buf 3 split_idx;
230230- Page.set_u16_be old_buf 5 !old_cell_start;
206206+ (* Left page: raw-copy remaining cells *)
207207+ let old_buf =
208208+ pack_cells ~page_size ~kind:Page.Leaf_table ~start:0 ~stop:split_idx
209209+ ~copy_cell:(fun i ->
210210+ let _cell, cell_size =
211211+ Cell.parse_table_leaf page ptrs.(i) ~usable_size:usable
212212+ in
213213+ String.sub page ptrs.(i) cell_size)
214214+ in
231215 Pager.write t.pager page_num (Bytes.unsafe_to_string old_buf);
232232-233216 { new_page = new_page_num; separator_rowid }
234217235235-(* Split an interior page *)
236218let split_interior t page_num =
237219 let page = Pager.read t.pager page_num in
238220 let header = Page.parse_header page 0 in
239221 let ptrs = Page.cell_pointers page 0 header in
240222 let page_size = Pager.page_size t.pager in
241241-242242- (* Split point - middle cell becomes separator, doesn't go to either page *)
243223 let split_idx = header.Page.cell_count / 2 in
244224 let sep_cell, _ = Cell.parse_table_interior page ptrs.(split_idx) in
245225 let separator_rowid = sep_cell.Cell.rowid in
246246-247247- (* Create new right page *)
226226+ (* Right page *)
248227 let new_page_num = Pager.allocate t.pager in
249249- let new_buf = Page.init ~page_size ~kind:Page.Interior_table in
250250-251251- (* The right child of split cell becomes the left-most child of new page *)
252252- (* Cells [split_idx+1..cell_count-1] go to new page *)
253253- let new_cell_content_start = ref page_size in
254254- for i = split_idx + 1 to header.Page.cell_count - 1 do
255255- let cell_off = ptrs.(i) in
256256- let cell, _ = Cell.parse_table_interior page cell_off in
257257- let cell_data =
258258- encode_table_interior_cell ~left_child:cell.Cell.left_child
259259- ~rowid:cell.Cell.rowid
260260- in
261261- new_cell_content_start :=
262262- write_cell new_buf ~cell_content_start:!new_cell_content_start
263263- ~cell:cell_data;
264264- let new_idx = i - split_idx - 1 in
265265- let ptr_off = Page.header_size Page.Interior_table + (new_idx * 2) in
266266- Page.set_u16_be new_buf ptr_off !new_cell_content_start
267267- done;
268268- let new_cell_count = header.Page.cell_count - split_idx - 1 in
269269- Page.set_u16_be new_buf 3 new_cell_count;
270270- Page.set_u16_be new_buf 5 !new_cell_content_start;
271271- (* Right child of new page is same as original *)
228228+ let new_buf =
229229+ pack_cells ~page_size ~kind:Page.Interior_table ~start:(split_idx + 1)
230230+ ~stop:header.Page.cell_count ~copy_cell:(fun i ->
231231+ let cell, _ = Cell.parse_table_interior page ptrs.(i) in
232232+ encode_table_interior_cell ~left_child:cell.Cell.left_child
233233+ ~rowid:cell.Cell.rowid)
234234+ in
272235 Page.set_u32_be new_buf 8 (Option.get header.Page.right_child);
273236 Pager.write t.pager new_page_num (Bytes.unsafe_to_string new_buf);
274274-275275- (* Compact original page: repack remaining cells [0..split_idx-1] *)
276276- let old_buf = Page.init ~page_size ~kind:Page.Interior_table in
277277- let old_cell_start = ref page_size in
278278- for i = 0 to split_idx - 1 do
279279- let _cell, cell_size = Cell.parse_table_interior page ptrs.(i) in
280280- let raw_cell = String.sub page ptrs.(i) cell_size in
281281- old_cell_start :=
282282- write_cell old_buf ~cell_content_start:!old_cell_start ~cell:raw_cell;
283283- let ptr_off = Page.header_size Page.Interior_table + (i * 2) in
284284- Page.set_u16_be old_buf ptr_off !old_cell_start
285285- done;
286286- Page.set_u16_be old_buf 3 split_idx;
287287- Page.set_u16_be old_buf 5 !old_cell_start;
237237+ (* Left page *)
238238+ let old_buf =
239239+ pack_cells ~page_size ~kind:Page.Interior_table ~start:0 ~stop:split_idx
240240+ ~copy_cell:(fun i ->
241241+ let _cell, cell_size = Cell.parse_table_interior page ptrs.(i) in
242242+ String.sub page ptrs.(i) cell_size)
243243+ in
288244 Page.set_u32_be old_buf 8 sep_cell.Cell.left_child;
289245 Pager.write t.pager page_num (Bytes.unsafe_to_string old_buf);
290290-291246 { new_page = new_page_num; separator_rowid }
292247293248(* Insert a separator into an interior page, potentially splitting *)