CASSANDRA-21133 Make bin/sstableupgrade functionally on par with nodetool upgradesstables#4825
CASSANDRA-21133 Make bin/sstableupgrade functionally on par with nodetool upgradesstables#4825arvindKandpal-ksolves wants to merge 2 commits into
Conversation
…etool upgradesstables
| sstableIdGenerator.get()); | ||
| assert !newDescriptor.fileFor(Components.DATA).exists(); | ||
| Descriptor newDescriptor; | ||
| while (true) |
There was a problem hiding this comment.
this might not happen in practice but it is worth saying that there is no limit as in how many times we loop, if there is some buggy ID supplier or we exhausted the namespace of these ids and all were on disk then we would spin for ever. Currently we have sequence based generator on integer and UUID generator on ... uuid, the namespace is pretty much "infinite" in practical terms so this we will not hit it, one would have to have like ~2 billions sstables on disk to exhaust (and then it would start to overflow)
There was a problem hiding this comment.
Yeah, agreed. With ~2 billion for sequence IDs and practically infinite for UUIDs, we shouldn't ever hit an infinite loop in the real case. Thanks for pointing this out.
| } | ||
|
|
||
| @Test | ||
| public void testNewSSTableDescriptorCollision() throws Exception |
There was a problem hiding this comment.
just saying we are not testing UUID-based generator but I dont think doing that is the absolute must given how it behaves.
There was a problem hiding this comment.
if needed we can try to add , otherwise I also thought there is no absolute required.
| sstableIdGenerator.get()); | ||
| assert !newDescriptor.fileFor(Components.DATA).exists(); | ||
| Descriptor newDescriptor; | ||
| while (true) |
There was a problem hiding this comment.
I think that thread safety is just delegated to how sstableIdGenerator.get() returns the new id, right? That is AtomicInteger, hence increased atomically, so two threads calling this stuff will always have different ids to check the existence of a file against.
@arvindKandpal-ksolves could you put a comment on while(true) about this and that this loop is meant to be a defense against offline / online generation for tooling's sake instead of in-process flow?
There was a problem hiding this comment.
Yes, exactly. The atomic increment takes care of thread safety in-process. I've added a comment above the while(true) loop to explain that this is purely a defense against offline tool generation.
|
Hi @smiklosovic , I have addressed most of the points, Please take a look. |
|
Hi, I am a bit confused the the description/intention of the patch:
|
|
@netudima currently there is no check if a tool operates against Cassandra turned off or not. It just fails or the behavior is unpredictable, in general. I was commenting on that here. From my perspective this is the correct solution to disparity of the functionality regardless whether this tool is run against online or offline Cassandra. If you want to not make it functionally on par, then we should prevent offline tools to run against running Cassandra. to your 2) because both tools run same code, but offline tool runs in a completely different process and it cant see what Cassandra state is. Generators of IDs are isolated, per process. We need to allocate new ID but allocation of an ID in one process does not guarantee that it is not already taken by another process. |
|
ok, then the MR description seems incorrect and confusing from this point of view, it is not a new logic which we are trying to fix, it is an attempt to adjust the existing logic.
For me it looks as quite independent activity. I understand the danger of the current offline tools and agree that a protection is needed but it is not related to adding a new parameter.. Also I suppose the ID conflict is not only the issue and just adding the optimistic locking loop would not make the tool safe to use, you still have other issues like (but not limited to):
So, for me it is a kind of separate independent story with a proper design to check if DB process exists or to implement proper ability to execute the tool and DB process concurrently.., mixing it with an offline tool flag adding is a bit confusing (at least for me). |
|
Fair enough. Your opinion then renders this PR irrelevant and OP should try to direct his effort on the check there is a running process or not before offline tools are executed. I can image such an endeavour would cause issues where we run offline tools when Cassandra is online regardless and change of this behavior might be disruptive to the stuff we are not aware of yet. We would need to replace such usages with their online counterparts which might not necessarily exist. |
|
I would create a separate story about adding to offine tools a logic to check if Cassandra process is alive: using PID file or a file lock for example UPD: I have found one - https://issues.apache.org/jira/browse/CASSANDRA-9555 |
|
jut to be clear: my concern is only about the ad-hoc attempt to make offline tool working safe in parallel with a running Cassandra process (the id loop logic). I do not have a problem with the functional change about adding a new option to sstableupgrade if it was the main goal of the patch. |
Make bin/sstableupgrade functionally on par with nodetool upgradesstables
What this PR does / why we need it:
This PR brings functional parity between
bin/sstableupgradeandnodetool upgradesstablesby introducing the-a/--include-all-sstablesflag to the offline tool.Previously,
bin/sstableupgradewould automatically skip SSTables that were already on the latest version. This patch allows users to force a rewrite of all SSTables even if they are on the current format.Technical Details & Safety:
Adding this flag to an offline tool introduced a known edge case: If the offline tool is run while the Cassandra node is online, it consumes a new SSTable ID on disk. However, the live node's internal
sstableIdGeneratorremains unaware of this. Upon the next flush, the live node attempts to use the same ID, which previously triggered ajava.lang.AssertionErrorinColumnFamilyStore.newSSTableDescriptor().To safely resolve this without introducing regressions:
assert !newDescriptor.fileFor(Components.DATA).exists();check innewSSTableDescriptorwith a safewhile(true)loop. It checks if the generated ID already exists on disk. If a collision is detected, it logs a warning and advances the generator, self-healing the state.StandaloneUpgraderto parse and apply the-aoption consistently.testNewSSTableDescriptorCollision) inColumnFamilyStoreTestthat probes the current ID, usesSSTableIdFactoryto pre-create files for future IDs (N+1,N+2), and verifies that the loop correctly skips them and yieldsN+3.StandaloneUpgraderTest.sstableupgrade.adoc.patch by Arvind Kandpal; reviewed by TBD for CASSANDRA-21133