18
18
*/
19
19
package org .apache .accumulo .test .functional ;
20
20
21
+ import static org .apache .accumulo .core .manager .state .TabletManagement .ManagementAction .BAD_STATE ;
21
22
import static org .apache .accumulo .core .manager .state .TabletManagement .ManagementAction .NEEDS_LOCATION_UPDATE ;
23
+ import static org .apache .accumulo .core .manager .state .TabletManagement .ManagementAction .NEEDS_RECOVERY ;
24
+ import static org .apache .accumulo .core .manager .state .TabletManagement .ManagementAction .NEEDS_SPLITTING ;
25
+ import static org .apache .accumulo .core .manager .state .TabletManagement .ManagementAction .NEEDS_VOLUME_REPLACEMENT ;
22
26
import static org .junit .jupiter .api .Assertions .assertEquals ;
27
+ import static org .junit .jupiter .api .Assertions .assertTrue ;
23
28
24
29
import java .io .IOException ;
25
30
import java .time .Duration ;
@@ -187,6 +192,10 @@ public void test() throws AccumuloException, AccumuloSecurityException, TableExi
187
192
assertEquals (expected , findTabletsNeedingAttention (client , metaCopy1 , tabletMgmtParams ),
188
193
"Should have four tablets with hosting availability changes" );
189
194
195
+ // test continue scan functionality, this test needs a table and tablet mgmt params that will
196
+ // return more than one tablet
197
+ testContinueScan (client , metaCopy1 , tabletMgmtParams );
198
+
190
199
// test the assigned case (no location)
191
200
removeLocation (client , metaCopy1 , t3 );
192
201
expected =
@@ -210,18 +219,15 @@ public void test() throws AccumuloException, AccumuloSecurityException, TableExi
210
219
// Test the recovery cases
211
220
createLogEntry (client , metaCopy5 , t1 );
212
221
setTabletAvailability (client , metaCopy5 , t1 , TabletAvailability .UNHOSTED .name ());
213
- expected = Map .of (endR1 ,
214
- Set .of (NEEDS_LOCATION_UPDATE , TabletManagement .ManagementAction .NEEDS_RECOVERY ));
222
+ expected = Map .of (endR1 , Set .of (NEEDS_LOCATION_UPDATE , NEEDS_RECOVERY ));
215
223
assertEquals (expected , findTabletsNeedingAttention (client , metaCopy5 , tabletMgmtParams ),
216
224
"Only 1 of 2 tablets in table t1 should be returned" );
217
225
setTabletAvailability (client , metaCopy5 , t1 , TabletAvailability .ONDEMAND .name ());
218
- expected = Map .of (endR1 ,
219
- Set .of (NEEDS_LOCATION_UPDATE , TabletManagement .ManagementAction .NEEDS_RECOVERY ));
226
+ expected = Map .of (endR1 , Set .of (NEEDS_LOCATION_UPDATE , NEEDS_RECOVERY ));
220
227
assertEquals (expected , findTabletsNeedingAttention (client , metaCopy5 , tabletMgmtParams ),
221
228
"Only 1 of 2 tablets in table t1 should be returned" );
222
229
setTabletAvailability (client , metaCopy5 , t1 , TabletAvailability .HOSTED .name ());
223
- expected = Map .of (endR1 ,
224
- Set .of (NEEDS_LOCATION_UPDATE , TabletManagement .ManagementAction .NEEDS_RECOVERY ), prevR1 ,
230
+ expected = Map .of (endR1 , Set .of (NEEDS_LOCATION_UPDATE , NEEDS_RECOVERY ), prevR1 ,
225
231
Set .of (NEEDS_LOCATION_UPDATE ));
226
232
assertEquals (expected , findTabletsNeedingAttention (client , metaCopy5 , tabletMgmtParams ),
227
233
"2 tablets in table t1 should be returned" );
@@ -248,8 +254,7 @@ public void test() throws AccumuloException, AccumuloSecurityException, TableExi
248
254
// for both MERGING and SPLITTING
249
255
setOperationId (client , metaCopy4 , t4 , null , TabletOperationType .MERGING );
250
256
createLogEntry (client , metaCopy4 , t4 );
251
- expected = Map .of (endR4 ,
252
- Set .of (NEEDS_LOCATION_UPDATE , TabletManagement .ManagementAction .NEEDS_RECOVERY ));
257
+ expected = Map .of (endR4 , Set .of (NEEDS_LOCATION_UPDATE , NEEDS_RECOVERY ));
253
258
assertEquals (expected , findTabletsNeedingAttention (client , metaCopy4 , tabletMgmtParams ),
254
259
"Should have a tablet needing attention because of wals" );
255
260
// Switch op to SPLITTING which should also need attention like MERGING
@@ -266,8 +271,7 @@ public void test() throws AccumuloException, AccumuloSecurityException, TableExi
266
271
// test the bad tablet location state case (inconsistent metadata)
267
272
tabletMgmtParams = createParameters (client );
268
273
addDuplicateLocation (client , metaCopy3 , t3 );
269
- expected = Map .of (prevR3 ,
270
- Set .of (NEEDS_LOCATION_UPDATE , TabletManagement .ManagementAction .BAD_STATE ));
274
+ expected = Map .of (prevR3 , Set .of (NEEDS_LOCATION_UPDATE , BAD_STATE ));
271
275
assertEquals (expected , findTabletsNeedingAttention (client , metaCopy3 , tabletMgmtParams ),
272
276
"Should have 1 tablet that needs a metadata repair" );
273
277
@@ -278,7 +282,7 @@ public void test() throws AccumuloException, AccumuloSecurityException, TableExi
278
282
Map <Path ,Path > replacements =
279
283
Map .of (new Path ("file:/vol1/accumulo/inst_id" ), new Path ("file:/vol2/accumulo/inst_id" ));
280
284
tabletMgmtParams = createParameters (client , replacements );
281
- expected = Map .of (prevR4 , Set .of (TabletManagement . ManagementAction . NEEDS_VOLUME_REPLACEMENT ));
285
+ expected = Map .of (prevR4 , Set .of (NEEDS_VOLUME_REPLACEMENT ));
282
286
assertEquals (expected , findTabletsNeedingAttention (client , metaCopy4 , tabletMgmtParams ),
283
287
"Should have one tablet that needs a volume replacement" );
284
288
@@ -291,7 +295,7 @@ public void test() throws AccumuloException, AccumuloSecurityException, TableExi
291
295
// Lower the split threshold for the table, should cause the files added to need attention.
292
296
client .tableOperations ().setProperty (tables [3 ], Property .TABLE_SPLIT_THRESHOLD .getKey (),
293
297
"1K" );
294
- expected = Map .of (prevR4 , Set .of (TabletManagement . ManagementAction . NEEDS_SPLITTING ));
298
+ expected = Map .of (prevR4 , Set .of (NEEDS_SPLITTING ));
295
299
assertEquals (expected , findTabletsNeedingAttention (client , metaCopy6 , tabletMgmtParams ),
296
300
"Should have one tablet that needs splitting" );
297
301
@@ -444,6 +448,29 @@ private Map<KeyExtent,Set<TabletManagement.ManagementAction>> findTabletsNeeding
444
448
return results ;
445
449
}
446
450
451
+ // Multiple places in the accumulo code will read a batch of keys and then take the last key and
452
+ // make it non inclusive to get the next batch. This test code simulates that and ensures the
453
+ // tablet mgmt iterator works with that.
454
+ private void testContinueScan (AccumuloClient client , String table ,
455
+ TabletManagementParameters tabletMgmtParams ) throws TableNotFoundException {
456
+ try (Scanner scanner = client .createScanner (table , Authorizations .EMPTY )) {
457
+ TabletManagementIterator .configureScanner (scanner , tabletMgmtParams );
458
+ List <Entry <Key ,Value >> entries1 = new ArrayList <>();
459
+ scanner .forEach (e -> entries1 .add (e ));
460
+ assertTrue (entries1 .size () > 1 );
461
+
462
+ // Create a range that does not include the first key from the last scan.
463
+ var range = new Range (entries1 .get (0 ).getKey (), false , null , true );
464
+ scanner .setRange (range );
465
+
466
+ // Ensure the first key excluded from the scan
467
+ List <Entry <Key ,Value >> entries2 = new ArrayList <>();
468
+ scanner .forEach (e -> entries2 .add (e ));
469
+ assertEquals (entries1 .size () - 1 , entries2 .size ());
470
+ assertEquals (entries1 .get (1 ).getKey (), entries2 .get (0 ).getKey ());
471
+ }
472
+ }
473
+
447
474
private void createTable (AccumuloClient client , String t , boolean online )
448
475
throws AccumuloSecurityException , AccumuloException , TableNotFoundException ,
449
476
TableExistsException {
0 commit comments