Пример #1
0
// Newx returns a NONSTANDARD UUID(lower probability of conflict).
func Newx() (uuid [16]byte) {
	var (
		timestamp = uuidTimestamp()
		sequence  uint32
	)

	gxMutex.Lock() // Lock
	switch {
	case timestamp > gxLastTimestamp:
		sequence = gxSequenceStart
		gxLastTimestamp = timestamp
		gxLastSequence = sequence
		gxMutex.Unlock() // Unlock
	case timestamp == gxLastTimestamp:
		sequence = (gxLastSequence + 1) & xSequenceMask
		if sequence == gxSequenceStart {
			timestamp = tillNext100nano(timestamp)
			gxLastTimestamp = timestamp
		}
		gxLastSequence = sequence
		gxMutex.Unlock() // Unlock
	default: // timestamp < xLastTimestamp
		gxSequenceStart = rand.Uint32() & xSequenceMask // NOTE
		sequence = gxSequenceStart
		gxLastTimestamp = timestamp
		gxLastSequence = sequence
		gxMutex.Unlock() // Unlock
	}

	// time_low
	uuid[0] = byte(timestamp >> 24)
	uuid[1] = byte(timestamp >> 16)
	uuid[2] = byte(timestamp >> 8)
	uuid[3] = byte(timestamp)

	// time_mid
	uuid[4] = byte(timestamp >> 40)
	uuid[5] = byte(timestamp >> 32)

	// time_hi_and_pid_low
	uuid[6] = byte(timestamp >> 52)
	uuid[7] = byte(timestamp>>48) << 4
	uuid[7] |= pid & 0x0F // pid, 4bits

	// clk_seq_hi_pid
	uuid[8] = byte(sequence>>8) & 0x3F
	uuid[8] |= (pid << 2) & 0xC0 // // pid, 2bits

	// clk_seq_low
	uuid[9] = byte(sequence)

	// node
	copy(uuid[10:], xNode)
	return
}
Пример #2
0
// New returns a STANDARD version 1 UUID.
func New() (uuid [16]byte) {
	var (
		timestamp = uuidTimestamp()
		sequence  uint32
	)

	gMutex.Lock() // Lock
	switch {
	case timestamp > gLastTimestamp:
		sequence = gSequenceStart
		gLastTimestamp = timestamp
		gLastSequence = sequence
		gMutex.Unlock() // Unlock
	case timestamp == gLastTimestamp:
		sequence = (gLastSequence + 1) & sequenceMask
		if sequence == gSequenceStart {
			timestamp = tillNext100nano(timestamp)
			gLastTimestamp = timestamp
		}
		gLastSequence = sequence
		gMutex.Unlock() // Unlock
	default: // timestamp < lastTimestamp
		gSequenceStart = rand.Uint32() & sequenceMask // NOTE
		sequence = gSequenceStart
		gLastTimestamp = timestamp
		gLastSequence = sequence
		gMutex.Unlock() // Unlock
	}

	// time_low
	uuid[0] = byte(timestamp >> 24)
	uuid[1] = byte(timestamp >> 16)
	uuid[2] = byte(timestamp >> 8)
	uuid[3] = byte(timestamp)

	// time_mid
	uuid[4] = byte(timestamp >> 40)
	uuid[5] = byte(timestamp >> 32)

	// time_hi_and_version
	uuid[6] = byte(timestamp>>56) & 0x0F
	uuid[6] |= 0x10 // version 1, 4bits
	uuid[7] = byte(timestamp >> 48)

	// clk_seq_hi_res
	uuid[8] = byte(sequence>>8) & 0x3F
	uuid[8] |= 0x80 // variant, 2bits

	// clk_seq_low
	uuid[9] = byte(sequence)

	// node
	copy(uuid[10:], node)
	return
}
Пример #3
0
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

var pid = byte(hash(uint64(os.Getpid()))) // 6-bit hash of os.Getpid(), read only.

// hash uint64 to a 6-bit integer value.
func hash(x uint64) uint64 {
	return (x ^ x>>6 ^ x>>12 ^ x>>18 ^ x>>24 ^ x>>30 ^ x>>36 ^ x>>42 ^ x>>48 ^ x>>54 ^ x>>60) & 0x3f
}

var xNode = internal.MAC[:] // read only.

const xSequenceMask uint32 = 0x3FFF // 14bits

var (
	gxMutex         sync.Mutex
	gxSequenceStart uint32 = rand.Uint32() & xSequenceMask
	gxLastTimestamp int64  = -1
	gxLastSequence  uint32 = gxSequenceStart
)

// Newx returns a NONSTANDARD UUID(lower probability of conflict).
func Newx() (uuid [16]byte) {
	var (
		timestamp = uuidTimestamp()
		sequence  uint32
	)

	gxMutex.Lock() // Lock
	switch {
	case timestamp > gxLastTimestamp:
		sequence = gxSequenceStart
Пример #4
0
// New returns a unique 32-byte url-safe string.
func New() string {
	var (
		timeNow     = time.Now()
		timeNowUnix = timeNow.Unix()

		timestamp = unix100nano(timeNow)
		sequence  uint32

		saltShouldUpdate = false
		saltSequence     uint32
	)

	gMutex.Lock() // Lock
	switch {
	case timestamp > gLastTimestamp:
		sequence = gSequenceStart
		gLastTimestamp = timestamp
		gLastSequence = sequence
	case timestamp == gLastTimestamp:
		sequence = (gLastSequence + 1) & sequenceMask
		if sequence == gSequenceStart {
			timestamp = tillNext100nano(timestamp)
			gLastTimestamp = timestamp
		}
		gLastSequence = sequence
	default:
		gSequenceStart = rand.Uint32() & sequenceMask // NOTE
		sequence = gSequenceStart
		gLastTimestamp = timestamp
		gLastSequence = sequence
	}
	if timeNowUnix >= gSaltLastUpdateTimestamp+saltUpdateInterval {
		saltShouldUpdate = true
		gSaltLastUpdateTimestamp = timeNowUnix
	}
	gSaltSequence++
	saltSequence = gSaltSequence
	gMutex.Unlock() // Unlock

	// 56bits unix100ns + 12bits pid + 12bits sequence + 48bits node + 64bits hashsum
	var idx [24]byte

	// time_low
	idx[0] = byte(timestamp >> 24)
	idx[1] = byte(timestamp >> 16)
	idx[2] = byte(timestamp >> 8)
	idx[3] = byte(timestamp)

	// time_mid
	idx[4] = byte(timestamp >> 40)
	idx[5] = byte(timestamp >> 32)

	// time_hi_and_pid_low
	idx[6] = byte(timestamp >> 48)
	idx[7] = byte(pid)

	// clk_seq_hi_pid
	idx[8] = byte(sequence>>8) & 0x0f
	idx[8] |= byte(pid>>8) << 4

	// clk_seq_low
	idx[9] = byte(sequence)

	// node
	copy(idx[10:], node)

	// hashsum
	if saltShouldUpdate {
		rand.Read(gSalt)
		copy(idx[16:], gSalt)
	} else {
		var src [8 + 4 + saltLen]byte // 8+4+43==55

		src[0] = byte(timestamp >> 56)
		src[1] = byte(timestamp >> 48)
		src[2] = byte(timestamp >> 40)
		src[3] = byte(timestamp >> 32)
		src[4] = byte(timestamp >> 24)
		src[5] = byte(timestamp >> 16)
		src[6] = byte(timestamp >> 8)
		src[7] = byte(timestamp)
		src[8] = byte(saltSequence >> 24)
		src[9] = byte(saltSequence >> 16)
		src[10] = byte(saltSequence >> 8)
		src[11] = byte(saltSequence)
		copy(src[12:], gSalt)

		hashsum := sha1.Sum(src[:])
		copy(idx[16:], hashsum[:])
	}

	id := make([]byte, 32)
	base64.URLEncoding.Encode(id, idx[:])
	return string(id)
}
Пример #5
0
}

var node = internal.MAC[:] // read only

const (
	sequenceMask       = 0xfff // 12bits
	saltLen            = 43    // see New(), 8+4+43==55<56, Best performance for sha1.
	saltUpdateInterval = 3600  // seconds
)

var (
	gSalt = make([]byte, saltLen)

	gMutex sync.Mutex // protect following

	gSequenceStart uint32 = rand.Uint32() & sequenceMask
	gLastTimestamp int64  = -1
	gLastSequence  uint32 = gSequenceStart

	gSaltLastUpdateTimestamp int64  = -saltUpdateInterval
	gSaltSequence            uint32 = rand.Uint32()
)

// New returns a unique 32-byte url-safe string.
func New() string {
	var (
		timeNow     = time.Now()
		timeNowUnix = timeNow.Unix()

		timestamp = unix100nano(timeNow)
		sequence  uint32