@@ -24,24 +24,55 @@ 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+ }
32+
2733func patchLinearizableOperations (operations []porcupine.Operation , reports []report.ClientReport , persistedRequests []model.EtcdRequest ) []porcupine.Operation {
2834 putRevision := putRevision (reports )
35+
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+ }
51+ }
52+ delArgs := make (map [model.DeleteOptions ]patchArgs )
53+ for opts , c := range clientDeleteCount {
54+ delArgs [opts ] = patchArgs {
55+ clientCount : c ,
56+ persistedCount : persistedDeleteCount [opts ],
57+ returnTime : delReturnTime [opts ],
58+ }
59+ }
60+
61+ return patchOperations (
62+ operations , putRevision , putArgs , delArgs ,
63+ )
3364}
3465
35- func putRevision (reports []report.ClientReport ) map [keyValue ]int64 {
36- requestRevision := map [keyValue ]int64 {}
66+ func putRevision (reports []report.ClientReport ) map [model. PutOptions ]int64 {
67+ requestRevision := map [model. PutOptions ]int64 {}
3768 for _ , client := range reports {
3869 for _ , watch := range client .Watch {
3970 for _ , resp := range watch .Responses {
4071 for _ , event := range resp .Events {
4172 switch event .Type {
4273 case model .RangeOperation :
4374 case model .PutOperation :
44- kv := keyValue {Key : event .Key , Value : event .Value }
75+ kv := model. PutOptions {Key : event .Key , Value : event .Value }
4576 requestRevision [kv ] = event .Revision
4677 case model .DeleteOperation :
4778 default :
@@ -54,7 +85,12 @@ func putRevision(reports []report.ClientReport) map[keyValue]int64 {
5485 return requestRevision
5586}
5687
57- func patchOperations (operations []porcupine.Operation , watchRevision , putReturnTime , clientPutCount , persistedPutCount map [keyValue ]int64 ) []porcupine.Operation {
88+ func patchOperations (
89+ operations []porcupine.Operation ,
90+ putRevision map [model.PutOptions ]int64 ,
91+ putArgs map [model.PutOptions ]patchArgs ,
92+ delArgs map [model.DeleteOptions ]patchArgs ,
93+ ) []porcupine.Operation {
5894 newOperations := make ([]porcupine.Operation , 0 , len (operations ))
5995
6096 for _ , op := range operations {
@@ -70,26 +106,44 @@ func patchOperations(operations []porcupine.Operation, watchRevision, putReturnT
70106 for _ , etcdOp := range append (request .Txn .OperationsOnSuccess , request .Txn .OperationsOnFailure ... ) {
71107 switch etcdOp .Type {
72108 case model .PutOperation :
73- kv := keyValue {Key : etcdOp .Put .Key , Value : etcdOp .Put .Value }
74- if _ , ok := persistedPutCount [kv ]; ok {
109+ kv := model.PutOptions {Key : etcdOp .Put .Key , Value : etcdOp .Put .Value }
110+ arg , ok := putArgs [kv ]
111+ if ! ok {
112+ continue
113+ }
114+ if arg .persistedCount > 0 {
75115 persisted = true
76116 }
77- if count := clientPutCount [ kv ]; count != 1 {
117+ if arg . clientCount != 1 {
78118 continue
79119 }
80- if revision , ok := watchRevision [kv ]; ok {
120+ if revision , ok := putRevision [kv ]; ok {
81121 txnRevision = revision
82122 }
83- if returnTime , ok := putReturnTime [ kv ]; ok {
84- op .Return = min (op .Return , returnTime )
123+ if arg . returnTime > 0 {
124+ op .Return = min (op .Return , arg . returnTime )
85125 }
86126 case model .DeleteOperation :
127+ key := model.DeleteOptions {Key : etcdOp .Put .Key }
128+ arg , ok := delArgs [key ]
129+ if ! ok {
130+ continue
131+ }
132+ if arg .persistedCount > 0 {
133+ persisted = true
134+ }
135+ if arg .clientCount != 1 {
136+ continue
137+ }
138+ if arg .returnTime > 0 {
139+ op .Return = min (op .Return , arg .returnTime )
140+ }
87141 case model .RangeOperation :
88142 default :
89143 panic (fmt .Sprintf ("unknown operation type %q" , etcdOp .Type ))
90144 }
91145 }
92- if isUniqueTxn (request .Txn , clientPutCount ) {
146+ if isUniqueTxn (request .Txn , putArgs , delArgs ) {
93147 if ! persisted {
94148 // Remove non persisted operations
95149 continue
@@ -106,12 +160,21 @@ func patchOperations(operations []porcupine.Operation, watchRevision, putReturnT
106160 return newOperations
107161}
108162
109- func isUniqueTxn (request * model.TxnRequest , clientRequestCount map [keyValue ]int64 ) bool {
110- return isUniqueOps (request .OperationsOnSuccess , clientRequestCount ) && isUniqueOps (request .OperationsOnFailure , clientRequestCount )
163+ func containsDeleteOp (txn * model.TxnRequest ) bool {
164+ for _ , op := range append (txn .OperationsOnSuccess , txn .OperationsOnFailure ... ) {
165+ if op .Type == model .DeleteOperation {
166+ return true
167+ }
168+ }
169+ return false
170+ }
171+
172+ func isUniqueTxn (request * model.TxnRequest , putArgs map [model.PutOptions ]patchArgs , delArgs map [model.DeleteOptions ]patchArgs ) bool {
173+ return isUniqueOps (request .OperationsOnSuccess , putArgs , delArgs ) && isUniqueOps (request .OperationsOnFailure , putArgs , delArgs )
111174}
112175
113- func isUniqueOps (ops []model.EtcdOperation , clientRequestCount map [keyValue ] int64 ) bool {
114- return hasUniqueWriteOperation (ops , clientRequestCount ) || ! hasWriteOperation (ops )
176+ func isUniqueOps (ops []model.EtcdOperation , putArgs map [model. PutOptions ] patchArgs , delArgs map [model. DeleteOptions ] patchArgs ) bool {
177+ return hasUniqueWriteOperation (ops , putArgs , delArgs ) || ! hasWriteOperation (ops )
115178}
116179
117180func hasWriteOperation (ops []model.EtcdOperation ) bool {
@@ -123,15 +186,19 @@ func hasWriteOperation(ops []model.EtcdOperation) bool {
123186 return false
124187}
125188
126- func hasUniqueWriteOperation (ops []model.EtcdOperation , clientRequestCount map [keyValue ] int64 ) bool {
189+ func hasUniqueWriteOperation (ops []model.EtcdOperation , putArgs map [model. PutOptions ] patchArgs , delArgs map [model. DeleteOptions ] patchArgs ) bool {
127190 for _ , operation := range ops {
128191 switch operation .Type {
129192 case model .PutOperation :
130- kv := keyValue {Key : operation .Put .Key , Value : operation .Put .Value }
131- if count := clientRequestCount [ kv ]; count == 1 {
193+ opt := model. PutOptions {Key : operation .Put .Key , Value : operation .Put .Value }
194+ if arg , ok := putArgs [ opt ]; ok && arg . clientCount == 1 {
132195 return true
133196 }
134197 case model .DeleteOperation :
198+ opt := model.DeleteOptions {Key : operation .Delete .Key }
199+ if arg , ok := delArgs [opt ]; ok && arg .clientCount == 1 {
200+ return true
201+ }
135202 case model .RangeOperation :
136203 default :
137204 panic (fmt .Sprintf ("unknown operation type %q" , operation .Type ))
@@ -140,25 +207,33 @@ func hasUniqueWriteOperation(ops []model.EtcdOperation, clientRequestCount map[k
140207 return false
141208}
142209
143- func uniquePutReturnTime (allOperations []porcupine.Operation , persistedRequests []model.EtcdRequest , clientPutCount map [keyValue ]int64 ) map [keyValue ]int64 {
144- earliestReturnTime := map [keyValue ]int64 {}
210+ func uniqueOperationReturnTime (allOps []porcupine.Operation , persistedRequests []model.EtcdRequest , clientPutCount map [model.PutOptions ]int64 , clientDeleteCount map [model.DeleteOptions ]int64 ) (map [model.PutOptions ]int64 , map [model.DeleteOptions ]int64 ) {
211+ putTimes := map [model.PutOptions ]int64 {}
212+ delTimes := map [model.DeleteOptions ]int64 {}
145213 var lastReturnTime int64
146- for _ , op := range allOperations {
214+ for _ , op := range allOps {
147215 request := op .Input .(model.EtcdRequest )
148216 switch request .Type {
149217 case model .Txn :
150218 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
219+ switch etcdOp .Type {
220+ case model .PutOperation :
221+ opt := model.PutOptions {Key : etcdOp .Put .Key , Value : etcdOp .Put .Value }
222+ if clientPutCount [opt ] > 1 {
223+ continue
224+ }
225+ if t , ok := putTimes [opt ]; ! ok || op .Return < t {
226+ putTimes [opt ] = op .Return
227+ }
228+ case model .DeleteOperation :
229+ opt := model.DeleteOptions {Key : etcdOp .Delete .Key }
230+ if clientDeleteCount [opt ] > 1 {
231+ continue
232+ }
233+ if t , ok := delTimes [opt ]; ! ok || op .Return < t {
234+ delTimes [opt ] = op .Return
235+ }
160236 }
161- earliestReturnTime [kv ] = op .Return
162237 }
163238 case model .Range :
164239 case model .LeaseGrant :
@@ -181,17 +256,25 @@ func uniquePutReturnTime(allOperations []porcupine.Operation, persistedRequests
181256 lastReturnTime --
182257 }
183258 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
259+ switch op .Type {
260+ case model .PutOperation :
261+ opt := model.PutOptions {Key : op .Put .Key , Value : op .Put .Value }
262+ if clientPutCount [opt ] > 1 {
263+ continue
264+ }
265+ if returnTime , ok := putTimes [opt ]; ok {
266+ lastReturnTime = min (returnTime , lastReturnTime )
267+ putTimes [opt ] = lastReturnTime
268+ }
269+ case model .DeleteOperation :
270+ opt := model.DeleteOptions {Key : op .Delete .Key }
271+ if clientDeleteCount [opt ] > 1 {
272+ continue
273+ }
274+ if returnTime , ok := delTimes [opt ]; ok {
275+ lastReturnTime = min (returnTime , lastReturnTime )
276+ delTimes [opt ] = lastReturnTime
277+ }
195278 }
196279 }
197280 case model .LeaseGrant :
@@ -201,11 +284,11 @@ func uniquePutReturnTime(allOperations []porcupine.Operation, persistedRequests
201284 panic (fmt .Sprintf ("Unknown request type: %q" , request .Type ))
202285 }
203286 }
204- return earliestReturnTime
287+ return putTimes , delTimes
205288}
206289
207- func countClientPuts (reports []report.ClientReport ) map [keyValue ]int64 {
208- counter := map [keyValue ]int64 {}
290+ func countClientPuts (reports []report.ClientReport ) map [model. PutOptions ]int64 {
291+ counter := map [model. PutOptions ]int64 {}
209292 for _ , client := range reports {
210293 for _ , op := range client .KeyValue {
211294 request := op .Input .(model.EtcdRequest )
@@ -215,21 +298,21 @@ func countClientPuts(reports []report.ClientReport) map[keyValue]int64 {
215298 return counter
216299}
217300
218- func countPersistedPuts (requests []model.EtcdRequest ) map [keyValue ]int64 {
219- counter := map [keyValue ]int64 {}
301+ func countPersistedPuts (requests []model.EtcdRequest ) map [model. PutOptions ]int64 {
302+ counter := map [model. PutOptions ]int64 {}
220303 for _ , request := range requests {
221304 countPuts (counter , request )
222305 }
223306 return counter
224307}
225308
226- func countPuts (counter map [keyValue ]int64 , request model.EtcdRequest ) {
309+ func countPuts (counter map [model. PutOptions ]int64 , request model.EtcdRequest ) {
227310 switch request .Type {
228311 case model .Txn :
229312 for _ , operation := range append (request .Txn .OperationsOnSuccess , request .Txn .OperationsOnFailure ... ) {
230313 switch operation .Type {
231314 case model .PutOperation :
232- kv := keyValue {Key : operation .Put .Key , Value : operation .Put .Value }
315+ kv := model. PutOptions {Key : operation .Put .Key , Value : operation .Put .Value }
233316 counter [kv ]++
234317 case model .DeleteOperation :
235318 case model .RangeOperation :
@@ -247,6 +330,57 @@ func countPuts(counter map[keyValue]int64, request model.EtcdRequest) {
247330 }
248331}
249332
333+ func uniqueDeleteReturnTime (allOps []porcupine.Operation , persisted []model.EtcdRequest , clientDeleteCount map [string ]int64 ) map [string ]int64 {
334+ times := map [string ]int64 {}
335+ for _ , op := range allOps {
336+ req := op .Input .(model.EtcdRequest )
337+ if req .Type == model .Txn {
338+ for _ , e := range append (req .Txn .OperationsOnSuccess , req .Txn .OperationsOnFailure ... ) {
339+ if e .Type != model .DeleteOperation {
340+ continue
341+ }
342+ k := e .Delete .Key
343+ if clientDeleteCount [k ] == 1 {
344+ if t , ok := times [k ]; ! ok || op .Return < t {
345+ times [k ] = op .Return
346+ }
347+ }
348+ }
349+ }
350+ }
351+ return times
352+ }
353+
354+ func countClientDeletes (reports []report.ClientReport ) map [model.DeleteOptions ]int64 {
355+ counter := map [model.DeleteOptions ]int64 {}
356+ for _ , client := range reports {
357+ for _ , op := range client .KeyValue {
358+ request := op .Input .(model.EtcdRequest )
359+ countDeletes (counter , request )
360+ }
361+ }
362+ return counter
363+ }
364+
365+ func countPersistedDeletes (requests []model.EtcdRequest ) map [model.DeleteOptions ]int64 {
366+ counter := map [model.DeleteOptions ]int64 {}
367+ for _ , req := range requests {
368+ countDeletes (counter , req )
369+ }
370+ return counter
371+ }
372+
373+ func countDeletes (counter map [model.DeleteOptions ]int64 , request model.EtcdRequest ) {
374+ if request .Type != model .Txn {
375+ return
376+ }
377+ for _ , operation := range append (request .Txn .OperationsOnSuccess , request .Txn .OperationsOnFailure ... ) {
378+ if operation .Type == model .DeleteOperation {
379+ counter [operation .Delete ]++
380+ }
381+ }
382+ }
383+
250384type keyValue struct {
251385 Key string
252386 Value model.ValueOrHash
0 commit comments