@peerbit/native-backbone 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/README.md +27 -0
- package/dist/src/benchmark.d.ts +19 -0
- package/dist/src/benchmark.d.ts.map +1 -0
- package/dist/src/benchmark.js +12 -0
- package/dist/src/benchmark.js.map +1 -0
- package/dist/src/index.d.ts +1561 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +3406 -0
- package/dist/src/index.js.map +1 -0
- package/dist/wasm/README.md +27 -0
- package/dist/wasm/native_backbone.d.ts +1609 -0
- package/dist/wasm/native_backbone.js +10221 -0
- package/dist/wasm/native_backbone_bg.wasm +0 -0
- package/dist/wasm/native_backbone_bg.wasm.d.ts +625 -0
- package/package.json +64 -0
- package/src/append_tx/committed_latest.rs +2063 -0
- package/src/append_tx/committed_no_next.rs +1165 -0
- package/src/append_tx/facts.rs +791 -0
- package/src/append_tx/mod.rs +751 -0
- package/src/append_tx/storage.rs +599 -0
- package/src/benchmark.ts +58 -0
- package/src/coordinates.rs +422 -0
- package/src/documents.rs +1698 -0
- package/src/graph_blocks.rs +362 -0
- package/src/index.ts +9134 -0
- package/src/js_interop.rs +448 -0
- package/src/lib.rs +144 -0
- package/src/profile.rs +164 -0
- package/src/raw_receive.rs +1724 -0
- package/src/shared_log_plan.rs +1464 -0
- package/src/sync_send.rs +180 -0
- package/src/wire_sync.rs +727 -0
|
@@ -0,0 +1,1464 @@
|
|
|
1
|
+
use js_sys::{Array, BigUint64Array, Uint32Array, Uint8Array};
|
|
2
|
+
use peerbit_indexer_core::storage::ByteStorage;
|
|
3
|
+
use peerbit_shared_log_rust::EntryCoordinateCommit;
|
|
4
|
+
use std::collections::HashSet;
|
|
5
|
+
use wasm_bindgen::prelude::*;
|
|
6
|
+
|
|
7
|
+
use crate::coordinates::{
|
|
8
|
+
coordinate_core_value_to_row, decode_coordinate_value, CoordinateCoreValue,
|
|
9
|
+
};
|
|
10
|
+
use crate::js_interop::{
|
|
11
|
+
array_from_value, ensure_same_len, number_strings_to_array, parse_u64_string,
|
|
12
|
+
string_batches_from_array, strings_from_array, strings_to_array, usize_values_from_array,
|
|
13
|
+
};
|
|
14
|
+
use crate::NativePeerbitBackbone;
|
|
15
|
+
|
|
16
|
+
pub(crate) fn leader_samples_to_rows(values: &[peerbit_shared_log_rust::LeaderSample]) -> Array {
|
|
17
|
+
let out = Array::new();
|
|
18
|
+
for value in values {
|
|
19
|
+
let row = Array::new();
|
|
20
|
+
row.push(&JsValue::from_str(&value.hash));
|
|
21
|
+
row.push(&JsValue::from_bool(value.intersecting));
|
|
22
|
+
out.push(&row);
|
|
23
|
+
}
|
|
24
|
+
out
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
pub(crate) fn leader_samples_to_optional_rows(
|
|
28
|
+
values: &Option<Vec<peerbit_shared_log_rust::LeaderSample>>,
|
|
29
|
+
) -> JsValue {
|
|
30
|
+
let Some(values) = values else {
|
|
31
|
+
return JsValue::UNDEFINED;
|
|
32
|
+
};
|
|
33
|
+
leader_samples_to_rows(values).into()
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
pub(crate) fn clamp_replicas_u32(value: u32, lower: u32, higher: u32) -> u32 {
|
|
37
|
+
value.min(higher).max(lower)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
#[allow(clippy::too_many_arguments)]
|
|
41
|
+
pub(crate) fn coordinate_commits_from_string_columns(
|
|
42
|
+
hashes: Array,
|
|
43
|
+
gids: Array,
|
|
44
|
+
hash_numbers: Array,
|
|
45
|
+
coordinate_batches: Array,
|
|
46
|
+
next_hash_batches: Array,
|
|
47
|
+
assigned_to_range_boundaries: Uint8Array,
|
|
48
|
+
requested_replicas: Array,
|
|
49
|
+
) -> Result<Vec<EntryCoordinateCommit>, JsValue> {
|
|
50
|
+
let hashes = strings_from_array(hashes)?;
|
|
51
|
+
let gids = strings_from_array(gids)?;
|
|
52
|
+
let hash_numbers = strings_from_array(hash_numbers)?;
|
|
53
|
+
let coordinate_batches = coordinate_batches_from_array(coordinate_batches)?;
|
|
54
|
+
let next_hash_batches =
|
|
55
|
+
string_batches_from_array(next_hash_batches, "coordinate commit next hashes")?;
|
|
56
|
+
let requested_replicas = usize_values_from_array(requested_replicas)?;
|
|
57
|
+
coordinate_commits_from_parts(
|
|
58
|
+
hashes,
|
|
59
|
+
gids,
|
|
60
|
+
hash_numbers
|
|
61
|
+
.iter()
|
|
62
|
+
.map(|value| parse_u64_string(value, "coordinate hash number"))
|
|
63
|
+
.collect::<Result<Vec<_>, _>>()?,
|
|
64
|
+
coordinate_batches,
|
|
65
|
+
next_hash_batches,
|
|
66
|
+
assigned_to_range_boundaries,
|
|
67
|
+
requested_replicas,
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
#[allow(clippy::too_many_arguments)]
|
|
72
|
+
pub(crate) fn coordinate_commits_from_u64_columns(
|
|
73
|
+
hashes: Array,
|
|
74
|
+
gids: Array,
|
|
75
|
+
hash_numbers: BigUint64Array,
|
|
76
|
+
coordinate_counts: Uint32Array,
|
|
77
|
+
coordinates: BigUint64Array,
|
|
78
|
+
next_hash_batches: Array,
|
|
79
|
+
assigned_to_range_boundaries: Uint8Array,
|
|
80
|
+
requested_replicas: Uint32Array,
|
|
81
|
+
) -> Result<Vec<EntryCoordinateCommit>, JsValue> {
|
|
82
|
+
let hashes = strings_from_array(hashes)?;
|
|
83
|
+
let gids = strings_from_array(gids)?;
|
|
84
|
+
let hash_numbers = hash_numbers.to_vec();
|
|
85
|
+
let coordinate_counts = coordinate_counts.to_vec();
|
|
86
|
+
let coordinates = coordinates.to_vec();
|
|
87
|
+
let next_hash_batches =
|
|
88
|
+
string_batches_from_array(next_hash_batches, "coordinate commit next hashes")?;
|
|
89
|
+
let requested_replicas = requested_replicas
|
|
90
|
+
.to_vec()
|
|
91
|
+
.into_iter()
|
|
92
|
+
.map(|value| value as usize)
|
|
93
|
+
.collect::<Vec<_>>();
|
|
94
|
+
ensure_same_len(
|
|
95
|
+
hashes.len(),
|
|
96
|
+
coordinate_counts.len(),
|
|
97
|
+
"coordinate commit coordinate counts",
|
|
98
|
+
)?;
|
|
99
|
+
let coordinate_total = coordinate_counts
|
|
100
|
+
.iter()
|
|
101
|
+
.try_fold(0usize, |sum, count| sum.checked_add(*count as usize))
|
|
102
|
+
.ok_or_else(|| JsValue::from_str("Coordinate count overflow"))?;
|
|
103
|
+
ensure_same_len(
|
|
104
|
+
coordinate_total,
|
|
105
|
+
coordinates.len(),
|
|
106
|
+
"coordinate commit flattened coordinates",
|
|
107
|
+
)?;
|
|
108
|
+
let mut coordinate_batches = Vec::with_capacity(coordinate_counts.len());
|
|
109
|
+
let mut offset = 0usize;
|
|
110
|
+
for count in coordinate_counts {
|
|
111
|
+
let end = offset + count as usize;
|
|
112
|
+
coordinate_batches.push(coordinates[offset..end].to_vec());
|
|
113
|
+
offset = end;
|
|
114
|
+
}
|
|
115
|
+
coordinate_commits_from_parts(
|
|
116
|
+
hashes,
|
|
117
|
+
gids,
|
|
118
|
+
hash_numbers,
|
|
119
|
+
coordinate_batches,
|
|
120
|
+
next_hash_batches,
|
|
121
|
+
assigned_to_range_boundaries,
|
|
122
|
+
requested_replicas,
|
|
123
|
+
)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
#[allow(clippy::too_many_arguments)]
|
|
127
|
+
fn coordinate_commits_from_parts(
|
|
128
|
+
hashes: Vec<String>,
|
|
129
|
+
gids: Vec<String>,
|
|
130
|
+
hash_numbers: Vec<u64>,
|
|
131
|
+
coordinate_batches: Vec<Vec<u64>>,
|
|
132
|
+
next_hash_batches: Vec<Vec<String>>,
|
|
133
|
+
assigned_to_range_boundaries: Uint8Array,
|
|
134
|
+
requested_replicas: Vec<usize>,
|
|
135
|
+
) -> Result<Vec<EntryCoordinateCommit>, JsValue> {
|
|
136
|
+
ensure_same_len(hashes.len(), gids.len(), "coordinate commit gid")?;
|
|
137
|
+
ensure_same_len(
|
|
138
|
+
hashes.len(),
|
|
139
|
+
hash_numbers.len(),
|
|
140
|
+
"coordinate commit hash number",
|
|
141
|
+
)?;
|
|
142
|
+
ensure_same_len(
|
|
143
|
+
hashes.len(),
|
|
144
|
+
coordinate_batches.len(),
|
|
145
|
+
"coordinate commit coordinates",
|
|
146
|
+
)?;
|
|
147
|
+
ensure_same_len(
|
|
148
|
+
hashes.len(),
|
|
149
|
+
next_hash_batches.len(),
|
|
150
|
+
"coordinate commit next hashes",
|
|
151
|
+
)?;
|
|
152
|
+
ensure_same_len(
|
|
153
|
+
hashes.len(),
|
|
154
|
+
assigned_to_range_boundaries.length() as usize,
|
|
155
|
+
"coordinate commit assigned flags",
|
|
156
|
+
)?;
|
|
157
|
+
ensure_same_len(
|
|
158
|
+
hashes.len(),
|
|
159
|
+
requested_replicas.len(),
|
|
160
|
+
"coordinate commit replicas",
|
|
161
|
+
)?;
|
|
162
|
+
|
|
163
|
+
let mut commits = Vec::with_capacity(hashes.len());
|
|
164
|
+
for (index, ((((hash, gid), coordinates), next_hashes), requested_replicas)) in hashes
|
|
165
|
+
.into_iter()
|
|
166
|
+
.zip(gids)
|
|
167
|
+
.zip(coordinate_batches)
|
|
168
|
+
.zip(next_hash_batches)
|
|
169
|
+
.zip(requested_replicas)
|
|
170
|
+
.enumerate()
|
|
171
|
+
{
|
|
172
|
+
commits.push(EntryCoordinateCommit {
|
|
173
|
+
hash,
|
|
174
|
+
gid,
|
|
175
|
+
hash_number: hash_numbers[index],
|
|
176
|
+
coordinates,
|
|
177
|
+
next_hashes,
|
|
178
|
+
assigned_to_range_boundary: assigned_to_range_boundaries.get_index(index as u32) != 0,
|
|
179
|
+
requested_replicas,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
Ok(commits)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
fn coordinate_batches_from_array(values: Array) -> Result<Vec<Vec<u64>>, JsValue> {
|
|
186
|
+
let mut out = Vec::with_capacity(values.length() as usize);
|
|
187
|
+
for index in 0..values.length() {
|
|
188
|
+
let value = values.get(index);
|
|
189
|
+
if !Array::is_array(&value) {
|
|
190
|
+
return Err(JsValue::from_str("Expected coordinate batch array"));
|
|
191
|
+
}
|
|
192
|
+
out.push(coordinate_numbers_from_array(Array::from(&value))?);
|
|
193
|
+
}
|
|
194
|
+
Ok(out)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
pub(crate) fn coordinate_numbers_from_array(values: Array) -> Result<Vec<u64>, JsValue> {
|
|
198
|
+
let mut out = Vec::with_capacity(values.length() as usize);
|
|
199
|
+
for index in 0..values.length() {
|
|
200
|
+
let value = values.get(index);
|
|
201
|
+
if let Some(value) = value.as_string() {
|
|
202
|
+
out.push(parse_u64_string(&value, "coordinate")?);
|
|
203
|
+
} else if let Some(value) = value.as_f64() {
|
|
204
|
+
out.push(value as u64);
|
|
205
|
+
} else {
|
|
206
|
+
return Err(JsValue::from_str("Expected coordinate string array"));
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
Ok(out)
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
#[wasm_bindgen]
|
|
213
|
+
impl NativePeerbitBackbone {
|
|
214
|
+
pub fn entry_coordinate_hashes(&self) -> Array {
|
|
215
|
+
self.shared_log.entry_coordinate_hashes()
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
pub fn get_entry_coordinates(&self, hash: &str) -> JsValue {
|
|
219
|
+
self.shared_log.get_entry_coordinates(hash)
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
#[allow(clippy::too_many_arguments)]
|
|
223
|
+
pub fn find_leaders(
|
|
224
|
+
&self,
|
|
225
|
+
cursors: Array,
|
|
226
|
+
replicas: usize,
|
|
227
|
+
role_age_ms: f64,
|
|
228
|
+
now: String,
|
|
229
|
+
peer_filter: JsValue,
|
|
230
|
+
expand_peer_filter: bool,
|
|
231
|
+
self_hash: String,
|
|
232
|
+
include_self: bool,
|
|
233
|
+
full_replica_fallback: bool,
|
|
234
|
+
include_strict_full_replica: bool,
|
|
235
|
+
) -> Result<Array, JsValue> {
|
|
236
|
+
self.shared_log.find_leaders(
|
|
237
|
+
cursors,
|
|
238
|
+
replicas,
|
|
239
|
+
role_age_ms,
|
|
240
|
+
now,
|
|
241
|
+
peer_filter,
|
|
242
|
+
expand_peer_filter,
|
|
243
|
+
self_hash,
|
|
244
|
+
include_self,
|
|
245
|
+
full_replica_fallback,
|
|
246
|
+
include_strict_full_replica,
|
|
247
|
+
)
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
#[allow(clippy::too_many_arguments)]
|
|
251
|
+
pub fn find_leaders_batch(
|
|
252
|
+
&self,
|
|
253
|
+
cursor_batches: Array,
|
|
254
|
+
replica_counts: Array,
|
|
255
|
+
role_age_ms: f64,
|
|
256
|
+
now: String,
|
|
257
|
+
peer_filter: JsValue,
|
|
258
|
+
expand_peer_filter: bool,
|
|
259
|
+
self_hash: String,
|
|
260
|
+
include_self: bool,
|
|
261
|
+
full_replica_fallback: bool,
|
|
262
|
+
include_strict_full_replica: bool,
|
|
263
|
+
) -> Result<Array, JsValue> {
|
|
264
|
+
self.shared_log.find_leaders_batch(
|
|
265
|
+
cursor_batches,
|
|
266
|
+
replica_counts,
|
|
267
|
+
role_age_ms,
|
|
268
|
+
now,
|
|
269
|
+
peer_filter,
|
|
270
|
+
expand_peer_filter,
|
|
271
|
+
self_hash,
|
|
272
|
+
include_self,
|
|
273
|
+
full_replica_fallback,
|
|
274
|
+
include_strict_full_replica,
|
|
275
|
+
)
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
pub fn get_grid(&self, from: String, count: usize) -> Result<Array, JsValue> {
|
|
279
|
+
self.shared_log.get_grid(from, count)
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
pub fn get_gid_coordinates(&self, gid: String, count: usize) -> Array {
|
|
283
|
+
self.shared_log.get_gid_coordinates(gid, count)
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
pub fn entry_hashes_for_hash_numbers(&self, hash_numbers: Array) -> Result<Array, JsValue> {
|
|
287
|
+
self.shared_log.entry_hashes_for_hash_numbers(hash_numbers)
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
pub fn entry_hashes_for_hash_numbers_u64(
|
|
291
|
+
&self,
|
|
292
|
+
hash_numbers: BigUint64Array,
|
|
293
|
+
) -> Result<Array, JsValue> {
|
|
294
|
+
self.shared_log
|
|
295
|
+
.entry_hashes_for_hash_numbers_u64(hash_numbers)
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
pub fn entry_hashes_for_hash_numbers_flat_u64(&self, hash_numbers: BigUint64Array) -> Array {
|
|
299
|
+
self.shared_log
|
|
300
|
+
.entry_hashes_for_hash_numbers_flat_u64(hash_numbers)
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
pub fn entry_hash_numbers_in_range(
|
|
304
|
+
&self,
|
|
305
|
+
start1: String,
|
|
306
|
+
end1: String,
|
|
307
|
+
start2: String,
|
|
308
|
+
end2: String,
|
|
309
|
+
) -> Result<Array, JsValue> {
|
|
310
|
+
self.shared_log
|
|
311
|
+
.entry_hash_numbers_in_range(start1, end1, start2, end2)
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
pub fn entry_hash_numbers_in_range_u64(
|
|
315
|
+
&self,
|
|
316
|
+
start1: String,
|
|
317
|
+
end1: String,
|
|
318
|
+
start2: String,
|
|
319
|
+
end2: String,
|
|
320
|
+
) -> Result<BigUint64Array, JsValue> {
|
|
321
|
+
self.shared_log
|
|
322
|
+
.entry_hash_numbers_in_range_u64(start1, end1, start2, end2)
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
pub fn count_entry_coordinates_in_ranges(
|
|
326
|
+
&self,
|
|
327
|
+
start1: Array,
|
|
328
|
+
end1: Array,
|
|
329
|
+
start2: Array,
|
|
330
|
+
end2: Array,
|
|
331
|
+
include_assigned_to_range_boundary: bool,
|
|
332
|
+
) -> Result<usize, JsValue> {
|
|
333
|
+
self.shared_log.count_entry_coordinates_in_ranges(
|
|
334
|
+
start1,
|
|
335
|
+
end1,
|
|
336
|
+
start2,
|
|
337
|
+
end2,
|
|
338
|
+
include_assigned_to_range_boundary,
|
|
339
|
+
)
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
pub fn entry_coordinate_fields(&self) -> Result<Array, JsValue> {
|
|
343
|
+
let out = Array::new();
|
|
344
|
+
for (_, value) in self.coordinate_values.entries() {
|
|
345
|
+
let coordinate = decode_coordinate_value(&value)?;
|
|
346
|
+
out.push(&coordinate_core_value_to_row(&coordinate));
|
|
347
|
+
}
|
|
348
|
+
Ok(out)
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
pub fn clear_shared_log(&mut self) {
|
|
352
|
+
self.shared_log.clear();
|
|
353
|
+
self.clear_coordinate_core();
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
pub fn clear_entry_coordinates(&mut self) {
|
|
357
|
+
self.shared_log.clear_entry_coordinates();
|
|
358
|
+
self.clear_coordinate_core();
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
#[allow(clippy::too_many_arguments)]
|
|
362
|
+
pub fn put_range(
|
|
363
|
+
&mut self,
|
|
364
|
+
id: String,
|
|
365
|
+
hash: String,
|
|
366
|
+
timestamp: String,
|
|
367
|
+
start1: String,
|
|
368
|
+
end1: String,
|
|
369
|
+
start2: String,
|
|
370
|
+
end2: String,
|
|
371
|
+
width: String,
|
|
372
|
+
mode: u8,
|
|
373
|
+
) -> Result<(), JsValue> {
|
|
374
|
+
self.shared_log
|
|
375
|
+
.put(id, hash, timestamp, start1, end1, start2, end2, width, mode)
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
pub fn delete_range(&mut self, id: &str) -> bool {
|
|
379
|
+
self.shared_log.delete(id)
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
pub fn put_entry_coordinates(
|
|
383
|
+
&mut self,
|
|
384
|
+
hash: String,
|
|
385
|
+
gid: String,
|
|
386
|
+
hash_number: String,
|
|
387
|
+
coordinates: Array,
|
|
388
|
+
assigned_to_range_boundary: bool,
|
|
389
|
+
requested_replicas: usize,
|
|
390
|
+
) -> Result<(), JsValue> {
|
|
391
|
+
let hash_for_core = hash.clone();
|
|
392
|
+
let gid_for_core = gid.clone();
|
|
393
|
+
let hash_number_for_core = hash_number.clone();
|
|
394
|
+
let coordinates_for_core = coordinates.clone();
|
|
395
|
+
self.shared_log.put_entry_coordinates(
|
|
396
|
+
hash,
|
|
397
|
+
gid,
|
|
398
|
+
hash_number,
|
|
399
|
+
coordinates,
|
|
400
|
+
assigned_to_range_boundary,
|
|
401
|
+
requested_replicas,
|
|
402
|
+
)?;
|
|
403
|
+
self.put_coordinate_core_from_parts(
|
|
404
|
+
hash_for_core,
|
|
405
|
+
gid_for_core,
|
|
406
|
+
&hash_number_for_core,
|
|
407
|
+
coordinates_for_core,
|
|
408
|
+
assigned_to_range_boundary,
|
|
409
|
+
requested_replicas,
|
|
410
|
+
0,
|
|
411
|
+
Vec::new(),
|
|
412
|
+
)
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
pub fn delete_entry_coordinates(&mut self, hash: &str) -> bool {
|
|
416
|
+
let deleted_shared_log = self.shared_log.delete_entry_coordinates(hash);
|
|
417
|
+
let deleted_core = self.delete_coordinate_core(hash);
|
|
418
|
+
deleted_shared_log || deleted_core
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
pub fn delete_entry_coordinates_batch(&mut self, hashes: Array) -> Result<(), JsValue> {
|
|
422
|
+
let hashes_for_core = hashes.clone();
|
|
423
|
+
self.shared_log.delete_entry_coordinates_batch(hashes)?;
|
|
424
|
+
self.delete_coordinate_core_batch(hashes_for_core)
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
pub fn commit_entry_coordinates(
|
|
428
|
+
&mut self,
|
|
429
|
+
hash: String,
|
|
430
|
+
gid: String,
|
|
431
|
+
hash_number: String,
|
|
432
|
+
coordinates: Array,
|
|
433
|
+
next_hashes: Array,
|
|
434
|
+
assigned_to_range_boundary: bool,
|
|
435
|
+
requested_replicas: usize,
|
|
436
|
+
) -> Result<(), JsValue> {
|
|
437
|
+
let hash_for_core = hash.clone();
|
|
438
|
+
let gid_for_core = gid.clone();
|
|
439
|
+
let hash_number_for_core = hash_number.clone();
|
|
440
|
+
let coordinates_for_core = coordinates.clone();
|
|
441
|
+
let next_hashes_for_core = next_hashes.clone();
|
|
442
|
+
self.shared_log.commit_entry_coordinates(
|
|
443
|
+
hash,
|
|
444
|
+
gid,
|
|
445
|
+
hash_number,
|
|
446
|
+
coordinates,
|
|
447
|
+
next_hashes,
|
|
448
|
+
assigned_to_range_boundary,
|
|
449
|
+
requested_replicas,
|
|
450
|
+
)?;
|
|
451
|
+
self.put_coordinate_core_from_parts(
|
|
452
|
+
hash_for_core,
|
|
453
|
+
gid_for_core,
|
|
454
|
+
&hash_number_for_core,
|
|
455
|
+
coordinates_for_core,
|
|
456
|
+
assigned_to_range_boundary,
|
|
457
|
+
requested_replicas,
|
|
458
|
+
0,
|
|
459
|
+
Vec::new(),
|
|
460
|
+
)?;
|
|
461
|
+
self.delete_coordinate_core_batch(next_hashes_for_core)
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
pub fn commit_entry_coordinates_batch(
|
|
465
|
+
&mut self,
|
|
466
|
+
hashes: Array,
|
|
467
|
+
gids: Array,
|
|
468
|
+
hash_numbers: Array,
|
|
469
|
+
coordinate_batches: Array,
|
|
470
|
+
next_hash_batches: Array,
|
|
471
|
+
assigned_to_range_boundaries: Uint8Array,
|
|
472
|
+
requested_replicas: Array,
|
|
473
|
+
) -> Result<(), JsValue> {
|
|
474
|
+
let commits = coordinate_commits_from_string_columns(
|
|
475
|
+
hashes,
|
|
476
|
+
gids,
|
|
477
|
+
hash_numbers,
|
|
478
|
+
coordinate_batches,
|
|
479
|
+
next_hash_batches,
|
|
480
|
+
assigned_to_range_boundaries,
|
|
481
|
+
requested_replicas,
|
|
482
|
+
)?;
|
|
483
|
+
self.commit_entry_coordinate_commits(commits);
|
|
484
|
+
Ok(())
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
pub fn commit_entry_coordinates_batch_u64(
|
|
488
|
+
&mut self,
|
|
489
|
+
hashes: Array,
|
|
490
|
+
gids: Array,
|
|
491
|
+
hash_numbers: BigUint64Array,
|
|
492
|
+
coordinate_counts: Uint32Array,
|
|
493
|
+
coordinates: BigUint64Array,
|
|
494
|
+
next_hash_batches: Array,
|
|
495
|
+
assigned_to_range_boundaries: Uint8Array,
|
|
496
|
+
requested_replicas: Uint32Array,
|
|
497
|
+
) -> Result<(), JsValue> {
|
|
498
|
+
let commits = coordinate_commits_from_u64_columns(
|
|
499
|
+
hashes,
|
|
500
|
+
gids,
|
|
501
|
+
hash_numbers,
|
|
502
|
+
coordinate_counts,
|
|
503
|
+
coordinates,
|
|
504
|
+
next_hash_batches,
|
|
505
|
+
assigned_to_range_boundaries,
|
|
506
|
+
requested_replicas,
|
|
507
|
+
)?;
|
|
508
|
+
self.commit_entry_coordinate_commits(commits);
|
|
509
|
+
Ok(())
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
pub fn add_gid_peers(
|
|
513
|
+
&mut self,
|
|
514
|
+
gid: String,
|
|
515
|
+
peers: Array,
|
|
516
|
+
reset: bool,
|
|
517
|
+
) -> Result<usize, JsValue> {
|
|
518
|
+
self.shared_log.add_gid_peers(gid, peers, reset)
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
pub fn remove_gid_peer(&mut self, peer: &str, gid: JsValue) -> Result<(), JsValue> {
|
|
522
|
+
self.shared_log.remove_gid_peer(peer, gid)
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
pub fn remove_gid_peers(&mut self, peer: &str, gids: Array) -> Result<(), JsValue> {
|
|
526
|
+
self.shared_log.remove_gid_peers(peer, gids)
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
pub fn delete_gid_peers(&mut self, gid: &str) -> bool {
|
|
530
|
+
self.shared_log.delete_gid_peers(gid)
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
pub fn clear_gid_peers(&mut self) {
|
|
534
|
+
self.shared_log.clear_gid_peers();
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
pub fn mark_entries_known_by_peer(
|
|
538
|
+
&mut self,
|
|
539
|
+
hashes: Array,
|
|
540
|
+
peer: String,
|
|
541
|
+
) -> Result<(), JsValue> {
|
|
542
|
+
self.shared_log.mark_entries_known_by_peer(hashes, peer)
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
pub fn remove_entries_known_by_peer(
|
|
546
|
+
&mut self,
|
|
547
|
+
hashes: Array,
|
|
548
|
+
peer: &str,
|
|
549
|
+
) -> Result<(), JsValue> {
|
|
550
|
+
self.shared_log.remove_entries_known_by_peer(hashes, peer)
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
pub fn remove_peer_from_entry_known_peers(&mut self, peer: &str) {
|
|
554
|
+
self.shared_log.remove_peer_from_entry_known_peers(peer);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
pub fn clear_entry_known_peers(&mut self) {
|
|
558
|
+
self.shared_log.clear_entry_known_peers();
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
#[allow(clippy::too_many_arguments)]
|
|
562
|
+
pub fn plan_entry_leaders_for_gid(
|
|
563
|
+
&self,
|
|
564
|
+
gid: String,
|
|
565
|
+
replicas: usize,
|
|
566
|
+
role_age_ms: f64,
|
|
567
|
+
now: String,
|
|
568
|
+
peer_filter: JsValue,
|
|
569
|
+
expand_peer_filter: bool,
|
|
570
|
+
self_hash: String,
|
|
571
|
+
include_self: bool,
|
|
572
|
+
full_replica_fallback: bool,
|
|
573
|
+
include_strict_full_replica: bool,
|
|
574
|
+
) -> Result<Array, JsValue> {
|
|
575
|
+
self.shared_log.plan_entry_leaders_for_gid(
|
|
576
|
+
gid,
|
|
577
|
+
replicas,
|
|
578
|
+
role_age_ms,
|
|
579
|
+
now,
|
|
580
|
+
peer_filter,
|
|
581
|
+
expand_peer_filter,
|
|
582
|
+
self_hash,
|
|
583
|
+
include_self,
|
|
584
|
+
full_replica_fallback,
|
|
585
|
+
include_strict_full_replica,
|
|
586
|
+
)
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
#[allow(clippy::too_many_arguments)]
|
|
590
|
+
pub fn plan_leaders_for_gids_batch(
|
|
591
|
+
&self,
|
|
592
|
+
gids: Array,
|
|
593
|
+
replica_counts: Array,
|
|
594
|
+
role_age_ms: f64,
|
|
595
|
+
now: String,
|
|
596
|
+
peer_filter: JsValue,
|
|
597
|
+
expand_peer_filter: bool,
|
|
598
|
+
self_hash: String,
|
|
599
|
+
include_self: bool,
|
|
600
|
+
full_replica_fallback: bool,
|
|
601
|
+
include_strict_full_replica: bool,
|
|
602
|
+
) -> Result<Array, JsValue> {
|
|
603
|
+
self.shared_log.plan_leaders_for_gids_batch(
|
|
604
|
+
gids,
|
|
605
|
+
replica_counts,
|
|
606
|
+
role_age_ms,
|
|
607
|
+
now,
|
|
608
|
+
peer_filter,
|
|
609
|
+
expand_peer_filter,
|
|
610
|
+
self_hash,
|
|
611
|
+
include_self,
|
|
612
|
+
full_replica_fallback,
|
|
613
|
+
include_strict_full_replica,
|
|
614
|
+
)
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
#[allow(clippy::too_many_arguments)]
|
|
618
|
+
pub fn plan_leader_samples_for_gids_batch(
|
|
619
|
+
&self,
|
|
620
|
+
gids: Array,
|
|
621
|
+
replica_counts: Array,
|
|
622
|
+
role_age_ms: f64,
|
|
623
|
+
now: String,
|
|
624
|
+
peer_filter: JsValue,
|
|
625
|
+
expand_peer_filter: bool,
|
|
626
|
+
self_hash: String,
|
|
627
|
+
include_self: bool,
|
|
628
|
+
full_replica_fallback: bool,
|
|
629
|
+
include_strict_full_replica: bool,
|
|
630
|
+
) -> Result<Array, JsValue> {
|
|
631
|
+
self.shared_log.plan_leader_samples_for_gids_batch(
|
|
632
|
+
gids,
|
|
633
|
+
replica_counts,
|
|
634
|
+
role_age_ms,
|
|
635
|
+
now,
|
|
636
|
+
peer_filter,
|
|
637
|
+
expand_peer_filter,
|
|
638
|
+
self_hash,
|
|
639
|
+
include_self,
|
|
640
|
+
full_replica_fallback,
|
|
641
|
+
include_strict_full_replica,
|
|
642
|
+
)
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
#[allow(clippy::too_many_arguments)]
|
|
646
|
+
pub fn plan_request_prune_leader_hints(
|
|
647
|
+
&self,
|
|
648
|
+
hashes: Array,
|
|
649
|
+
skip_hashes: Array,
|
|
650
|
+
role_age_ms: f64,
|
|
651
|
+
now: String,
|
|
652
|
+
peer_filter: JsValue,
|
|
653
|
+
expand_peer_filter: bool,
|
|
654
|
+
self_hash: String,
|
|
655
|
+
include_self: bool,
|
|
656
|
+
full_replica_fallback: bool,
|
|
657
|
+
include_strict_full_replica: bool,
|
|
658
|
+
) -> Result<Array, JsValue> {
|
|
659
|
+
let hashes = strings_from_array(hashes)?;
|
|
660
|
+
let skip_hashes = strings_from_array(skip_hashes)?;
|
|
661
|
+
let skip_hashes = if skip_hashes.is_empty() {
|
|
662
|
+
None
|
|
663
|
+
} else {
|
|
664
|
+
Some(skip_hashes.into_iter().collect::<HashSet<String>>())
|
|
665
|
+
};
|
|
666
|
+
let metadata = self.log.entry_prune_metadata_values(&hashes);
|
|
667
|
+
let entry_rows = Array::new();
|
|
668
|
+
let mut present_block_hashes = Vec::new();
|
|
669
|
+
let mut candidate_hashes = Vec::new();
|
|
670
|
+
let mut candidate_gids = Vec::new();
|
|
671
|
+
let mut candidate_replicas = Vec::new();
|
|
672
|
+
|
|
673
|
+
for (hash, metadata) in hashes.iter().zip(metadata) {
|
|
674
|
+
let has_block = self.blocks.has(hash);
|
|
675
|
+
if has_block {
|
|
676
|
+
present_block_hashes.push(hash.clone());
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
let Some((gid, data, replicas)) = metadata else {
|
|
680
|
+
continue;
|
|
681
|
+
};
|
|
682
|
+
let requested_replicas = replicas
|
|
683
|
+
.map(|replicas| replicas as usize)
|
|
684
|
+
.or_else(|| self.shared_log.entry_requested_replicas(hash));
|
|
685
|
+
|
|
686
|
+
let row = Array::new();
|
|
687
|
+
row.push(&JsValue::from_str(hash));
|
|
688
|
+
row.push(&JsValue::from_str(&gid));
|
|
689
|
+
match requested_replicas {
|
|
690
|
+
Some(replicas) => row.push(&JsValue::from_f64(replicas as f64)),
|
|
691
|
+
None => row.push(&JsValue::UNDEFINED),
|
|
692
|
+
};
|
|
693
|
+
match data.as_ref().filter(|_| requested_replicas.is_none()) {
|
|
694
|
+
Some(data) => row.push(&Uint8Array::from(data.as_slice())),
|
|
695
|
+
None => row.push(&JsValue::UNDEFINED),
|
|
696
|
+
};
|
|
697
|
+
entry_rows.push(&row);
|
|
698
|
+
|
|
699
|
+
if has_block
|
|
700
|
+
&& skip_hashes
|
|
701
|
+
.as_ref()
|
|
702
|
+
.map_or(true, |skip_hashes| !skip_hashes.contains(hash))
|
|
703
|
+
{
|
|
704
|
+
if let Some(replicas) = requested_replicas {
|
|
705
|
+
candidate_hashes.push(hash.clone());
|
|
706
|
+
candidate_gids.push(gid);
|
|
707
|
+
candidate_replicas.push(replicas);
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
let local_flags = if candidate_hashes.is_empty() {
|
|
713
|
+
Vec::new()
|
|
714
|
+
} else {
|
|
715
|
+
self.shared_log.local_leader_flags_for_gids_batch(
|
|
716
|
+
&candidate_gids,
|
|
717
|
+
&candidate_replicas,
|
|
718
|
+
role_age_ms,
|
|
719
|
+
&now,
|
|
720
|
+
peer_filter,
|
|
721
|
+
expand_peer_filter,
|
|
722
|
+
&self_hash,
|
|
723
|
+
include_self,
|
|
724
|
+
full_replica_fallback,
|
|
725
|
+
include_strict_full_replica,
|
|
726
|
+
)?
|
|
727
|
+
};
|
|
728
|
+
let local_leader_hashes = candidate_hashes
|
|
729
|
+
.iter()
|
|
730
|
+
.zip(local_flags)
|
|
731
|
+
.filter_map(|(hash, is_local)| is_local.then(|| hash.clone()))
|
|
732
|
+
.collect::<Vec<_>>();
|
|
733
|
+
|
|
734
|
+
let out = Array::new();
|
|
735
|
+
out.push(&entry_rows);
|
|
736
|
+
out.push(&strings_to_array(present_block_hashes));
|
|
737
|
+
out.push(&strings_to_array(local_leader_hashes));
|
|
738
|
+
out.push(&strings_to_array(candidate_gids));
|
|
739
|
+
out.push(&strings_to_array(candidate_hashes));
|
|
740
|
+
Ok(out)
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
#[allow(clippy::too_many_arguments)]
|
|
744
|
+
pub fn plan_request_prune_leader_hint_columns(
|
|
745
|
+
&self,
|
|
746
|
+
hashes: Array,
|
|
747
|
+
skip_hashes: Array,
|
|
748
|
+
role_age_ms: f64,
|
|
749
|
+
now: String,
|
|
750
|
+
peer_filter: JsValue,
|
|
751
|
+
expand_peer_filter: bool,
|
|
752
|
+
self_hash: String,
|
|
753
|
+
include_self: bool,
|
|
754
|
+
full_replica_fallback: bool,
|
|
755
|
+
include_strict_full_replica: bool,
|
|
756
|
+
) -> Result<Array, JsValue> {
|
|
757
|
+
let hashes = strings_from_array(hashes)?;
|
|
758
|
+
let skip_hashes = strings_from_array(skip_hashes)?;
|
|
759
|
+
let skip_hashes = if skip_hashes.is_empty() {
|
|
760
|
+
None
|
|
761
|
+
} else {
|
|
762
|
+
Some(skip_hashes.into_iter().collect::<HashSet<String>>())
|
|
763
|
+
};
|
|
764
|
+
let metadata = self.log.entry_prune_metadata_values(&hashes);
|
|
765
|
+
let gids = Array::new();
|
|
766
|
+
let data_rows = Array::new();
|
|
767
|
+
let mut replica_counts = Vec::with_capacity(hashes.len());
|
|
768
|
+
let mut present_block_flags = Vec::with_capacity(hashes.len());
|
|
769
|
+
let mut candidate_indexes = Vec::new();
|
|
770
|
+
let mut candidate_gids = Vec::new();
|
|
771
|
+
let mut candidate_replicas = Vec::new();
|
|
772
|
+
|
|
773
|
+
for (index, (hash, metadata)) in hashes.iter().zip(metadata).enumerate() {
|
|
774
|
+
let has_block = self.blocks.has(hash);
|
|
775
|
+
present_block_flags.push(u8::from(has_block));
|
|
776
|
+
|
|
777
|
+
let Some((gid, data, replicas)) = metadata else {
|
|
778
|
+
gids.push(&JsValue::UNDEFINED);
|
|
779
|
+
data_rows.push(&JsValue::UNDEFINED);
|
|
780
|
+
replica_counts.push(0);
|
|
781
|
+
continue;
|
|
782
|
+
};
|
|
783
|
+
let requested_replicas = replicas
|
|
784
|
+
.map(|replicas| replicas as usize)
|
|
785
|
+
.or_else(|| self.shared_log.entry_requested_replicas(hash));
|
|
786
|
+
|
|
787
|
+
gids.push(&JsValue::from_str(&gid));
|
|
788
|
+
replica_counts.push(requested_replicas.unwrap_or(0) as u32);
|
|
789
|
+
match data.as_ref().filter(|_| requested_replicas.is_none()) {
|
|
790
|
+
Some(data) => data_rows.push(&Uint8Array::from(data.as_slice())),
|
|
791
|
+
None => data_rows.push(&JsValue::UNDEFINED),
|
|
792
|
+
};
|
|
793
|
+
|
|
794
|
+
if has_block
|
|
795
|
+
&& skip_hashes
|
|
796
|
+
.as_ref()
|
|
797
|
+
.map_or(true, |skip_hashes| !skip_hashes.contains(hash))
|
|
798
|
+
{
|
|
799
|
+
if let Some(replicas) = requested_replicas {
|
|
800
|
+
candidate_indexes.push(index);
|
|
801
|
+
candidate_gids.push(gid);
|
|
802
|
+
candidate_replicas.push(replicas);
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
let local_flags = if candidate_gids.is_empty() {
|
|
808
|
+
Vec::new()
|
|
809
|
+
} else {
|
|
810
|
+
self.shared_log.local_leader_flags_for_gids_batch(
|
|
811
|
+
&candidate_gids,
|
|
812
|
+
&candidate_replicas,
|
|
813
|
+
role_age_ms,
|
|
814
|
+
&now,
|
|
815
|
+
peer_filter,
|
|
816
|
+
expand_peer_filter,
|
|
817
|
+
&self_hash,
|
|
818
|
+
include_self,
|
|
819
|
+
full_replica_fallback,
|
|
820
|
+
include_strict_full_replica,
|
|
821
|
+
)?
|
|
822
|
+
};
|
|
823
|
+
let mut local_leader_flags = vec![0u8; hashes.len()];
|
|
824
|
+
for (index, is_local) in candidate_indexes.iter().zip(local_flags) {
|
|
825
|
+
local_leader_flags[*index] = u8::from(is_local);
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
let mut peer_history_removed_flags = vec![0u8; hashes.len()];
|
|
829
|
+
for index in candidate_indexes {
|
|
830
|
+
peer_history_removed_flags[index] = 1;
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
let out = Array::new();
|
|
834
|
+
out.push(&gids);
|
|
835
|
+
out.push(&data_rows);
|
|
836
|
+
out.push(&Uint8Array::from(present_block_flags.as_slice()));
|
|
837
|
+
out.push(&Uint8Array::from(local_leader_flags.as_slice()));
|
|
838
|
+
out.push(&Uint32Array::from(replica_counts.as_slice()));
|
|
839
|
+
out.push(&strings_to_array(candidate_gids));
|
|
840
|
+
out.push(&Uint8Array::from(peer_history_removed_flags.as_slice()));
|
|
841
|
+
Ok(out)
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
#[allow(clippy::too_many_arguments)]
|
|
845
|
+
pub fn plan_request_prune_all_confirmed(
|
|
846
|
+
&mut self,
|
|
847
|
+
hashes: Array,
|
|
848
|
+
prune_peer: String,
|
|
849
|
+
role_age_ms: f64,
|
|
850
|
+
now: String,
|
|
851
|
+
peer_filter: JsValue,
|
|
852
|
+
expand_peer_filter: bool,
|
|
853
|
+
self_hash: String,
|
|
854
|
+
include_self: bool,
|
|
855
|
+
full_replica_fallback: bool,
|
|
856
|
+
include_strict_full_replica: bool,
|
|
857
|
+
) -> Result<Array, JsValue> {
|
|
858
|
+
let hashes = strings_from_array(hashes)?;
|
|
859
|
+
let peer_history_gids = self.plan_request_prune_all_confirmed_core(
|
|
860
|
+
hashes,
|
|
861
|
+
&prune_peer,
|
|
862
|
+
role_age_ms,
|
|
863
|
+
&now,
|
|
864
|
+
peer_filter,
|
|
865
|
+
expand_peer_filter,
|
|
866
|
+
&self_hash,
|
|
867
|
+
include_self,
|
|
868
|
+
full_replica_fallback,
|
|
869
|
+
include_strict_full_replica,
|
|
870
|
+
)?;
|
|
871
|
+
let out = Array::new();
|
|
872
|
+
match peer_history_gids {
|
|
873
|
+
Some(peer_history_gids) => {
|
|
874
|
+
out.push(&JsValue::TRUE);
|
|
875
|
+
out.push(&strings_to_array(peer_history_gids));
|
|
876
|
+
}
|
|
877
|
+
None => {
|
|
878
|
+
out.push(&JsValue::FALSE);
|
|
879
|
+
out.push(&Array::new());
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
Ok(out)
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
#[allow(clippy::too_many_arguments)]
|
|
886
|
+
pub fn plan_request_prune_all_confirmed_no_gid_return(
|
|
887
|
+
&mut self,
|
|
888
|
+
hashes: Array,
|
|
889
|
+
prune_peer: String,
|
|
890
|
+
role_age_ms: f64,
|
|
891
|
+
now: String,
|
|
892
|
+
peer_filter: JsValue,
|
|
893
|
+
expand_peer_filter: bool,
|
|
894
|
+
self_hash: String,
|
|
895
|
+
include_self: bool,
|
|
896
|
+
full_replica_fallback: bool,
|
|
897
|
+
include_strict_full_replica: bool,
|
|
898
|
+
) -> Result<bool, JsValue> {
|
|
899
|
+
let hashes = strings_from_array(hashes)?;
|
|
900
|
+
if self.shared_log.gid_peer_history_empty_core() {
|
|
901
|
+
if let Some(all_confirmed) = self.try_plan_request_prune_full_replica_confirm(
|
|
902
|
+
&hashes,
|
|
903
|
+
role_age_ms,
|
|
904
|
+
&now,
|
|
905
|
+
peer_filter.clone(),
|
|
906
|
+
expand_peer_filter,
|
|
907
|
+
&self_hash,
|
|
908
|
+
include_self,
|
|
909
|
+
full_replica_fallback,
|
|
910
|
+
include_strict_full_replica,
|
|
911
|
+
)? {
|
|
912
|
+
return Ok(all_confirmed);
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
Ok(self
|
|
916
|
+
.plan_request_prune_all_confirmed_core(
|
|
917
|
+
hashes,
|
|
918
|
+
&prune_peer,
|
|
919
|
+
role_age_ms,
|
|
920
|
+
&now,
|
|
921
|
+
peer_filter,
|
|
922
|
+
expand_peer_filter,
|
|
923
|
+
&self_hash,
|
|
924
|
+
include_self,
|
|
925
|
+
full_replica_fallback,
|
|
926
|
+
include_strict_full_replica,
|
|
927
|
+
)?
|
|
928
|
+
.is_some())
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
#[allow(clippy::too_many_arguments)]
|
|
932
|
+
pub fn plan_entry_assignment_for_gid(
|
|
933
|
+
&self,
|
|
934
|
+
gid: String,
|
|
935
|
+
replicas: usize,
|
|
936
|
+
role_age_ms: f64,
|
|
937
|
+
now: String,
|
|
938
|
+
peer_filter: JsValue,
|
|
939
|
+
expand_peer_filter: bool,
|
|
940
|
+
self_hash: String,
|
|
941
|
+
include_self: bool,
|
|
942
|
+
full_replica_fallback: bool,
|
|
943
|
+
include_strict_full_replica: bool,
|
|
944
|
+
) -> Result<Array, JsValue> {
|
|
945
|
+
self.shared_log.plan_entry_assignment_for_gid(
|
|
946
|
+
gid,
|
|
947
|
+
replicas,
|
|
948
|
+
role_age_ms,
|
|
949
|
+
now,
|
|
950
|
+
peer_filter,
|
|
951
|
+
expand_peer_filter,
|
|
952
|
+
self_hash,
|
|
953
|
+
include_self,
|
|
954
|
+
full_replica_fallback,
|
|
955
|
+
include_strict_full_replica,
|
|
956
|
+
)
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
#[allow(clippy::too_many_arguments)]
|
|
960
|
+
pub fn plan_repair_dispatch_for_entries(
|
|
961
|
+
&self,
|
|
962
|
+
entry_hashes: Array,
|
|
963
|
+
entry_gids: Array,
|
|
964
|
+
entry_requested_replicas: Array,
|
|
965
|
+
entry_coordinate_batches: Array,
|
|
966
|
+
pending_modes: Array,
|
|
967
|
+
pending_peers_by_mode: Array,
|
|
968
|
+
optimistic_peers_by_mode: Array,
|
|
969
|
+
full_replica_repair_candidates: Array,
|
|
970
|
+
full_replica_repair_candidate_count: usize,
|
|
971
|
+
role_age_ms: f64,
|
|
972
|
+
now: String,
|
|
973
|
+
peer_filter: JsValue,
|
|
974
|
+
expand_peer_filter: bool,
|
|
975
|
+
self_hash: String,
|
|
976
|
+
include_self: bool,
|
|
977
|
+
full_replica_fallback: bool,
|
|
978
|
+
include_strict_full_replica: bool,
|
|
979
|
+
) -> Result<Array, JsValue> {
|
|
980
|
+
self.shared_log.plan_repair_dispatch_for_entries(
|
|
981
|
+
entry_hashes,
|
|
982
|
+
entry_gids,
|
|
983
|
+
entry_requested_replicas,
|
|
984
|
+
entry_coordinate_batches,
|
|
985
|
+
pending_modes,
|
|
986
|
+
pending_peers_by_mode,
|
|
987
|
+
optimistic_peers_by_mode,
|
|
988
|
+
full_replica_repair_candidates,
|
|
989
|
+
full_replica_repair_candidate_count,
|
|
990
|
+
role_age_ms,
|
|
991
|
+
now,
|
|
992
|
+
peer_filter,
|
|
993
|
+
expand_peer_filter,
|
|
994
|
+
self_hash,
|
|
995
|
+
include_self,
|
|
996
|
+
full_replica_fallback,
|
|
997
|
+
include_strict_full_replica,
|
|
998
|
+
)
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
#[allow(clippy::too_many_arguments)]
|
|
1002
|
+
pub fn plan_repair_dispatch_for_resident_entries(
|
|
1003
|
+
&self,
|
|
1004
|
+
pending_modes: Array,
|
|
1005
|
+
pending_peers_by_mode: Array,
|
|
1006
|
+
optimistic_gids_by_mode: Array,
|
|
1007
|
+
optimistic_peers_by_gid_by_mode: Array,
|
|
1008
|
+
full_replica_repair_candidates: Array,
|
|
1009
|
+
full_replica_repair_candidate_count: usize,
|
|
1010
|
+
role_age_ms: f64,
|
|
1011
|
+
now: String,
|
|
1012
|
+
peer_filter: JsValue,
|
|
1013
|
+
expand_peer_filter: bool,
|
|
1014
|
+
self_hash: String,
|
|
1015
|
+
include_self: bool,
|
|
1016
|
+
full_replica_fallback: bool,
|
|
1017
|
+
include_strict_full_replica: bool,
|
|
1018
|
+
) -> Result<Array, JsValue> {
|
|
1019
|
+
self.shared_log.plan_repair_dispatch_for_resident_entries(
|
|
1020
|
+
pending_modes,
|
|
1021
|
+
pending_peers_by_mode,
|
|
1022
|
+
optimistic_gids_by_mode,
|
|
1023
|
+
optimistic_peers_by_gid_by_mode,
|
|
1024
|
+
full_replica_repair_candidates,
|
|
1025
|
+
full_replica_repair_candidate_count,
|
|
1026
|
+
role_age_ms,
|
|
1027
|
+
now,
|
|
1028
|
+
peer_filter,
|
|
1029
|
+
expand_peer_filter,
|
|
1030
|
+
self_hash,
|
|
1031
|
+
include_self,
|
|
1032
|
+
full_replica_fallback,
|
|
1033
|
+
include_strict_full_replica,
|
|
1034
|
+
)
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
#[allow(clippy::too_many_arguments)]
|
|
1038
|
+
pub fn plan_local_append_for_gid_compact(
|
|
1039
|
+
&mut self,
|
|
1040
|
+
entry_hash: String,
|
|
1041
|
+
gid: String,
|
|
1042
|
+
entry_hash_number: String,
|
|
1043
|
+
next_hashes: Array,
|
|
1044
|
+
replicas: usize,
|
|
1045
|
+
role_age_ms: f64,
|
|
1046
|
+
now: String,
|
|
1047
|
+
peer_filter: JsValue,
|
|
1048
|
+
expand_peer_filter: bool,
|
|
1049
|
+
self_hash: String,
|
|
1050
|
+
include_self: bool,
|
|
1051
|
+
full_replica_fallback: bool,
|
|
1052
|
+
include_strict_full_replica: bool,
|
|
1053
|
+
) -> Result<Array, JsValue> {
|
|
1054
|
+
let next_hashes_for_core = next_hashes.clone();
|
|
1055
|
+
let row = self.shared_log.plan_local_append_for_gid_compact(
|
|
1056
|
+
entry_hash,
|
|
1057
|
+
gid,
|
|
1058
|
+
entry_hash_number,
|
|
1059
|
+
next_hashes,
|
|
1060
|
+
replicas,
|
|
1061
|
+
role_age_ms,
|
|
1062
|
+
now,
|
|
1063
|
+
peer_filter,
|
|
1064
|
+
expand_peer_filter,
|
|
1065
|
+
self_hash,
|
|
1066
|
+
include_self,
|
|
1067
|
+
full_replica_fallback,
|
|
1068
|
+
include_strict_full_replica,
|
|
1069
|
+
)?;
|
|
1070
|
+
self.commit_coordinate_core_from_compact_row(
|
|
1071
|
+
row.get(3),
|
|
1072
|
+
next_hashes_for_core,
|
|
1073
|
+
Array::new(),
|
|
1074
|
+
0,
|
|
1075
|
+
Vec::new(),
|
|
1076
|
+
)?;
|
|
1077
|
+
Ok(row)
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
#[allow(clippy::too_many_arguments)]
|
|
1081
|
+
pub fn commit_local_append_for_gid_compact(
|
|
1082
|
+
&mut self,
|
|
1083
|
+
entry_hash: String,
|
|
1084
|
+
gid: String,
|
|
1085
|
+
entry_hash_number: String,
|
|
1086
|
+
next_hashes: Array,
|
|
1087
|
+
delete_hashes: Array,
|
|
1088
|
+
replicas: usize,
|
|
1089
|
+
role_age_ms: f64,
|
|
1090
|
+
now: String,
|
|
1091
|
+
peer_filter: JsValue,
|
|
1092
|
+
expand_peer_filter: bool,
|
|
1093
|
+
self_hash: String,
|
|
1094
|
+
include_self: bool,
|
|
1095
|
+
full_replica_fallback: bool,
|
|
1096
|
+
include_strict_full_replica: bool,
|
|
1097
|
+
) -> Result<Array, JsValue> {
|
|
1098
|
+
let next_hashes_for_core = next_hashes.clone();
|
|
1099
|
+
let delete_hashes_for_core = delete_hashes.clone();
|
|
1100
|
+
let row = self.shared_log.commit_local_append_for_gid_compact(
|
|
1101
|
+
entry_hash,
|
|
1102
|
+
gid,
|
|
1103
|
+
entry_hash_number,
|
|
1104
|
+
next_hashes,
|
|
1105
|
+
delete_hashes,
|
|
1106
|
+
replicas,
|
|
1107
|
+
role_age_ms,
|
|
1108
|
+
now,
|
|
1109
|
+
peer_filter,
|
|
1110
|
+
expand_peer_filter,
|
|
1111
|
+
self_hash,
|
|
1112
|
+
include_self,
|
|
1113
|
+
full_replica_fallback,
|
|
1114
|
+
include_strict_full_replica,
|
|
1115
|
+
)?;
|
|
1116
|
+
self.commit_coordinate_core_from_compact_row(
|
|
1117
|
+
row.get(3),
|
|
1118
|
+
next_hashes_for_core,
|
|
1119
|
+
delete_hashes_for_core,
|
|
1120
|
+
0,
|
|
1121
|
+
Vec::new(),
|
|
1122
|
+
)?;
|
|
1123
|
+
Ok(row)
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
#[allow(clippy::too_many_arguments)]
|
|
1127
|
+
pub fn plan_append_for_gid(
|
|
1128
|
+
&mut self,
|
|
1129
|
+
entry_hash: String,
|
|
1130
|
+
gid: String,
|
|
1131
|
+
entry_hash_number: String,
|
|
1132
|
+
next_hashes: Array,
|
|
1133
|
+
replicas: usize,
|
|
1134
|
+
full_replica_candidates: Array,
|
|
1135
|
+
fallback_recipients: Array,
|
|
1136
|
+
delivery_self_hash: String,
|
|
1137
|
+
delivery_enabled: bool,
|
|
1138
|
+
reliability_ack: bool,
|
|
1139
|
+
min_acks: JsValue,
|
|
1140
|
+
require_recipients: bool,
|
|
1141
|
+
role_age_ms: f64,
|
|
1142
|
+
now: String,
|
|
1143
|
+
peer_filter: JsValue,
|
|
1144
|
+
expand_peer_filter: bool,
|
|
1145
|
+
self_hash: String,
|
|
1146
|
+
include_self: bool,
|
|
1147
|
+
full_replica_fallback: bool,
|
|
1148
|
+
include_strict_full_replica: bool,
|
|
1149
|
+
) -> Result<Array, JsValue> {
|
|
1150
|
+
let next_hashes_for_core = next_hashes.clone();
|
|
1151
|
+
let row = self.shared_log.plan_append_for_gid(
|
|
1152
|
+
entry_hash,
|
|
1153
|
+
gid,
|
|
1154
|
+
entry_hash_number,
|
|
1155
|
+
next_hashes,
|
|
1156
|
+
replicas,
|
|
1157
|
+
full_replica_candidates,
|
|
1158
|
+
fallback_recipients,
|
|
1159
|
+
delivery_self_hash,
|
|
1160
|
+
delivery_enabled,
|
|
1161
|
+
reliability_ack,
|
|
1162
|
+
min_acks,
|
|
1163
|
+
require_recipients,
|
|
1164
|
+
role_age_ms,
|
|
1165
|
+
now,
|
|
1166
|
+
peer_filter,
|
|
1167
|
+
expand_peer_filter,
|
|
1168
|
+
self_hash,
|
|
1169
|
+
include_self,
|
|
1170
|
+
full_replica_fallback,
|
|
1171
|
+
include_strict_full_replica,
|
|
1172
|
+
)?;
|
|
1173
|
+
self.commit_coordinate_core_from_compact_row(
|
|
1174
|
+
row.get(5),
|
|
1175
|
+
next_hashes_for_core,
|
|
1176
|
+
Array::new(),
|
|
1177
|
+
0,
|
|
1178
|
+
Vec::new(),
|
|
1179
|
+
)?;
|
|
1180
|
+
Ok(row)
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
#[allow(clippy::too_many_arguments)]
|
|
1184
|
+
pub fn plan_append_for_gids_batch(
|
|
1185
|
+
&mut self,
|
|
1186
|
+
entry_hashes: Array,
|
|
1187
|
+
gids: Array,
|
|
1188
|
+
entry_hash_numbers: Array,
|
|
1189
|
+
next_hash_batches: Array,
|
|
1190
|
+
replica_counts: Array,
|
|
1191
|
+
full_replica_candidates: Array,
|
|
1192
|
+
fallback_recipients: Array,
|
|
1193
|
+
delivery_self_hash: String,
|
|
1194
|
+
delivery_enabled: bool,
|
|
1195
|
+
reliability_ack: bool,
|
|
1196
|
+
min_acks: JsValue,
|
|
1197
|
+
require_recipients: bool,
|
|
1198
|
+
role_age_ms: f64,
|
|
1199
|
+
now: String,
|
|
1200
|
+
peer_filter: JsValue,
|
|
1201
|
+
expand_peer_filter: bool,
|
|
1202
|
+
self_hash: String,
|
|
1203
|
+
include_self: bool,
|
|
1204
|
+
full_replica_fallback: bool,
|
|
1205
|
+
include_strict_full_replica: bool,
|
|
1206
|
+
) -> Result<Array, JsValue> {
|
|
1207
|
+
let next_hash_batches_for_core = next_hash_batches.clone();
|
|
1208
|
+
let rows = self.shared_log.plan_append_for_gids_batch(
|
|
1209
|
+
entry_hashes,
|
|
1210
|
+
gids,
|
|
1211
|
+
entry_hash_numbers,
|
|
1212
|
+
next_hash_batches,
|
|
1213
|
+
replica_counts,
|
|
1214
|
+
full_replica_candidates,
|
|
1215
|
+
fallback_recipients,
|
|
1216
|
+
delivery_self_hash,
|
|
1217
|
+
delivery_enabled,
|
|
1218
|
+
reliability_ack,
|
|
1219
|
+
min_acks,
|
|
1220
|
+
require_recipients,
|
|
1221
|
+
role_age_ms,
|
|
1222
|
+
now,
|
|
1223
|
+
peer_filter,
|
|
1224
|
+
expand_peer_filter,
|
|
1225
|
+
self_hash,
|
|
1226
|
+
include_self,
|
|
1227
|
+
full_replica_fallback,
|
|
1228
|
+
include_strict_full_replica,
|
|
1229
|
+
)?;
|
|
1230
|
+
for index in 0..rows.length() {
|
|
1231
|
+
let row = array_from_value(rows.get(index), "append batch plan row")?;
|
|
1232
|
+
let next_hashes = array_from_value(
|
|
1233
|
+
next_hash_batches_for_core.get(index),
|
|
1234
|
+
"append batch next hashes",
|
|
1235
|
+
)?;
|
|
1236
|
+
self.commit_coordinate_core_from_compact_row(
|
|
1237
|
+
row.get(5),
|
|
1238
|
+
next_hashes,
|
|
1239
|
+
Array::new(),
|
|
1240
|
+
0,
|
|
1241
|
+
Vec::new(),
|
|
1242
|
+
)?;
|
|
1243
|
+
}
|
|
1244
|
+
Ok(rows)
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
#[allow(clippy::too_many_arguments)]
|
|
1248
|
+
pub fn plan_receive_coordinates_for_gids_batch(
|
|
1249
|
+
&mut self,
|
|
1250
|
+
entry_hashes: Array,
|
|
1251
|
+
gids: Array,
|
|
1252
|
+
entry_hash_numbers: Array,
|
|
1253
|
+
next_hash_batches: Array,
|
|
1254
|
+
replica_counts: Array,
|
|
1255
|
+
role_age_ms: f64,
|
|
1256
|
+
now: String,
|
|
1257
|
+
peer_filter: JsValue,
|
|
1258
|
+
expand_peer_filter: bool,
|
|
1259
|
+
self_hash: String,
|
|
1260
|
+
include_self: bool,
|
|
1261
|
+
full_replica_fallback: bool,
|
|
1262
|
+
include_strict_full_replica: bool,
|
|
1263
|
+
) -> Result<Array, JsValue> {
|
|
1264
|
+
let next_hash_batches_for_core = next_hash_batches.clone();
|
|
1265
|
+
let rows = self.shared_log.plan_receive_coordinates_for_gids_batch(
|
|
1266
|
+
entry_hashes,
|
|
1267
|
+
gids,
|
|
1268
|
+
entry_hash_numbers,
|
|
1269
|
+
next_hash_batches,
|
|
1270
|
+
replica_counts,
|
|
1271
|
+
role_age_ms,
|
|
1272
|
+
now,
|
|
1273
|
+
peer_filter,
|
|
1274
|
+
expand_peer_filter,
|
|
1275
|
+
self_hash,
|
|
1276
|
+
include_self,
|
|
1277
|
+
full_replica_fallback,
|
|
1278
|
+
include_strict_full_replica,
|
|
1279
|
+
)?;
|
|
1280
|
+
for index in 0..rows.length() {
|
|
1281
|
+
let row = array_from_value(rows.get(index), "receive coordinate batch plan row")?;
|
|
1282
|
+
let next_hashes = array_from_value(
|
|
1283
|
+
next_hash_batches_for_core.get(index),
|
|
1284
|
+
"receive coordinate batch next hashes",
|
|
1285
|
+
)?;
|
|
1286
|
+
self.commit_coordinate_core_from_compact_row(
|
|
1287
|
+
row.get(4),
|
|
1288
|
+
next_hashes,
|
|
1289
|
+
Array::new(),
|
|
1290
|
+
0,
|
|
1291
|
+
Vec::new(),
|
|
1292
|
+
)?;
|
|
1293
|
+
}
|
|
1294
|
+
Ok(rows)
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
impl NativePeerbitBackbone {
|
|
1299
|
+
pub(crate) fn commit_entry_coordinate_commits(&mut self, commits: Vec<EntryCoordinateCommit>) {
|
|
1300
|
+
if !commits.is_empty() {
|
|
1301
|
+
self.coordinate_index.reserve(commits.len());
|
|
1302
|
+
self.coordinate_values.reserve(commits.len());
|
|
1303
|
+
}
|
|
1304
|
+
for commit in &commits {
|
|
1305
|
+
self.put_coordinate_core(
|
|
1306
|
+
commit.hash.clone(),
|
|
1307
|
+
&commit.gid,
|
|
1308
|
+
commit.hash_number,
|
|
1309
|
+
&commit.coordinates,
|
|
1310
|
+
commit.assigned_to_range_boundary,
|
|
1311
|
+
commit.requested_replicas,
|
|
1312
|
+
0,
|
|
1313
|
+
Vec::new(),
|
|
1314
|
+
true,
|
|
1315
|
+
);
|
|
1316
|
+
self.delete_coordinate_core_strings(&commit.next_hashes);
|
|
1317
|
+
}
|
|
1318
|
+
self.shared_log.commit_entry_coordinates_batch_core(commits);
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
#[allow(clippy::too_many_arguments)]
|
|
1322
|
+
fn try_plan_request_prune_full_replica_confirm(
|
|
1323
|
+
&self,
|
|
1324
|
+
hashes: &[String],
|
|
1325
|
+
role_age_ms: f64,
|
|
1326
|
+
now: &str,
|
|
1327
|
+
peer_filter: JsValue,
|
|
1328
|
+
expand_peer_filter: bool,
|
|
1329
|
+
self_hash: &str,
|
|
1330
|
+
include_self: bool,
|
|
1331
|
+
full_replica_fallback: bool,
|
|
1332
|
+
include_strict_full_replica: bool,
|
|
1333
|
+
) -> Result<Option<bool>, JsValue> {
|
|
1334
|
+
if hashes.is_empty() {
|
|
1335
|
+
return Ok(Some(false));
|
|
1336
|
+
}
|
|
1337
|
+
let mut common_replicas = None;
|
|
1338
|
+
for hash in hashes {
|
|
1339
|
+
if !self.blocks.has(hash) {
|
|
1340
|
+
return Ok(Some(false));
|
|
1341
|
+
}
|
|
1342
|
+
let Some((_, replicas)) = self.log.entry_prune_confirm_metadata_ref(hash) else {
|
|
1343
|
+
return Ok(Some(false));
|
|
1344
|
+
};
|
|
1345
|
+
let Some(requested_replicas) = replicas
|
|
1346
|
+
.map(|replicas| replicas as usize)
|
|
1347
|
+
.or_else(|| self.shared_log.entry_requested_replicas(hash))
|
|
1348
|
+
else {
|
|
1349
|
+
return Ok(Some(false));
|
|
1350
|
+
};
|
|
1351
|
+
match common_replicas {
|
|
1352
|
+
Some(common_replicas) if common_replicas != requested_replicas => {
|
|
1353
|
+
return Ok(None);
|
|
1354
|
+
}
|
|
1355
|
+
Some(_) => {}
|
|
1356
|
+
None => common_replicas = Some(requested_replicas),
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
let Some(common_replicas) = common_replicas else {
|
|
1361
|
+
return Ok(Some(false));
|
|
1362
|
+
};
|
|
1363
|
+
self.shared_log.full_replica_self_leader_for_replicas(
|
|
1364
|
+
common_replicas,
|
|
1365
|
+
role_age_ms,
|
|
1366
|
+
now,
|
|
1367
|
+
peer_filter,
|
|
1368
|
+
expand_peer_filter,
|
|
1369
|
+
self_hash,
|
|
1370
|
+
include_self,
|
|
1371
|
+
full_replica_fallback,
|
|
1372
|
+
include_strict_full_replica,
|
|
1373
|
+
)
|
|
1374
|
+
}
|
|
1375
|
+
|
|
1376
|
+
#[allow(clippy::too_many_arguments)]
|
|
1377
|
+
fn plan_request_prune_all_confirmed_core(
|
|
1378
|
+
&mut self,
|
|
1379
|
+
hashes: Vec<String>,
|
|
1380
|
+
prune_peer: &str,
|
|
1381
|
+
role_age_ms: f64,
|
|
1382
|
+
now: &str,
|
|
1383
|
+
peer_filter: JsValue,
|
|
1384
|
+
expand_peer_filter: bool,
|
|
1385
|
+
self_hash: &str,
|
|
1386
|
+
include_self: bool,
|
|
1387
|
+
full_replica_fallback: bool,
|
|
1388
|
+
include_strict_full_replica: bool,
|
|
1389
|
+
) -> Result<Option<Vec<String>>, JsValue> {
|
|
1390
|
+
let empty = || Ok(None);
|
|
1391
|
+
if hashes.is_empty() {
|
|
1392
|
+
return empty();
|
|
1393
|
+
}
|
|
1394
|
+
|
|
1395
|
+
let mut candidate_gids = Vec::with_capacity(hashes.len());
|
|
1396
|
+
let mut candidate_replicas = Vec::with_capacity(hashes.len());
|
|
1397
|
+
|
|
1398
|
+
for hash in hashes.iter() {
|
|
1399
|
+
if !self.blocks.has(hash) {
|
|
1400
|
+
return empty();
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1403
|
+
let Some((gid, replicas)) = self.log.entry_prune_confirm_metadata_ref(hash) else {
|
|
1404
|
+
return empty();
|
|
1405
|
+
};
|
|
1406
|
+
let Some(requested_replicas) = replicas
|
|
1407
|
+
.map(|replicas| replicas as usize)
|
|
1408
|
+
.or_else(|| self.shared_log.entry_requested_replicas(hash))
|
|
1409
|
+
else {
|
|
1410
|
+
return empty();
|
|
1411
|
+
};
|
|
1412
|
+
|
|
1413
|
+
candidate_gids.push(gid.to_string());
|
|
1414
|
+
candidate_replicas.push(requested_replicas);
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
let all_local_leaders = self.shared_log.all_local_leaders_for_gids_batch(
|
|
1418
|
+
&candidate_gids,
|
|
1419
|
+
&candidate_replicas,
|
|
1420
|
+
role_age_ms,
|
|
1421
|
+
now,
|
|
1422
|
+
peer_filter,
|
|
1423
|
+
expand_peer_filter,
|
|
1424
|
+
self_hash,
|
|
1425
|
+
include_self,
|
|
1426
|
+
full_replica_fallback,
|
|
1427
|
+
include_strict_full_replica,
|
|
1428
|
+
)?;
|
|
1429
|
+
if !all_local_leaders {
|
|
1430
|
+
return empty();
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
self.shared_log
|
|
1434
|
+
.remove_gid_peers_core(prune_peer, &candidate_gids);
|
|
1435
|
+
Ok(Some(candidate_gids))
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1438
|
+
pub(crate) fn put_decoded_coordinate_core(
|
|
1439
|
+
&mut self,
|
|
1440
|
+
coordinate: CoordinateCoreValue,
|
|
1441
|
+
record_journal: bool,
|
|
1442
|
+
) -> Result<(), JsValue> {
|
|
1443
|
+
self.shared_log.put_entry_coordinates(
|
|
1444
|
+
coordinate.hash.clone(),
|
|
1445
|
+
coordinate.gid.clone(),
|
|
1446
|
+
coordinate.hash_number.to_string(),
|
|
1447
|
+
number_strings_to_array(&coordinate.coordinates),
|
|
1448
|
+
coordinate.assigned_to_range_boundary,
|
|
1449
|
+
coordinate.requested_replicas,
|
|
1450
|
+
)?;
|
|
1451
|
+
self.put_coordinate_core(
|
|
1452
|
+
coordinate.hash,
|
|
1453
|
+
&coordinate.gid,
|
|
1454
|
+
coordinate.hash_number,
|
|
1455
|
+
&coordinate.coordinates,
|
|
1456
|
+
coordinate.assigned_to_range_boundary,
|
|
1457
|
+
coordinate.requested_replicas,
|
|
1458
|
+
coordinate.wall_time,
|
|
1459
|
+
coordinate.meta_bytes,
|
|
1460
|
+
record_journal,
|
|
1461
|
+
);
|
|
1462
|
+
Ok(())
|
|
1463
|
+
}
|
|
1464
|
+
}
|