|
42 | 42 | import org.apache.accumulo.core.clientImpl.ClientContext;
|
43 | 43 | import org.apache.accumulo.core.data.ByteSequence;
|
44 | 44 | import org.apache.accumulo.core.data.Key;
|
| 45 | +import org.apache.accumulo.core.data.PartialKey; |
| 46 | +import org.apache.accumulo.core.data.Range; |
45 | 47 | import org.apache.accumulo.core.data.TableId;
|
46 | 48 | import org.apache.accumulo.core.data.Value;
|
47 | 49 | import org.apache.accumulo.core.dataImpl.KeyExtent;
|
@@ -558,6 +560,58 @@ private static Optional<TServerInstance> checkServer(ClientContext context, Stri
|
558 | 560 | .map(address -> new TServerInstance(address, stat.getEphemeralOwner()));
|
559 | 561 | }
|
560 | 562 |
|
| 563 | + public static void validate(TabletMetadata tm) { |
| 564 | + if (tm == null) { |
| 565 | + throw new IllegalStateException("TabletMetadata cannot be null"); |
| 566 | + } |
| 567 | + |
| 568 | + Text prevEndRowText = tm.getPrevEndRow(); |
| 569 | + Text endRowText = tm.getEndRow(); |
| 570 | + |
| 571 | + // Allow validation even if prevEndRow is missing, as long as endRowText exists |
| 572 | + Key prevEndRowKey = (prevEndRowText != null) ? new Key(prevEndRowText) : null; |
| 573 | + Key endRowKey = (endRowText != null) ? new Key(endRowText) : null; |
| 574 | + |
| 575 | + Collection<StoredTabletFile> files = tm.getFiles(); |
| 576 | + if (files == null || files.isEmpty()) { |
| 577 | + return; |
| 578 | + } |
| 579 | + |
| 580 | + for (StoredTabletFile file : files) { |
| 581 | + if (!isFileRangeValid(file, prevEndRowKey, endRowKey)) { |
| 582 | + throw new IllegalStateException("File range " + file.getRange() |
| 583 | + + " is inconsistent with tablet range [" + prevEndRowText + ", " + endRowText + "]"); |
| 584 | + } |
| 585 | + } |
| 586 | + } |
| 587 | + |
| 588 | + private static boolean isFileRangeValid(StoredTabletFile file, Key prevEndRowKey, Key endRowKey) { |
| 589 | + Range fileRange = file.getRange(); |
| 590 | + |
| 591 | + if (fileRange == null) { |
| 592 | + return false; |
| 593 | + } |
| 594 | + |
| 595 | + Key fileStartKey = fileRange.getStartKey(); |
| 596 | + Key fileEndKey = fileRange.getEndKey(); |
| 597 | + |
| 598 | + // If start key is null, assume it starts at the beginning of the tablet |
| 599 | + if (fileStartKey == null) { |
| 600 | + fileStartKey = prevEndRowKey != null ? prevEndRowKey.followingKey(PartialKey.ROW) : null; |
| 601 | + } |
| 602 | + |
| 603 | + if (fileEndKey == null) { |
| 604 | + fileEndKey = endRowKey; |
| 605 | + } |
| 606 | + |
| 607 | + if (prevEndRowKey != null |
| 608 | + && fileStartKey.compareTo(prevEndRowKey.followingKey(PartialKey.ROW)) < 0) { |
| 609 | + return false; // File starts before the valid range |
| 610 | + } |
| 611 | + return endRowKey == null || fileEndKey.compareTo(endRowKey) <= 0; // File extends beyond the |
| 612 | + // tablet's end row |
| 613 | + } |
| 614 | + |
561 | 615 | static class Builder {
|
562 | 616 | private TableId tableId;
|
563 | 617 | private Text prevEndRow;
|
|
0 commit comments