package rand import ( "encoding/binary" "math/rand" "sync" "github.com/influxdata/influxdb/v2" ) var _ influxdb.IDGenerator = (*OrgBucketID)(nil) // OrgBucketID creates an id that does not have ascii // backslash, commas, or spaces. Used to create IDs for organizations // and buckets. // // It is implemented without those characters because orgbucket // pairs are placed in the old measurement field. Measurement // was interpreted as a string delimited with commas. Therefore, // to continue to use the underlying storage engine we need to // sanitize ids. // // Safe for concurrent use by multiple goroutines. type OrgBucketID struct { m sync.Mutex src *rand.Rand } // NewOrgBucketID creates an influxdb.IDGenerator that creates // random numbers seeded with seed. Ascii backslash, comma, // and space are manipulated by incrementing. // // Typically, seed with `time.Now().UnixNano()` func NewOrgBucketID(seed int64) *OrgBucketID { return &OrgBucketID{ src: rand.New(rand.NewSource(seed)), } } // Seed allows one to override the current seed. // Typically, this override is done for tests. func (r *OrgBucketID) Seed(seed int64) { r.m.Lock() r.src = rand.New(rand.NewSource(seed)) r.m.Unlock() } // ID generates an ID that does not have backslashes, commas, or spaces. func (r *OrgBucketID) ID() influxdb.ID { r.m.Lock() n := r.src.Uint64() r.m.Unlock() n = sanitize(n) return influxdb.ID(n) } func sanitize(n uint64) uint64 { b := make([]byte, 8) binary.BigEndian.PutUint64(b, n) for i := range b { switch b[i] { // these bytes must be remove here to prevent the need // to escape/unescape. See the models package for // additional detail. // \ , " " case 0x5C, 0x2C, 0x20: b[i] = b[i] + 1 } } return binary.BigEndian.Uint64(b) }