@@ -44,7 +44,8 @@ import (
44
44
// b. UPDATED we simply update it with the new value.
45
45
// c. REMOVED it means that at this point in the ledger the entry is removed
46
46
// so updating it returns an error.
47
- // d. RESTORED we update it with the new value but keep the change type as RESTORED.
47
+ // d. RESTORED we update it with the new value but keep the change type as
48
+ // RESTORED.
48
49
// 3. If the change is REMOVE it checks if any change connected to given entry
49
50
// is already in the cache. If not, it adds REMOVE change. Otherwise, if
50
51
// existing change is:
@@ -56,26 +57,37 @@ import (
56
57
// change means the entry exists in a DB.
57
58
// c. REMOVED it returns error because we can't remove an entry that was
58
59
// already removed.
59
- // d. RESTORED it means the entry doesn't exist in the DB, so it's a noop
60
- // so remove the entry from the cache.
61
- // 4. If the change is RESTORED it checks if any change related to the given entry
62
- // already exists in the cache. If not, it adds the RESTORED change. Otherwise,
63
- // returns an error since restoration is only possible for previously archived/evicted
64
- // entries. If the entry was created, updated or removed within the same ledger, restoration
65
- // is not possible.
60
+ // d. RESTORED depending on the change compactor's configuration, we may or
61
+ // may not emit a REMOVE change type for an entry that was restored earlier
62
+ // in the ledger.
63
+ // 4. If the change is RESTORED it checks if any change related to the given
64
+ // entry already exists in the cache. If not, it adds the RESTORED change.
65
+ // Otherwise, it returns an error because only expired entries can be
66
+ // restored. If the entry was created, updated or removed in the same
67
+ // ledger, it's not expired.
66
68
type ChangeCompactor struct {
67
69
// ledger key => Change
68
- cache map [string ]Change
69
- encodingBuffer * xdr.EncodingBuffer
70
- emitExpiredEntriesRemovedChange bool
70
+ cache map [string ]Change
71
+ encodingBuffer * xdr.EncodingBuffer
72
+ config * ChangeCompactorConfig
73
+ }
74
+
75
+ type ChangeCompactorConfig struct {
76
+ EmitExpiredEntryRemovedChange bool
77
+ }
78
+
79
+ func NewChangeCompactorDefaultConfig () * ChangeCompactorConfig {
80
+ return & ChangeCompactorConfig {
81
+ EmitExpiredEntryRemovedChange : true ,
82
+ }
71
83
}
72
84
73
85
// NewChangeCompactor returns a new ChangeCompactor.
74
- func NewChangeCompactor (emitExpiredEntriesRemovedChange bool ) * ChangeCompactor {
86
+ func NewChangeCompactor (config * ChangeCompactorConfig ) * ChangeCompactor {
75
87
return & ChangeCompactor {
76
- cache : make (map [string ]Change ),
77
- encodingBuffer : xdr .NewEncodingBuffer (),
78
- emitExpiredEntriesRemovedChange : emitExpiredEntriesRemovedChange ,
88
+ cache : make (map [string ]Change ),
89
+ encodingBuffer : xdr .NewEncodingBuffer (),
90
+ config : config ,
79
91
}
80
92
}
81
93
@@ -104,16 +116,10 @@ func (c *ChangeCompactor) AddChange(change Change) error {
104
116
// addCreatedChange adds a change to the cache, but returns an error if create
105
117
// change is unexpected.
106
118
func (c * ChangeCompactor ) addCreatedChange (change Change ) error {
107
- // safe, since we later cast to string (causing a copy)
108
- key , err := change .Post .LedgerKey ()
119
+ ledgerKey , err := c .getLedgerKey (change .Post )
109
120
if err != nil {
110
- return errors . Wrap ( err , "error getting ledger key for new entry" )
121
+ return err
111
122
}
112
- ledgerKey , err := c .encodingBuffer .UnsafeMarshalBinary (key )
113
- if err != nil {
114
- return errors .Wrap (err , "error marshaling ledger key for new entry" )
115
- }
116
-
117
123
ledgerKeyString := string (ledgerKey )
118
124
119
125
existingChange , exist := c .cache [ledgerKeyString ]
@@ -136,7 +142,7 @@ func (c *ChangeCompactor) addCreatedChange(change Change) error {
136
142
// If existing type is removed it means that this entry does exist
137
143
// in a DB so we update entry change.
138
144
c .cache [ledgerKeyString ] = Change {
139
- Type : key .Type ,
145
+ Type : change .Type ,
140
146
Pre : existingChange .Pre ,
141
147
Post : change .Post ,
142
148
ChangeType : xdr .LedgerEntryChangeTypeLedgerEntryUpdated ,
@@ -148,19 +154,26 @@ func (c *ChangeCompactor) addCreatedChange(change Change) error {
148
154
return nil
149
155
}
150
156
151
- // addUpdatedChange adds a change to the cache, but returns an error if update
152
- // change is unexpected.
153
- func (c * ChangeCompactor ) addUpdatedChange (change Change ) error {
157
+ func (c * ChangeCompactor ) getLedgerKey (ledgerEntry * xdr.LedgerEntry ) ([]byte , error ) {
154
158
// safe, since we later cast to string (causing a copy)
155
- key , err := change . Post .LedgerKey ()
159
+ key , err := ledgerEntry .LedgerKey ()
156
160
if err != nil {
157
- return errors .Wrap (err , "error getting ledger key for updated entry" )
161
+ return nil , errors .Wrap (err , "error getting ledger key for new entry" )
158
162
}
159
163
ledgerKey , err := c .encodingBuffer .UnsafeMarshalBinary (key )
160
164
if err != nil {
161
- return errors .Wrap (err , "error marshaling ledger key for updated entry" )
165
+ return nil , errors .Wrap (err , "error marshaling ledger key for new entry" )
162
166
}
167
+ return ledgerKey , nil
168
+ }
163
169
170
+ // addUpdatedChange adds a change to the cache, but returns an error if update
171
+ // change is unexpected.
172
+ func (c * ChangeCompactor ) addUpdatedChange (change Change ) error {
173
+ ledgerKey , err := c .getLedgerKey (change .Post )
174
+ if err != nil {
175
+ return err
176
+ }
164
177
ledgerKeyString := string (ledgerKey )
165
178
166
179
existingChange , exist := c .cache [ledgerKeyString ]
@@ -174,15 +187,16 @@ func (c *ChangeCompactor) addUpdatedChange(change Change) error {
174
187
// If existing type is created it means that this entry does not
175
188
// exist in a DB so we update entry change.
176
189
c .cache [ledgerKeyString ] = Change {
177
- Type : key .Type ,
178
- Pre : existingChange .Pre , // = nil
179
- Post : change .Post ,
190
+ Type : change .Type ,
191
+ Pre : existingChange .Pre , // = nil
192
+ Post : change .Post ,
193
+ ChangeType : existingChange .ChangeType ,
180
194
}
181
195
case xdr .LedgerEntryChangeTypeLedgerEntryUpdated :
182
196
fallthrough
183
197
case xdr .LedgerEntryChangeTypeLedgerEntryRestored :
184
198
c .cache [ledgerKeyString ] = Change {
185
- Type : key .Type ,
199
+ Type : change .Type ,
186
200
Pre : existingChange .Pre ,
187
201
Post : change .Post ,
188
202
ChangeType : existingChange .ChangeType , //keep the existing change type
@@ -202,16 +216,10 @@ func (c *ChangeCompactor) addUpdatedChange(change Change) error {
202
216
// addRemovedChange adds a change to the cache, but returns an error if remove
203
217
// change is unexpected.
204
218
func (c * ChangeCompactor ) addRemovedChange (change Change ) error {
205
- // safe, since we later cast to string (causing a copy)
206
- key , err := change .Pre .LedgerKey ()
219
+ ledgerKey , err := c .getLedgerKey (change .Pre )
207
220
if err != nil {
208
- return errors . Wrap ( err , "error getting ledger key for removed entry" )
221
+ return err
209
222
}
210
- ledgerKey , err := c .encodingBuffer .UnsafeMarshalBinary (key )
211
- if err != nil {
212
- return errors .Wrap (err , "error marshaling ledger key for removed entry" )
213
- }
214
-
215
223
ledgerKeyString := string (ledgerKey )
216
224
217
225
existingChange , exist := c .cache [ledgerKeyString ]
@@ -227,7 +235,7 @@ func (c *ChangeCompactor) addRemovedChange(change Change) error {
227
235
delete (c .cache , ledgerKeyString )
228
236
case xdr .LedgerEntryChangeTypeLedgerEntryUpdated :
229
237
c .cache [ledgerKeyString ] = Change {
230
- Type : key .Type ,
238
+ Type : change .Type ,
231
239
Pre : existingChange .Pre ,
232
240
Post : nil ,
233
241
ChangeType : change .ChangeType ,
@@ -238,9 +246,9 @@ func (c *ChangeCompactor) addRemovedChange(change Change) error {
238
246
base64 .StdEncoding .EncodeToString (ledgerKey ),
239
247
))
240
248
case xdr .LedgerEntryChangeTypeLedgerEntryRestored :
241
- if c .emitExpiredEntriesRemovedChange {
249
+ if c .config . EmitExpiredEntryRemovedChange {
242
250
c .cache [ledgerKeyString ] = Change {
243
- Type : key .Type ,
251
+ Type : change .Type ,
244
252
Pre : change .Pre ,
245
253
Post : nil ,
246
254
ChangeType : change .ChangeType ,
@@ -259,16 +267,10 @@ func (c *ChangeCompactor) addRemovedChange(change Change) error {
259
267
// addRestoredChange adds a change to the cache, but returns an error if the restore
260
268
// change is unexpected.
261
269
func (c * ChangeCompactor ) addRestoredChange (change Change ) error {
262
- // safe, since we later cast to string (causing a copy)
263
- key , err := change .Post .LedgerKey ()
270
+ ledgerKey , err := c .getLedgerKey (change .Post )
264
271
if err != nil {
265
- return errors . Wrap ( err , "error getting ledger key for updated entry" )
272
+ return err
266
273
}
267
- ledgerKey , err := c .encodingBuffer .UnsafeMarshalBinary (key )
268
- if err != nil {
269
- return errors .Wrap (err , "error marshaling ledger key for updated entry" )
270
- }
271
-
272
274
ledgerKeyString := string (ledgerKey )
273
275
274
276
if _ , exist := c .cache [ledgerKeyString ]; exist {
0 commit comments