@@ -2,6 +2,7 @@ use crate::state::command::EntryCommand;
2
2
use bytes:: { Buf , BufMut , Bytes , BytesMut } ;
3
3
use iggy:: bytes_serializable:: BytesSerializable ;
4
4
use iggy:: error:: IggyError ;
5
+ use iggy:: utils:: checksum;
5
6
use iggy:: utils:: timestamp:: IggyTimestamp ;
6
7
use std:: fmt:: { Display , Formatter } ;
7
8
@@ -13,6 +14,7 @@ use std::fmt::{Display, Formatter};
13
14
/// - `flags` - Reserved for future use
14
15
/// - `timestamp` - Timestamp when the command was issued
15
16
/// - `user_id` - User ID of the user who issued the command
17
+ /// - `checksum` - Checksum of the entry
16
18
/// - `code` - Command code
17
19
/// - `command` - Payload of the command
18
20
/// - `context` - Optional context e.g. used to enrich the payload with additional data
@@ -25,8 +27,9 @@ pub struct StateEntry {
25
27
pub flags : u64 ,
26
28
pub timestamp : IggyTimestamp ,
27
29
pub user_id : u32 ,
28
- pub command : EntryCommand ,
30
+ pub checksum : u32 ,
29
31
pub context : Bytes ,
32
+ pub command : EntryCommand ,
30
33
}
31
34
32
35
impl StateEntry {
@@ -50,25 +53,57 @@ impl StateEntry {
50
53
flags,
51
54
timestamp,
52
55
user_id,
56
+ checksum : Self :: calculate_checksum (
57
+ index, term, leader_id, version, flags, timestamp, user_id, & context, & command,
58
+ ) ,
53
59
context,
54
60
command,
55
61
}
56
62
}
63
+
64
+ #[ allow( clippy:: too_many_arguments) ]
65
+ fn calculate_checksum (
66
+ index : u64 ,
67
+ term : u64 ,
68
+ leader_id : u32 ,
69
+ version : u32 ,
70
+ flags : u64 ,
71
+ timestamp : IggyTimestamp ,
72
+ user_id : u32 ,
73
+ context : & Bytes ,
74
+ command : & EntryCommand ,
75
+ ) -> u32 {
76
+ let command = command. to_bytes ( ) ;
77
+ let mut bytes =
78
+ BytesMut :: with_capacity ( 8 + 8 + 4 + 4 + 8 + 8 + 4 + 4 + context. len ( ) + command. len ( ) ) ;
79
+ bytes. put_u64_le ( index) ;
80
+ bytes. put_u64_le ( term) ;
81
+ bytes. put_u32_le ( leader_id) ;
82
+ bytes. put_u32_le ( version) ;
83
+ bytes. put_u64_le ( flags) ;
84
+ bytes. put_u64_le ( timestamp. into ( ) ) ;
85
+ bytes. put_u32_le ( user_id) ;
86
+ bytes. put_u32_le ( context. len ( ) as u32 ) ;
87
+ bytes. put_slice ( context) ;
88
+ bytes. extend ( command) ;
89
+ checksum:: calculate ( & bytes. freeze ( ) )
90
+ }
57
91
}
58
92
59
93
impl Display for StateEntry {
60
94
fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std:: fmt:: Result {
61
95
write ! (
62
96
f,
63
- "StateEntry {{ index: {}, term: {}, leader ID: {}, version: {}, flags: {}, timestamp: {}, user ID: {}, command: {:?} }}" ,
97
+ "StateEntry {{ index: {}, term: {}, leader ID: {}, version: {}, flags: {}, timestamp: {}, user ID: {}, checksum: {}, command: {:?} }}" ,
64
98
self . index,
65
99
self . term,
66
100
self . leader_id,
67
101
self . version,
68
102
self . flags,
69
103
self . timestamp,
70
104
self . user_id,
71
- self . command,
105
+ self . checksum,
106
+ self . command
72
107
)
73
108
}
74
109
}
@@ -77,18 +112,19 @@ impl BytesSerializable for StateEntry {
77
112
fn to_bytes ( & self ) -> Bytes {
78
113
let command = self . command . to_bytes ( ) ;
79
114
let mut bytes = BytesMut :: with_capacity (
80
- 8 + 8 + 4 + 4 + 8 + 8 + 4 + 4 + self . context . len ( ) + command. len ( ) ,
115
+ 8 + 8 + 4 + 4 + 8 + 8 + 4 + 4 + 4 + self . context . len ( ) + command. len ( ) ,
81
116
) ;
82
117
bytes. put_u64_le ( self . index ) ;
83
118
bytes. put_u64_le ( self . term ) ;
84
119
bytes. put_u32_le ( self . leader_id ) ;
85
120
bytes. put_u32_le ( self . version ) ;
86
121
bytes. put_u64_le ( self . flags ) ;
87
- bytes. put_u64_le ( self . timestamp . as_micros ( ) ) ;
122
+ bytes. put_u64_le ( self . timestamp . into ( ) ) ;
88
123
bytes. put_u32_le ( self . user_id ) ;
124
+ bytes. put_u32_le ( self . checksum ) ;
89
125
bytes. put_u32_le ( self . context . len ( ) as u32 ) ;
90
126
bytes. put_slice ( & self . context ) ;
91
- bytes. extend ( self . command . to_bytes ( ) ) ;
127
+ bytes. extend ( command) ;
92
128
bytes. freeze ( )
93
129
}
94
130
@@ -103,9 +139,10 @@ impl BytesSerializable for StateEntry {
103
139
let flags = bytes. slice ( 24 ..32 ) . get_u64_le ( ) ;
104
140
let timestamp = IggyTimestamp :: from ( bytes. slice ( 32 ..40 ) . get_u64_le ( ) ) ;
105
141
let user_id = bytes. slice ( 40 ..44 ) . get_u32_le ( ) ;
106
- let context_length = bytes. slice ( 44 ..48 ) . get_u32_le ( ) as usize ;
107
- let context = bytes. slice ( 48 ..48 + context_length) ;
108
- let command = EntryCommand :: from_bytes ( bytes. slice ( 48 + context_length..) ) ?;
142
+ let checksum = bytes. slice ( 44 ..48 ) . get_u32_le ( ) ;
143
+ let context_length = bytes. slice ( 48 ..52 ) . get_u32_le ( ) as usize ;
144
+ let context = bytes. slice ( 52 ..52 + context_length) ;
145
+ let command = EntryCommand :: from_bytes ( bytes. slice ( 52 + context_length..) ) ?;
109
146
110
147
Ok ( StateEntry {
111
148
index,
@@ -115,6 +152,7 @@ impl BytesSerializable for StateEntry {
115
152
flags,
116
153
timestamp,
117
154
user_id,
155
+ checksum,
118
156
context,
119
157
command,
120
158
} )
0 commit comments