Skip to content

Variant V7 #48

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

Merged
merged 6 commits into from
Jul 1, 2022
Merged

Variant V7 #48

merged 6 commits into from
Jul 1, 2022

Conversation

Hellblazer
Copy link
Contributor

@Hellblazer Hellblazer commented Jun 15, 2022

Implements #46.

public synchronized long getTimestamp()
public long getTimestamp()
{
return getTimestamp(kClockOffset);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

took the synchronized off and just punt to the protected version with the Gregorian offset

* timestamp source - the number of milliseconds seconds since midnight 1 Jan 1970 UTC,
* leap seconds excluded
*/
public long getTimestampV7()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new timestamp for variant 7

return getTimestamp(0);
}

protected synchronized long getTimestamp(long offset)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original timestamp method, with the offset passed in

int midhi = (clockHi << 16) | (clockHi >>> 16);
final byte[] b = new byte[2];
_random.nextBytes(b);
midhi = midhi | (((b[0] & 0xFF) << 8) + (b[1] & 0xFF));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My brain is turned to mush from advanced age, so hopefully this is correct.

// and reconstruct
long l1 = (((long) clockLo) << 32) | midhiL;
// last detail: must force 2 MSB to be '10'
long _uuidL2;
Copy link
Contributor Author

@Hellblazer Hellblazer Jun 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spec talks about the "variant" here in the 2 msb of this long, but I couldn't find what to use.

not sure how you managed to keep your mind when originally implementing this stuff.

// and reconstruct
long l1 = (((long) clockLo) << 32) | midhiL;
// last detail: must force 2 MSB to be '10'
long _uuidL2 = _toLong(buffer, 2);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

include variant?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That 2-bit var is a mystery to me... I don't get what that is, after reading and re-reading the spec. There's separate 4-bit version already so... what is this 2-bit thing. :-/

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to future self: "variant" is 0x10 as per:

https://www.rfc-editor.org/rfc/rfc4122#section-4.1.1

and remains the same from the earlier spec. So that's all good. Although new code does the right thing and calls UUIDUtil.constructUUID with type so it all gets set properly.

Still fails because I am an idiot when it comes to bit twiddling
@Override
public UUID generate()
{
final long rawTimestamp = _timer.getTimestampV7();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cowtowncoder I am still a moron when it comes to bit twiddling. Have no idea what I'm doing wrong here ;)

I've fallen and I can't get up

// first we'll collect the UUID time stamp which is
// the number of 100-nanosecond intervals since
// 00:00:00.00 15 October 1582
long uuid_time = 0L;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think this is correct, but...

checkUUIDArrayForUniqueness(uuid_array);

// check that all uuids have timestamps between the start and end time
// checkUUIDArrayForCorrectCreationTimeEpoch(uuid_array, start_time, end_time);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uncomment when my sanity is restored

@cowtowncoder
Copy link
Owner

Ok thanks; hope to read this later today... sounds like there may be quite a bit to digest again :)

@Hellblazer
Copy link
Contributor Author

No worries. I’m likely just doing something obviously silly.

{
// we need to convert from 100-nanosecond units (as used in UUIDs)
// to millisecond units as used in UTC based time
final long MILLI_CONVERSION_FACTOR = 10000L;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, no, Variant 7 uses time value in milliseconds, not 100 nsec (unlike variants 1 and 6)

@cowtowncoder
Copy link
Owner

Ok, so, my head is hurting wrt bit/byte shuffling code so I'll check that another day.

But I did notice one problem: code assumes that Variant 7 uses 100nsec granularity, like existing time-based variant 1 (and new 6). But as far as I can read, spec says that V7 uses millisecond granularity for simplicity. This is the reason why those 12 bits of randomness are needed to pad up things.

So, this complicates changes to UUIDTimer a bit; it may be that getTimestamp() method just needs to be mostly copied into getTimestampV7(). That's not a big deal I am guessing. But refactoring it to minimize duplication may result in more awkward code.

Other than that looks good; I hope to look more into this within next couple days; at latest on Juneteenth when I might have a Free OSS Coding Day for a change. :)

@Hellblazer
Copy link
Contributor Author

Think this should be correct now.

@Override
public UUID generate()
{
ByteBuffer buff = ByteBuffer.allocate(2 * 8);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

taking the cowards way out with a byte buffer

@cowtowncoder
Copy link
Owner

@Hellblazer I do believe this is correct! Good job & apologies once again for unreliable follow-up.
I'll try to re-re-read once over and the only thing I'll probably try to change is figure out how that Random sharing ought to work. But that's a trivial detail.

@cowtowncoder cowtowncoder merged commit c2424e8 into cowtowncoder:master Jul 1, 2022
buff.position(6);
buff.put(buffer);
buff.position(0);
buff.putLong(rawTimestamp << 16);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah. I think this would overwrite bytes #6 and #7, so need to reverse the order.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants