Write everything after the nodes table: the edges/vectors/token_vectors data * tables, metadata tables, all indexes, and the sqlite_master page-1 + file * header. `nodes_root` is the root of the already-written nodes table. Closes * w->fp before returning (success or error). */
| 1977 | * header. `nodes_root` is the root of the already-written nodes table. Closes |
| 1978 | * w->fp before returning (success or error). */ |
| 1979 | static int write_db_after_nodes(write_db_ctx_t *w, uint32_t nodes_root) { |
| 1980 | FILE *fp = w->fp; |
| 1981 | CBMDumpNode *nodes = w->nodes; |
| 1982 | int node_count = w->node_count; |
| 1983 | CBMDumpEdge *edges = w->edges; |
| 1984 | int edge_count = w->edge_count; |
| 1985 | |
| 1986 | // Phase 1 (cont.): remaining data tables (edge + vector + token_vector records) |
| 1987 | CBM_PROF_START(t_data); |
| 1988 | uint32_t edges_root; |
| 1989 | uint32_t vectors_root; |
| 1990 | uint32_t token_vecs_root; |
| 1991 | int rc = |
| 1992 | write_one_table(w, &edges_root, w->edges, w->edge_count, adapt_build_edge, adapt_edge_id); |
| 1993 | if (rc != 0) { |
| 1994 | (void)fclose(fp); |
| 1995 | return rc; |
| 1996 | } |
| 1997 | rc = write_one_table(w, &vectors_root, w->vectors, w->vector_count, adapt_build_vector, |
| 1998 | adapt_vector_id); |
| 1999 | if (rc != 0) { |
| 2000 | (void)fclose(fp); |
| 2001 | return rc; |
| 2002 | } |
| 2003 | rc = write_one_table(w, &token_vecs_root, w->token_vecs, w->token_vec_count, |
| 2004 | adapt_build_token_vec, adapt_token_vec_id); |
| 2005 | if (rc != 0) { |
| 2006 | (void)fclose(fp); |
| 2007 | return rc; |
| 2008 | } |
| 2009 | CBM_PROF_END_N("write_db", "1_data_tables", t_data, node_count + edge_count); |
| 2010 | |
| 2011 | // Phase 2: Metadata tables (projects, file_hashes, summaries, sqlite_sequence) |
| 2012 | CBM_PROF_START(t_meta); |
| 2013 | uint32_t projects_root; |
| 2014 | uint32_t file_hashes_root; |
| 2015 | uint32_t summaries_root; |
| 2016 | uint32_t sqlite_seq_root; |
| 2017 | write_metadata_tables(w, &projects_root, &file_hashes_root, &summaries_root, &sqlite_seq_root); |
| 2018 | uint32_t next_page = w->next_page; |
| 2019 | CBM_PROF_END("write_db", "2_metadata_tables", t_meta); |
| 2020 | |
| 2021 | // --- Build indexes (all sorted by key columns before writing) --- |
| 2022 | |
| 2023 | // Set sort contexts for qsort comparators. |
| 2024 | g_sort_nodes = nodes; |
| 2025 | g_sort_edges = edges; |
| 2026 | |
| 2027 | // Parallel sort: all 11 index permutations sorted simultaneously. |
| 2028 | // Sorting is O(N log N) per index — the dominant CPU cost in index building. |
| 2029 | // Cell building + B-tree writing remains serial (sequential page allocation). |
| 2030 | SortJob nsorts[] = { |
| 2031 | {node_count, cmp_node_by_label, NULL}, |
| 2032 | {node_count, cmp_node_by_name, NULL}, |
| 2033 | {node_count, cmp_node_by_file, NULL}, |
| 2034 | {node_count, cmp_node_by_qn, NULL}, |
| 2035 | }; |
| 2036 | SortJob esorts[] = { |
no test coverage detected