Write leaf pages for an index, returns root page.
| 1278 | |
| 1279 | // Write leaf pages for an index, returns root page. |
| 1280 | static uint32_t write_index_btree(FILE *fp, uint32_t *next_page, uint8_t **cells, int *cell_lens, |
| 1281 | int count) { |
| 1282 | if (count == 0) { |
| 1283 | return write_empty_index_leaf(fp, next_page); |
| 1284 | } |
| 1285 | |
| 1286 | /* Spill oversized index payloads to overflow pages BEFORE page building so |
| 1287 | * every cell added below is within the local-payload limit (see |
| 1288 | * INDEX_OVERFLOW_MAX_LOCAL). Overflow pages are allocated from *next_page |
| 1289 | * ahead of the leaf pages, which is fine — page order is arbitrary. */ |
| 1290 | for (int i = 0; i < count; i++) { |
| 1291 | cells[i] = overflowize_index_cell(fp, next_page, cells[i], &cell_lens[i]); |
| 1292 | } |
| 1293 | |
| 1294 | PageBuilder pb; |
| 1295 | pb_init(&pb, fp, *next_page, true); |
| 1296 | |
| 1297 | for (int i = 0; i < count; i++) { |
| 1298 | if (!pb_cell_fits(&pb, cell_lens[i])) { |
| 1299 | if (pb.cell_count > 0) { |
| 1300 | if (!pb_promote_and_flush(&pb, cells, cell_lens, i - SKIP_ONE)) { |
| 1301 | return 0; |
| 1302 | } |
| 1303 | } |
| 1304 | // After flush, check if the cell still doesn't fit on an empty page. |
| 1305 | // Index cells larger than a full page can never be stored; skip them. |
| 1306 | if (!pb_cell_fits(&pb, cell_lens[i])) { |
| 1307 | (void)fprintf(stderr, "cbm_write_db: index cell oversized, skipped len=%d idx=%d\n", |
| 1308 | cell_lens[i], i); |
| 1309 | continue; |
| 1310 | } |
| 1311 | } |
| 1312 | pb_add_cell(&pb, cells[i], cell_lens[i]); |
| 1313 | } |
| 1314 | |
| 1315 | if (pb.cell_count > 0) { |
| 1316 | if (!pb_ensure_leaf_cap(&pb)) { |
| 1317 | return 0; |
| 1318 | } |
| 1319 | pb.leaves[pb.leaf_count].max_key = 0; |
| 1320 | int last = count - SKIP_ONE; |
| 1321 | pb.leaves[pb.leaf_count].sep_cell = (uint8_t *)malloc(cell_lens[last]); |
| 1322 | memcpy(pb.leaves[pb.leaf_count].sep_cell, cells[last], cell_lens[last]); |
| 1323 | pb.leaves[pb.leaf_count].sep_cell_len = cell_lens[last]; |
| 1324 | pb_flush_leaf(&pb); |
| 1325 | } |
| 1326 | |
| 1327 | *next_page = pb.next_page; |
| 1328 | |
| 1329 | uint32_t root; |
| 1330 | if (!pb.leaves) { |
| 1331 | root = 0; |
| 1332 | } else if (pb.leaf_count == SKIP_ONE) { |
| 1333 | root = pb.leaves[0].page_num; |
| 1334 | } else { |
| 1335 | root = pb_build_interior(&pb, true); |
| 1336 | *next_page = pb.next_page; |
| 1337 | } |
no test coverage detected