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