diff --git a/api/id/id.go b/api/id/id.go index 9f6d3a4b9..dc71ec3e6 100644 --- a/api/id/id.go +++ b/api/id/id.go @@ -11,7 +11,7 @@ type Id [16]byte var ( machineID uint64 - counter uint64 + counter uint32 ) // SetMachineId may only be called by one thread before any id generation @@ -45,11 +45,15 @@ func SetMachineIdHost(addr net.IP, port uint16) { // Ids are sortable within (not between, thanks to clocks) each machine, with // a modified base32 encoding exposed for convenience in API usage. func New() Id { - var id Id t := time.Now() // NOTE compiler optimizes out division by constant for us ms := uint64(t.Unix())*1000 + uint64(t.Nanosecond()/int(time.Millisecond)) - count := atomic.AddUint64(&counter, 1) + count := atomic.AddUint32(&counter, 1) + return newID(ms, machineID, count) +} + +func newID(ms, machineID uint64, count uint32) Id { + var id Id id[0] = byte(ms >> 40) id[1] = byte(ms >> 32) @@ -58,14 +62,13 @@ func New() Id { id[4] = byte(ms >> 8) id[5] = byte(ms) - id[6] = byte(machineID >> 12) - id[7] = byte(machineID >> 4) + id[6] = byte(machineID >> 40) + id[7] = byte(machineID >> 32) + id[8] = byte(machineID >> 24) + id[9] = byte(machineID >> 16) + id[10] = byte(machineID >> 8) + id[11] = byte(machineID) - id[8] = byte(machineID<<4) | byte((count<<4)>>60) - - id[9] = byte(count >> 48) - id[10] = byte(count >> 40) - id[11] = byte(count >> 32) id[12] = byte(count >> 24) id[13] = byte(count >> 16) id[14] = byte(count >> 8) diff --git a/api/id/id_test.go b/api/id/id_test.go index a21f21cec..136b7ceb9 100644 --- a/api/id/id_test.go +++ b/api/id/id_test.go @@ -1,7 +1,12 @@ package id import ( + "encoding/binary" + "fmt" + "math" + "net" "testing" + "time" ) func BenchmarkGen(b *testing.B) { @@ -28,3 +33,31 @@ func BenchmarkUnmarshalText(b *testing.B) { _ = id } } + +func TestIdRaw(t *testing.T) { + SetMachineIdHost(net.IP{127, 0, 0, 1}, 8080) + + ts := time.Now() + ms := uint64(ts.Unix())*1000 + uint64(ts.Nanosecond()/int(time.Millisecond)) + count := uint32(math.MaxUint32) + id := newID(ms, machineID, count) + fmt.Println(len(id), id) + + var buf [8]byte + copy(buf[2:], id[:6]) + idTime := binary.BigEndian.Uint64(buf[:]) + if ms != idTime { + t.Fatal("id time doesn't not match time given", ms, idTime) + } + + copy(buf[2:], id[6:12]) + idMid := binary.BigEndian.Uint64(buf[:]) + if idMid != machineID { + t.Fatal("machine id mismatch", idMid, machineID) + } + + idCount := binary.BigEndian.Uint32(id[12:16]) + if idCount != count { + t.Fatal("count mismatch", idCount, count) + } +}