@@ -24,24 +24,54 @@ 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 )
2935 persistedPutCount := countPersistedPuts (persistedRequests )
3036 clientPutCount := countClientPuts (reports )
31- putReturnTime := uniquePutReturnTime (operations , persistedRequests , clientPutCount )
32- return patchOperations (operations , putRevision , putReturnTime , clientPutCount , persistedPutCount )
37+
38+ persistedDeleteCount := countPersistedDeletes (persistedRequests )
39+ clientDeleteCount := countClientDeletes (reports )
40+
41+ putReturnTime , delReturnTime := uniqueOperationReturnTime (operations , persistedRequests , clientPutCount , clientDeleteCount )
42+
43+ putArgs := make (map [model.PutOptions ]patchArgs )
44+ for opts , c := range clientPutCount {
45+ putArgs [opts ] = patchArgs {
46+ clientCount : c ,
47+ persistedCount : persistedPutCount [opts ],
48+ returnTime : putReturnTime [opts ],
49+ }
50+ }
51+ delArgs := make (map [model.DeleteOptions ]patchArgs )
52+ for opts , c := range clientDeleteCount {
53+ delArgs [opts ] = patchArgs {
54+ clientCount : c ,
55+ persistedCount : persistedDeleteCount [opts ],
56+ returnTime : delReturnTime [opts ],
57+ }
58+ }
59+
60+ return patchOperations (
61+ operations , putRevision , putArgs , delArgs ,
62+ )
3363}
3464
35- func putRevision (reports []report.ClientReport ) map [keyValue ]int64 {
36- requestRevision := map [keyValue ]int64 {}
65+ func putRevision (reports []report.ClientReport ) map [model. PutOptions ]int64 {
66+ requestRevision := map [model. PutOptions ]int64 {}
3767 for _ , client := range reports {
3868 for _ , watch := range client .Watch {
3969 for _ , resp := range watch .Responses {
4070 for _ , event := range resp .Events {
4171 switch event .Type {
4272 case model .RangeOperation :
4373 case model .PutOperation :
44- kv := keyValue {Key : event .Key , Value : event .Value }
74+ kv := model. PutOptions {Key : event .Key , Value : event .Value }
4575 requestRevision [kv ] = event .Revision
4676 case model .DeleteOperation :
4777 default :
@@ -54,7 +84,12 @@ func putRevision(reports []report.ClientReport) map[keyValue]int64 {
5484 return requestRevision
5585}
5686
57- func patchOperations (operations []porcupine.Operation , watchRevision , putReturnTime , clientPutCount , persistedPutCount map [keyValue ]int64 ) []porcupine.Operation {
87+ func patchOperations (
88+ operations []porcupine.Operation ,
89+ putRevision map [model.PutOptions ]int64 ,
90+ putArgs map [model.PutOptions ]patchArgs ,
91+ delArgs map [model.DeleteOptions ]patchArgs ,
92+ ) []porcupine.Operation {
5893 newOperations := make ([]porcupine.Operation , 0 , len (operations ))
5994
6095 for _ , op := range operations {
@@ -70,26 +105,39 @@ func patchOperations(operations []porcupine.Operation, watchRevision, putReturnT
70105 for _ , etcdOp := range append (request .Txn .OperationsOnSuccess , request .Txn .OperationsOnFailure ... ) {
71106 switch etcdOp .Type {
72107 case model .PutOperation :
73- kv := keyValue {Key : etcdOp .Put .Key , Value : etcdOp .Put .Value }
74- if _ , ok := persistedPutCount [kv ]; ok {
108+ kv := model.PutOptions {Key : etcdOp .Put .Key , Value : etcdOp .Put .Value }
109+ arg , ok := putArgs [kv ]
110+ if ok {
75111 persisted = true
76112 }
77- if count := clientPutCount [ kv ]; count != 1 {
113+ if arg . clientCount != 1 {
78114 continue
79115 }
80- if revision , ok := watchRevision [kv ]; ok {
116+ if revision , ok := putRevision [kv ]; ok {
81117 txnRevision = revision
82118 }
83- if returnTime , ok := putReturnTime [kv ]; ok {
84- op .Return = min (op .Return , returnTime )
85- }
119+ op .Return = min (op .Return , arg .returnTime )
86120 case model .DeleteOperation :
121+ key := model.DeleteOptions {Key : etcdOp .Delete .Key }
122+ arg , ok := delArgs [key ]
123+ if ! ok {
124+ continue
125+ }
126+ if arg .persistedCount > 0 {
127+ persisted = true
128+ }
129+ if arg .clientCount != 1 {
130+ continue
131+ }
132+ if arg .returnTime > 0 {
133+ op .Return = min (op .Return , arg .returnTime )
134+ }
87135 case model .RangeOperation :
88136 default :
89137 panic (fmt .Sprintf ("unknown operation type %q" , etcdOp .Type ))
90138 }
91139 }
92- if isUniqueTxn (request .Txn , clientPutCount ) {
140+ if isUniqueTxn (request .Txn , putArgs , delArgs ) {
93141 if ! persisted {
94142 // Remove non persisted operations
95143 continue
@@ -106,12 +154,21 @@ func patchOperations(operations []porcupine.Operation, watchRevision, putReturnT
106154 return newOperations
107155}
108156
109- func isUniqueTxn (request * model.TxnRequest , clientRequestCount map [keyValue ]int64 ) bool {
110- return isUniqueOps (request .OperationsOnSuccess , clientRequestCount ) && isUniqueOps (request .OperationsOnFailure , clientRequestCount )
157+ func containsDeleteOp (txn * model.TxnRequest ) bool {
158+ for _ , op := range append (txn .OperationsOnSuccess , txn .OperationsOnFailure ... ) {
159+ if op .Type == model .DeleteOperation {
160+ return true
161+ }
162+ }
163+ return false
111164}
112165
113- func isUniqueOps (ops []model.EtcdOperation , clientRequestCount map [keyValue ]int64 ) bool {
114- return hasUniqueWriteOperation (ops , clientRequestCount ) || ! hasWriteOperation (ops )
166+ func isUniqueTxn (request * model.TxnRequest , putArgs map [model.PutOptions ]patchArgs , delArgs map [model.DeleteOptions ]patchArgs ) bool {
167+ return isUniqueOps (request .OperationsOnSuccess , putArgs , delArgs ) && isUniqueOps (request .OperationsOnFailure , putArgs , delArgs )
168+ }
169+
170+ func isUniqueOps (ops []model.EtcdOperation , putArgs map [model.PutOptions ]patchArgs , delArgs map [model.DeleteOptions ]patchArgs ) bool {
171+ return hasUniqueWriteOperation (ops , putArgs , delArgs ) || ! hasWriteOperation (ops )
115172}
116173
117174func hasWriteOperation (ops []model.EtcdOperation ) bool {
@@ -123,15 +180,19 @@ func hasWriteOperation(ops []model.EtcdOperation) bool {
123180 return false
124181}
125182
126- func hasUniqueWriteOperation (ops []model.EtcdOperation , clientRequestCount map [keyValue ] int64 ) bool {
183+ func hasUniqueWriteOperation (ops []model.EtcdOperation , putArgs map [model. PutOptions ] patchArgs , delArgs map [model. DeleteOptions ] patchArgs ) bool {
127184 for _ , operation := range ops {
128185 switch operation .Type {
129186 case model .PutOperation :
130- kv := keyValue {Key : operation .Put .Key , Value : operation .Put .Value }
131- if count := clientRequestCount [kv ]; count == 1 {
187+ kv := model. PutOptions {Key : operation .Put .Key , Value : operation .Put .Value }
188+ if arg , ok := putArgs [kv ]; ok && arg . clientCount == 1 {
132189 return true
133190 }
134191 case model .DeleteOperation :
192+ kv := model.DeleteOptions {Key : operation .Delete .Key }
193+ if arg , ok := delArgs [kv ]; ok && arg .clientCount == 1 {
194+ return true
195+ }
135196 case model .RangeOperation :
136197 default :
137198 panic (fmt .Sprintf ("unknown operation type %q" , operation .Type ))
@@ -140,25 +201,35 @@ func hasUniqueWriteOperation(ops []model.EtcdOperation, clientRequestCount map[k
140201 return false
141202}
142203
143- func uniquePutReturnTime (allOperations []porcupine.Operation , persistedRequests []model.EtcdRequest , clientPutCount map [keyValue ]int64 ) map [keyValue ]int64 {
144- earliestReturnTime := map [keyValue ]int64 {}
204+ 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 ) {
205+ putTimes := map [model.PutOptions ]int64 {}
206+ delTimes := map [model.DeleteOptions ]int64 {}
145207 var lastReturnTime int64
146208 for _ , op := range allOperations {
147209 request := op .Input .(model.EtcdRequest )
148210 switch request .Type {
149211 case model .Txn :
150212 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
213+ switch etcdOp .Type {
214+ case model .PutOperation :
215+ kv := model.PutOptions {Key : etcdOp .Put .Key , Value : etcdOp .Put .Value }
216+ if clientPutCount [kv ] > 1 {
217+ continue
218+ }
219+ if returnTime , ok := putTimes [kv ]; ! ok || returnTime > op .Return {
220+ putTimes [kv ] = op .Return
221+ }
222+ putTimes [kv ] = op .Return
223+ case model .DeleteOperation :
224+ kv := model.DeleteOptions {Key : etcdOp .Delete .Key }
225+ if clientDeleteCount [kv ] > 1 {
226+ continue
227+ }
228+ if returnTime , ok := delTimes [kv ]; ! ok || returnTime > op .Return {
229+ delTimes [kv ] = op .Return
230+ }
231+ delTimes [kv ] = op .Return
160232 }
161- earliestReturnTime [kv ] = op .Return
162233 }
163234 case model .Range :
164235 case model .LeaseGrant :
@@ -181,17 +252,25 @@ func uniquePutReturnTime(allOperations []porcupine.Operation, persistedRequests
181252 lastReturnTime --
182253 }
183254 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
255+ switch op .Type {
256+ case model .PutOperation :
257+ kv := model.PutOptions {Key : op .Put .Key , Value : op .Put .Value }
258+ if clientPutCount [kv ] > 1 {
259+ continue
260+ }
261+ if returnTime , ok := putTimes [kv ]; ok {
262+ lastReturnTime = min (returnTime , lastReturnTime )
263+ putTimes [kv ] = lastReturnTime
264+ }
265+ case model .DeleteOperation :
266+ kv := model.DeleteOptions {Key : op .Delete .Key }
267+ if clientDeleteCount [kv ] > 1 {
268+ continue
269+ }
270+ if returnTime , ok := delTimes [kv ]; ok {
271+ lastReturnTime = min (returnTime , lastReturnTime )
272+ delTimes [kv ] = lastReturnTime
273+ }
195274 }
196275 }
197276 case model .LeaseGrant :
@@ -201,11 +280,11 @@ func uniquePutReturnTime(allOperations []porcupine.Operation, persistedRequests
201280 panic (fmt .Sprintf ("Unknown request type: %q" , request .Type ))
202281 }
203282 }
204- return earliestReturnTime
283+ return putTimes , delTimes
205284}
206285
207- func countClientPuts (reports []report.ClientReport ) map [keyValue ]int64 {
208- counter := map [keyValue ]int64 {}
286+ func countClientPuts (reports []report.ClientReport ) map [model. PutOptions ]int64 {
287+ counter := map [model. PutOptions ]int64 {}
209288 for _ , client := range reports {
210289 for _ , op := range client .KeyValue {
211290 request := op .Input .(model.EtcdRequest )
@@ -215,21 +294,21 @@ func countClientPuts(reports []report.ClientReport) map[keyValue]int64 {
215294 return counter
216295}
217296
218- func countPersistedPuts (requests []model.EtcdRequest ) map [keyValue ]int64 {
219- counter := map [keyValue ]int64 {}
297+ func countPersistedPuts (requests []model.EtcdRequest ) map [model. PutOptions ]int64 {
298+ counter := map [model. PutOptions ]int64 {}
220299 for _ , request := range requests {
221300 countPuts (counter , request )
222301 }
223302 return counter
224303}
225304
226- func countPuts (counter map [keyValue ]int64 , request model.EtcdRequest ) {
305+ func countPuts (counter map [model. PutOptions ]int64 , request model.EtcdRequest ) {
227306 switch request .Type {
228307 case model .Txn :
229308 for _ , operation := range append (request .Txn .OperationsOnSuccess , request .Txn .OperationsOnFailure ... ) {
230309 switch operation .Type {
231310 case model .PutOperation :
232- kv := keyValue {Key : operation .Put .Key , Value : operation .Put .Value }
311+ kv := model. PutOptions {Key : operation .Put .Key , Value : operation .Put .Value }
233312 counter [kv ]++
234313 case model .DeleteOperation :
235314 case model .RangeOperation :
@@ -247,6 +326,36 @@ func countPuts(counter map[keyValue]int64, request model.EtcdRequest) {
247326 }
248327}
249328
329+ func countClientDeletes (reports []report.ClientReport ) map [model.DeleteOptions ]int64 {
330+ counter := map [model.DeleteOptions ]int64 {}
331+ for _ , client := range reports {
332+ for _ , op := range client .KeyValue {
333+ request := op .Input .(model.EtcdRequest )
334+ countDeletes (counter , request )
335+ }
336+ }
337+ return counter
338+ }
339+
340+ func countPersistedDeletes (requests []model.EtcdRequest ) map [model.DeleteOptions ]int64 {
341+ counter := map [model.DeleteOptions ]int64 {}
342+ for _ , req := range requests {
343+ countDeletes (counter , req )
344+ }
345+ return counter
346+ }
347+
348+ func countDeletes (counter map [model.DeleteOptions ]int64 , request model.EtcdRequest ) {
349+ if request .Type != model .Txn {
350+ return
351+ }
352+ for _ , operation := range append (request .Txn .OperationsOnSuccess , request .Txn .OperationsOnFailure ... ) {
353+ if operation .Type == model .DeleteOperation {
354+ counter [operation .Delete ]++
355+ }
356+ }
357+ }
358+
250359type keyValue struct {
251360 Key string
252361 Value model.ValueOrHash
0 commit comments