koo created CASSANDRA-21685:
-------------------------------

             Summary: Size calculation mismatch in EncodingStats and 
SerializationHeader local deletion time
                 Key: CASSANDRA-21685
                 URL: https://issues.apache.org/jira/browse/CASSANDRA-21685
             Project: Apache Cassandra
          Issue Type: Bug
            Reporter: koo


While working on CASSANDRA-21535, CompactionsCQLTest failed 
(testCompactionInvalidRowDeletion and testIndexedReaderRowDeletion). The cause 
is that some serializers calculate the size in a different way from how they 
write the value.
h3. Problem

In EncodingStats.Serializer, the write path casts the value to int, but the 
size path keeps it as long:

 
{code:java}
// serialize()
out.writeUnsignedVInt32((int)(stats.minLocalDeletionTime - 
DELETION_TIME_EPOCH));
// serializedSize()
TypeSizes.sizeofUnsignedVInt(stats.minLocalDeletionTime - DELETION_TIME_EPOCH)
{code}


SerializationHeader has the same pattern:

 
{code:java}
// writeLocalDeletionTime()
out.writeUnsignedVInt32((int) (localDeletionTime - stats.minLocalDeletionTime));
// localDeletionTimeSerializedSize()
TypeSizes.sizeofUnsignedVInt(localDeletionTime - stats.minLocalDeletionTime);
{code}
 

If the value fits in a signed int, both give the same result. But when 
minLocalDeletionTime holds an invalid or capped deletion time, the delta is 
around 2.85e9 and does not fit in a signed int:

* size path: sizeofUnsignedVInt(2852087294L) -> 5 bytes
* write path: the (int) cast wraps to -1442880002, and writeUnsignedVInt32 
sign-extends it -> 9 bytes

So serializedSize() returns a smaller value than the bytes actually written.
h3. Proposed fix

Apply the same (int) cast in the size calculation, in both 
EncodingStats.Serializer.serializedSize() and 
SerializationHeader.localDeletionTimeSerializedSize(). This makes the size 
match the written bytes. It does not change any serialized byte, so there is no 
compatibility impact.

This change does not fix the root problem described below. But I think it is 
still clearly useful on its own, because the calculated size should always 
match the actual bytes written. This is why I am opening this ticket separately.
h3. Out of scope

The written value itself does not round-trip. deserialize() reads it back with 
readUnsignedVInt32(), so the original value is not restored 
(minLocalDeletionTime comes back as -2).

Fixing this needs a change to the serialized format, which is used by both 
SSTables and messaging. So we would also need to handle compatibility with 
older versions and with data that is already written. I think the people who 
maintain the project over the long term should decide the policy for this, so I 
am leaving it out of this ticket.



--
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