|
46 | 46 | import java.util.concurrent.Executors; |
47 | 47 | import java.util.concurrent.Future; |
48 | 48 | import java.util.concurrent.ThreadLocalRandom; |
| 49 | +import java.util.stream.Collectors; |
49 | 50 | import org.apache.commons.lang3.StringUtils; |
50 | 51 | import org.apache.hadoop.conf.Configuration; |
51 | 52 | import org.apache.hadoop.conf.Configured; |
|
109 | 110 | import org.slf4j.Logger; |
110 | 111 | import org.slf4j.LoggerFactory; |
111 | 112 |
|
112 | | -import org.apache.hbase.thirdparty.com.google.common.base.MoreObjects; |
113 | 113 | import org.apache.hbase.thirdparty.com.google.common.util.concurrent.ThreadFactoryBuilder; |
114 | 114 | import org.apache.hbase.thirdparty.com.google.gson.Gson; |
115 | 115 |
|
@@ -348,37 +348,69 @@ public void setStatus(String msg) { |
348 | 348 | * opts.replicas}. |
349 | 349 | */ |
350 | 350 | static boolean checkTable(Admin admin, TestOptions opts) throws IOException { |
351 | | - TableName tableName = TableName.valueOf(opts.tableName); |
352 | | - boolean needsDelete = false, exists = admin.tableExists(tableName); |
353 | | - boolean isReadCmd = opts.cmdName.toLowerCase(Locale.ROOT).contains("read") |
| 351 | + final TableName tableName = TableName.valueOf(opts.tableName); |
| 352 | + final boolean exists = admin.tableExists(tableName); |
| 353 | + final boolean isReadCmd = opts.cmdName.toLowerCase(Locale.ROOT).contains("read") |
354 | 354 | || opts.cmdName.toLowerCase(Locale.ROOT).contains("scan"); |
355 | | - boolean isDeleteCmd = opts.cmdName.toLowerCase(Locale.ROOT).contains("delete"); |
356 | | - if (!exists && (isReadCmd || isDeleteCmd)) { |
| 355 | + final boolean isDeleteCmd = opts.cmdName.toLowerCase(Locale.ROOT).contains("delete"); |
| 356 | + final boolean needsData = isReadCmd || isDeleteCmd; |
| 357 | + if (!exists && needsData) { |
357 | 358 | throw new IllegalStateException( |
358 | | - "Must specify an existing table for read commands. Run a write command first."); |
| 359 | + "Must specify an existing table for read/delete commands. Run a write command first."); |
359 | 360 | } |
360 | 361 | HTableDescriptor desc = |
361 | 362 | exists ? admin.getTableDescriptor(TableName.valueOf(opts.tableName)) : null; |
362 | | - byte[][] splits = getSplits(opts); |
| 363 | + final byte[][] splits = getSplits(opts); |
363 | 364 |
|
364 | 365 | // recreate the table when user has requested presplit or when existing |
365 | 366 | // {RegionSplitPolicy,replica count} does not match requested, or when the |
366 | 367 | // number of column families does not match requested. |
367 | | - if ( |
368 | | - (exists && opts.presplitRegions != DEFAULT_OPTS.presplitRegions |
369 | | - && opts.presplitRegions != admin.getRegions(tableName).size()) |
370 | | - || (!isReadCmd && desc != null |
371 | | - && !StringUtils.equals(desc.getRegionSplitPolicyClassName(), opts.splitPolicy)) |
372 | | - || (!(isReadCmd || isDeleteCmd) && desc != null |
373 | | - && desc.getRegionReplication() != opts.replicas) |
374 | | - || (desc != null && desc.getColumnFamilyCount() != opts.families) |
375 | | - ) { |
376 | | - needsDelete = true; |
377 | | - // wait, why did it delete my table?!? |
378 | | - LOG.debug(MoreObjects.toStringHelper("needsDelete").add("needsDelete", needsDelete) |
379 | | - .add("isReadCmd", isReadCmd).add("exists", exists).add("desc", desc) |
380 | | - .add("presplit", opts.presplitRegions).add("splitPolicy", opts.splitPolicy) |
381 | | - .add("replicas", opts.replicas).add("families", opts.families).toString()); |
| 368 | + final boolean regionCountChanged = |
| 369 | + exists && opts.presplitRegions != DEFAULT_OPTS.presplitRegions |
| 370 | + && opts.presplitRegions != admin.getRegions(tableName).size(); |
| 371 | + final boolean splitPolicyChanged = |
| 372 | + exists && !StringUtils.equals(desc.getRegionSplitPolicyClassName(), opts.splitPolicy); |
| 373 | + final boolean regionReplicationChanged = exists && desc.getRegionReplication() != opts.replicas; |
| 374 | + final boolean columnFamilyCountChanged = exists && desc.getColumnFamilyCount() != opts.families; |
| 375 | + |
| 376 | + boolean needsDelete = regionCountChanged || splitPolicyChanged || regionReplicationChanged |
| 377 | + || columnFamilyCountChanged; |
| 378 | + |
| 379 | + if (needsDelete) { |
| 380 | + final List<String> errors = new ArrayList<>(); |
| 381 | + if (columnFamilyCountChanged) { |
| 382 | + final String error = String.format("--families=%d, but found %d column families", |
| 383 | + opts.families, desc.getColumnFamilyCount()); |
| 384 | + if (needsData) { |
| 385 | + // We can't proceed the test in this case |
| 386 | + throw new IllegalStateException( |
| 387 | + "Cannot proceed the test. Run a write command first: " + error); |
| 388 | + } |
| 389 | + errors.add(error); |
| 390 | + } |
| 391 | + if (regionCountChanged) { |
| 392 | + errors.add(String.format("--presplit=%d, but found %d regions", opts.presplitRegions, |
| 393 | + admin.getRegions(tableName).size())); |
| 394 | + } |
| 395 | + if (splitPolicyChanged) { |
| 396 | + errors.add(String.format("--splitPolicy=%s, but current policy is %s", opts.splitPolicy, |
| 397 | + desc.getRegionSplitPolicyClassName())); |
| 398 | + } |
| 399 | + if (regionReplicationChanged) { |
| 400 | + errors.add(String.format("--replicas=%d, but found %d replicas", opts.replicas, |
| 401 | + desc.getRegionReplication())); |
| 402 | + } |
| 403 | + final String reason = |
| 404 | + errors.stream().map(s -> '[' + s + ']').collect(Collectors.joining(", ")); |
| 405 | + |
| 406 | + if (needsData) { |
| 407 | + LOG.warn("Unexpected or incorrect options provided for {}. " |
| 408 | + + "Please verify whether the detected inconsistencies are expected or ignorable: {}. " |
| 409 | + + "The test will proceed, but the results may not be reliable.", opts.cmdName, reason); |
| 410 | + needsDelete = false; |
| 411 | + } else { |
| 412 | + LOG.info("Table will be recreated: " + reason); |
| 413 | + } |
382 | 414 | } |
383 | 415 |
|
384 | 416 | // remove an existing table |
|
0 commit comments