| 189 | } |
| 190 | |
| 191 | ACTOR static Future<Reference<Task>> getOne(Reference<ReadYourWritesTransaction> tr, |
| 192 | Reference<TaskBucket> taskBucket) { |
| 193 | if (taskBucket->priority_batch) |
| 194 | tr->setOption(FDBTransactionOptions::PRIORITY_BATCH); |
| 195 | |
| 196 | taskBucket->setOptions(tr); |
| 197 | |
| 198 | // give it some chances for the timed out tasks to get into the task loop in the case of |
| 199 | // many other new tasks get added so that the timed out tasks never get chances to re-run |
| 200 | if (deterministicRandom()->random01() < CLIENT_KNOBS->TASKBUCKET_CHECK_TIMEOUT_CHANCE) { |
| 201 | bool anyTimeouts = wait(requeueTimedOutTasks(tr, taskBucket)); |
| 202 | CODE_PROBE(anyTimeouts, "Found a task that timed out"); |
| 203 | } |
| 204 | |
| 205 | state std::vector<Future<Optional<Key>>> taskKeyFutures(CLIENT_KNOBS->TASKBUCKET_MAX_PRIORITY + 1); |
| 206 | |
| 207 | // Start looking for a task at each priority, highest first |
| 208 | state int pri; |
| 209 | for (pri = CLIENT_KNOBS->TASKBUCKET_MAX_PRIORITY; pri >= 0; --pri) |
| 210 | taskKeyFutures[pri] = getTaskKey(tr, taskBucket, pri); |
| 211 | |
| 212 | // Task key and subspace it is located in. |
| 213 | state Optional<Key> taskKey; |
| 214 | state Subspace availableSpace; |
| 215 | |
| 216 | // In priority order from highest to lowest, wait for fetch to finish and if it found a task then cancel the |
| 217 | // rest. |
| 218 | for (pri = CLIENT_KNOBS->TASKBUCKET_MAX_PRIORITY; pri >= 0; --pri) { |
| 219 | // If we already have a task key then cancel this fetch |
| 220 | if (taskKey.present()) |
| 221 | taskKeyFutures[pri].cancel(); |
| 222 | else { |
| 223 | Optional<Key> key = wait(taskKeyFutures[pri]); |
| 224 | if (key.present()) { |
| 225 | taskKey = key; |
| 226 | availableSpace = taskBucket->getAvailableSpace(pri); |
| 227 | } |
| 228 | } |
| 229 | } |
| 230 | |
| 231 | // If we don't have a task key, requeue timed out tasks and try again by calling self. |
| 232 | if (!taskKey.present()) { |
| 233 | bool anyTimeouts = wait(requeueTimedOutTasks(tr, taskBucket)); |
| 234 | // If there were timeouts, try to get a task since there should now be one in one of the available spaces. |
| 235 | if (anyTimeouts) { |
| 236 | CODE_PROBE(true, "Try to get one task from timeouts subspace"); |
| 237 | Reference<Task> task = wait(getOne(tr, taskBucket)); |
| 238 | return task; |
| 239 | } |
| 240 | return Reference<Task>(); |
| 241 | } |
| 242 | |
| 243 | // Now we know the task key is present and we have the available space for the task's priority |
| 244 | state Tuple t = availableSpace.unpack(taskKey.get()); |
| 245 | state Key taskUID = t.getString(0); |
| 246 | state Subspace taskAvailableSpace = availableSpace.get(taskUID); |
| 247 | |
| 248 | state Reference<Task> task(new Task()); |
nothing calls this directly
no test coverage detected