@@ -88,7 +88,7 @@ public void skipOnAborted() {
88
88
* This used to fail, but we've since compacted top n so it actually succeeds now.
89
89
*/
90
90
public void testSortByManyLongsSuccess () throws IOException {
91
- initManyLongs ();
91
+ initManyLongs (10 );
92
92
Map <String , Object > response = sortByManyLongs (500 );
93
93
ListMatcher columns = matchesList ().item (matchesMap ().entry ("name" , "a" ).entry ("type" , "long" ))
94
94
.item (matchesMap ().entry ("name" , "b" ).entry ("type" , "long" ));
@@ -105,7 +105,7 @@ public void testSortByManyLongsSuccess() throws IOException {
105
105
* This used to crash the node with an out of memory, but now it just trips a circuit breaker.
106
106
*/
107
107
public void testSortByManyLongsTooMuchMemory () throws IOException {
108
- initManyLongs ();
108
+ initManyLongs (10 );
109
109
// 5000 is plenty to break on most nodes
110
110
assertCircuitBreaks (attempt -> sortByManyLongs (attempt * 5000 ));
111
111
}
@@ -114,7 +114,7 @@ public void testSortByManyLongsTooMuchMemory() throws IOException {
114
114
* This should record an async response with a {@link CircuitBreakingException}.
115
115
*/
116
116
public void testSortByManyLongsTooMuchMemoryAsync () throws IOException {
117
- initManyLongs ();
117
+ initManyLongs (10 );
118
118
Request request = new Request ("POST" , "/_query/async" );
119
119
request .addParameter ("error_trace" , "" );
120
120
request .setJsonEntity (makeSortByManyLongs (5000 ).toString ().replace ("\n " , "\\ n" ));
@@ -191,6 +191,29 @@ public void testSortByManyLongsTooMuchMemoryAsync() throws IOException {
191
191
);
192
192
}
193
193
194
+ public void testSortByManyLongsGiantTopN () throws IOException {
195
+ initManyLongs (10 );
196
+ assertMap (
197
+ sortBySomeLongsLimit (100000 ),
198
+ matchesMap ().entry ("took" , greaterThan (0 ))
199
+ .entry ("is_partial" , false )
200
+ .entry ("columns" , List .of (Map .of ("name" , "MAX(a)" , "type" , "long" )))
201
+ .entry ("values" , List .of (List .of (9 )))
202
+ .entry ("documents_found" , greaterThan (0 ))
203
+ .entry ("values_loaded" , greaterThan (0 ))
204
+ );
205
+ }
206
+
207
+ public void testSortByManyLongsGiantTopNTooMuchMemory () throws IOException {
208
+ initManyLongs (20 );
209
+ assertCircuitBreaks (attempt -> sortBySomeLongsLimit (attempt * 500000 ));
210
+ }
211
+
212
+ public void testStupidTopN () throws IOException {
213
+ initManyLongs (1 ); // Doesn't actually matter how much data there is.
214
+ assertCircuitBreaks (attempt -> sortBySomeLongsLimit (2147483630 ));
215
+ }
216
+
194
217
private static final int MAX_ATTEMPTS = 5 ;
195
218
196
219
interface TryCircuitBreaking {
@@ -249,11 +272,25 @@ private StringBuilder makeSortByManyLongs(int count) {
249
272
return query ;
250
273
}
251
274
275
+ private Map <String , Object > sortBySomeLongsLimit (int count ) throws IOException {
276
+ logger .info ("sorting by 5 longs, keeping {}" , count );
277
+ return responseAsMap (query (makeSortBySomeLongsLimit (count ), null ));
278
+ }
279
+
280
+ private String makeSortBySomeLongsLimit (int count ) {
281
+ StringBuilder query = new StringBuilder ("{\" query\" : \" FROM manylongs\n " );
282
+ query .append ("| SORT a, b, c, d, e\n " );
283
+ query .append ("| LIMIT " ).append (count ).append ("\n " );
284
+ query .append ("| STATS MAX(a)\n " );
285
+ query .append ("\" }" );
286
+ return query .toString ();
287
+ }
288
+
252
289
/**
253
290
* This groups on about 200 columns which is a lot but has never caused us trouble.
254
291
*/
255
292
public void testGroupOnSomeLongs () throws IOException {
256
- initManyLongs ();
293
+ initManyLongs (10 );
257
294
Response resp = groupOnManyLongs (200 );
258
295
Map <String , Object > map = responseAsMap (resp );
259
296
ListMatcher columns = matchesList ().item (matchesMap ().entry ("name" , "MAX(a)" ).entry ("type" , "long" ));
@@ -265,7 +302,7 @@ public void testGroupOnSomeLongs() throws IOException {
265
302
* This groups on 5000 columns which used to throw a {@link StackOverflowError}.
266
303
*/
267
304
public void testGroupOnManyLongs () throws IOException {
268
- initManyLongs ();
305
+ initManyLongs (10 );
269
306
Response resp = groupOnManyLongs (5000 );
270
307
Map <String , Object > map = responseAsMap (resp );
271
308
ListMatcher columns = matchesList ().item (matchesMap ().entry ("name" , "MAX(a)" ).entry ("type" , "long" ));
@@ -333,15 +370,15 @@ private Response concat(int evals) throws IOException {
333
370
*/
334
371
public void testManyConcat () throws IOException {
335
372
int strings = 300 ;
336
- initManyLongs ();
373
+ initManyLongs (10 );
337
374
assertManyStrings (manyConcat ("FROM manylongs" , strings ), strings );
338
375
}
339
376
340
377
/**
341
378
* Hits a circuit breaker by building many moderately long strings.
342
379
*/
343
380
public void testHugeManyConcat () throws IOException {
344
- initManyLongs ();
381
+ initManyLongs (10 );
345
382
// 2000 is plenty to break on most nodes
346
383
assertCircuitBreaks (attempt -> manyConcat ("FROM manylongs" , attempt * 2000 ));
347
384
}
@@ -412,15 +449,15 @@ private Map<String, Object> manyConcat(String init, int strings) throws IOExcept
412
449
*/
413
450
public void testManyRepeat () throws IOException {
414
451
int strings = 30 ;
415
- initManyLongs ();
452
+ initManyLongs (10 );
416
453
assertManyStrings (manyRepeat ("FROM manylongs" , strings ), 30 );
417
454
}
418
455
419
456
/**
420
457
* Hits a circuit breaker by building many moderately long strings.
421
458
*/
422
459
public void testHugeManyRepeat () throws IOException {
423
- initManyLongs ();
460
+ initManyLongs (10 );
424
461
// 75 is plenty to break on most nodes
425
462
assertCircuitBreaks (attempt -> manyRepeat ("FROM manylongs" , attempt * 75 ));
426
463
}
@@ -478,7 +515,7 @@ private void assertManyStrings(Map<String, Object> resp, int strings) throws IOE
478
515
}
479
516
480
517
public void testManyEval () throws IOException {
481
- initManyLongs ();
518
+ initManyLongs (10 );
482
519
Map <String , Object > response = manyEval (1 );
483
520
ListMatcher columns = matchesList ();
484
521
columns = columns .item (matchesMap ().entry ("name" , "a" ).entry ("type" , "long" ));
@@ -493,7 +530,7 @@ public void testManyEval() throws IOException {
493
530
}
494
531
495
532
public void testTooManyEval () throws IOException {
496
- initManyLongs ();
533
+ initManyLongs (10 );
497
534
// 490 is plenty to fail on most nodes
498
535
assertCircuitBreaks (attempt -> manyEval (attempt * 490 ));
499
536
}
@@ -808,24 +845,34 @@ private Map<String, Object> enrichExplosion(int sensorDataCount, int lookupEntri
808
845
}
809
846
}
810
847
811
- private void initManyLongs () throws IOException {
848
+ private void initManyLongs (int countPerLong ) throws IOException {
812
849
logger .info ("loading many documents with longs" );
813
850
StringBuilder bulk = new StringBuilder ();
814
- for (int a = 0 ; a < 10 ; a ++) {
815
- for (int b = 0 ; b < 10 ; b ++) {
816
- for (int c = 0 ; c < 10 ; c ++) {
817
- for (int d = 0 ; d < 10 ; d ++) {
818
- for (int e = 0 ; e < 10 ; e ++) {
851
+ int flush = 0 ;
852
+ for (int a = 0 ; a < countPerLong ; a ++) {
853
+ for (int b = 0 ; b < countPerLong ; b ++) {
854
+ for (int c = 0 ; c < countPerLong ; c ++) {
855
+ for (int d = 0 ; d < countPerLong ; d ++) {
856
+ for (int e = 0 ; e < countPerLong ; e ++) {
819
857
bulk .append (String .format (Locale .ROOT , """
820
858
{"create":{}}
821
859
{"a":%d,"b":%d,"c":%d,"d":%d,"e":%d}
822
860
""" , a , b , c , d , e ));
861
+ flush ++;
862
+ if (flush % 10_000 == 0 ) {
863
+ bulk ("manylongs" , bulk .toString ());
864
+ bulk .setLength (0 );
865
+ logger .info (
866
+ "flushing {}/{} to manylongs" ,
867
+ flush ,
868
+ countPerLong * countPerLong * countPerLong * countPerLong * countPerLong
869
+ );
870
+
871
+ }
823
872
}
824
873
}
825
874
}
826
875
}
827
- bulk ("manylongs" , bulk .toString ());
828
- bulk .setLength (0 );
829
876
}
830
877
initIndex ("manylongs" , bulk .toString ());
831
878
}
0 commit comments