@@ -88,8 +88,7 @@ type nestedPendingOperations struct {
88
88
}
89
89
90
90
type operation struct {
91
- volumeName v1.UniqueVolumeName
92
- podName types.UniquePodName
91
+ key operationKey
93
92
operationName string
94
93
operationPending bool
95
94
expBackoff exponentialbackoff.ExponentialBackoff
@@ -101,18 +100,19 @@ func (grm *nestedPendingOperations) Run(
101
100
generatedOperations types.GeneratedOperations ) error {
102
101
grm .lock .Lock ()
103
102
defer grm .lock .Unlock ()
104
- opExists , previousOpIndex := grm .isOperationExists (volumeName , podName )
103
+
104
+ opKey := operationKey {volumeName , podName }
105
+
106
+ opExists , previousOpIndex := grm .isOperationExists (opKey )
105
107
if opExists {
106
108
previousOp := grm .operations [previousOpIndex ]
107
109
// Operation already exists
108
110
if previousOp .operationPending {
109
111
// Operation is pending
110
- operationKey := getOperationKey (volumeName , podName )
111
- return NewAlreadyExistsError (operationKey )
112
+ return NewAlreadyExistsError (opKey )
112
113
}
113
114
114
- operationKey := getOperationKey (volumeName , podName )
115
- backOffErr := previousOp .expBackoff .SafeToRetry (operationKey )
115
+ backOffErr := previousOp .expBackoff .SafeToRetry (opKey .String ())
116
116
if backOffErr != nil {
117
117
if previousOp .operationName == generatedOperations .OperationName {
118
118
return backOffErr
@@ -124,15 +124,13 @@ func (grm *nestedPendingOperations) Run(
124
124
125
125
// Update existing operation to mark as pending.
126
126
grm .operations [previousOpIndex ].operationPending = true
127
- grm .operations [previousOpIndex ].volumeName = volumeName
128
- grm .operations [previousOpIndex ].podName = podName
127
+ grm .operations [previousOpIndex ].key = opKey
129
128
} else {
130
129
// Create a new operation
131
130
grm .operations = append (grm .operations ,
132
131
operation {
132
+ key : opKey ,
133
133
operationPending : true ,
134
- volumeName : volumeName ,
135
- podName : podName ,
136
134
operationName : generatedOperations .OperationName ,
137
135
expBackoff : exponentialbackoff.ExponentialBackoff {},
138
136
})
@@ -142,7 +140,7 @@ func (grm *nestedPendingOperations) Run(
142
140
// Handle unhandled panics (very unlikely)
143
141
defer k8sRuntime .HandleCrash ()
144
142
// Handle completion of and error, if any, from operationFunc()
145
- defer grm .operationComplete (volumeName , podName , & detailedErr )
143
+ defer grm .operationComplete (opKey , & detailedErr )
146
144
return generatedOperations .Run ()
147
145
}()
148
146
@@ -156,67 +154,58 @@ func (grm *nestedPendingOperations) IsOperationPending(
156
154
grm .lock .RLock ()
157
155
defer grm .lock .RUnlock ()
158
156
159
- exist , previousOpIndex := grm .isOperationExists (volumeName , podName )
157
+ opKey := operationKey {volumeName , podName }
158
+ exist , previousOpIndex := grm .isOperationExists (opKey )
160
159
if exist && grm .operations [previousOpIndex ].operationPending {
161
160
return true
162
161
}
163
162
return false
164
163
}
165
164
166
165
// This is an internal function and caller should acquire and release the lock
167
- func (grm * nestedPendingOperations ) isOperationExists (
168
- volumeName v1.UniqueVolumeName ,
169
- podName types.UniquePodName ) (bool , int ) {
166
+ func (grm * nestedPendingOperations ) isOperationExists (key operationKey ) (bool , int ) {
170
167
171
168
// If volumeName is empty, operation can be executed concurrently
172
- if volumeName == EmptyUniqueVolumeName {
169
+ if key . volumeName == EmptyUniqueVolumeName {
173
170
return false , - 1
174
171
}
175
172
176
173
for previousOpIndex , previousOp := range grm .operations {
177
- if previousOp .volumeName != volumeName {
178
- // No match, keep searching
179
- continue
180
- }
174
+ volumeNameMatch := previousOp .key .volumeName == key .volumeName
175
+
176
+ podNameMatch := previousOp .key .podName == EmptyUniquePodName ||
177
+ key .podName == EmptyUniquePodName ||
178
+ previousOp .key .podName == key .podName
181
179
182
- if previousOp .podName != EmptyUniquePodName &&
183
- podName != EmptyUniquePodName &&
184
- previousOp .podName != podName {
185
- // No match, keep searching
186
- continue
187
- }
188
180
189
- // Match
190
- return true , previousOpIndex
181
+ if volumeNameMatch && podNameMatch {
182
+ return true , previousOpIndex
183
+ }
191
184
}
185
+
192
186
return false , - 1
193
187
}
194
188
195
- func (grm * nestedPendingOperations ) getOperation (
196
- volumeName v1.UniqueVolumeName ,
197
- podName types.UniquePodName ) (uint , error ) {
189
+ func (grm * nestedPendingOperations ) getOperation (key operationKey ) (uint , error ) {
198
190
// Assumes lock has been acquired by caller.
199
191
200
192
for i , op := range grm .operations {
201
- if op .volumeName == volumeName &&
202
- op .podName == podName {
193
+ if op .key . volumeName == key . volumeName &&
194
+ op .key . podName == key . podName {
203
195
return uint (i ), nil
204
196
}
205
197
}
206
198
207
- logOperationKey := getOperationKey (volumeName , podName )
208
- return 0 , fmt .Errorf ("Operation %q not found" , logOperationKey )
199
+ return 0 , fmt .Errorf ("Operation %q not found" , key )
209
200
}
210
201
211
- func (grm * nestedPendingOperations ) deleteOperation (
202
+ func (grm * nestedPendingOperations ) deleteOperation (key operationKey ) {
212
203
// Assumes lock has been acquired by caller.
213
- volumeName v1.UniqueVolumeName ,
214
- podName types.UniquePodName ) {
215
204
216
205
opIndex := - 1
217
206
for i , op := range grm .operations {
218
- if op .volumeName == volumeName &&
219
- op .podName == podName {
207
+ if op .key . volumeName == key . volumeName &&
208
+ op .key . podName == key . podName {
220
209
opIndex = i
221
210
break
222
211
}
@@ -227,8 +216,7 @@ func (grm *nestedPendingOperations) deleteOperation(
227
216
grm .operations = grm .operations [:len (grm .operations )- 1 ]
228
217
}
229
218
230
- func (grm * nestedPendingOperations ) operationComplete (
231
- volumeName v1.UniqueVolumeName , podName types.UniquePodName , err * error ) {
219
+ func (grm * nestedPendingOperations ) operationComplete (key operationKey , err * error ) {
232
220
// Defer operations are executed in Last-In is First-Out order. In this case
233
221
// the lock is acquired first when operationCompletes begins, and is
234
222
// released when the method finishes, after the lock is released cond is
@@ -239,24 +227,20 @@ func (grm *nestedPendingOperations) operationComplete(
239
227
240
228
if * err == nil || ! grm .exponentialBackOffOnError {
241
229
// Operation completed without error, or exponentialBackOffOnError disabled
242
- grm .deleteOperation (volumeName , podName )
230
+ grm .deleteOperation (key )
243
231
if * err != nil {
244
232
// Log error
245
- logOperationKey := getOperationKey (volumeName , podName )
246
- klog .Errorf ("operation %s failed with: %v" ,
247
- logOperationKey ,
248
- * err )
233
+ klog .Errorf ("operation %s failed with: %v" , key , * err )
249
234
}
250
235
return
251
236
}
252
237
253
238
// Operation completed with error and exponentialBackOffOnError Enabled
254
- existingOpIndex , getOpErr := grm .getOperation (volumeName , podName )
239
+ existingOpIndex , getOpErr := grm .getOperation (key )
255
240
if getOpErr != nil {
256
241
// Failed to find existing operation
257
- logOperationKey := getOperationKey (volumeName , podName )
258
242
klog .Errorf ("Operation %s completed. error: %v. exponentialBackOffOnError is enabled, but failed to get operation to update." ,
259
- logOperationKey ,
243
+ key ,
260
244
* err )
261
245
return
262
246
}
@@ -265,10 +249,8 @@ func (grm *nestedPendingOperations) operationComplete(
265
249
grm .operations [existingOpIndex ].operationPending = false
266
250
267
251
// Log error
268
- operationKey :=
269
- getOperationKey (volumeName , podName )
270
252
klog .Errorf ("%v" , grm .operations [existingOpIndex ].expBackoff .
271
- GenerateNoRetriesPermittedMsg (operationKey ))
253
+ GenerateNoRetriesPermittedMsg (key . String () ))
272
254
}
273
255
274
256
func (grm * nestedPendingOperations ) Wait () {
@@ -280,21 +262,22 @@ func (grm *nestedPendingOperations) Wait() {
280
262
}
281
263
}
282
264
283
- func getOperationKey (
284
- volumeName v1.UniqueVolumeName , podName types.UniquePodName ) string {
285
- podNameStr := ""
286
- if podName != EmptyUniquePodName {
287
- podNameStr = fmt .Sprintf (" (%q)" , podName )
288
- }
265
+ type operationKey struct {
266
+ volumeName v1.UniqueVolumeName
267
+ podName types.UniquePodName
268
+ }
269
+
270
+ func (key operationKey ) String () string {
271
+ podNameStr := fmt .Sprintf (" (%q)" , key .podName )
289
272
290
273
return fmt .Sprintf ("%q%s" ,
291
- volumeName ,
274
+ key . volumeName ,
292
275
podNameStr )
293
276
}
294
277
295
278
// NewAlreadyExistsError returns a new instance of AlreadyExists error.
296
- func NewAlreadyExistsError (operationKey string ) error {
297
- return alreadyExistsError {operationKey }
279
+ func NewAlreadyExistsError (key operationKey ) error {
280
+ return alreadyExistsError {key }
298
281
}
299
282
300
283
// IsAlreadyExists returns true if an error returned from
@@ -313,7 +296,7 @@ func IsAlreadyExists(err error) bool {
313
296
// new operation can not be started because an operation with the same operation
314
297
// name is already executing.
315
298
type alreadyExistsError struct {
316
- operationKey string
299
+ operationKey operationKey
317
300
}
318
301
319
302
var _ error = alreadyExistsError {}
0 commit comments