diff --git a/internal/uuid/uuid.go b/internal/uuid/uuid.go deleted file mode 100644 index d433ccaf5..000000000 --- a/internal/uuid/uuid.go +++ /dev/null @@ -1,126 +0,0 @@ -// Package uuid provides simple UUID generation. Only version 4 style UUIDs -// can be generated. -// -// Please see http://tools.ietf.org/html/rfc4122 for details on UUIDs. -package uuid - -import ( - "crypto/rand" - "fmt" - "io" - "os" - "syscall" - "time" -) - -const ( - // Bits is the number of bits in a UUID - Bits = 128 - - // Size is the number of bytes in a UUID - Size = Bits / 8 - - format = "%08x-%04x-%04x-%04x-%012x" -) - -var ( - // ErrUUIDInvalid indicates a parsed string is not a valid uuid. - ErrUUIDInvalid = fmt.Errorf("invalid uuid") - - // Loggerf can be used to override the default logging destination. Such - // log messages in this library should be logged at warning or higher. - Loggerf = func(format string, args ...interface{}) {} -) - -// UUID represents a UUID value. UUIDs can be compared and set to other values -// and accessed by byte. -type UUID [Size]byte - -// Generate creates a new, version 4 uuid. -func Generate() (u UUID) { - const ( - // ensures we backoff for less than 450ms total. Use the following to - // select new value, in units of 10ms: - // n*(n+1)/2 = d -> n^2 + n - 2d -> n = (sqrt(8d + 1) - 1)/2 - maxretries = 9 - backoff = time.Millisecond * 10 - ) - - var ( - totalBackoff time.Duration - count int - retries int - ) - - for { - // This should never block but the read may fail. Because of this, - // we just try to read the random number generator until we get - // something. This is a very rare condition but may happen. - b := time.Duration(retries) * backoff - time.Sleep(b) - totalBackoff += b - - n, err := io.ReadFull(rand.Reader, u[count:]) - if err != nil { - if retryOnError(err) && retries < maxretries { - count += n - retries++ - Loggerf("error generating version 4 uuid, retrying: %v", err) - continue - } - - // Any other errors represent a system problem. What did someone - // do to /dev/urandom? - panic(fmt.Errorf("error reading random number generator, retried for %v: %v", totalBackoff.String(), err)) - } - - break - } - - u[6] = (u[6] & 0x0f) | 0x40 // set version byte - u[8] = (u[8] & 0x3f) | 0x80 // set high order byte 0b10{8,9,a,b} - - return u -} - -// Parse attempts to extract a uuid from the string or returns an error. -func Parse(s string) (u UUID, err error) { - if len(s) != 36 { - return UUID{}, ErrUUIDInvalid - } - - // create stack addresses for each section of the uuid. - p := make([][]byte, 5) - - if _, err := fmt.Sscanf(s, format, &p[0], &p[1], &p[2], &p[3], &p[4]); err != nil { - return u, err - } - - copy(u[0:4], p[0]) - copy(u[4:6], p[1]) - copy(u[6:8], p[2]) - copy(u[8:10], p[3]) - copy(u[10:16], p[4]) - - return -} - -func (u UUID) String() string { - return fmt.Sprintf(format, u[:4], u[4:6], u[6:8], u[8:10], u[10:]) -} - -// retryOnError tries to detect whether or not retrying would be fruitful. -func retryOnError(err error) bool { - switch err := err.(type) { - case *os.PathError: - return retryOnError(err.Err) // unpack the target error - case syscall.Errno: - if err == syscall.EPERM { - // EPERM represents an entropy pool exhaustion, a condition under - // which we backoff and retry. - return true - } - } - - return false -} diff --git a/internal/uuid/uuid_test.go b/internal/uuid/uuid_test.go deleted file mode 100644 index 09c3a7bb4..000000000 --- a/internal/uuid/uuid_test.go +++ /dev/null @@ -1,48 +0,0 @@ -package uuid - -import ( - "testing" -) - -const iterations = 1000 - -func TestUUID4Generation(t *testing.T) { - for i := 0; i < iterations; i++ { - u := Generate() - - if u[6]&0xf0 != 0x40 { - t.Fatalf("version byte not correctly set: %v, %08b %08b", u, u[6], u[6]&0xf0) - } - - if u[8]&0xc0 != 0x80 { - t.Fatalf("top order 8th byte not correctly set: %v, %b", u, u[8]) - } - } -} - -func TestParseAndEquality(t *testing.T) { - for i := 0; i < iterations; i++ { - u := Generate() - - parsed, err := Parse(u.String()) - if err != nil { - t.Fatalf("error parsing uuid %v: %v", u, err) - } - - if parsed != u { - t.Fatalf("parsing round trip failed: %v != %v", parsed, u) - } - } - - for _, c := range []string{ - "bad", - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", // correct length, incorrect format - " 20cc7775-2671-43c7-8742-51d1cfa23258", // leading space - "20cc7775-2671-43c7-8742-51d1cfa23258 ", // trailing space - "00000000-0000-0000-0000-x00000000000", // out of range character - } { - if _, err := Parse(c); err == nil { - t.Fatalf("parsing %q should have failed", c) - } - } -}