@@ -29,7 +29,21 @@ func patchLinearizableOperations(operations []porcupine.Operation, reports []rep
2929 persistedPutCount := countPersistedPuts (persistedRequests )
3030 clientPutCount := countClientPuts (reports )
3131 putReturnTime := uniquePutReturnTime (operations , persistedRequests , clientPutCount )
32- return patchOperations (operations , putRevision , putReturnTime , clientPutCount , persistedPutCount )
32+
33+ persistedDeleteCount := countPersistedDeletes (persistedRequests )
34+ clientDeleteCount := countClientDeletes (reports )
35+ deleteReturnTime := uniqueDeleteReturnTime (operations , persistedRequests , clientDeleteCount )
36+
37+ persistedCompactCount := countPersistedCompacts (persistedRequests )
38+ clientCompactCount := countClientCompacts (reports )
39+ compactReturnTime := uniqueCompactReturnTime (operations , persistedRequests , clientCompactCount )
40+
41+ return patchOperations (
42+ operations , putRevision , putReturnTime , clientPutCount , persistedPutCount ,
43+ clientDeleteCount , persistedDeleteCount ,
44+ clientCompactCount , persistedCompactCount ,
45+ deleteReturnTime , compactReturnTime ,
46+ )
3347}
3448
3549func putRevision (reports []report.ClientReport ) map [keyValue ]int64 {
@@ -54,7 +68,14 @@ func putRevision(reports []report.ClientReport) map[keyValue]int64 {
5468 return requestRevision
5569}
5670
57- func patchOperations (operations []porcupine.Operation , watchRevision , putReturnTime , clientPutCount , persistedPutCount map [keyValue ]int64 ) []porcupine.Operation {
71+ func patchOperations (
72+ operations []porcupine.Operation ,
73+ watchRevision , putReturnTime , clientPutCount , persistedPutCount map [keyValue ]int64 ,
74+ clientDeleteCount , persistedDeleteCount map [string ]int64 ,
75+ clientCompactCount , persistedCompactCount map [int64 ]int64 ,
76+ deleteReturnTime map [string ]int64 ,
77+ compactReturnTime map [int64 ]int64 ,
78+ ) []porcupine.Operation {
5879 newOperations := make ([]porcupine.Operation , 0 , len (operations ))
5980
6081 for _ , op := range operations {
@@ -84,6 +105,27 @@ func patchOperations(operations []porcupine.Operation, watchRevision, putReturnT
84105 op .Return = min (op .Return , returnTime )
85106 }
86107 case model .DeleteOperation :
108+ key := etcdOp .Delete .Key
109+ if _ , ok := persistedDeleteCount [key ]; ok {
110+ persisted = true
111+ }
112+ if count := clientDeleteCount [key ]; count != 1 {
113+ continue
114+ }
115+ if returnTime , ok := deleteReturnTime [key ]; ok {
116+ op .Return = min (op .Return , returnTime )
117+ }
118+ case model .CompactOperation :
119+ rev := etcdOp .Compact .Revision
120+ if _ , ok := persistedCompactCount [rev ]; ok {
121+ persisted = true
122+ }
123+ if count := clientCompactCount [rev ]; count != 1 {
124+ continue
125+ }
126+ if returnTime , ok := compactReturnTime [rev ]; ok {
127+ op .Return = min (op .Return , returnTime )
128+ }
87129 case model .RangeOperation :
88130 default :
89131 panic (fmt .Sprintf ("unknown operation type %q" , etcdOp .Type ))
@@ -247,6 +289,96 @@ func countPuts(counter map[keyValue]int64, request model.EtcdRequest) {
247289 }
248290}
249291
292+ func uniqueDeleteReturnTime (allOps []porcupine.Operation , persisted []model.EtcdRequest , clientDeleteCount map [string ]int64 ) map [string ]int64 {
293+ times := map [string ]int64 {}
294+ for _ , op := range allOps {
295+ req := op .Input .(model.EtcdRequest )
296+ if req .Type == model .Txn {
297+ for _ , e := range append (req .Txn .OperationsOnSuccess , req .Txn .OperationsOnFailure ... ) {
298+ if e .Type != model .DeleteOperation {
299+ continue
300+ }
301+ k := e .Delete .Key
302+ if clientDeleteCount [k ] == 1 {
303+ if t , ok := times [k ]; ! ok || op .Return < t {
304+ times [k ] = op .Return
305+ }
306+ }
307+ }
308+ }
309+ }
310+ return times
311+ }
312+
313+ func countClientDeletes (reports []report.ClientReport ) map [string ]int64 {
314+ counter := map [string ]int64 {}
315+ for _ , client := range reports {
316+ for _ , op := range client .KeyValue {
317+ request := op .Input .(model.EtcdRequest )
318+ countDeletes (counter , request )
319+ }
320+ }
321+ return counter
322+ }
323+
324+ func countPersistedDeletes (requests []model.EtcdRequest ) map [string ]int64 {
325+ counter := map [string ]int64 {}
326+ for _ , req := range requests {
327+ countDeletes (counter , req )
328+ }
329+ return counter
330+ }
331+
332+ func countDeletes (counter map [string ]int64 , request model.EtcdRequest ) {
333+ if request .Type != model .Txn {
334+ return
335+ }
336+ for _ , operation := range append (request .Txn .OperationsOnSuccess , request .Txn .OperationsOnFailure ... ) {
337+ if operation .Type == model .DeleteOperation {
338+ counter [operation .Delete .Key ]++
339+ }
340+ }
341+ }
342+
343+ func uniqueCompactReturnTime (allOps []porcupine.Operation , persisted []model.EtcdRequest , clientCompactCount map [int64 ]int64 ) map [int64 ]int64 {
344+ times := map [int64 ]int64 {}
345+ for _ , op := range allOps {
346+ req := op .Input .(model.EtcdRequest )
347+ if req .Type == model .Compact {
348+ rev := req .Compact .Revision
349+ if clientCompactCount [rev ] == 1 {
350+ if t , ok := times [rev ]; ! ok || op .Return < t {
351+ times [rev ] = op .Return
352+ }
353+ }
354+ }
355+ }
356+ return times
357+ }
358+
359+ func countClientCompacts (reports []report.ClientReport ) map [int64 ]int64 {
360+ counter := map [int64 ]int64 {}
361+ for _ , client := range reports {
362+ for _ , op := range client .KeyValue {
363+ request := op .Input .(model.EtcdRequest )
364+ if request .Type == model .Compact {
365+ counter [request .Compact .Revision ]++
366+ }
367+ }
368+ }
369+ return counter
370+ }
371+
372+ func countPersistedCompacts (requests []model.EtcdRequest ) map [int64 ]int64 {
373+ counter := map [int64 ]int64 {}
374+ for _ , req := range requests {
375+ if req .Type == model .Compact {
376+ counter [req .Compact .Revision ]++
377+ }
378+ }
379+ return counter
380+ }
381+
250382type keyValue struct {
251383 Key string
252384 Value model.ValueOrHash
0 commit comments