Skip to content

Commit 7ce7aff

Browse files
Reindex negative TimeValue fix (#54057)
Reindex would use timeValueNanos(System.nanoTime()). The intended use for TimeValue is as a duration, not as absolute time. In particular, this could result in negative TimeValue's, being unsupported in #53913. Modified to use the bare long nano-second value.
1 parent fc498f6 commit 7ce7aff

File tree

4 files changed

+26
-28
lines changed

4 files changed

+26
-28
lines changed

modules/reindex/src/main/java/org/elasticsearch/index/reindex/AbstractAsyncBulkByScrollAction.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -248,16 +248,16 @@ public void start() {
248248
void onScrollResponse(ScrollableHitSource.AsyncResponse asyncResponse) {
249249
// lastBatchStartTime is essentially unused (see WorkerBulkByScrollTaskState.throttleWaitTime. Leaving it for now, since it seems
250250
// like a bug?
251-
onScrollResponse(new TimeValue(System.nanoTime()), this.lastBatchSize, asyncResponse);
251+
onScrollResponse(System.nanoTime(), this.lastBatchSize, asyncResponse);
252252
}
253253

254254
/**
255255
* Process a scroll response.
256-
* @param lastBatchStartTime the time when the last batch started. Used to calculate the throttling delay.
256+
* @param lastBatchStartTimeNS the time when the last batch started. Used to calculate the throttling delay.
257257
* @param lastBatchSize the size of the last batch. Used to calculate the throttling delay.
258258
* @param asyncResponse the response to process from ScrollableHitSource
259259
*/
260-
void onScrollResponse(TimeValue lastBatchStartTime, int lastBatchSize, ScrollableHitSource.AsyncResponse asyncResponse) {
260+
void onScrollResponse(long lastBatchStartTimeNS, int lastBatchSize, ScrollableHitSource.AsyncResponse asyncResponse) {
261261
ScrollableHitSource.Response response = asyncResponse.response();
262262
logger.debug("[{}]: got scroll response with [{}] hits", task.getId(), response.getHits().size());
263263
if (task.isCancelled()) {
@@ -285,7 +285,7 @@ protected void doRun() throws Exception {
285285
* It is important that the batch start time be calculated from here, scroll response to scroll response. That way the time
286286
* waiting on the scroll doesn't count against this batch in the throttle.
287287
*/
288-
prepareBulkRequest(timeValueNanos(System.nanoTime()), asyncResponse);
288+
prepareBulkRequest(System.nanoTime(), asyncResponse);
289289
}
290290

291291
@Override
@@ -294,15 +294,15 @@ public void onFailure(Exception e) {
294294
}
295295
};
296296
prepareBulkRequestRunnable = (AbstractRunnable) threadPool.getThreadContext().preserveContext(prepareBulkRequestRunnable);
297-
worker.delayPrepareBulkRequest(threadPool, lastBatchStartTime, lastBatchSize, prepareBulkRequestRunnable);
297+
worker.delayPrepareBulkRequest(threadPool, lastBatchStartTimeNS, lastBatchSize, prepareBulkRequestRunnable);
298298
}
299299

300300
/**
301301
* Prepare the bulk request. Called on the generic thread pool after some preflight checks have been done one the SearchResponse and any
302302
* delay has been slept. Uses the generic thread pool because reindex is rare enough not to need its own thread pool and because the
303303
* thread may be blocked by the user script.
304304
*/
305-
void prepareBulkRequest(TimeValue thisBatchStartTime, ScrollableHitSource.AsyncResponse asyncResponse) {
305+
void prepareBulkRequest(long thisBatchStartTimeNS, ScrollableHitSource.AsyncResponse asyncResponse) {
306306
ScrollableHitSource.Response response = asyncResponse.response();
307307
logger.debug("[{}]: preparing bulk request", task.getId());
308308
if (task.isCancelled()) {
@@ -328,12 +328,12 @@ void prepareBulkRequest(TimeValue thisBatchStartTime, ScrollableHitSource.AsyncR
328328
/*
329329
* If we noop-ed the entire batch then just skip to the next batch or the BulkRequest would fail validation.
330330
*/
331-
notifyDone(thisBatchStartTime, asyncResponse, 0);
331+
notifyDone(thisBatchStartTimeNS, asyncResponse, 0);
332332
return;
333333
}
334334
request.timeout(mainRequest.getTimeout());
335335
request.waitForActiveShards(mainRequest.getWaitForActiveShards());
336-
sendBulkRequest(request, () -> notifyDone(thisBatchStartTime, asyncResponse, request.requests().size()));
336+
sendBulkRequest(request, () -> notifyDone(thisBatchStartTimeNS, asyncResponse, request.requests().size()));
337337
}
338338

339339
/**
@@ -419,14 +419,14 @@ void onBulkResponse(BulkResponse response, Runnable onSuccess) {
419419
}
420420
}
421421

422-
void notifyDone(TimeValue thisBatchStartTime, ScrollableHitSource.AsyncResponse asyncResponse, int batchSize) {
422+
void notifyDone(long thisBatchStartTimeNS, ScrollableHitSource.AsyncResponse asyncResponse, int batchSize) {
423423
if (task.isCancelled()) {
424424
logger.debug("[{}]: finishing early because the task was cancelled", task.getId());
425425
finishHim(null);
426426
return;
427427
}
428428
this.lastBatchSize = batchSize;
429-
asyncResponse.done(worker.throttleWaitTime(thisBatchStartTime, timeValueNanos(System.nanoTime()), batchSize));
429+
asyncResponse.done(worker.throttleWaitTime(thisBatchStartTimeNS, System.nanoTime(), batchSize));
430430
}
431431

432432
private void recordFailure(Failure failure, List<Failure> failures) {

modules/reindex/src/test/java/org/elasticsearch/index/reindex/AsyncBulkByScrollActionTests.java

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,6 @@
112112
import static org.apache.lucene.util.TestUtil.randomSimpleString;
113113
import static org.elasticsearch.action.bulk.BackoffPolicy.constantBackoff;
114114
import static org.elasticsearch.common.unit.TimeValue.timeValueMillis;
115-
import static org.elasticsearch.common.unit.TimeValue.timeValueNanos;
116115
import static org.elasticsearch.common.unit.TimeValue.timeValueSeconds;
117116
import static org.hamcrest.Matchers.contains;
118117
import static org.hamcrest.Matchers.containsString;
@@ -256,7 +255,7 @@ public void testScrollResponseSetsTotal() {
256255

257256
long total = randomIntBetween(0, Integer.MAX_VALUE);
258257
ScrollableHitSource.Response response = new ScrollableHitSource.Response(false, emptyList(), total, emptyList(), null);
259-
simulateScrollResponse(new DummyAsyncBulkByScrollAction(), timeValueSeconds(0), 0, response);
258+
simulateScrollResponse(new DummyAsyncBulkByScrollAction(), 0, 0, response);
260259
assertEquals(total, testTask.getStatus().getTotal());
261260
}
262261

@@ -269,7 +268,7 @@ public void testScrollResponseBatchingBehavior() throws Exception {
269268
Hit hit = new ScrollableHitSource.BasicHit("index", "type", "id", 0);
270269
ScrollableHitSource.Response response = new ScrollableHitSource.Response(false, emptyList(), 1, singletonList(hit), null);
271270
DummyAsyncBulkByScrollAction action = new DummyAsyncBulkByScrollAction();
272-
simulateScrollResponse(action, timeValueNanos(System.nanoTime()), 0, response);
271+
simulateScrollResponse(action, System.nanoTime(), 0, response);
273272

274273
// Use assert busy because the update happens on another thread
275274
final int expectedBatches = batches;
@@ -355,7 +354,7 @@ public ScheduledCancellable schedule(Runnable command, TimeValue delay, String n
355354
}
356355
});
357356
ScrollableHitSource.Response response = new ScrollableHitSource.Response(false, emptyList(), 0, emptyList(), null);
358-
simulateScrollResponse(new DummyAsyncBulkByScrollAction(), timeValueNanos(System.nanoTime()), 10, response);
357+
simulateScrollResponse(new DummyAsyncBulkByScrollAction(), System.nanoTime(), 10, response);
359358
ExecutionException e = expectThrows(ExecutionException.class, () -> listener.get());
360359
assertThat(e.getCause(), instanceOf(EsRejectedExecutionException.class));
361360
assertThat(e.getCause(), hasToString(containsString("test")));
@@ -373,7 +372,7 @@ public void testShardFailuresAbortRequest() throws Exception {
373372
SearchFailure shardFailure = new SearchFailure(new RuntimeException("test"));
374373
ScrollableHitSource.Response scrollResponse = new ScrollableHitSource.Response(false, singletonList(shardFailure), 0,
375374
emptyList(), null);
376-
simulateScrollResponse(new DummyAsyncBulkByScrollAction(), timeValueNanos(System.nanoTime()), 0, scrollResponse);
375+
simulateScrollResponse(new DummyAsyncBulkByScrollAction(), System.nanoTime(), 0, scrollResponse);
377376
BulkByScrollResponse response = listener.get();
378377
assertThat(response.getBulkFailures(), empty());
379378
assertThat(response.getSearchFailures(), contains(shardFailure));
@@ -387,7 +386,7 @@ public void testShardFailuresAbortRequest() throws Exception {
387386
*/
388387
public void testSearchTimeoutsAbortRequest() throws Exception {
389388
ScrollableHitSource.Response scrollResponse = new ScrollableHitSource.Response(true, emptyList(), 0, emptyList(), null);
390-
simulateScrollResponse(new DummyAsyncBulkByScrollAction(), timeValueNanos(System.nanoTime()), 0, scrollResponse);
389+
simulateScrollResponse(new DummyAsyncBulkByScrollAction(), System.nanoTime(), 0, scrollResponse);
391390
BulkByScrollResponse response = listener.get();
392391
assertThat(response.getBulkFailures(), empty());
393392
assertThat(response.getSearchFailures(), empty());
@@ -424,7 +423,7 @@ protected AbstractAsyncBulkByScrollAction.RequestWrapper<?> buildRequest(Hit doc
424423
ScrollableHitSource.BasicHit hit = new ScrollableHitSource.BasicHit("index", "type", "id", 0);
425424
hit.setSource(new BytesArray("{}"), XContentType.JSON);
426425
ScrollableHitSource.Response response = new ScrollableHitSource.Response(false, emptyList(), 1, singletonList(hit), null);
427-
simulateScrollResponse(action, timeValueNanos(System.nanoTime()), 0, response);
426+
simulateScrollResponse(action, System.nanoTime(), 0, response);
428427
ExecutionException e = expectThrows(ExecutionException.class, () -> listener.get());
429428
assertThat(e.getCause(), instanceOf(RuntimeException.class));
430429
assertThat(e.getCause().getMessage(), equalTo("surprise"));
@@ -620,7 +619,7 @@ public void testCancelBeforeInitialSearch() throws Exception {
620619
}
621620

622621
public void testCancelBeforeScrollResponse() throws Exception {
623-
cancelTaskCase((DummyAsyncBulkByScrollAction action) -> simulateScrollResponse(action, timeValueNanos(System.nanoTime()), 1,
622+
cancelTaskCase((DummyAsyncBulkByScrollAction action) -> simulateScrollResponse(action, System.nanoTime(), 1,
624623
new ScrollableHitSource.Response(false, emptyList(), between(1, 100000), emptyList(), null)));
625624
}
626625

@@ -635,7 +634,7 @@ public void testCancelBeforeOnBulkResponse() throws Exception {
635634
}
636635

637636
public void testCancelBeforeStartNextScroll() throws Exception {
638-
TimeValue now = timeValueNanos(System.nanoTime());
637+
long now = System.nanoTime();
639638
cancelTaskCase((DummyAsyncBulkByScrollAction action) -> action.notifyDone(now, null, 0));
640639
}
641640

@@ -684,7 +683,7 @@ public ScheduledCancellable schedule(Runnable command, TimeValue delay, String n
684683
ScrollableHitSource.Response response = new ScrollableHitSource.Response(false, emptyList(), total, emptyList(), null);
685684
// Use a long delay here so the test will time out if the cancellation doesn't reschedule the throttled task
686685
worker.rethrottle(1);
687-
simulateScrollResponse(action, timeValueNanos(System.nanoTime()), 1000, response);
686+
simulateScrollResponse(action, System.nanoTime(), 1000, response);
688687

689688
// Now that we've got our cancel we'll just verify that it all came through all right
690689
assertEquals(reason, listener.get(10, TimeUnit.SECONDS).getReasonCancelled());
@@ -713,7 +712,7 @@ private void cancelTaskCase(Consumer<DummyAsyncBulkByScrollAction> testMe) throw
713712
/**
714713
* Simulate a scroll response by setting the scroll id and firing the onScrollResponse method.
715714
*/
716-
private void simulateScrollResponse(DummyAsyncBulkByScrollAction action, TimeValue lastBatchTime, int lastBatchSize,
715+
private void simulateScrollResponse(DummyAsyncBulkByScrollAction action, long lastBatchTime, int lastBatchSize,
717716
ScrollableHitSource.Response response) {
718717
action.setScroll(scrollId());
719718
action.onScrollResponse(lastBatchTime, lastBatchSize, new ScrollableHitSource.AsyncResponse() {

server/src/main/java/org/elasticsearch/index/reindex/WorkerBulkByScrollTaskState.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,11 +182,11 @@ TimeValue throttledUntil() {
182182
* Schedule prepareBulkRequestRunnable to run after some delay. This is where throttling plugs into reindexing so the request can be
183183
* rescheduled over and over again.
184184
*/
185-
public void delayPrepareBulkRequest(ThreadPool threadPool, TimeValue lastBatchStartTime, int lastBatchSize,
185+
public void delayPrepareBulkRequest(ThreadPool threadPool, long lastBatchStartTimeNS, int lastBatchSize,
186186
AbstractRunnable prepareBulkRequestRunnable) {
187187
// Synchronize so we are less likely to schedule the same request twice.
188188
synchronized (delayedPrepareBulkRequestReference) {
189-
TimeValue delay = throttleWaitTime(lastBatchStartTime, timeValueNanos(System.nanoTime()), lastBatchSize);
189+
TimeValue delay = throttleWaitTime(lastBatchStartTimeNS, System.nanoTime(), lastBatchSize);
190190
logger.debug("[{}]: preparing bulk request for [{}]", task.getId(), delay);
191191
try {
192192
delayedPrepareBulkRequestReference.set(new DelayedPrepareBulkRequest(threadPool, getRequestsPerSecond(),
@@ -197,8 +197,8 @@ public void delayPrepareBulkRequest(ThreadPool threadPool, TimeValue lastBatchSt
197197
}
198198
}
199199

200-
public TimeValue throttleWaitTime(TimeValue lastBatchStartTime, TimeValue now, int lastBatchSize) {
201-
long earliestNextBatchStartTime = now.nanos() + (long) perfectlyThrottledBatchTime(lastBatchSize);
200+
public TimeValue throttleWaitTime(long lastBatchStartTimeNS, long nowNS, int lastBatchSize) {
201+
long earliestNextBatchStartTime = nowNS + (long) perfectlyThrottledBatchTime(lastBatchSize);
202202
long waitTime = min(MAX_THROTTLE_WAIT_TIME.nanos(), max(0, earliestNextBatchStartTime - System.nanoTime()));
203203
return timeValueNanos(waitTime);
204204
}

server/src/test/java/org/elasticsearch/index/reindex/WorkerBulkByScrollTaskStateTests.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
import java.util.concurrent.TimeUnit;
3737
import java.util.concurrent.atomic.AtomicBoolean;
3838

39-
import static org.elasticsearch.common.unit.TimeValue.timeValueNanos;
4039
import static org.elasticsearch.common.unit.TimeValue.timeValueSeconds;
4140
import static org.hamcrest.Matchers.both;
4241
import static org.hamcrest.Matchers.closeTo;
@@ -152,7 +151,7 @@ public ScheduledCancellable schedule(Runnable command, TimeValue delay, String n
152151
}
153152
};
154153
try {
155-
workerState.delayPrepareBulkRequest(threadPool, timeValueNanos(System.nanoTime()), batchSizeForMaxDelay,
154+
workerState.delayPrepareBulkRequest(threadPool, System.nanoTime(), batchSizeForMaxDelay,
156155
new AbstractRunnable() {
157156
@Override
158157
protected void doRun() throws Exception {
@@ -225,7 +224,7 @@ public boolean isCancelled() {
225224
};
226225
try {
227226
// Have the task use the thread pool to delay a task that does nothing
228-
workerState.delayPrepareBulkRequest(threadPool, timeValueSeconds(0), 1, new AbstractRunnable() {
227+
workerState.delayPrepareBulkRequest(threadPool, 0, 1, new AbstractRunnable() {
229228
@Override
230229
protected void doRun() throws Exception {
231230
}

0 commit comments

Comments
 (0)