1- use serde:: Deserialize ;
2- use serde_with:: { serde_as, DeserializeAs , SerializeAs } ;
1+ use serde_with:: serde_as;
32use std:: {
3+ collections:: { hash_map:: Entry , HashMap } ,
44 fs:: { create_dir_all, File } ,
55 io:: { self , BufReader , Read , Write } ,
66 path:: Path ,
@@ -39,13 +39,11 @@ pub struct LedgerSnapshot {
3939 pub min_persistent_entry_ttl : u32 ,
4040 pub min_temp_entry_ttl : u32 ,
4141 pub max_entry_ttl : u32 ,
42- #[ serde_as( as = "LedgerEntryVec" ) ]
43- pub ledger_entries : Vec < ( Box < LedgerKey > , ( Box < LedgerEntry > , Option < u32 > ) ) > ,
42+ ledger_entries : LedgerEntries ,
4443}
4544
4645/// Extended ledger entry that includes the live util ledger sequence. Provides a more compact
47- /// form of the tuple used in [`LedgerSnapshot::ledger_entries`], to reduce the size of the snapshot
48- /// when serialized to JSON.
46+ /// form of the entry storage, to reduce the size of the snapshot when serialized to JSON.
4947#[ derive( Debug , Clone , serde:: Deserialize ) ]
5048struct LedgerEntryExt {
5149 entry : Box < LedgerEntry > ,
@@ -60,19 +58,72 @@ struct LedgerEntryExtRef<'a> {
6058 live_until : Option < u32 > ,
6159}
6260
63- struct LedgerEntryVec ;
61+ /// Storage for ledger entries. Uses a [`HashMap`] for O(1) keyed
62+ /// read/write access and a [`Vec`] of keys to preserve insertion order for serialization.
63+ /// Removed keys are left as tombstones in `keys` and filtered out during iteration.
64+ #[ derive( Clone , Debug , Default , Eq ) ]
65+ pub struct LedgerEntries {
66+ map : HashMap < Box < LedgerKey > , ( Box < LedgerEntry > , Option < u32 > ) > ,
67+ keys : Vec < Box < LedgerKey > > ,
68+ }
69+
70+ impl PartialEq for LedgerEntries {
71+ fn eq ( & self , other : & Self ) -> bool {
72+ self . map == other. map
73+ && self
74+ . keys
75+ . iter ( )
76+ . filter ( |k| self . map . contains_key ( k. as_ref ( ) ) )
77+ . eq ( other
78+ . keys
79+ . iter ( )
80+ . filter ( |k| other. map . contains_key ( k. as_ref ( ) ) ) )
81+ }
82+ }
83+
84+ impl LedgerEntries {
85+ /// Get the entry for a given key, if it exists.
86+ fn get ( & self , key : & LedgerKey ) -> Option < & ( Box < LedgerEntry > , Option < u32 > ) > {
87+ self . map . get ( key)
88+ }
89+
90+ /// Insert or replace the entry for a given key.
91+ fn insert ( & mut self , key : Box < LedgerKey > , value : ( Box < LedgerEntry > , Option < u32 > ) ) {
92+ match self . map . entry ( key) {
93+ Entry :: Occupied ( mut e) => {
94+ e. insert ( value) ;
95+ }
96+ Entry :: Vacant ( e) => {
97+ self . keys . push ( e. key ( ) . clone ( ) ) ;
98+ e. insert ( value) ;
99+ }
100+ }
101+ }
102+
103+ /// Remove the entry for a given key, if it exists.
104+ fn remove ( & mut self , key : & LedgerKey ) {
105+ self . map . remove ( key) ;
106+ }
64107
65- impl < ' a > SerializeAs < Vec < ( Box < LedgerKey > , ( Box < LedgerEntry > , Option < u32 > ) ) > > for LedgerEntryVec {
66- fn serialize_as < S > (
67- source : & Vec < ( Box < LedgerKey > , ( Box < LedgerEntry > , Option < u32 > ) ) > ,
68- serializer : S ,
69- ) -> Result < S :: Ok , S :: Error >
70- where
71- S : serde:: Serializer ,
72- {
108+ /// Iterate over the entries in insertion order
109+ fn iter ( & self ) -> impl Iterator < Item = ( & Box < LedgerKey > , & ( Box < LedgerEntry > , Option < u32 > ) ) > {
110+ self . keys
111+ . iter ( )
112+ . filter_map ( |k| self . map . get ( k) . map ( |v| ( k, v) ) )
113+ }
114+
115+ /// Clear all entries from the storage.
116+ fn clear ( & mut self ) {
117+ self . keys . clear ( ) ;
118+ self . map . clear ( ) ;
119+ }
120+ }
121+
122+ impl serde:: Serialize for LedgerEntries {
123+ fn serialize < S : serde:: Serializer > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error > {
73124 use serde:: ser:: SerializeSeq ;
74- let mut seq = serializer. serialize_seq ( Some ( source . len ( ) ) ) ?;
75- for ( _, ( entry, live_until) ) in source {
125+ let mut seq = serializer. serialize_seq ( Some ( self . map . len ( ) ) ) ?;
126+ for ( _, ( entry, live_until) ) in self . iter ( ) {
76127 seq. serialize_element ( & LedgerEntryExtRef {
77128 entry,
78129 live_until : * live_until,
@@ -82,32 +133,29 @@ impl<'a> SerializeAs<Vec<(Box<LedgerKey>, (Box<LedgerEntry>, Option<u32>))>> for
82133 }
83134}
84135
85- impl < ' de > DeserializeAs < ' de , Vec < ( Box < LedgerKey > , ( Box < LedgerEntry > , Option < u32 > ) ) > >
86- for LedgerEntryVec
87- {
88- fn deserialize_as < D > (
89- deserializer : D ,
90- ) -> Result < Vec < ( Box < LedgerKey > , ( Box < LedgerEntry > , Option < u32 > ) ) > , D :: Error >
91- where
92- D : serde:: Deserializer < ' de > ,
93- {
136+ impl < ' de > serde:: Deserialize < ' de > for LedgerEntries {
137+ fn deserialize < D : serde:: Deserializer < ' de > > ( deserializer : D ) -> Result < Self , D :: Error > {
94138 #[ derive( serde:: Deserialize ) ]
95139 #[ serde( untagged) ]
96140 enum Format {
97141 V2 ( Vec < LedgerEntryExt > ) ,
98142 V1 ( Vec < ( Box < LedgerKey > , ( Box < LedgerEntry > , Option < u32 > ) ) > ) ,
99143 }
100-
144+ let mut entries = LedgerEntries :: default ( ) ;
101145 match Format :: deserialize ( deserializer) ? {
102- Format :: V2 ( entries) => Ok ( entries
103- . into_iter ( )
104- . map ( |LedgerEntryExt { entry, live_until } | {
146+ Format :: V2 ( raw) => {
147+ for LedgerEntryExt { entry, live_until } in raw {
105148 let key = Box :: new ( entry. to_key ( ) ) ;
106- ( key, ( entry, live_until) )
107- } )
108- . collect ( ) ) ,
109- Format :: V1 ( entries) => Ok ( entries) ,
149+ entries. insert ( key, ( entry, live_until) ) ;
150+ }
151+ }
152+ Format :: V1 ( raw) => {
153+ for ( key, value) in raw {
154+ entries. insert ( key, value) ;
155+ }
156+ }
110157 }
158+ Ok ( entries)
111159 }
112160}
113161
@@ -164,11 +212,16 @@ impl LedgerSnapshot {
164212 self . max_entry_ttl = info. max_entry_ttl ;
165213 }
166214
167- /// Get the entries in the snapshot.
215+ /// Count the number of entries in the snapshot.
216+ pub fn count_entries ( & self ) -> usize {
217+ self . ledger_entries . map . len ( )
218+ }
219+
220+ /// Iterate over all the entries in the snapshot, in insertion order.
168221 pub fn entries (
169222 & self ,
170223 ) -> impl IntoIterator < Item = ( & Box < LedgerKey > , & ( Box < LedgerEntry > , Option < u32 > ) ) > {
171- self . ledger_entries . iter ( ) . map ( | ( k , v ) | ( k , v ) )
224+ self . ledger_entries . iter ( )
172225 }
173226
174227 /// Replace the entries in the snapshot with the entries in the iterator.
@@ -178,7 +231,7 @@ impl LedgerSnapshot {
178231 ) {
179232 self . ledger_entries . clear ( ) ;
180233 for ( k, e) in entries {
181- self . ledger_entries . push ( ( k. clone ( ) , ( e. 0 . clone ( ) , e. 1 ) ) ) ;
234+ self . ledger_entries . insert ( k. clone ( ) , ( e. 0 . clone ( ) , e. 1 ) ) ;
182235 }
183236 }
184237
@@ -190,19 +243,13 @@ impl LedgerSnapshot {
190243 entries : impl IntoIterator < Item = & ' a ( Rc < LedgerKey > , Option < ( Rc < LedgerEntry > , Option < u32 > ) > ) > ,
191244 ) {
192245 for ( k, e) in entries {
193- let i = self . ledger_entries . iter ( ) . position ( |( ik, _) | * * ik == * * k) ;
194246 if let Some ( ( entry, live_until_ledger) ) = e {
195- let new = (
247+ self . ledger_entries . insert (
196248 Box :: new ( ( * * k) . clone ( ) ) ,
197249 ( Box :: new ( ( * * entry) . clone ( ) ) , * live_until_ledger) ,
198250 ) ;
199- if let Some ( i) = i {
200- self . ledger_entries [ i] = new;
201- } else {
202- self . ledger_entries . push ( new) ;
203- }
204- } else if let Some ( i) = i {
205- self . ledger_entries . swap_remove ( i) ;
251+ } else {
252+ self . ledger_entries . remove ( k) ;
206253 }
207254 }
208255 }
@@ -245,7 +292,7 @@ impl Default for LedgerSnapshot {
245292 timestamp : Default :: default ( ) ,
246293 network_id : Default :: default ( ) ,
247294 base_reserve : Default :: default ( ) ,
248- ledger_entries : Vec :: default ( ) ,
295+ ledger_entries : LedgerEntries :: default ( ) ,
249296 min_persistent_entry_ttl : Default :: default ( ) ,
250297 min_temp_entry_ttl : Default :: default ( ) ,
251298 max_entry_ttl : Default :: default ( ) ,
@@ -258,8 +305,8 @@ impl SnapshotSource for &LedgerSnapshot {
258305 & self ,
259306 key : & Rc < LedgerKey > ,
260307 ) -> Result < Option < ( Rc < LedgerEntry > , Option < u32 > ) > , HostError > {
261- match self . ledger_entries . iter ( ) . find ( | ( k , _ ) | * * k == * * key) {
262- Some ( ( _ , v ) ) => Ok ( Some ( ( Rc :: new ( * v. 0 . clone ( ) ) , v. 1 ) ) ) ,
308+ match self . ledger_entries . get ( key) {
309+ Some ( v ) => Ok ( Some ( ( Rc :: new ( * v. 0 . clone ( ) ) , v. 1 ) ) ) ,
263310 None => Ok ( None ) ,
264311 }
265312 }
0 commit comments