@@ -24,37 +24,78 @@ import (
2424 "go.etcd.io/etcd/tests/v3/robustness/report"
2525)
2626
27+ type patchArgs struct {
28+ returnTime int64
29+ clientCount int64
30+ persistedCount int64
31+ revision int64
32+ }
33+
2734func patchLinearizableOperations (operations []porcupine.Operation , reports []report.ClientReport , persistedRequests []model.EtcdRequest ) []porcupine.Operation {
28- putRevision := putRevision (reports )
35+ putRevision , delRevision := watchRevisions (reports )
2936 persistedPutCount := countPersistedPuts (persistedRequests )
3037 clientPutCount := countClientPuts (reports )
31- putReturnTime := uniquePutReturnTime (operations , persistedRequests , clientPutCount )
32- return patchOperations (operations , putRevision , putReturnTime , clientPutCount , persistedPutCount )
38+
39+ persistedDeleteCount := countPersistedDeletes (persistedRequests )
40+ clientDeleteCount := countClientDeletes (reports )
41+
42+ putReturnTime , delReturnTime := uniqueOperationReturnTime (operations , persistedRequests , clientPutCount , clientDeleteCount )
43+
44+ putArgs := make (map [model.PutOptions ]patchArgs )
45+ for opts , c := range clientPutCount {
46+ putArgs [opts ] = patchArgs {
47+ clientCount : c ,
48+ persistedCount : persistedPutCount [opts ],
49+ returnTime : putReturnTime [opts ],
50+ revision : putRevision [opts ],
51+ }
52+ }
53+ delArgs := make (map [model.DeleteOptions ]patchArgs )
54+ for opts , c := range clientDeleteCount {
55+ delArgs [opts ] = patchArgs {
56+ clientCount : c ,
57+ persistedCount : persistedDeleteCount [opts ],
58+ returnTime : delReturnTime [opts ],
59+ revision : delRevision [opts ],
60+ }
61+ }
62+
63+ return patchOperations (
64+ operations , putArgs , delArgs ,
65+ )
3366}
3467
35- func putRevision (reports []report.ClientReport ) map [keyValue ]int64 {
36- requestRevision := map [keyValue ]int64 {}
68+ func watchRevisions (reports []report.ClientReport ) (map [model.PutOptions ]int64 , map [model.DeleteOptions ]int64 ) {
69+ putRevisions := map [model.PutOptions ]int64 {}
70+ delRevisions := map [model.DeleteOptions ]int64 {}
71+
3772 for _ , client := range reports {
3873 for _ , watch := range client .Watch {
3974 for _ , resp := range watch .Responses {
4075 for _ , event := range resp .Events {
4176 switch event .Type {
4277 case model .RangeOperation :
4378 case model .PutOperation :
44- kv := keyValue {Key : event .Key , Value : event .Value }
45- requestRevision [kv ] = event .Revision
79+ kv := model. PutOptions {Key : event .Key , Value : event .Value }
80+ putRevisions [kv ] = event .Revision
4681 case model .DeleteOperation :
82+ kv := model.DeleteOptions {Key : event .Key } // ADD: Track delete revisions
83+ delRevisions [kv ] = event .Revision
4784 default :
4885 panic (fmt .Sprintf ("unknown event type %q" , event .Type ))
4986 }
5087 }
5188 }
5289 }
5390 }
54- return requestRevision
91+ return putRevisions , delRevisions
5592}
5693
57- func patchOperations (operations []porcupine.Operation , watchRevision , putReturnTime , clientPutCount , persistedPutCount map [keyValue ]int64 ) []porcupine.Operation {
94+ func patchOperations (
95+ operations []porcupine.Operation ,
96+ putArgs map [model.PutOptions ]patchArgs ,
97+ delArgs map [model.DeleteOptions ]patchArgs ,
98+ ) []porcupine.Operation {
5899 newOperations := make ([]porcupine.Operation , 0 , len (operations ))
59100
60101 for _ , op := range operations {
@@ -70,26 +111,47 @@ func patchOperations(operations []porcupine.Operation, watchRevision, putReturnT
70111 for _ , etcdOp := range append (request .Txn .OperationsOnSuccess , request .Txn .OperationsOnFailure ... ) {
71112 switch etcdOp .Type {
72113 case model .PutOperation :
73- kv := keyValue {Key : etcdOp .Put .Key , Value : etcdOp .Put .Value }
74- if _ , ok := persistedPutCount [kv ]; ok {
114+ kv := model.PutOptions {Key : etcdOp .Put .Key , Value : etcdOp .Put .Value }
115+ arg , ok := putArgs [kv ]
116+ if ! ok {
117+ continue
118+ }
119+ if arg .persistedCount > 0 {
75120 persisted = true
76121 }
77- if count := clientPutCount [ kv ]; count != 1 {
122+ if arg . clientCount != 1 {
78123 continue
79124 }
80- if revision , ok := watchRevision [ kv ]; ok {
81- txnRevision = revision
125+ if arg . revision > 0 {
126+ txnRevision = arg . revision
82127 }
83- if returnTime , ok := putReturnTime [ kv ]; ok {
84- op .Return = min (op .Return , returnTime )
128+ if arg . returnTime > 0 {
129+ op .Return = min (op .Return , arg . returnTime )
85130 }
86131 case model .DeleteOperation :
132+ kv := model.DeleteOptions {Key : etcdOp .Delete .Key }
133+ arg , ok := delArgs [kv ]
134+ if ! ok {
135+ continue
136+ }
137+ if arg .persistedCount > 0 {
138+ persisted = true
139+ }
140+ if arg .clientCount != 1 {
141+ continue
142+ }
143+ if arg .revision > 0 {
144+ txnRevision = arg .revision
145+ }
146+ if arg .returnTime > 0 {
147+ op .Return = min (op .Return , arg .returnTime )
148+ }
87149 case model .RangeOperation :
88150 default :
89151 panic (fmt .Sprintf ("unknown operation type %q" , etcdOp .Type ))
90152 }
91153 }
92- if isUniqueTxn (request .Txn , clientPutCount ) {
154+ if isUniqueTxn (request .Txn , putArgs , delArgs ) {
93155 if ! persisted {
94156 // Remove non persisted operations
95157 continue
@@ -106,12 +168,12 @@ func patchOperations(operations []porcupine.Operation, watchRevision, putReturnT
106168 return newOperations
107169}
108170
109- func isUniqueTxn (request * model.TxnRequest , clientRequestCount map [keyValue ] int64 ) bool {
110- return isUniqueOps (request .OperationsOnSuccess , clientRequestCount ) && isUniqueOps (request .OperationsOnFailure , clientRequestCount )
171+ func isUniqueTxn (request * model.TxnRequest , putArgs map [model. PutOptions ] patchArgs , delArgs map [model. DeleteOptions ] patchArgs ) bool {
172+ return isUniqueOps (request .OperationsOnSuccess , putArgs , delArgs ) && isUniqueOps (request .OperationsOnFailure , putArgs , delArgs )
111173}
112174
113- func isUniqueOps (ops []model.EtcdOperation , clientRequestCount map [keyValue ] int64 ) bool {
114- return hasUniqueWriteOperation (ops , clientRequestCount ) || ! hasWriteOperation (ops )
175+ func isUniqueOps (ops []model.EtcdOperation , putArgs map [model. PutOptions ] patchArgs , delArgs map [model. DeleteOptions ] patchArgs ) bool {
176+ return hasUniqueWriteOperation (ops , putArgs , delArgs ) || ! hasWriteOperation (ops )
115177}
116178
117179func hasWriteOperation (ops []model.EtcdOperation ) bool {
@@ -123,15 +185,19 @@ func hasWriteOperation(ops []model.EtcdOperation) bool {
123185 return false
124186}
125187
126- func hasUniqueWriteOperation (ops []model.EtcdOperation , clientRequestCount map [keyValue ] int64 ) bool {
188+ func hasUniqueWriteOperation (ops []model.EtcdOperation , putArgs map [model. PutOptions ] patchArgs , delArgs map [model. DeleteOptions ] patchArgs ) bool {
127189 for _ , operation := range ops {
128190 switch operation .Type {
129191 case model .PutOperation :
130- kv := keyValue {Key : operation .Put .Key , Value : operation .Put .Value }
131- if count := clientRequestCount [kv ]; count == 1 {
192+ kv := model. PutOptions {Key : operation .Put .Key , Value : operation .Put .Value }
193+ if arg , ok := putArgs [kv ]; ok && arg . clientCount == 1 {
132194 return true
133195 }
134196 case model .DeleteOperation :
197+ kv := model.DeleteOptions {Key : operation .Delete .Key }
198+ if arg , ok := delArgs [kv ]; ok && arg .clientCount == 1 {
199+ return true
200+ }
135201 case model .RangeOperation :
136202 default :
137203 panic (fmt .Sprintf ("unknown operation type %q" , operation .Type ))
@@ -140,25 +206,33 @@ func hasUniqueWriteOperation(ops []model.EtcdOperation, clientRequestCount map[k
140206 return false
141207}
142208
143- func uniquePutReturnTime (allOperations []porcupine.Operation , persistedRequests []model.EtcdRequest , clientPutCount map [keyValue ]int64 ) map [keyValue ]int64 {
144- earliestReturnTime := map [keyValue ]int64 {}
209+ func uniqueOperationReturnTime (allOperations []porcupine.Operation , persistedRequests []model.EtcdRequest , clientPutCount map [model.PutOptions ]int64 , clientDeleteCount map [model.DeleteOptions ]int64 ) (map [model.PutOptions ]int64 , map [model.DeleteOptions ]int64 ) {
210+ putTimes := map [model.PutOptions ]int64 {}
211+ delTimes := map [model.DeleteOptions ]int64 {}
145212 var lastReturnTime int64
146213 for _ , op := range allOperations {
147214 request := op .Input .(model.EtcdRequest )
148215 switch request .Type {
149216 case model .Txn :
150217 for _ , etcdOp := range append (request .Txn .OperationsOnSuccess , request .Txn .OperationsOnFailure ... ) {
151- if etcdOp .Type != model .PutOperation {
152- continue
153- }
154- kv := keyValue {Key : etcdOp .Put .Key , Value : etcdOp .Put .Value }
155- if count := clientPutCount [kv ]; count > 1 {
156- continue
157- }
158- if returnTime , ok := earliestReturnTime [kv ]; ! ok || returnTime > op .Return {
159- earliestReturnTime [kv ] = op .Return
218+ switch etcdOp .Type {
219+ case model .PutOperation :
220+ kv := model.PutOptions {Key : etcdOp .Put .Key , Value : etcdOp .Put .Value }
221+ if clientPutCount [kv ] > 1 {
222+ continue
223+ }
224+ if returnTime , ok := putTimes [kv ]; ! ok || returnTime > op .Return {
225+ putTimes [kv ] = op .Return
226+ }
227+ case model .DeleteOperation :
228+ kv := model.DeleteOptions {Key : etcdOp .Delete .Key }
229+ if clientDeleteCount [kv ] > 1 {
230+ continue
231+ }
232+ if returnTime , ok := delTimes [kv ]; ! ok || returnTime > op .Return {
233+ delTimes [kv ] = op .Return
234+ }
160235 }
161- earliestReturnTime [kv ] = op .Return
162236 }
163237 case model .Range :
164238 case model .LeaseGrant :
@@ -181,17 +255,25 @@ func uniquePutReturnTime(allOperations []porcupine.Operation, persistedRequests
181255 lastReturnTime --
182256 }
183257 for _ , op := range request .Txn .OperationsOnSuccess {
184- if op .Type != model .PutOperation {
185- continue
186- }
187- kv := keyValue {Key : op .Put .Key , Value : op .Put .Value }
188- if count := clientPutCount [kv ]; count > 1 {
189- continue
190- }
191- returnTime , ok := earliestReturnTime [kv ]
192- if ok {
193- lastReturnTime = min (returnTime , lastReturnTime )
194- earliestReturnTime [kv ] = lastReturnTime
258+ switch op .Type {
259+ case model .PutOperation :
260+ kv := model.PutOptions {Key : op .Put .Key , Value : op .Put .Value }
261+ if clientPutCount [kv ] > 1 {
262+ continue
263+ }
264+ if returnTime , ok := putTimes [kv ]; ok {
265+ lastReturnTime = min (returnTime , lastReturnTime )
266+ putTimes [kv ] = lastReturnTime
267+ }
268+ case model .DeleteOperation :
269+ kv := model.DeleteOptions {Key : op .Delete .Key }
270+ if clientDeleteCount [kv ] > 1 {
271+ continue
272+ }
273+ if returnTime , ok := delTimes [kv ]; ok {
274+ lastReturnTime = min (returnTime , lastReturnTime )
275+ delTimes [kv ] = lastReturnTime
276+ }
195277 }
196278 }
197279 case model .LeaseGrant :
@@ -201,11 +283,11 @@ func uniquePutReturnTime(allOperations []porcupine.Operation, persistedRequests
201283 panic (fmt .Sprintf ("Unknown request type: %q" , request .Type ))
202284 }
203285 }
204- return earliestReturnTime
286+ return putTimes , delTimes
205287}
206288
207- func countClientPuts (reports []report.ClientReport ) map [keyValue ]int64 {
208- counter := map [keyValue ]int64 {}
289+ func countClientPuts (reports []report.ClientReport ) map [model. PutOptions ]int64 {
290+ counter := map [model. PutOptions ]int64 {}
209291 for _ , client := range reports {
210292 for _ , op := range client .KeyValue {
211293 request := op .Input .(model.EtcdRequest )
@@ -215,21 +297,21 @@ func countClientPuts(reports []report.ClientReport) map[keyValue]int64 {
215297 return counter
216298}
217299
218- func countPersistedPuts (requests []model.EtcdRequest ) map [keyValue ]int64 {
219- counter := map [keyValue ]int64 {}
300+ func countPersistedPuts (requests []model.EtcdRequest ) map [model. PutOptions ]int64 {
301+ counter := map [model. PutOptions ]int64 {}
220302 for _ , request := range requests {
221303 countPuts (counter , request )
222304 }
223305 return counter
224306}
225307
226- func countPuts (counter map [keyValue ]int64 , request model.EtcdRequest ) {
308+ func countPuts (counter map [model. PutOptions ]int64 , request model.EtcdRequest ) {
227309 switch request .Type {
228310 case model .Txn :
229311 for _ , operation := range append (request .Txn .OperationsOnSuccess , request .Txn .OperationsOnFailure ... ) {
230312 switch operation .Type {
231313 case model .PutOperation :
232- kv := keyValue {Key : operation .Put .Key , Value : operation .Put .Value }
314+ kv := model. PutOptions {Key : operation .Put .Key , Value : operation .Put .Value }
233315 counter [kv ]++
234316 case model .DeleteOperation :
235317 case model .RangeOperation :
@@ -247,7 +329,32 @@ func countPuts(counter map[keyValue]int64, request model.EtcdRequest) {
247329 }
248330}
249331
250- type keyValue struct {
251- Key string
252- Value model.ValueOrHash
332+ func countClientDeletes (reports []report.ClientReport ) map [model.DeleteOptions ]int64 {
333+ counter := map [model.DeleteOptions ]int64 {}
334+ for _ , client := range reports {
335+ for _ , op := range client .KeyValue {
336+ request := op .Input .(model.EtcdRequest )
337+ countDeletes (counter , request )
338+ }
339+ }
340+ return counter
341+ }
342+
343+ func countPersistedDeletes (requests []model.EtcdRequest ) map [model.DeleteOptions ]int64 {
344+ counter := map [model.DeleteOptions ]int64 {}
345+ for _ , req := range requests {
346+ countDeletes (counter , req )
347+ }
348+ return counter
349+ }
350+
351+ func countDeletes (counter map [model.DeleteOptions ]int64 , request model.EtcdRequest ) {
352+ if request .Type != model .Txn {
353+ return
354+ }
355+ for _ , operation := range append (request .Txn .OperationsOnSuccess , request .Txn .OperationsOnFailure ... ) {
356+ if operation .Type == model .DeleteOperation {
357+ counter [operation .Delete ]++
358+ }
359+ }
253360}
0 commit comments