GCC Code Coverage Report


Directory: src/
File: src/index/centroid_page.c
Date: 2026-09-30 11:11:31
Exec Total Coverage
Lines: 43 43 100.0%
Functions: 4 4 100.0%
Branches: 4 4 100.0%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2026 Tiger Data, Inc.
3 * Licensed under the PostgreSQL License. See LICENSE for details.
4 *
5 * centroid_page.c - Centroid tree page operations
6 *
7 * Implements page initialization and entry insertion for centroid pages
8 * using bidirectional growth: metadata forward, vector data backward.
9 * The data format (RaBitQ, float32, float16) is stored in the page
10 * opaque flags and determines per-entry data size.
11 */
12
13 #include "index/centroid_page.h"
14
15 void
16 2209 prism_centroid_page_init_fmt(Page page, uint8_t level, PrismCentroidFormat fmt)
17 {
18 2209 PageInit(page, BLCKSZ, sizeof(PrismCentroidPageOpaque));
19
20 /* Initialize the opaque area */
21 2209 PrismCentroidPageOpaque *opaque = PRISM_CENTROID_OPAQUE(page);
22 2209 opaque->next_blkno = InvalidBlockNumber;
23 2209 opaque->entry_count = 0;
24 2209 opaque->level = level;
25 2209 opaque->flags = fmt & PRISM_CENTROID_FMT_MASK;
26 2209 opaque->page_id = PRISM_CENTROID_PAGE_ID;
27 2209 }
28
29 void *
30 6623 prism_centroid_page_add_entry_begin(
31 Page page,
32 Dimension dim,
33 BlockNumber child_blkno,
34 uint16_t child_count,
35 uint16_t flags)
36 {
37
2/2
✓ Branch 1 taken 1599 times.
✓ Branch 2 taken 5024 times.
6623 if (!prism_centroid_page_has_room(page, dim, false))
38 8 return NULL;
39
40 6611 PageHeader header = (PageHeader)page;
41 6611 PrismCentroidPageOpaque *opaque = PRISM_CENTROID_OPAQUE(page);
42 6611 PrismCentroidFormat fmt = prism_centroid_page_format(page);
43 6611 uint16_t index = opaque->entry_count;
44
45 /* Write metadata (forward region) */
46 6611 PrismCentroidEntryMeta *meta = prism_centroid_meta_mut(page, index);
47 6611 meta->child_blkno = child_blkno;
48 6611 meta->child_count = child_count;
49 6611 meta->flags = flags;
50
51 /* Reserve data space (backward region) */
52 6611 uint32_t data_size = prism_centroid_data_size(dim, fmt);
53 6611 header->pd_upper -= data_size;
54
55 6611 opaque->entry_count = index + 1;
56
57 /*
58 * Recompute rather than advance: a page committed outside index build
59 * comes back with pd_lower covering the hole (see
60 * prism_centroid_meta_end), so incrementing it would leave the page
61 * looking permanently full.
62 */
63 8202 header->pd_lower = (LocationIndex)
64 6611 prism_centroid_meta_end(page, opaque->entry_count);
65
66 6611 return page + header->pd_upper;
67 }
68
69 bool
70 2266 prism_centroid_page_add_entry(
71 Page page,
72 Dimension dim,
73 BlockNumber child_blkno,
74 uint16_t child_count,
75 uint16_t flags,
76 const void *data)
77 {
78 2266 PrismCentroidFormat fmt = prism_centroid_page_format(page);
79 2266 uint32_t data_size = prism_centroid_data_size(dim, fmt);
80
81 2266 void *dest = prism_centroid_page_add_entry_begin(
82 page, dim, child_blkno, child_count, flags);
83
2/2
✓ Branch 0 taken 378 times.
✓ Branch 1 taken 1888 times.
2266 if (dest == NULL)
84 8 return false;
85
86 2254 memcpy(dest, data, data_size);
87 2254 return true;
88 }
89
90 void
91 138 prism_centroid_page_overwrite_entry(
92 Page page,
93 Dimension dim,
94 uint32_t index,
95 BlockNumber child_blkno,
96 const void *data)
97 {
98 138 PrismCentroidFormat fmt = prism_centroid_page_format(page);
99 138 uint32_t data_size = prism_centroid_data_size(dim, fmt);
100
101 /*
102 * In-place replacement of an existing entry: rewrite the fixed-size
103 * metadata slot (forward region) and the fixed-size data slot (backward
104 * region) without touching pd_lower/pd_upper or entry_count, so the page
105 * layout is unchanged and no relayout is needed. child_count/flags are
106 * preserved (a leaf entry stays a leaf). Used by the incremental split to
107 * repoint a leaf at its first child list and update its routing centroid.
108 */
109 138 PrismCentroidEntryMeta *meta = prism_centroid_meta_mut(page, index);
110 138 meta->child_blkno = child_blkno;
111
112 138 void *dest = (char *)PageGetSpecialPointer(page) -
113 138 (size_t)(index + 1) * data_size;
114 138 memcpy(dest, data, data_size);
115 138 }
116