|
47 | 47 | import com.google.common.annotations.VisibleForTesting; |
48 | 48 | import com.google.common.base.Preconditions; |
49 | 49 | import com.google.common.base.Predicates; |
50 | | -import com.google.common.collect.ArrayListMultimap; |
51 | 50 | import com.google.common.collect.Collections2; |
52 | 51 | import com.google.common.collect.ConcurrentHashMultiset; |
53 | 52 | import com.google.common.collect.ImmutableList; |
@@ -577,8 +576,10 @@ private AllSSTableOpStatus parallelAllSSTableOperation(final ColumnFamilyStore c |
577 | 576 | if (compacting == null) |
578 | 577 | return AllSSTableOpStatus.UNABLE_TO_CANCEL; |
579 | 578 |
|
580 | | - Iterable<SSTableReader> sstables = Lists.newArrayList(operation.filterSSTables(compacting)); |
581 | | - if (Iterables.isEmpty(sstables)) |
| 579 | + List<SSTableReader> sstables = Lists.newArrayList(operation.filterSSTables(compacting)); |
| 580 | + int originalCount = compacting.originals().size(); |
| 581 | + int processedCount = sstables.size(); |
| 582 | + if (sstables.isEmpty()) |
582 | 583 | { |
583 | 584 | logger.info("No sstables to {} for {}.{}", operationName, keyspace, table); |
584 | 585 | return AllSSTableOpStatus.SUCCESSFUL; |
@@ -610,7 +611,13 @@ public Object call() throws Exception |
610 | 611 | } |
611 | 612 | } |
612 | 613 | FBUtilities.waitOnFutures(futures); |
613 | | - assert compacting.originals().isEmpty(); |
| 614 | + // For full-set operations processedCount == originalCount, so compacting.originals() |
| 615 | + // is empty here; for user-defined / partial operations the un-touched sstables stay |
| 616 | + // in compacting.originals(). Either way the count must shrink by exactly what we |
| 617 | + // split out. |
| 618 | + assert compacting.originals().size() == originalCount - processedCount |
| 619 | + : String.format("originals=%d, expected %d after processing %d sstables", |
| 620 | + compacting.originals().size(), originalCount - processedCount, processedCount); |
614 | 621 | logger.info("Finished {} for {}.{} successfully", operationType, keyspace, table); |
615 | 622 | return AllSSTableOpStatus.SUCCESSFUL; |
616 | 623 | } |
@@ -839,7 +846,19 @@ public void execute(LifecycleTransaction txn) throws IOException |
839 | 846 | }, jobs, OperationType.CLEANUP); |
840 | 847 | } |
841 | 848 |
|
842 | | - public AllSSTableOpStatus performGarbageCollection(final ColumnFamilyStore cfStore, TombstoneOption tombstoneOption, int jobs) throws InterruptedException, ExecutionException |
| 849 | + public AllSSTableOpStatus performGarbageCollection(ColumnFamilyStore cfStore, TombstoneOption tombstoneOption, int jobs) |
| 850 | + { |
| 851 | + return performGarbageCollection(cfStore, tombstoneOption, jobs, descriptor -> true); |
| 852 | + } |
| 853 | + |
| 854 | + public AllSSTableOpStatus performGarbageCollection(ColumnFamilyStore cfStore, TombstoneOption tombstoneOption, int jobs, Collection<Descriptor> dataFiles) |
| 855 | + { |
| 856 | + Set<Descriptor> files = new HashSet<>(dataFiles); |
| 857 | + return performGarbageCollection(cfStore, tombstoneOption, jobs, files::contains); |
| 858 | + } |
| 859 | + |
| 860 | + @VisibleForTesting |
| 861 | + AllSSTableOpStatus performGarbageCollection(ColumnFamilyStore cfStore, TombstoneOption tombstoneOption, int jobs, Predicate<Descriptor> allowedFile) |
843 | 862 | { |
844 | 863 | assert !cfStore.isIndex(); |
845 | 864 |
|
@@ -877,12 +896,14 @@ public Iterable<SSTableReader> filterSSTables(LifecycleTransaction transaction) |
877 | 896 | filteredSSTables.addAll(transaction.originals()); |
878 | 897 | } |
879 | 898 |
|
880 | | - filteredSSTables.sort(SSTableReader.maxTimestampAscending); |
881 | | - return filteredSSTables; |
| 899 | + return filteredSSTables.stream() |
| 900 | + .filter(reader -> allowedFile.test(reader.descriptor)) |
| 901 | + .sorted(SSTableReader.maxTimestampAscending) |
| 902 | + .collect(Collectors.toList()); |
882 | 903 | } |
883 | 904 |
|
884 | 905 | @Override |
885 | | - public void execute(LifecycleTransaction txn) throws IOException |
| 906 | + public void execute(LifecycleTransaction txn) |
886 | 907 | { |
887 | 908 | logger.debug("Garbage collecting {}", txn.originals()); |
888 | 909 | CompactionTask task = new CompactionTask(cfStore, txn, getDefaultGcBefore(cfStore, FBUtilities.nowInSeconds())) |
@@ -1334,22 +1355,7 @@ private static Collection<SSTableReader> sstablesWithKeys(ColumnFamilyStore cfs, |
1334 | 1355 | @Override |
1335 | 1356 | public void forceUserDefinedCompaction(String dataFiles) |
1336 | 1357 | { |
1337 | | - String[] filenames = dataFiles.split(","); |
1338 | | - Multimap<ColumnFamilyStore, Descriptor> descriptors = ArrayListMultimap.create(); |
1339 | | - |
1340 | | - for (String filename : filenames) |
1341 | | - { |
1342 | | - // extract keyspace and columnfamily name from filename |
1343 | | - Descriptor desc = Descriptor.fromFileWithComponent(new File(filename.trim()), false).left; |
1344 | | - if (Schema.instance.getTableMetadataRef(desc) == null) |
1345 | | - { |
1346 | | - logger.warn("Schema does not exist for file {}. Skipping.", filename); |
1347 | | - continue; |
1348 | | - } |
1349 | | - // group by keyspace/columnfamily |
1350 | | - ColumnFamilyStore cfs = Keyspace.open(desc.ksname).getColumnFamilyStore(desc.cfname); |
1351 | | - descriptors.put(cfs, cfs.getDirectories().find(new File(filename.trim()).name())); |
1352 | | - } |
| 1358 | + Multimap<ColumnFamilyStore, Descriptor> descriptors = Descriptor.fromFilenamesGrouped(Arrays.asList(dataFiles.split(","))); |
1353 | 1359 |
|
1354 | 1360 | List<Future<?>> futures = new ArrayList<>(descriptors.size()); |
1355 | 1361 | long nowInSec = FBUtilities.nowInSeconds(); |
|
0 commit comments