// Package sonyflake implements Sonyflake, a distributed unique ID generator inspired by Twitter's Snowflake.
//第一位为未使用(实际上也可作为long的符号位),接下来的41位为毫秒级时间,然后5位datacenter标识位,5位机器ID(并不算标识符,实际是为线程标识),然后12位该毫秒内的当前毫秒内的计数,加起来刚好64位,为一个Long型。
// A Sonyflake ID is composed of
//     39 bits for time in units of 10 msec
//      8 bits for a sequence number
//     16 bits for a machine id
package sonyflake
import (
    "errors"
    "net"
    "sync"
    "time"
)
// These constants are the bit lengths of Sonyflake ID parts.
const (
    BitLenTime      = 39                               // bit length of time
    BitLenSequence  = 8                                // bit length of sequence number
    BitLenMachineID = 63 - BitLenTime - BitLenSequence // bit length of machine id
)
// Settings configures Sonyflake:
//
// StartTime is the time since which the Sonyflake time is defined as the elapsed time.
// If StartTime is 0, the start time of the Sonyflake is set to "2014-09-01 00:00:00 +0000 UTC".
// If StartTime is ahead of the current time, Sonyflake is not created.
//
// MachineID returns the unique ID of the Sonyflake instance.
// If MachineID returns an error, Sonyflake is not created.
// If MachineID is nil, default MachineID is used.
// Default MachineID returns the lower 16 bits of the private IP address.
//
// CheckMachineID validates the uniqueness of the machine ID.
// If CheckMachineID returns false, Sonyflake is not created.
// If CheckMachineID is nil, no validation is done.
type Settings struct {    StartTime      time.Time
    MachineID      func() (uint16, error)
    CheckMachineID func(uint16) bool
}
// Sonyflake is a distributed unique ID generator.
type Sonyflake struct {    mutex       *sync.Mutex
    startTime   int64
    elapsedTime int64
    sequence    uint16
    machineID   uint16
}
// NewSonyflake returns a new Sonyflake configured with the given Settings.
// NewSonyflake returns nil in the following cases:
// - Settings.StartTime is ahead of the current time.
// - Settings.MachineID returns an error.
// - Settings.CheckMachineID returns false.
func NewSonyflake(st Settings) *Sonyflake {    sf := new(Sonyflake)
    sf.mutex = new(sync.Mutex)
    sf.sequence = uint16(1<<BitLenSequence - 1)
    if st.StartTime.After(time.Now()) {        return nil
    }
    if st.StartTime.IsZero() {        sf.startTime = toSonyflakeTime(time.Date(2014, 9, 1, 0, 0, 0, 0, time.UTC))
    } else {        sf.startTime = toSonyflakeTime(st.StartTime)
    }
    var err error
    if st.MachineID == nil {        sf.machineID, err = lower16BitPrivateIP()
    } else {        sf.machineID, err = st.MachineID()
    }
    if err != nil || (st.CheckMachineID != nil && !st.CheckMachineID(sf.machineID)) {        return nil
    }
    return sf
}
// NextID generates a next unique ID.
// After the Sonyflake time overflows, NextID returns an error.
func (sf *Sonyflake) NextID() (uint64, error) {    const maskSequence = uint16(1<<BitLenSequence - 1)
    sf.mutex.Lock()
    defer sf.mutex.Unlock()
    current := currentElapsedTime(sf.startTime)
    if sf.elapsedTime < current {        sf.elapsedTime = current
        sf.sequence = 0
    } else { // sf.elapsedTime >= current        sf.sequence = (sf.sequence + 1) & maskSequence
        if sf.sequence == 0 {            sf.elapsedTime++
            overtime := sf.elapsedTime - current
            time.Sleep(sleepTime((overtime)))
        }
    }
    return sf.toID()
}
const sonyflakeTimeUnit = 1e7 // nsec, i.e. 10 msec
func toSonyflakeTime(t time.Time) int64 {    return t.UTC().UnixNano() / sonyflakeTimeUnit
}
func currentElapsedTime(startTime int64) int64 {    return toSonyflakeTime(time.Now()) - startTime
}
func sleepTime(overtime int64) time.Duration {    return time.Duration(overtime)*10*time.Millisecond -
        time.Duration(time.Now().UTC().UnixNano()%sonyflakeTimeUnit)*time.Nanosecond
}
func (sf *Sonyflake) toID() (uint64, error) {    if sf.elapsedTime >= 1<<BitLenTime {        return 0, errors.New("over the time limit")    }
    return uint64(sf.elapsedTime)<<(BitLenSequence+BitLenMachineID) |
        uint64(sf.sequence)<<BitLenMachineID |
        uint64(sf.machineID), nil
}
func privateIPv4() (net.IP, error) {    as, err := net.InterfaceAddrs()
    if err != nil {        return nil, err
    }
    for _, a := range as {        ipnet, ok := a.(*net.IPNet)
        if !ok || ipnet.IP.IsLoopback() {            continue
        }
        ip := ipnet.IP.To4()
        if isPrivateIPv4(ip) {            return ip, nil
        }
    }
    return nil, errors.New("no private ip address")}
func isPrivateIPv4(ip net.IP) bool {    return ip != nil &&
        (ip[0] == 10 || ip[0] == 172 && (ip[1] >= 16 && ip[1] < 32) || ip[0] == 192 && ip[1] == 168)
}
func lower16BitPrivateIP() (uint16, error) {    ip, err := privateIPv4()
    if err != nil {        return 0, err
    }
    return uint16(ip[2])<<8 + uint16(ip[3]), nil
}
// Decompose returns a set of Sonyflake ID parts.
func Decompose(id uint64) map[string]uint64 {    const maskSequence = uint64((1<<BitLenSequence - 1) << BitLenMachineID)
    const maskMachineID = uint64(1<<BitLenMachineID - 1)
    msb := id >> 63
    time := id >> (BitLenSequence + BitLenMachineID)
    sequence := id & maskSequence >> BitLenMachineID
    machineID := id & maskMachineID
    return map[string]uint64{        "id":         id,
        "msb":        msb,
        "time":       time,
        "sequence":   sequence,
        "machine-id": machineID,
    }
}