-
Notifications
You must be signed in to change notification settings - Fork 25.3k
Fixes ByteSizeValue to serialise correctly #27702
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
jenkins please retest this |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left a few comments.
if (out.getVersion().before(Version.V_6_2_0)) { | ||
out.writeVLong(getBytes()); | ||
} else { | ||
out.writeZLong(getBytes()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can do better here? Write out the bytes and write out the unit and read them on de-serialization to preserve the unit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. see 74273ea
if (size <= 0) { | ||
return String.valueOf(size); | ||
} | ||
return getBytes() + ByteSizeUnit.BYTES.getSuffix(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not size
and unit
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can do this but to maintain backward compatibility I think we need to keep the parse method converting the unit to bytes for 6.x and can only make it keep the unit in a followup PR for only the master branch. It also means that we can't compare the string representations in BizeSizeValueTests#testParse
[1] since the parsed version will always be in bytes but the original will be in any unit. I think this is ok because we chack the original and the parsed version are equal but I wanted to point it out. Does this sound ok to you? (see 74273ea)
[1] https://github.com/elastic/elasticsearch/pull/27702/files#diff-6be961ed1a7543ed4fff562bef6b5680R240
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I think I have got a bwc to change the parsing to preserve the unit as well. To keep it bwc I've made it revert to converting the unit to bytes if the input value is fractional. see f00c3bf
@jasontedor I pushed a couple of commits to address your comments. Could you take another look? |
jenkins retest this |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left some questions but the change looks good.
@@ -105,26 +134,33 @@ public double getPbFrac() { | |||
return ((double) getBytes()) / ByteSizeUnit.C5; | |||
} | |||
|
|||
public String getStringRep() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add javadocs to explain how this differs from toString()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, see ad16a5c
if (size > Long.MAX_VALUE / unit.toBytes(1)) { | ||
throw new IllegalArgumentException( | ||
"Values greater than " + Long.MAX_VALUE + " bytes are not supported: " + size + unit.getSuffix()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should it also fail if size is < -1 or if size == -1 and unit != BYTES?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, see ad16a5c
@jpountz @jasontedor thanks for the reviews. I've addressed the last review comments and will merge this when I get a green build |
}; | ||
|
||
FsInfo.Path[] node3FSInfo = new FsInfo.Path[] { | ||
new FsInfo.Path("/most", "/dev/sda", 100, 90, 70), | ||
new FsInfo.Path("/least", "/dev/sda", 10, -8, 0), | ||
new FsInfo.Path("/least", "/dev/sda", 10, -1, 0), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jasontedor this is the test I am unsure about. It failed when I added code to reject negative bytes values (expect the special -1 value) because this test explicitly checked that negative values for disk stats were accepted but the disk is skipped. From looking at FSProbe#L143 which is where we gather the disk statistics it seems that we can't actually get negative values here and instead any value reported by the OS as negative are interpreted by FSProbe as an overflow and are converted to Long.MAX_VALUE
.
I changed this test to use the special -1 value instead and check the disks are still skipped but maybe we actually don't need this test at all?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, the test was doing unrealistic things so I am fine with the change you made here. Let's keep whether or not the test is needed as a separate issue. There's probably other cleanup to do here, like adding asserts in FsInfo.Path about not seeing negative values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
jenkins test this please |
This fix makes a few fixes to ByteSizeValue to make it possible to perform round-trip serialisation: * Changes wire serialisation to use Zlong methods instead of VLong methods. This is needed because the value `-1` is accepted but previously if `-1` is supplied it cannot be serialised using the wire protocol. * Limits the supplied size to be no more than Long.MAX_VALUE when converted to bytes. Previously values greater than Long.MAX_VALUE bytes were accepted but would be silently interpreted as Long.MAX_VALUE bytes rather than erroring so the user had no idea the value was not being used the way they had intended. I consider this a bug and so fine to include this bug fix in a minor version but I am open to other points of view. * Adds a `getStringRep()` method that can be used when serialising the value to JSON. This will print the bytes value if the size is positive, `”0”` if the size is `0` and `”-1”` if the size is `-1`. * Adds logic to detect fractional values when parsing from a String and emits a deprecation warning in this case. * Modifies hashCode and equals methods to work with long values rather than doubles so they don’t run into precision problems when dealing with large values. Previous to this change the equals method would not detect small differences in the values (e.g. 1-1000 bytes ranges) if the actual values where very large (e.g. PBs). This was due to the values being in the order of 10^18 but doubles only maintaining a precision of ~10^15. Closes #27568
This should be bwc since in the case that the input is fractional it reverts back to the old method of parsing it to the bytes value.
This will be changed to 6.2 when the fix has been backported
* Fixes ByteSizeValue to serialise correctly This fix makes a few fixes to ByteSizeValue to make it possible to perform round-trip serialisation: * Changes wire serialisation to use Zlong methods instead of VLong methods. This is needed because the value `-1` is accepted but previously if `-1` is supplied it cannot be serialised using the wire protocol. * Limits the supplied size to be no more than Long.MAX_VALUE when converted to bytes. Previously values greater than Long.MAX_VALUE bytes were accepted but would be silently interpreted as Long.MAX_VALUE bytes rather than erroring so the user had no idea the value was not being used the way they had intended. I consider this a bug and so fine to include this bug fix in a minor version but I am open to other points of view. * Adds a `getStringRep()` method that can be used when serialising the value to JSON. This will print the bytes value if the size is positive, `”0”` if the size is `0` and `”-1”` if the size is `-1`. * Adds logic to detect fractional values when parsing from a String and emits a deprecation warning in this case. * Modifies hashCode and equals methods to work with long values rather than doubles so they don’t run into precision problems when dealing with large values. Previous to this change the equals method would not detect small differences in the values (e.g. 1-1000 bytes ranges) if the actual values where very large (e.g. PBs). This was due to the values being in the order of 10^18 but doubles only maintaining a precision of ~10^15. Closes #27568 * Fix bytes settings default value to not use fractional values * Fixes test * Addresses review comments * Modifies parsing to preserve unit This should be bwc since in the case that the input is fractional it reverts back to the old method of parsing it to the bytes value. * Addresses more review comments * Fixes tests * Temporarily changes version check to 7.0.0 This will be changed to 6.2 when the fix has been backported
This reverts commit c355677.
* Fixes ByteSizeValue to serialise correctly This fix makes a few fixes to ByteSizeValue to make it possible to perform round-trip serialisation: * Changes wire serialisation to use Zlong methods instead of VLong methods. This is needed because the value `-1` is accepted but previously if `-1` is supplied it cannot be serialised using the wire protocol. * Limits the supplied size to be no more than Long.MAX_VALUE when converted to bytes. Previously values greater than Long.MAX_VALUE bytes were accepted but would be silently interpreted as Long.MAX_VALUE bytes rather than erroring so the user had no idea the value was not being used the way they had intended. I consider this a bug and so fine to include this bug fix in a minor version but I am open to other points of view. * Adds a `getStringRep()` method that can be used when serialising the value to JSON. This will print the bytes value if the size is positive, `”0”` if the size is `0` and `”-1”` if the size is `-1`. * Adds logic to detect fractional values when parsing from a String and emits a deprecation warning in this case. * Modifies hashCode and equals methods to work with long values rather than doubles so they don’t run into precision problems when dealing with large values. Previous to this change the equals method would not detect small differences in the values (e.g. 1-1000 bytes ranges) if the actual values where very large (e.g. PBs). This was due to the values being in the order of 10^18 but doubles only maintaining a precision of ~10^15. Closes #27568 * Fix bytes settings default value to not use fractional values * Fixes test * Addresses review comments * Modifies parsing to preserve unit This should be bwc since in the case that the input is fractional it reverts back to the old method of parsing it to the bytes value. * Addresses more review comments * Fixes tests * Temporarily changes version check to 7.0.0 This will be changed to 6.2 when the fix has been backported
Backport to 6.x is done but leaving the label as a reminder to change the bwc version on master to 6.2.0 once the builds have caught up with the backport |
@colings86 I went ahead and pushed 54b1fed to correct the bwc version on master because I think mixed cluster tests were failing, hope this was okay. Can you check briefly. |
@cbuescher thanks for doing that. |
We deprecated fractional byte size values in 6.2 with PR #27702 However, we didn't add a related item to the 6.2 deprecation docs. This adds the missing item to the 7.15 deprecation docs.
This fix makes a few fixes to ByteSizeValue to make it possible to perform round-trip serialisation:
-1
is accepted but previously if-1
is supplied it cannot be serialised using the wire protocol.getStringRep()
method that can be used when serialising the value to JSON. This will print the bytes value if the size is positive,”0”
if the size is0
and”-1”
if the size is-1
.Closes #27568