krabka_verified/producer_snapshot/
replay_start.rs1#[cfg(creusot)]
2use super::{
3 kafka_reload_keeps, kafka_replay_start, snapshot_last_record_valid, snapshot_transaction_valid,
4};
5use {
6 super::{ProducerReloadRange, ProducerSnapshotEntryFacts, producer_snapshot_reload_keeps},
7 creusot_std::prelude::*,
8};
9
10#[cfg(creusot)]
12#[cfg_attr(test, mutants::skip)]
13#[logic(open)]
14pub fn snapshot_entry_valid_model(snapshot_offset: Int, entry: ProducerSnapshotEntryFacts) -> bool {
19 pearlite! {
20 snapshot_offset >= 0
21 && entry.producer_id@ >= 0
22 && entry.producer_epoch@ >= 0
23 && entry.coordinator_epoch@ >= -1
24 && snapshot_last_record_valid(snapshot_offset, entry)
25 && snapshot_transaction_valid(snapshot_offset, entry)
26 }
27}
28
29#[ensures(result == snapshot_entry_valid_model(snapshot_offset@, entry))]
32#[must_use]
33pub fn producer_snapshot_entry_valid(
34 snapshot_offset: i64,
35 entry: ProducerSnapshotEntryFacts,
36) -> bool {
37 let last_record_valid =
38 (entry.last_offset == -1 && entry.last_sequence == -1 && entry.offset_delta == 0)
39 || (entry.last_offset >= 0
40 && entry.last_sequence >= 0
41 && entry.offset_delta >= 0
42 && entry.last_offset >= i64::from(entry.offset_delta)
43 && entry.last_offset < snapshot_offset);
44 let transaction_valid = entry.current_txn_first_offset == -1
45 || (entry.current_txn_first_offset >= 0
46 && entry.current_txn_first_offset < snapshot_offset
47 && entry.current_txn_first_offset <= entry.last_offset);
48 snapshot_offset >= 0
49 && entry.producer_id >= 0
50 && entry.producer_epoch >= 0
51 && entry.coordinator_epoch >= -1
52 && last_record_valid
53 && transaction_valid
54}
55
56#[ensures((result != None) == (range.log_start@ >= 0
68 && range.log_start@ <= range.log_end@
69 && range.local_start@ >= 0
70 && range.local_start@ <= range.log_end@
71 && match snapshot {
72 Some(offset) => kafka_reload_keeps(offset@, range.log_start@, range.log_end@),
73 None => true,
74 }))]
75#[ensures(forall<start: i64> result == Some(start) ==> start@ == kafka_replay_start(range, snapshot))]
76#[must_use]
77pub fn producer_snapshot_replay_start(
78 range: ProducerReloadRange,
79 snapshot: Option<i64>,
80) -> Option<i64> {
81 if range.log_start < 0
82 || range.log_end < range.log_start
83 || range.local_start < 0
84 || range.log_end < range.local_start
85 {
86 return None;
87 }
88 let map_end = match snapshot {
89 Some(offset) if producer_snapshot_reload_keeps(offset, range) => offset,
90 Some(_) => return None,
91 None => range.log_start,
92 };
93 Some(map_end.max(range.local_start))
94}