linkrs_storage/edge/immutable_csr/
pack.rs1use linkrs_core::types::Timestamp;
2use linkrs_core::StorageError;
3
4use super::super::{
5 BundledCsr, ColdStamps, HotNbr, MutableCsr, Nbr, PureTopologyCsr, SingleMutableCsr,
6 INVALID_EDGE_ID,
7};
8use super::ImmutableCsr;
9use bitvec::vec::BitVec;
10
11pub(crate) fn frozen_error() -> StorageError {
12 StorageError::invalid_operation(
13 "frozen CSR group rejects writes: unfreeze the group before writing".to_string(),
14 )
15}
16
17pub(crate) fn frozen_row_key(nbr: &Nbr) -> (u32, i64, u64) {
20 (nbr.endpoint, nbr.rank, nbr.edge_id.0)
21}
22
23fn sort_packed_row(row: &mut Vec<Nbr>) {
27 row.retain(|nbr| nbr.edge_id != INVALID_EDGE_ID);
28 row.sort_by_key(frozen_row_key);
29}
30
31pub(crate) fn frozen_key_range(hot: &[HotNbr], endpoint: u32, rank: i64) -> (usize, usize) {
35 let lo = hot.partition_point(|h| (h.endpoint, h.rank) < (endpoint, rank));
36 let hi = hot.partition_point(|h| (h.endpoint, h.rank) <= (endpoint, rank));
37 (lo, hi)
38}
39
40impl ImmutableCsr {
41 pub fn new() -> Self {
43 Self {
44 hot_entries: Vec::new(),
45 cold_entries: Vec::new(),
46 degrees: Vec::new(),
47 offsets: Vec::new(),
48 edge_count: 0,
49 values: Vec::new(),
50 valid: BitVec::new(),
51 }
52 }
53
54 pub fn clear(&mut self) {
56 self.hot_entries.clear();
57 self.cold_entries.clear();
58 self.degrees.clear();
59 self.offsets.clear();
60 self.edge_count = 0;
61 self.values.clear();
62 self.valid.clear();
63 }
64
65 pub fn vertex_capacity(&self) -> usize {
67 self.degrees.len()
68 }
69
70 pub(crate) fn packed_hot(&self) -> &[HotNbr] {
72 &self.hot_entries
73 }
74
75 pub(crate) fn packed_cold(&self) -> &[ColdStamps] {
77 &self.cold_entries
78 }
79
80 pub(crate) fn packed_degrees(&self) -> &[u32] {
82 &self.degrees
83 }
84
85 pub fn edge_count(&self) -> u64 {
87 self.edge_count
88 }
89
90 pub fn pack_from_mutable(csr: &MutableCsr) -> Self {
98 Self::pack_from_rows(
99 csr.vertex_capacity(),
100 csr.edge_count() as usize,
101 |local, row| {
102 csr.fill_physical_into(local, row);
103 },
104 )
105 }
106
107 pub fn pack_single_from(csr: &SingleMutableCsr) -> Self {
112 Self::pack_from_rows(
113 csr.vertex_capacity(),
114 csr.edge_count() as usize,
115 |local, row| {
116 csr.fill_physical_into(local, row);
117 },
118 )
119 }
120
121 pub fn pack_from_pure(csr: &PureTopologyCsr) -> Self {
128 Self::pack_from_rows(
129 csr.vertex_capacity(),
130 csr.edge_count() as usize,
131 |local, row| {
132 row.clear();
133 csr.visit_physical(local, |nbr| {
134 row.push(nbr);
135 true
136 });
137 },
138 )
139 }
140
141 pub fn pack_from_bundled(csr: &BundledCsr) -> Self {
149 Self::pack_valued_rows(
150 csr.vertex_capacity(),
151 csr.edge_count() as usize,
152 |local, row, vals| {
153 row.clear();
154 vals.clear();
155 csr.visit_physical_with_values(local, |nbr, value| {
156 row.push(nbr);
157 vals.push(value);
158 true
159 });
160 },
161 )
162 }
163
164 fn pack_from_rows(
169 rows: usize,
170 edge_hint: usize,
171 mut fill_row: impl FnMut(u32, &mut Vec<Nbr>),
172 ) -> Self {
173 let mut hot_entries = Vec::with_capacity(edge_hint);
174 let mut cold_entries = Vec::with_capacity(edge_hint);
175 let mut degrees = Vec::with_capacity(rows);
176 let mut row_buf = Vec::new();
177 let mut live = 0u64;
178 for local in 0..rows {
179 fill_row(local as u32, &mut row_buf);
180 sort_packed_row(&mut row_buf);
181 degrees.push(row_buf.len() as u32);
182 for nbr in &row_buf {
183 if nbr.edge_id != INVALID_EDGE_ID && nbr.delete_ts == Timestamp::MAX {
184 live += 1;
185 }
186 hot_entries.push(nbr.hot());
187 cold_entries.push(nbr.cold());
188 }
189 }
190 let mut packed = Self {
191 hot_entries,
192 cold_entries,
193 degrees,
194 offsets: Vec::with_capacity(rows),
195 edge_count: live,
196 values: Vec::new(),
197 valid: BitVec::new(),
198 };
199 packed.rebuild_offsets();
200 packed
201 }
202
203 fn pack_valued_rows(
211 rows: usize,
212 edge_hint: usize,
213 mut fill_row: impl FnMut(u32, &mut Vec<Nbr>, &mut Vec<Option<u64>>),
214 ) -> Self {
215 let mut hot_entries = Vec::with_capacity(edge_hint);
216 let mut cold_entries = Vec::with_capacity(edge_hint);
217 let mut values = Vec::with_capacity(edge_hint);
218 let mut valid = BitVec::new();
219 let mut degrees = Vec::with_capacity(rows);
220 let mut row_buf = Vec::new();
221 let mut val_buf = Vec::new();
222 let mut pairs = Vec::new();
223 let mut live = 0u64;
224 for local in 0..rows {
225 fill_row(local as u32, &mut row_buf, &mut val_buf);
226 pairs.clear();
227 pairs.extend(row_buf.drain(..).zip(val_buf.drain(..)));
228 pairs.retain(|(nbr, _)| nbr.edge_id != INVALID_EDGE_ID);
229 pairs.sort_by_key(|(nbr, _)| frozen_row_key(nbr));
230 degrees.push(pairs.len() as u32);
231 for (nbr, value) in &pairs {
232 if nbr.edge_id != INVALID_EDGE_ID && nbr.delete_ts == Timestamp::MAX {
233 live += 1;
234 }
235 hot_entries.push(nbr.hot());
236 cold_entries.push(nbr.cold());
237 values.push(value.unwrap_or(0));
238 valid.push(value.is_some());
239 }
240 }
241 let mut packed = Self {
242 hot_entries,
243 cold_entries,
244 degrees,
245 offsets: Vec::with_capacity(rows),
246 edge_count: live,
247 values,
248 valid,
249 };
250 packed.rebuild_offsets();
251 packed
252 }
253
254 pub(crate) fn rebuild_offsets(&mut self) {
255 self.offsets.clear();
256 self.offsets.reserve(self.degrees.len());
257 let mut base = 0u32;
258 for degree in &self.degrees {
259 self.offsets.push(base);
260 base = base.saturating_add(*degree);
261 }
262 }
263}