[ 
https://issues.apache.org/jira/browse/CASSANDRA-16772?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18114516#comment-18114516
 ] 

Mykyta Bozhenko commented on CASSANDRA-16772:
---------------------------------------------

Patch: https://github.com/apache/cassandra/pull/5153

The grouping map is HashMap<ColumnFamilyStore, Descriptor>, so when several 
files of the same table are passed, each put overwrites the previous one and 
only the last file is cleaned; the rest are dropped without a warning. The 
patch uses Descriptor.fromFilenamesGrouped(), the Multimap helper you pointed 
at, which forceUserDefinedCompaction already uses, and iterates every 
descriptor per table. Two small things in the same method: the isJoined() check 
moves ahead of filename parsing, and a null transaction from tryModify (the 
SSTable is already compacting) is logged and skipped instead of being 
dereferenced.

Test: a two-token ring where the local node owns three of six partitions and 
three SSTables hold two partitions each; cleanup is requested for two of them. 
Both requested originals must be replaced by outputs containing exactly the 
owned partition, and the third SSTable must stay untouched. Against unpatched 
production it fails with "Requested original must be replaced: .../pa-1-big", 
i.e. the first requested file is left alone.

You noted in 2021 that forceUserDefinedCleanup is not wired to nodetool and may 
be dead code. I checked trunk: there is still no production caller, it is 
reachable only over JMX through CompactionManagerMBean. So the more useful 
question may be whether this should be fixed or removed; the patch is there 
either way.

> User Defined nodetool cleanup only processes one SSTable per table
> ------------------------------------------------------------------
>
>                 Key: CASSANDRA-16772
>                 URL: https://issues.apache.org/jira/browse/CASSANDRA-16772
>             Project: Apache Cassandra
>          Issue Type: Bug
>          Components: Local/SSTable
>            Reporter: Scott Carey
>            Assignee: Scott Carey
>            Priority: Normal
>             Fix For: 3.11.x
>
>          Time Spent: 10m
>  Remaining Estimate: 0h
>
> User defined nodetool cleanup uses a HashMap instead of a MultiMap to group 
> the user provided SSTables by table.  This means it only keeps one file per 
> source table.
> It also means the unit test for this component is not sufficient.
> As part of https://issues.apache.org/jira/browse/CASSANDRA-16767  I 
> introduced a helper method on Descriptor:
> {code:java}
> public static Multimap<ColumnFamilyStore, Descriptor> 
> fromFilenamesGrouped(Collection<String> filenames) {code}
> That should be used instead of the custom logic in 
> CompactionManager.forceUserDefinedCleanup.
>  
> Broken existing code:
> {code:java}
>         HashMap<ColumnFamilyStore, Descriptor> descriptors = 
> Maps.newHashMap();        for (String filename : filenames)
>         {
>             // extract keyspace and columnfamily name from filename
>             Descriptor desc = Descriptor.fromFilename(filename.trim());
>             if (Schema.instance.getCFMetaData(desc) == null)
>             {
>                 logger.warn("Schema does not exist for file {}. Skipping.", 
> filename);
>                 continue;
>             }
>             // group by keyspace/columnfamily
>             ColumnFamilyStore cfs = 
> Keyspace.open(desc.ksname).getColumnFamilyStore(desc.cfname);
>             desc = cfs.getDirectories().find(new 
> File(filename.trim()).getName());
>             if (desc != null)
>                 descriptors.put(cfs, desc);
>         } {code}
>  
> Contents of helper method introduced in other ticket:
> {code:java}
>  public static Multimap<ColumnFamilyStore, Descriptor> 
> fromFilenamesGrouped(Collection<String> filenames) {
>       Multimap<ColumnFamilyStore, Descriptor> descriptors = 
> ArrayListMultimap.create();      for (String filename : filenames)
>       {
>           // extract keyspace and columnfamily name from filename
>           Descriptor desc = Descriptor.fromFilename(filename.trim());
>           if (Schema.instance.getCFMetaData(desc) == null)
>           {
>               logger.warn("Schema does not exist for file {}. Skipping.", 
> filename);
>               continue;
>           }
>           // group by keyspace/columnfamily
>           ColumnFamilyStore cfs = 
> Keyspace.open(desc.ksname).getColumnFamilyStore(desc.cfname);
>           desc = cfs.getDirectories().find(new 
> File(filename.trim()).getName());
>           if (desc != null)
>             descriptors.put(cfs, desc);
>       }
>       return descriptors;
>     } {code}



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to