Replace uuid dependency with internal library
Signed-off-by: Stephen J Day <stephen.day@docker.com>
This commit is contained in:
parent
2317f721a3
commit
36e34a55ad
26 changed files with 189 additions and 1222 deletions
5
Godeps/Godeps.json
generated
5
Godeps/Godeps.json
generated
|
@ -5,11 +5,6 @@
|
||||||
"./..."
|
"./..."
|
||||||
],
|
],
|
||||||
"Deps": [
|
"Deps": [
|
||||||
{
|
|
||||||
"ImportPath": "code.google.com/p/go-uuid/uuid",
|
|
||||||
"Comment": "null-15",
|
|
||||||
"Rev": "35bc42037350f0078e3c974c6ea690f1926603ab"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/AdRoll/goamz/aws",
|
"ImportPath": "github.com/AdRoll/goamz/aws",
|
||||||
"Rev": "cc210f45dcb9889c2769a274522be2bf70edfb99"
|
"Rev": "cc210f45dcb9889c2769a274522be2bf70edfb99"
|
||||||
|
|
27
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/LICENSE
generated
vendored
27
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/LICENSE
generated
vendored
|
@ -1,27 +0,0 @@
|
||||||
Copyright (c) 2009,2014 Google Inc. All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are
|
|
||||||
met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the following disclaimer
|
|
||||||
in the documentation and/or other materials provided with the
|
|
||||||
distribution.
|
|
||||||
* Neither the name of Google Inc. nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
84
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/dce.go
generated
vendored
84
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/dce.go
generated
vendored
|
@ -1,84 +0,0 @@
|
||||||
// Copyright 2011 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
// A Domain represents a Version 2 domain
|
|
||||||
type Domain byte
|
|
||||||
|
|
||||||
// Domain constants for DCE Security (Version 2) UUIDs.
|
|
||||||
const (
|
|
||||||
Person = Domain(0)
|
|
||||||
Group = Domain(1)
|
|
||||||
Org = Domain(2)
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewDCESecurity returns a DCE Security (Version 2) UUID.
|
|
||||||
//
|
|
||||||
// The domain should be one of Person, Group or Org.
|
|
||||||
// On a POSIX system the id should be the users UID for the Person
|
|
||||||
// domain and the users GID for the Group. The meaning of id for
|
|
||||||
// the domain Org or on non-POSIX systems is site defined.
|
|
||||||
//
|
|
||||||
// For a given domain/id pair the same token may be returned for up to
|
|
||||||
// 7 minutes and 10 seconds.
|
|
||||||
func NewDCESecurity(domain Domain, id uint32) UUID {
|
|
||||||
uuid := NewUUID()
|
|
||||||
if uuid != nil {
|
|
||||||
uuid[6] = (uuid[6] & 0x0f) | 0x20 // Version 2
|
|
||||||
uuid[9] = byte(domain)
|
|
||||||
binary.BigEndian.PutUint32(uuid[0:], id)
|
|
||||||
}
|
|
||||||
return uuid
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewDCEPerson returns a DCE Security (Version 2) UUID in the person
|
|
||||||
// domain with the id returned by os.Getuid.
|
|
||||||
//
|
|
||||||
// NewDCEPerson(Person, uint32(os.Getuid()))
|
|
||||||
func NewDCEPerson() UUID {
|
|
||||||
return NewDCESecurity(Person, uint32(os.Getuid()))
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewDCEGroup returns a DCE Security (Version 2) UUID in the group
|
|
||||||
// domain with the id returned by os.Getgid.
|
|
||||||
//
|
|
||||||
// NewDCEGroup(Group, uint32(os.Getgid()))
|
|
||||||
func NewDCEGroup() UUID {
|
|
||||||
return NewDCESecurity(Group, uint32(os.Getgid()))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Domain returns the domain for a Version 2 UUID or false.
|
|
||||||
func (uuid UUID) Domain() (Domain, bool) {
|
|
||||||
if v, _ := uuid.Version(); v != 2 {
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
return Domain(uuid[9]), true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Id returns the id for a Version 2 UUID or false.
|
|
||||||
func (uuid UUID) Id() (uint32, bool) {
|
|
||||||
if v, _ := uuid.Version(); v != 2 {
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
return binary.BigEndian.Uint32(uuid[0:4]), true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d Domain) String() string {
|
|
||||||
switch d {
|
|
||||||
case Person:
|
|
||||||
return "Person"
|
|
||||||
case Group:
|
|
||||||
return "Group"
|
|
||||||
case Org:
|
|
||||||
return "Org"
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("Domain%d", int(d))
|
|
||||||
}
|
|
8
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/doc.go
generated
vendored
8
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/doc.go
generated
vendored
|
@ -1,8 +0,0 @@
|
||||||
// Copyright 2011 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// The uuid package generates and inspects UUIDs.
|
|
||||||
//
|
|
||||||
// UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security Services.
|
|
||||||
package uuid
|
|
53
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/hash.go
generated
vendored
53
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/hash.go
generated
vendored
|
@ -1,53 +0,0 @@
|
||||||
// Copyright 2011 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/md5"
|
|
||||||
"crypto/sha1"
|
|
||||||
"hash"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Well known Name Space IDs and UUIDs
|
|
||||||
var (
|
|
||||||
NameSpace_DNS = Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
|
|
||||||
NameSpace_URL = Parse("6ba7b811-9dad-11d1-80b4-00c04fd430c8")
|
|
||||||
NameSpace_OID = Parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8")
|
|
||||||
NameSpace_X500 = Parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8")
|
|
||||||
NIL = Parse("00000000-0000-0000-0000-000000000000")
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewHash returns a new UUID dervied from the hash of space concatenated with
|
|
||||||
// data generated by h. The hash should be at least 16 byte in length. The
|
|
||||||
// first 16 bytes of the hash are used to form the UUID. The version of the
|
|
||||||
// UUID will be the lower 4 bits of version. NewHash is used to implement
|
|
||||||
// NewMD5 and NewSHA1.
|
|
||||||
func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID {
|
|
||||||
h.Reset()
|
|
||||||
h.Write(space)
|
|
||||||
h.Write([]byte(data))
|
|
||||||
s := h.Sum(nil)
|
|
||||||
uuid := make([]byte, 16)
|
|
||||||
copy(uuid, s)
|
|
||||||
uuid[6] = (uuid[6] & 0x0f) | uint8((version&0xf)<<4)
|
|
||||||
uuid[8] = (uuid[8] & 0x3f) | 0x80 // RFC 4122 variant
|
|
||||||
return uuid
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewMD5 returns a new MD5 (Version 3) UUID based on the
|
|
||||||
// supplied name space and data.
|
|
||||||
//
|
|
||||||
// NewHash(md5.New(), space, data, 3)
|
|
||||||
func NewMD5(space UUID, data []byte) UUID {
|
|
||||||
return NewHash(md5.New(), space, data, 3)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewSHA1 returns a new SHA1 (Version 5) UUID based on the
|
|
||||||
// supplied name space and data.
|
|
||||||
//
|
|
||||||
// NewHash(sha1.New(), space, data, 5)
|
|
||||||
func NewSHA1(space UUID, data []byte) UUID {
|
|
||||||
return NewHash(sha1.New(), space, data, 5)
|
|
||||||
}
|
|
30
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/json.go
generated
vendored
30
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/json.go
generated
vendored
|
@ -1,30 +0,0 @@
|
||||||
// Copyright 2014 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import "errors"
|
|
||||||
|
|
||||||
func (u UUID) MarshalJSON() ([]byte, error) {
|
|
||||||
if len(u) == 0 {
|
|
||||||
return []byte(`""`), nil
|
|
||||||
}
|
|
||||||
return []byte(`"` + u.String() + `"`), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UUID) UnmarshalJSON(data []byte) error {
|
|
||||||
if len(data) == 0 || string(data) == `""` {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if len(data) < 2 || data[0] != '"' || data[len(data)-1] != '"' {
|
|
||||||
return errors.New("invalid UUID format")
|
|
||||||
}
|
|
||||||
data = data[1 : len(data)-1]
|
|
||||||
uu := Parse(string(data))
|
|
||||||
if uu == nil {
|
|
||||||
return errors.New("invalid UUID format")
|
|
||||||
}
|
|
||||||
*u = uu
|
|
||||||
return nil
|
|
||||||
}
|
|
32
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/json_test.go
generated
vendored
32
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/json_test.go
generated
vendored
|
@ -1,32 +0,0 @@
|
||||||
// Copyright 2014 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
var testUUID = Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479")
|
|
||||||
|
|
||||||
func TestJSON(t *testing.T) {
|
|
||||||
type S struct {
|
|
||||||
ID1 UUID
|
|
||||||
ID2 UUID
|
|
||||||
}
|
|
||||||
s1 := S{ID1: testUUID}
|
|
||||||
data, err := json.Marshal(&s1)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
var s2 S
|
|
||||||
if err := json.Unmarshal(data, &s2); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(&s1, &s2) {
|
|
||||||
t.Errorf("got %#v, want %#v", s2, s1)
|
|
||||||
}
|
|
||||||
}
|
|
101
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/node.go
generated
vendored
101
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/node.go
generated
vendored
|
@ -1,101 +0,0 @@
|
||||||
// Copyright 2011 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import "net"
|
|
||||||
|
|
||||||
var (
|
|
||||||
interfaces []net.Interface // cached list of interfaces
|
|
||||||
ifname string // name of interface being used
|
|
||||||
nodeID []byte // hardware for version 1 UUIDs
|
|
||||||
)
|
|
||||||
|
|
||||||
// NodeInterface returns the name of the interface from which the NodeID was
|
|
||||||
// derived. The interface "user" is returned if the NodeID was set by
|
|
||||||
// SetNodeID.
|
|
||||||
func NodeInterface() string {
|
|
||||||
return ifname
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetNodeInterface selects the hardware address to be used for Version 1 UUIDs.
|
|
||||||
// If name is "" then the first usable interface found will be used or a random
|
|
||||||
// Node ID will be generated. If a named interface cannot be found then false
|
|
||||||
// is returned.
|
|
||||||
//
|
|
||||||
// SetNodeInterface never fails when name is "".
|
|
||||||
func SetNodeInterface(name string) bool {
|
|
||||||
if interfaces == nil {
|
|
||||||
var err error
|
|
||||||
interfaces, err = net.Interfaces()
|
|
||||||
if err != nil && name != "" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, ifs := range interfaces {
|
|
||||||
if len(ifs.HardwareAddr) >= 6 && (name == "" || name == ifs.Name) {
|
|
||||||
if setNodeID(ifs.HardwareAddr) {
|
|
||||||
ifname = ifs.Name
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We found no interfaces with a valid hardware address. If name
|
|
||||||
// does not specify a specific interface generate a random Node ID
|
|
||||||
// (section 4.1.6)
|
|
||||||
if name == "" {
|
|
||||||
if nodeID == nil {
|
|
||||||
nodeID = make([]byte, 6)
|
|
||||||
}
|
|
||||||
randomBits(nodeID)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// NodeID returns a slice of a copy of the current Node ID, setting the Node ID
|
|
||||||
// if not already set.
|
|
||||||
func NodeID() []byte {
|
|
||||||
if nodeID == nil {
|
|
||||||
SetNodeInterface("")
|
|
||||||
}
|
|
||||||
nid := make([]byte, 6)
|
|
||||||
copy(nid, nodeID)
|
|
||||||
return nid
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetNodeID sets the Node ID to be used for Version 1 UUIDs. The first 6 bytes
|
|
||||||
// of id are used. If id is less than 6 bytes then false is returned and the
|
|
||||||
// Node ID is not set.
|
|
||||||
func SetNodeID(id []byte) bool {
|
|
||||||
if setNodeID(id) {
|
|
||||||
ifname = "user"
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func setNodeID(id []byte) bool {
|
|
||||||
if len(id) < 6 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if nodeID == nil {
|
|
||||||
nodeID = make([]byte, 6)
|
|
||||||
}
|
|
||||||
copy(nodeID, id)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// NodeID returns the 6 byte node id encoded in uuid. It returns nil if uuid is
|
|
||||||
// not valid. The NodeID is only well defined for version 1 and 2 UUIDs.
|
|
||||||
func (uuid UUID) NodeID() []byte {
|
|
||||||
if len(uuid) != 16 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
node := make([]byte, 6)
|
|
||||||
copy(node, uuid[10:])
|
|
||||||
return node
|
|
||||||
}
|
|
66
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/seq_test.go
generated
vendored
66
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/seq_test.go
generated
vendored
|
@ -1,66 +0,0 @@
|
||||||
// Copyright 2014 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"flag"
|
|
||||||
"runtime"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// This test is only run when --regressions is passed on the go test line.
|
|
||||||
var regressions = flag.Bool("regressions", false, "run uuid regression tests")
|
|
||||||
|
|
||||||
// TestClockSeqRace tests for a particular race condition of returning two
|
|
||||||
// identical Version1 UUIDs. The duration of 1 minute was chosen as the race
|
|
||||||
// condition, before being fixed, nearly always occured in under 30 seconds.
|
|
||||||
func TestClockSeqRace(t *testing.T) {
|
|
||||||
if !*regressions {
|
|
||||||
t.Skip("skipping regression tests")
|
|
||||||
}
|
|
||||||
duration := time.Minute
|
|
||||||
|
|
||||||
done := make(chan struct{})
|
|
||||||
defer close(done)
|
|
||||||
|
|
||||||
ch := make(chan UUID, 10000)
|
|
||||||
ncpu := runtime.NumCPU()
|
|
||||||
switch ncpu {
|
|
||||||
case 0, 1:
|
|
||||||
// We can't run the test effectively.
|
|
||||||
t.Skip("skipping race test, only one CPU detected")
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
runtime.GOMAXPROCS(ncpu)
|
|
||||||
}
|
|
||||||
for i := 0; i < ncpu; i++ {
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-done:
|
|
||||||
return
|
|
||||||
case ch <- NewUUID():
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
uuids := make(map[string]bool)
|
|
||||||
cnt := 0
|
|
||||||
start := time.Now()
|
|
||||||
for u := range ch {
|
|
||||||
s := u.String()
|
|
||||||
if uuids[s] {
|
|
||||||
t.Errorf("duplicate uuid after %d in %v: %s", cnt, time.Since(start), s)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
uuids[s] = true
|
|
||||||
if time.Since(start) > duration {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cnt++
|
|
||||||
}
|
|
||||||
}
|
|
132
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/time.go
generated
vendored
132
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/time.go
generated
vendored
|
@ -1,132 +0,0 @@
|
||||||
// Copyright 2014 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// A Time represents a time as the number of 100's of nanoseconds since 15 Oct
|
|
||||||
// 1582.
|
|
||||||
type Time int64
|
|
||||||
|
|
||||||
const (
|
|
||||||
lillian = 2299160 // Julian day of 15 Oct 1582
|
|
||||||
unix = 2440587 // Julian day of 1 Jan 1970
|
|
||||||
epoch = unix - lillian // Days between epochs
|
|
||||||
g1582 = epoch * 86400 // seconds between epochs
|
|
||||||
g1582ns100 = g1582 * 10000000 // 100s of a nanoseconds between epochs
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
mu sync.Mutex
|
|
||||||
lasttime uint64 // last time we returned
|
|
||||||
clock_seq uint16 // clock sequence for this run
|
|
||||||
|
|
||||||
timeNow = time.Now // for testing
|
|
||||||
)
|
|
||||||
|
|
||||||
// UnixTime converts t the number of seconds and nanoseconds using the Unix
|
|
||||||
// epoch of 1 Jan 1970.
|
|
||||||
func (t Time) UnixTime() (sec, nsec int64) {
|
|
||||||
sec = int64(t - g1582ns100)
|
|
||||||
nsec = (sec % 10000000) * 100
|
|
||||||
sec /= 10000000
|
|
||||||
return sec, nsec
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTime returns the current Time (100s of nanoseconds since 15 Oct 1582) and
|
|
||||||
// clock sequence as well as adjusting the clock sequence as needed. An error
|
|
||||||
// is returned if the current time cannot be determined.
|
|
||||||
func GetTime() (Time, uint16, error) {
|
|
||||||
defer mu.Unlock()
|
|
||||||
mu.Lock()
|
|
||||||
return getTime()
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTime() (Time, uint16, error) {
|
|
||||||
t := timeNow()
|
|
||||||
|
|
||||||
// If we don't have a clock sequence already, set one.
|
|
||||||
if clock_seq == 0 {
|
|
||||||
setClockSequence(-1)
|
|
||||||
}
|
|
||||||
now := uint64(t.UnixNano()/100) + g1582ns100
|
|
||||||
|
|
||||||
// If time has gone backwards with this clock sequence then we
|
|
||||||
// increment the clock sequence
|
|
||||||
if now <= lasttime {
|
|
||||||
clock_seq = ((clock_seq + 1) & 0x3fff) | 0x8000
|
|
||||||
}
|
|
||||||
lasttime = now
|
|
||||||
return Time(now), clock_seq, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClockSequence returns the current clock sequence, generating one if not
|
|
||||||
// already set. The clock sequence is only used for Version 1 UUIDs.
|
|
||||||
//
|
|
||||||
// The uuid package does not use global static storage for the clock sequence or
|
|
||||||
// the last time a UUID was generated. Unless SetClockSequence a new random
|
|
||||||
// clock sequence is generated the first time a clock sequence is requested by
|
|
||||||
// ClockSequence, GetTime, or NewUUID. (section 4.2.1.1) sequence is generated
|
|
||||||
// for
|
|
||||||
func ClockSequence() int {
|
|
||||||
defer mu.Unlock()
|
|
||||||
mu.Lock()
|
|
||||||
return clockSequence()
|
|
||||||
}
|
|
||||||
|
|
||||||
func clockSequence() int {
|
|
||||||
if clock_seq == 0 {
|
|
||||||
setClockSequence(-1)
|
|
||||||
}
|
|
||||||
return int(clock_seq & 0x3fff)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetClockSeq sets the clock sequence to the lower 14 bits of seq. Setting to
|
|
||||||
// -1 causes a new sequence to be generated.
|
|
||||||
func SetClockSequence(seq int) {
|
|
||||||
defer mu.Unlock()
|
|
||||||
mu.Lock()
|
|
||||||
setClockSequence(seq)
|
|
||||||
}
|
|
||||||
|
|
||||||
func setClockSequence(seq int) {
|
|
||||||
if seq == -1 {
|
|
||||||
var b [2]byte
|
|
||||||
randomBits(b[:]) // clock sequence
|
|
||||||
seq = int(b[0])<<8 | int(b[1])
|
|
||||||
}
|
|
||||||
old_seq := clock_seq
|
|
||||||
clock_seq = uint16(seq&0x3fff) | 0x8000 // Set our variant
|
|
||||||
if old_seq != clock_seq {
|
|
||||||
lasttime = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in
|
|
||||||
// uuid. It returns false if uuid is not valid. The time is only well defined
|
|
||||||
// for version 1 and 2 UUIDs.
|
|
||||||
func (uuid UUID) Time() (Time, bool) {
|
|
||||||
if len(uuid) != 16 {
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
time := int64(binary.BigEndian.Uint32(uuid[0:4]))
|
|
||||||
time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32
|
|
||||||
time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48
|
|
||||||
return Time(time), true
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClockSequence returns the clock sequence encoded in uuid. It returns false
|
|
||||||
// if uuid is not valid. The clock sequence is only well defined for version 1
|
|
||||||
// and 2 UUIDs.
|
|
||||||
func (uuid UUID) ClockSequence() (int, bool) {
|
|
||||||
if len(uuid) != 16 {
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
return int(binary.BigEndian.Uint16(uuid[8:10])) & 0x3fff, true
|
|
||||||
}
|
|
43
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/util.go
generated
vendored
43
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/util.go
generated
vendored
|
@ -1,43 +0,0 @@
|
||||||
// Copyright 2011 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
// randomBits completely fills slice b with random data.
|
|
||||||
func randomBits(b []byte) {
|
|
||||||
if _, err := io.ReadFull(rander, b); err != nil {
|
|
||||||
panic(err.Error()) // rand should never fail
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// xvalues returns the value of a byte as a hexadecimal digit or 255.
|
|
||||||
var xvalues = []byte{
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
}
|
|
||||||
|
|
||||||
// xtob converts the the first two hex bytes of x into a byte.
|
|
||||||
func xtob(x string) (byte, bool) {
|
|
||||||
b1 := xvalues[x[0]]
|
|
||||||
b2 := xvalues[x[1]]
|
|
||||||
return (b1 << 4) | b2, b1 != 255 && b2 != 255
|
|
||||||
}
|
|
163
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/uuid.go
generated
vendored
163
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/uuid.go
generated
vendored
|
@ -1,163 +0,0 @@
|
||||||
// Copyright 2011 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/rand"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC
|
|
||||||
// 4122.
|
|
||||||
type UUID []byte
|
|
||||||
|
|
||||||
// A Version represents a UUIDs version.
|
|
||||||
type Version byte
|
|
||||||
|
|
||||||
// A Variant represents a UUIDs variant.
|
|
||||||
type Variant byte
|
|
||||||
|
|
||||||
// Constants returned by Variant.
|
|
||||||
const (
|
|
||||||
Invalid = Variant(iota) // Invalid UUID
|
|
||||||
RFC4122 // The variant specified in RFC4122
|
|
||||||
Reserved // Reserved, NCS backward compatibility.
|
|
||||||
Microsoft // Reserved, Microsoft Corporation backward compatibility.
|
|
||||||
Future // Reserved for future definition.
|
|
||||||
)
|
|
||||||
|
|
||||||
var rander = rand.Reader // random function
|
|
||||||
|
|
||||||
// New returns a new random (version 4) UUID as a string. It is a convenience
|
|
||||||
// function for NewRandom().String().
|
|
||||||
func New() string {
|
|
||||||
return NewRandom().String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse decodes s into a UUID or returns nil. Both the UUID form of
|
|
||||||
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
|
|
||||||
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded.
|
|
||||||
func Parse(s string) UUID {
|
|
||||||
if len(s) == 36+9 {
|
|
||||||
if strings.ToLower(s[:9]) != "urn:uuid:" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
s = s[9:]
|
|
||||||
} else if len(s) != 36 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
uuid := make([]byte, 16)
|
|
||||||
for i, x := range []int{
|
|
||||||
0, 2, 4, 6,
|
|
||||||
9, 11,
|
|
||||||
14, 16,
|
|
||||||
19, 21,
|
|
||||||
24, 26, 28, 30, 32, 34} {
|
|
||||||
if v, ok := xtob(s[x:]); !ok {
|
|
||||||
return nil
|
|
||||||
} else {
|
|
||||||
uuid[i] = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return uuid
|
|
||||||
}
|
|
||||||
|
|
||||||
// Equal returns true if uuid1 and uuid2 are equal.
|
|
||||||
func Equal(uuid1, uuid2 UUID) bool {
|
|
||||||
return bytes.Equal(uuid1, uuid2)
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
||||||
// , or "" if uuid is invalid.
|
|
||||||
func (uuid UUID) String() string {
|
|
||||||
if uuid == nil || len(uuid) != 16 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
b := []byte(uuid)
|
|
||||||
return fmt.Sprintf("%08x-%04x-%04x-%04x-%012x",
|
|
||||||
b[:4], b[4:6], b[6:8], b[8:10], b[10:])
|
|
||||||
}
|
|
||||||
|
|
||||||
// URN returns the RFC 2141 URN form of uuid,
|
|
||||||
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, or "" if uuid is invalid.
|
|
||||||
func (uuid UUID) URN() string {
|
|
||||||
if uuid == nil || len(uuid) != 16 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
b := []byte(uuid)
|
|
||||||
return fmt.Sprintf("urn:uuid:%08x-%04x-%04x-%04x-%012x",
|
|
||||||
b[:4], b[4:6], b[6:8], b[8:10], b[10:])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Variant returns the variant encoded in uuid. It returns Invalid if
|
|
||||||
// uuid is invalid.
|
|
||||||
func (uuid UUID) Variant() Variant {
|
|
||||||
if len(uuid) != 16 {
|
|
||||||
return Invalid
|
|
||||||
}
|
|
||||||
switch {
|
|
||||||
case (uuid[8] & 0xc0) == 0x80:
|
|
||||||
return RFC4122
|
|
||||||
case (uuid[8] & 0xe0) == 0xc0:
|
|
||||||
return Microsoft
|
|
||||||
case (uuid[8] & 0xe0) == 0xe0:
|
|
||||||
return Future
|
|
||||||
default:
|
|
||||||
return Reserved
|
|
||||||
}
|
|
||||||
panic("unreachable")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Version returns the verison of uuid. It returns false if uuid is not
|
|
||||||
// valid.
|
|
||||||
func (uuid UUID) Version() (Version, bool) {
|
|
||||||
if len(uuid) != 16 {
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
return Version(uuid[6] >> 4), true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v Version) String() string {
|
|
||||||
if v > 15 {
|
|
||||||
return fmt.Sprintf("BAD_VERSION_%d", v)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("VERSION_%d", v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v Variant) String() string {
|
|
||||||
switch v {
|
|
||||||
case RFC4122:
|
|
||||||
return "RFC4122"
|
|
||||||
case Reserved:
|
|
||||||
return "Reserved"
|
|
||||||
case Microsoft:
|
|
||||||
return "Microsoft"
|
|
||||||
case Future:
|
|
||||||
return "Future"
|
|
||||||
case Invalid:
|
|
||||||
return "Invalid"
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("BadVariant%d", int(v))
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetRand sets the random number generator to r, which implents io.Reader.
|
|
||||||
// If r.Read returns an error when the package requests random data then
|
|
||||||
// a panic will be issued.
|
|
||||||
//
|
|
||||||
// Calling SetRand with nil sets the random number generator to the default
|
|
||||||
// generator.
|
|
||||||
func SetRand(r io.Reader) {
|
|
||||||
if r == nil {
|
|
||||||
rander = rand.Reader
|
|
||||||
return
|
|
||||||
}
|
|
||||||
rander = r
|
|
||||||
}
|
|
390
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/uuid_test.go
generated
vendored
390
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/uuid_test.go
generated
vendored
|
@ -1,390 +0,0 @@
|
||||||
// Copyright 2011 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type test struct {
|
|
||||||
in string
|
|
||||||
version Version
|
|
||||||
variant Variant
|
|
||||||
isuuid bool
|
|
||||||
}
|
|
||||||
|
|
||||||
var tests = []test{
|
|
||||||
{"f47ac10b-58cc-0372-8567-0e02b2c3d479", 0, RFC4122, true},
|
|
||||||
{"f47ac10b-58cc-1372-8567-0e02b2c3d479", 1, RFC4122, true},
|
|
||||||
{"f47ac10b-58cc-2372-8567-0e02b2c3d479", 2, RFC4122, true},
|
|
||||||
{"f47ac10b-58cc-3372-8567-0e02b2c3d479", 3, RFC4122, true},
|
|
||||||
{"f47ac10b-58cc-4372-8567-0e02b2c3d479", 4, RFC4122, true},
|
|
||||||
{"f47ac10b-58cc-5372-8567-0e02b2c3d479", 5, RFC4122, true},
|
|
||||||
{"f47ac10b-58cc-6372-8567-0e02b2c3d479", 6, RFC4122, true},
|
|
||||||
{"f47ac10b-58cc-7372-8567-0e02b2c3d479", 7, RFC4122, true},
|
|
||||||
{"f47ac10b-58cc-8372-8567-0e02b2c3d479", 8, RFC4122, true},
|
|
||||||
{"f47ac10b-58cc-9372-8567-0e02b2c3d479", 9, RFC4122, true},
|
|
||||||
{"f47ac10b-58cc-a372-8567-0e02b2c3d479", 10, RFC4122, true},
|
|
||||||
{"f47ac10b-58cc-b372-8567-0e02b2c3d479", 11, RFC4122, true},
|
|
||||||
{"f47ac10b-58cc-c372-8567-0e02b2c3d479", 12, RFC4122, true},
|
|
||||||
{"f47ac10b-58cc-d372-8567-0e02b2c3d479", 13, RFC4122, true},
|
|
||||||
{"f47ac10b-58cc-e372-8567-0e02b2c3d479", 14, RFC4122, true},
|
|
||||||
{"f47ac10b-58cc-f372-8567-0e02b2c3d479", 15, RFC4122, true},
|
|
||||||
|
|
||||||
{"urn:uuid:f47ac10b-58cc-4372-0567-0e02b2c3d479", 4, Reserved, true},
|
|
||||||
{"URN:UUID:f47ac10b-58cc-4372-0567-0e02b2c3d479", 4, Reserved, true},
|
|
||||||
{"f47ac10b-58cc-4372-0567-0e02b2c3d479", 4, Reserved, true},
|
|
||||||
{"f47ac10b-58cc-4372-1567-0e02b2c3d479", 4, Reserved, true},
|
|
||||||
{"f47ac10b-58cc-4372-2567-0e02b2c3d479", 4, Reserved, true},
|
|
||||||
{"f47ac10b-58cc-4372-3567-0e02b2c3d479", 4, Reserved, true},
|
|
||||||
{"f47ac10b-58cc-4372-4567-0e02b2c3d479", 4, Reserved, true},
|
|
||||||
{"f47ac10b-58cc-4372-5567-0e02b2c3d479", 4, Reserved, true},
|
|
||||||
{"f47ac10b-58cc-4372-6567-0e02b2c3d479", 4, Reserved, true},
|
|
||||||
{"f47ac10b-58cc-4372-7567-0e02b2c3d479", 4, Reserved, true},
|
|
||||||
{"f47ac10b-58cc-4372-8567-0e02b2c3d479", 4, RFC4122, true},
|
|
||||||
{"f47ac10b-58cc-4372-9567-0e02b2c3d479", 4, RFC4122, true},
|
|
||||||
{"f47ac10b-58cc-4372-a567-0e02b2c3d479", 4, RFC4122, true},
|
|
||||||
{"f47ac10b-58cc-4372-b567-0e02b2c3d479", 4, RFC4122, true},
|
|
||||||
{"f47ac10b-58cc-4372-c567-0e02b2c3d479", 4, Microsoft, true},
|
|
||||||
{"f47ac10b-58cc-4372-d567-0e02b2c3d479", 4, Microsoft, true},
|
|
||||||
{"f47ac10b-58cc-4372-e567-0e02b2c3d479", 4, Future, true},
|
|
||||||
{"f47ac10b-58cc-4372-f567-0e02b2c3d479", 4, Future, true},
|
|
||||||
|
|
||||||
{"f47ac10b158cc-5372-a567-0e02b2c3d479", 0, Invalid, false},
|
|
||||||
{"f47ac10b-58cc25372-a567-0e02b2c3d479", 0, Invalid, false},
|
|
||||||
{"f47ac10b-58cc-53723a567-0e02b2c3d479", 0, Invalid, false},
|
|
||||||
{"f47ac10b-58cc-5372-a56740e02b2c3d479", 0, Invalid, false},
|
|
||||||
{"f47ac10b-58cc-5372-a567-0e02-2c3d479", 0, Invalid, false},
|
|
||||||
{"g47ac10b-58cc-4372-a567-0e02b2c3d479", 0, Invalid, false},
|
|
||||||
}
|
|
||||||
|
|
||||||
var constants = []struct {
|
|
||||||
c interface{}
|
|
||||||
name string
|
|
||||||
}{
|
|
||||||
{Person, "Person"},
|
|
||||||
{Group, "Group"},
|
|
||||||
{Org, "Org"},
|
|
||||||
{Invalid, "Invalid"},
|
|
||||||
{RFC4122, "RFC4122"},
|
|
||||||
{Reserved, "Reserved"},
|
|
||||||
{Microsoft, "Microsoft"},
|
|
||||||
{Future, "Future"},
|
|
||||||
{Domain(17), "Domain17"},
|
|
||||||
{Variant(42), "BadVariant42"},
|
|
||||||
}
|
|
||||||
|
|
||||||
func testTest(t *testing.T, in string, tt test) {
|
|
||||||
uuid := Parse(in)
|
|
||||||
if ok := (uuid != nil); ok != tt.isuuid {
|
|
||||||
t.Errorf("Parse(%s) got %v expected %v\b", in, ok, tt.isuuid)
|
|
||||||
}
|
|
||||||
if uuid == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if v := uuid.Variant(); v != tt.variant {
|
|
||||||
t.Errorf("Variant(%s) got %d expected %d\b", in, v, tt.variant)
|
|
||||||
}
|
|
||||||
if v, _ := uuid.Version(); v != tt.version {
|
|
||||||
t.Errorf("Version(%s) got %d expected %d\b", in, v, tt.version)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUUID(t *testing.T) {
|
|
||||||
for _, tt := range tests {
|
|
||||||
testTest(t, tt.in, tt)
|
|
||||||
testTest(t, strings.ToUpper(tt.in), tt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConstants(t *testing.T) {
|
|
||||||
for x, tt := range constants {
|
|
||||||
v, ok := tt.c.(fmt.Stringer)
|
|
||||||
if !ok {
|
|
||||||
t.Errorf("%x: %v: not a stringer", x, v)
|
|
||||||
} else if s := v.String(); s != tt.name {
|
|
||||||
v, _ := tt.c.(int)
|
|
||||||
t.Errorf("%x: Constant %T:%d gives %q, expected %q\n", x, tt.c, v, s, tt.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRandomUUID(t *testing.T) {
|
|
||||||
m := make(map[string]bool)
|
|
||||||
for x := 1; x < 32; x++ {
|
|
||||||
uuid := NewRandom()
|
|
||||||
s := uuid.String()
|
|
||||||
if m[s] {
|
|
||||||
t.Errorf("NewRandom returned duplicated UUID %s\n", s)
|
|
||||||
}
|
|
||||||
m[s] = true
|
|
||||||
if v, _ := uuid.Version(); v != 4 {
|
|
||||||
t.Errorf("Random UUID of version %s\n", v)
|
|
||||||
}
|
|
||||||
if uuid.Variant() != RFC4122 {
|
|
||||||
t.Errorf("Random UUID is variant %d\n", uuid.Variant())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNew(t *testing.T) {
|
|
||||||
m := make(map[string]bool)
|
|
||||||
for x := 1; x < 32; x++ {
|
|
||||||
s := New()
|
|
||||||
if m[s] {
|
|
||||||
t.Errorf("New returned duplicated UUID %s\n", s)
|
|
||||||
}
|
|
||||||
m[s] = true
|
|
||||||
uuid := Parse(s)
|
|
||||||
if uuid == nil {
|
|
||||||
t.Errorf("New returned %q which does not decode\n", s)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if v, _ := uuid.Version(); v != 4 {
|
|
||||||
t.Errorf("Random UUID of version %s\n", v)
|
|
||||||
}
|
|
||||||
if uuid.Variant() != RFC4122 {
|
|
||||||
t.Errorf("Random UUID is variant %d\n", uuid.Variant())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func clockSeq(t *testing.T, uuid UUID) int {
|
|
||||||
seq, ok := uuid.ClockSequence()
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("%s: invalid clock sequence\n", uuid)
|
|
||||||
}
|
|
||||||
return seq
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestClockSeq(t *testing.T) {
|
|
||||||
// Fake time.Now for this test to return a monotonically advancing time; restore it at end.
|
|
||||||
defer func(orig func() time.Time) { timeNow = orig }(timeNow)
|
|
||||||
monTime := time.Now()
|
|
||||||
timeNow = func() time.Time {
|
|
||||||
monTime = monTime.Add(1 * time.Second)
|
|
||||||
return monTime
|
|
||||||
}
|
|
||||||
|
|
||||||
SetClockSequence(-1)
|
|
||||||
uuid1 := NewUUID()
|
|
||||||
uuid2 := NewUUID()
|
|
||||||
|
|
||||||
if clockSeq(t, uuid1) != clockSeq(t, uuid2) {
|
|
||||||
t.Errorf("clock sequence %d != %d\n", clockSeq(t, uuid1), clockSeq(t, uuid2))
|
|
||||||
}
|
|
||||||
|
|
||||||
SetClockSequence(-1)
|
|
||||||
uuid2 = NewUUID()
|
|
||||||
|
|
||||||
// Just on the very off chance we generated the same sequence
|
|
||||||
// two times we try again.
|
|
||||||
if clockSeq(t, uuid1) == clockSeq(t, uuid2) {
|
|
||||||
SetClockSequence(-1)
|
|
||||||
uuid2 = NewUUID()
|
|
||||||
}
|
|
||||||
if clockSeq(t, uuid1) == clockSeq(t, uuid2) {
|
|
||||||
t.Errorf("Duplicate clock sequence %d\n", clockSeq(t, uuid1))
|
|
||||||
}
|
|
||||||
|
|
||||||
SetClockSequence(0x1234)
|
|
||||||
uuid1 = NewUUID()
|
|
||||||
if seq := clockSeq(t, uuid1); seq != 0x1234 {
|
|
||||||
t.Errorf("%s: expected seq 0x1234 got 0x%04x\n", uuid1, seq)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCoding(t *testing.T) {
|
|
||||||
text := "7d444840-9dc0-11d1-b245-5ffdce74fad2"
|
|
||||||
urn := "urn:uuid:7d444840-9dc0-11d1-b245-5ffdce74fad2"
|
|
||||||
data := UUID{
|
|
||||||
0x7d, 0x44, 0x48, 0x40,
|
|
||||||
0x9d, 0xc0,
|
|
||||||
0x11, 0xd1,
|
|
||||||
0xb2, 0x45,
|
|
||||||
0x5f, 0xfd, 0xce, 0x74, 0xfa, 0xd2,
|
|
||||||
}
|
|
||||||
if v := data.String(); v != text {
|
|
||||||
t.Errorf("%x: encoded to %s, expected %s\n", data, v, text)
|
|
||||||
}
|
|
||||||
if v := data.URN(); v != urn {
|
|
||||||
t.Errorf("%x: urn is %s, expected %s\n", data, v, urn)
|
|
||||||
}
|
|
||||||
|
|
||||||
uuid := Parse(text)
|
|
||||||
if !Equal(uuid, data) {
|
|
||||||
t.Errorf("%s: decoded to %s, expected %s\n", text, uuid, data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestVersion1(t *testing.T) {
|
|
||||||
uuid1 := NewUUID()
|
|
||||||
uuid2 := NewUUID()
|
|
||||||
|
|
||||||
if Equal(uuid1, uuid2) {
|
|
||||||
t.Errorf("%s:duplicate uuid\n", uuid1)
|
|
||||||
}
|
|
||||||
if v, _ := uuid1.Version(); v != 1 {
|
|
||||||
t.Errorf("%s: version %s expected 1\n", uuid1, v)
|
|
||||||
}
|
|
||||||
if v, _ := uuid2.Version(); v != 1 {
|
|
||||||
t.Errorf("%s: version %s expected 1\n", uuid2, v)
|
|
||||||
}
|
|
||||||
n1 := uuid1.NodeID()
|
|
||||||
n2 := uuid2.NodeID()
|
|
||||||
if !bytes.Equal(n1, n2) {
|
|
||||||
t.Errorf("Different nodes %x != %x\n", n1, n2)
|
|
||||||
}
|
|
||||||
t1, ok := uuid1.Time()
|
|
||||||
if !ok {
|
|
||||||
t.Errorf("%s: invalid time\n", uuid1)
|
|
||||||
}
|
|
||||||
t2, ok := uuid2.Time()
|
|
||||||
if !ok {
|
|
||||||
t.Errorf("%s: invalid time\n", uuid2)
|
|
||||||
}
|
|
||||||
q1, ok := uuid1.ClockSequence()
|
|
||||||
if !ok {
|
|
||||||
t.Errorf("%s: invalid clock sequence\n", uuid1)
|
|
||||||
}
|
|
||||||
q2, ok := uuid2.ClockSequence()
|
|
||||||
if !ok {
|
|
||||||
t.Errorf("%s: invalid clock sequence", uuid2)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case t1 == t2 && q1 == q2:
|
|
||||||
t.Errorf("time stopped\n")
|
|
||||||
case t1 > t2 && q1 == q2:
|
|
||||||
t.Errorf("time reversed\n")
|
|
||||||
case t1 < t2 && q1 != q2:
|
|
||||||
t.Errorf("clock sequence chaned unexpectedly\n")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNodeAndTime(t *testing.T) {
|
|
||||||
// Time is February 5, 1998 12:30:23.136364800 AM GMT
|
|
||||||
|
|
||||||
uuid := Parse("7d444840-9dc0-11d1-b245-5ffdce74fad2")
|
|
||||||
node := []byte{0x5f, 0xfd, 0xce, 0x74, 0xfa, 0xd2}
|
|
||||||
|
|
||||||
ts, ok := uuid.Time()
|
|
||||||
if ok {
|
|
||||||
c := time.Unix(ts.UnixTime())
|
|
||||||
want := time.Date(1998, 2, 5, 0, 30, 23, 136364800, time.UTC)
|
|
||||||
if !c.Equal(want) {
|
|
||||||
t.Errorf("Got time %v, want %v", c, want)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
t.Errorf("%s: bad time\n", uuid)
|
|
||||||
}
|
|
||||||
if !bytes.Equal(node, uuid.NodeID()) {
|
|
||||||
t.Errorf("Expected node %v got %v\n", node, uuid.NodeID())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMD5(t *testing.T) {
|
|
||||||
uuid := NewMD5(NameSpace_DNS, []byte("python.org")).String()
|
|
||||||
want := "6fa459ea-ee8a-3ca4-894e-db77e160355e"
|
|
||||||
if uuid != want {
|
|
||||||
t.Errorf("MD5: got %q expected %q\n", uuid, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSHA1(t *testing.T) {
|
|
||||||
uuid := NewSHA1(NameSpace_DNS, []byte("python.org")).String()
|
|
||||||
want := "886313e1-3b8a-5372-9b90-0c9aee199e5d"
|
|
||||||
if uuid != want {
|
|
||||||
t.Errorf("SHA1: got %q expected %q\n", uuid, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNodeID(t *testing.T) {
|
|
||||||
nid := []byte{1, 2, 3, 4, 5, 6}
|
|
||||||
SetNodeInterface("")
|
|
||||||
s := NodeInterface()
|
|
||||||
if s == "" || s == "user" {
|
|
||||||
t.Errorf("NodeInterface %q after SetInteface\n", s)
|
|
||||||
}
|
|
||||||
node1 := NodeID()
|
|
||||||
if node1 == nil {
|
|
||||||
t.Errorf("NodeID nil after SetNodeInterface\n", s)
|
|
||||||
}
|
|
||||||
SetNodeID(nid)
|
|
||||||
s = NodeInterface()
|
|
||||||
if s != "user" {
|
|
||||||
t.Errorf("Expected NodeInterface %q got %q\n", "user", s)
|
|
||||||
}
|
|
||||||
node2 := NodeID()
|
|
||||||
if node2 == nil {
|
|
||||||
t.Errorf("NodeID nil after SetNodeID\n", s)
|
|
||||||
}
|
|
||||||
if bytes.Equal(node1, node2) {
|
|
||||||
t.Errorf("NodeID not changed after SetNodeID\n", s)
|
|
||||||
} else if !bytes.Equal(nid, node2) {
|
|
||||||
t.Errorf("NodeID is %x, expected %x\n", node2, nid)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testDCE(t *testing.T, name string, uuid UUID, domain Domain, id uint32) {
|
|
||||||
if uuid == nil {
|
|
||||||
t.Errorf("%s failed\n", name)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if v, _ := uuid.Version(); v != 2 {
|
|
||||||
t.Errorf("%s: %s: expected version 2, got %s\n", name, uuid, v)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if v, ok := uuid.Domain(); !ok || v != domain {
|
|
||||||
if !ok {
|
|
||||||
t.Errorf("%s: %d: Domain failed\n", name, uuid)
|
|
||||||
} else {
|
|
||||||
t.Errorf("%s: %s: expected domain %d, got %d\n", name, uuid, domain, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if v, ok := uuid.Id(); !ok || v != id {
|
|
||||||
if !ok {
|
|
||||||
t.Errorf("%s: %d: Id failed\n", name, uuid)
|
|
||||||
} else {
|
|
||||||
t.Errorf("%s: %s: expected id %d, got %d\n", name, uuid, id, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDCE(t *testing.T) {
|
|
||||||
testDCE(t, "NewDCESecurity", NewDCESecurity(42, 12345678), 42, 12345678)
|
|
||||||
testDCE(t, "NewDCEPerson", NewDCEPerson(), Person, uint32(os.Getuid()))
|
|
||||||
testDCE(t, "NewDCEGroup", NewDCEGroup(), Group, uint32(os.Getgid()))
|
|
||||||
}
|
|
||||||
|
|
||||||
type badRand struct{}
|
|
||||||
|
|
||||||
func (r badRand) Read(buf []byte) (int, error) {
|
|
||||||
for i, _ := range buf {
|
|
||||||
buf[i] = byte(i)
|
|
||||||
}
|
|
||||||
return len(buf), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBadRand(t *testing.T) {
|
|
||||||
SetRand(badRand{})
|
|
||||||
uuid1 := New()
|
|
||||||
uuid2 := New()
|
|
||||||
if uuid1 != uuid2 {
|
|
||||||
t.Errorf("execpted duplicates, got %q and %q\n", uuid1, uuid2)
|
|
||||||
}
|
|
||||||
SetRand(nil)
|
|
||||||
uuid1 = New()
|
|
||||||
uuid2 = New()
|
|
||||||
if uuid1 == uuid2 {
|
|
||||||
t.Errorf("unexecpted duplicates, got %q\n", uuid1)
|
|
||||||
}
|
|
||||||
}
|
|
41
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/version1.go
generated
vendored
41
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/version1.go
generated
vendored
|
@ -1,41 +0,0 @@
|
||||||
// Copyright 2011 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewUUID returns a Version 1 UUID based on the current NodeID and clock
|
|
||||||
// sequence, and the current time. If the NodeID has not been set by SetNodeID
|
|
||||||
// or SetNodeInterface then it will be set automatically. If the NodeID cannot
|
|
||||||
// be set NewUUID returns nil. If clock sequence has not been set by
|
|
||||||
// SetClockSequence then it will be set automatically. If GetTime fails to
|
|
||||||
// return the current NewUUID returns nil.
|
|
||||||
func NewUUID() UUID {
|
|
||||||
if nodeID == nil {
|
|
||||||
SetNodeInterface("")
|
|
||||||
}
|
|
||||||
|
|
||||||
now, seq, err := GetTime()
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
uuid := make([]byte, 16)
|
|
||||||
|
|
||||||
time_low := uint32(now & 0xffffffff)
|
|
||||||
time_mid := uint16((now >> 32) & 0xffff)
|
|
||||||
time_hi := uint16((now >> 48) & 0x0fff)
|
|
||||||
time_hi |= 0x1000 // Version 1
|
|
||||||
|
|
||||||
binary.BigEndian.PutUint32(uuid[0:], time_low)
|
|
||||||
binary.BigEndian.PutUint16(uuid[4:], time_mid)
|
|
||||||
binary.BigEndian.PutUint16(uuid[6:], time_hi)
|
|
||||||
binary.BigEndian.PutUint16(uuid[8:], seq)
|
|
||||||
copy(uuid[10:], nodeID)
|
|
||||||
|
|
||||||
return uuid
|
|
||||||
}
|
|
25
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/version4.go
generated
vendored
25
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/version4.go
generated
vendored
|
@ -1,25 +0,0 @@
|
||||||
// Copyright 2011 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
// Random returns a Random (Version 4) UUID or panics.
|
|
||||||
//
|
|
||||||
// The strength of the UUIDs is based on the strength of the crypto/rand
|
|
||||||
// package.
|
|
||||||
//
|
|
||||||
// A note about uniqueness derived from from the UUID Wikipedia entry:
|
|
||||||
//
|
|
||||||
// Randomly generated UUIDs have 122 random bits. One's annual risk of being
|
|
||||||
// hit by a meteorite is estimated to be one chance in 17 billion, that
|
|
||||||
// means the probability is about 0.00000000006 (6 × 10−11),
|
|
||||||
// equivalent to the odds of creating a few tens of trillions of UUIDs in a
|
|
||||||
// year and having one duplicate.
|
|
||||||
func NewRandom() UUID {
|
|
||||||
uuid := make([]byte, 16)
|
|
||||||
randomBits([]byte(uuid))
|
|
||||||
uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4
|
|
||||||
uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10
|
|
||||||
return uuid
|
|
||||||
}
|
|
|
@ -1,7 +1,7 @@
|
||||||
package context
|
package context
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"code.google.com/p/go-uuid/uuid"
|
"github.com/docker/distribution/uuid"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ func (ic *instanceContext) Value(key interface{}) interface{} {
|
||||||
|
|
||||||
var background = &instanceContext{
|
var background = &instanceContext{
|
||||||
Context: context.Background(),
|
Context: context.Background(),
|
||||||
id: uuid.New(),
|
id: uuid.Generate().String(),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Background returns a non-nil, empty Context. The background context
|
// Background returns a non-nil, empty Context. The background context
|
||||||
|
|
|
@ -8,8 +8,8 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.google.com/p/go-uuid/uuid"
|
|
||||||
log "github.com/Sirupsen/logrus"
|
log "github.com/Sirupsen/logrus"
|
||||||
|
"github.com/docker/distribution/uuid"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ func WithRequest(ctx Context, r *http.Request) Context {
|
||||||
return &httpRequestContext{
|
return &httpRequestContext{
|
||||||
Context: ctx,
|
Context: ctx,
|
||||||
startedAt: time.Now(),
|
startedAt: time.Now(),
|
||||||
id: uuid.New(), // assign the request a unique.
|
id: uuid.Generate().String(),
|
||||||
r: r,
|
r: r,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@ package context
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/docker/distribution/uuid"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -99,3 +101,8 @@ func getLogrusLogger(ctx Context, keys ...interface{}) *logrus.Entry {
|
||||||
|
|
||||||
return logger.WithFields(fields)
|
return logger.WithFields(fields)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// inject a logger into the uuid library.
|
||||||
|
uuid.Loggerf = GetLogger(Background()).Warnf
|
||||||
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.google.com/p/go-uuid/uuid"
|
"github.com/docker/distribution/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
// WithTrace allocates a traced timing span in a new context. This allows a
|
// WithTrace allocates a traced timing span in a new context. This allows a
|
||||||
|
@ -45,7 +45,7 @@ func WithTrace(ctx Context) (Context, func(format string, a ...interface{})) {
|
||||||
f := runtime.FuncForPC(pc)
|
f := runtime.FuncForPC(pc)
|
||||||
ctx = &traced{
|
ctx = &traced{
|
||||||
Context: ctx,
|
Context: ctx,
|
||||||
id: uuid.New(),
|
id: uuid.Generate().String(),
|
||||||
start: time.Now(),
|
start: time.Now(),
|
||||||
parent: GetStringValue(ctx, "trace.id"),
|
parent: GetStringValue(ctx, "trace.id"),
|
||||||
fnname: f.Name(),
|
fnname: f.Name(),
|
||||||
|
|
|
@ -4,11 +4,11 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.google.com/p/go-uuid/uuid"
|
|
||||||
"github.com/docker/distribution"
|
"github.com/docker/distribution"
|
||||||
"github.com/docker/distribution/context"
|
"github.com/docker/distribution/context"
|
||||||
"github.com/docker/distribution/digest"
|
"github.com/docker/distribution/digest"
|
||||||
"github.com/docker/distribution/manifest"
|
"github.com/docker/distribution/manifest"
|
||||||
|
"github.com/docker/distribution/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
type bridge struct {
|
type bridge struct {
|
||||||
|
@ -149,7 +149,7 @@ func (b *bridge) createEvent(action string) *Event {
|
||||||
// createEvent returns a new event, timestamped, with the specified action.
|
// createEvent returns a new event, timestamped, with the specified action.
|
||||||
func createEvent(action string) *Event {
|
func createEvent(action string) *Event {
|
||||||
return &Event{
|
return &Event{
|
||||||
ID: uuid.New(),
|
ID: uuid.Generate().String(),
|
||||||
Timestamp: time.Now(),
|
Timestamp: time.Now(),
|
||||||
Action: action,
|
Action: action,
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.google.com/p/go-uuid/uuid"
|
"github.com/docker/distribution/uuid"
|
||||||
|
|
||||||
"github.com/docker/distribution"
|
"github.com/docker/distribution"
|
||||||
"github.com/docker/distribution/context"
|
"github.com/docker/distribution/context"
|
||||||
|
@ -141,7 +141,7 @@ func TestBlobUploadChunked(t *testing.T) {
|
||||||
b1[513:1024],
|
b1[513:1024],
|
||||||
}
|
}
|
||||||
repo := "test.example.com/uploadrepo"
|
repo := "test.example.com/uploadrepo"
|
||||||
uuids := []string{uuid.New()}
|
uuids := []string{uuid.Generate().String()}
|
||||||
m = append(m, testutil.RequestResponseMapping{
|
m = append(m, testutil.RequestResponseMapping{
|
||||||
Request: testutil.Request{
|
Request: testutil.Request{
|
||||||
Method: "POST",
|
Method: "POST",
|
||||||
|
@ -159,7 +159,7 @@ func TestBlobUploadChunked(t *testing.T) {
|
||||||
})
|
})
|
||||||
offset := 0
|
offset := 0
|
||||||
for i, chunk := range chunks {
|
for i, chunk := range chunks {
|
||||||
uuids = append(uuids, uuid.New())
|
uuids = append(uuids, uuid.Generate().String())
|
||||||
newOffset := offset + len(chunk)
|
newOffset := offset + len(chunk)
|
||||||
m = append(m, testutil.RequestResponseMapping{
|
m = append(m, testutil.RequestResponseMapping{
|
||||||
Request: testutil.Request{
|
Request: testutil.Request{
|
||||||
|
@ -256,7 +256,7 @@ func TestBlobUploadMonolithic(t *testing.T) {
|
||||||
dgst, b1 := newRandomBlob(1024)
|
dgst, b1 := newRandomBlob(1024)
|
||||||
var m testutil.RequestResponseMap
|
var m testutil.RequestResponseMap
|
||||||
repo := "test.example.com/uploadrepo"
|
repo := "test.example.com/uploadrepo"
|
||||||
uploadID := uuid.New()
|
uploadID := uuid.Generate().String()
|
||||||
m = append(m, testutil.RequestResponseMapping{
|
m = append(m, testutil.RequestResponseMapping{
|
||||||
Request: testutil.Request{
|
Request: testutil.Request{
|
||||||
Method: "POST",
|
Method: "POST",
|
||||||
|
|
|
@ -4,11 +4,11 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.google.com/p/go-uuid/uuid"
|
|
||||||
"github.com/docker/distribution"
|
"github.com/docker/distribution"
|
||||||
"github.com/docker/distribution/context"
|
"github.com/docker/distribution/context"
|
||||||
"github.com/docker/distribution/digest"
|
"github.com/docker/distribution/digest"
|
||||||
"github.com/docker/distribution/registry/storage/driver"
|
"github.com/docker/distribution/registry/storage/driver"
|
||||||
|
"github.com/docker/distribution/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
// linkedBlobStore provides a full BlobService that namespaces the blobs to a
|
// linkedBlobStore provides a full BlobService that namespaces the blobs to a
|
||||||
|
@ -85,7 +85,7 @@ func (lbs *linkedBlobStore) Put(ctx context.Context, mediaType string, p []byte)
|
||||||
func (lbs *linkedBlobStore) Create(ctx context.Context) (distribution.BlobWriter, error) {
|
func (lbs *linkedBlobStore) Create(ctx context.Context) (distribution.BlobWriter, error) {
|
||||||
context.GetLogger(ctx).Debug("(*linkedBlobStore).Writer")
|
context.GetLogger(ctx).Debug("(*linkedBlobStore).Writer")
|
||||||
|
|
||||||
uuid := uuid.New()
|
uuid := uuid.Generate().String()
|
||||||
startedAt := time.Now().UTC()
|
startedAt := time.Now().UTC()
|
||||||
|
|
||||||
path, err := lbs.blobStore.pm.path(uploadDataPathSpec{
|
path, err := lbs.blobStore.pm.path(uploadDataPathSpec{
|
||||||
|
|
|
@ -5,10 +5,10 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.google.com/p/go-uuid/uuid"
|
|
||||||
log "github.com/Sirupsen/logrus"
|
log "github.com/Sirupsen/logrus"
|
||||||
"github.com/docker/distribution/context"
|
"github.com/docker/distribution/context"
|
||||||
storageDriver "github.com/docker/distribution/registry/storage/driver"
|
storageDriver "github.com/docker/distribution/registry/storage/driver"
|
||||||
|
"github.com/docker/distribution/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
// uploadData stored the location of temporary files created during a layer upload
|
// uploadData stored the location of temporary files created during a layer upload
|
||||||
|
@ -116,8 +116,8 @@ func getOutstandingUploads(ctx context.Context, driver storageDriver.StorageDriv
|
||||||
func uUIDFromPath(path string) (string, bool) {
|
func uUIDFromPath(path string) (string, bool) {
|
||||||
components := strings.Split(path, "/")
|
components := strings.Split(path, "/")
|
||||||
for i := len(components) - 1; i >= 0; i-- {
|
for i := len(components) - 1; i >= 0; i-- {
|
||||||
if uuid := uuid.Parse(components[i]); uuid != nil {
|
if u, err := uuid.Parse(components[i]); err == nil {
|
||||||
return uuid.String(), i == len(components)-1
|
return u.String(), i == len(components)-1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "", false
|
return "", false
|
||||||
|
|
|
@ -6,10 +6,10 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.google.com/p/go-uuid/uuid"
|
|
||||||
"github.com/docker/distribution/context"
|
"github.com/docker/distribution/context"
|
||||||
"github.com/docker/distribution/registry/storage/driver"
|
"github.com/docker/distribution/registry/storage/driver"
|
||||||
"github.com/docker/distribution/registry/storage/driver/inmemory"
|
"github.com/docker/distribution/registry/storage/driver/inmemory"
|
||||||
|
"github.com/docker/distribution/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
var pm = defaultPathMapper
|
var pm = defaultPathMapper
|
||||||
|
@ -18,7 +18,7 @@ func testUploadFS(t *testing.T, numUploads int, repoName string, startedAt time.
|
||||||
d := inmemory.New()
|
d := inmemory.New()
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
for i := 0; i < numUploads; i++ {
|
for i := 0; i < numUploads; i++ {
|
||||||
addUploads(ctx, t, d, uuid.New(), repoName, startedAt)
|
addUploads(ctx, t, d, uuid.Generate().String(), repoName, startedAt)
|
||||||
}
|
}
|
||||||
return d, ctx
|
return d, ctx
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ func TestPurgeAll(t *testing.T) {
|
||||||
fs, ctx := testUploadFS(t, uploadCount, "test-repo", oneHourAgo)
|
fs, ctx := testUploadFS(t, uploadCount, "test-repo", oneHourAgo)
|
||||||
|
|
||||||
// Ensure > 1 repos are purged
|
// Ensure > 1 repos are purged
|
||||||
addUploads(ctx, t, fs, uuid.New(), "test-repo2", oneHourAgo)
|
addUploads(ctx, t, fs, uuid.Generate().String(), "test-repo2", oneHourAgo)
|
||||||
uploadCount++
|
uploadCount++
|
||||||
|
|
||||||
deleted, errs := PurgeUploads(ctx, fs, time.Now(), true)
|
deleted, errs := PurgeUploads(ctx, fs, time.Now(), true)
|
||||||
|
@ -95,7 +95,7 @@ func TestPurgeSome(t *testing.T) {
|
||||||
newUploadCount := 4
|
newUploadCount := 4
|
||||||
|
|
||||||
for i := 0; i < newUploadCount; i++ {
|
for i := 0; i < newUploadCount; i++ {
|
||||||
addUploads(ctx, t, fs, uuid.New(), "test-repo", time.Now().Add(1*time.Hour))
|
addUploads(ctx, t, fs, uuid.Generate().String(), "test-repo", time.Now().Add(1*time.Hour))
|
||||||
}
|
}
|
||||||
|
|
||||||
deleted, errs := PurgeUploads(ctx, fs, time.Now(), true)
|
deleted, errs := PurgeUploads(ctx, fs, time.Now(), true)
|
||||||
|
@ -115,7 +115,7 @@ func TestPurgeOnlyUploads(t *testing.T) {
|
||||||
|
|
||||||
// Create a directory tree outside _uploads and ensure
|
// Create a directory tree outside _uploads and ensure
|
||||||
// these files aren't deleted.
|
// these files aren't deleted.
|
||||||
dataPath, err := pm.path(uploadDataPathSpec{name: "test-repo", id: uuid.New()})
|
dataPath, err := pm.path(uploadDataPathSpec{name: "test-repo", id: uuid.Generate().String()})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf(err.Error())
|
t.Fatalf(err.Error())
|
||||||
}
|
}
|
||||||
|
|
112
uuid/uuid.go
Normal file
112
uuid/uuid.go
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
// 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"
|
||||||
|
"log"
|
||||||
|
"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 = log.Printf
|
||||||
|
)
|
||||||
|
|
||||||
|
// 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
|
||||||
|
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
|
||||||
|
|
||||||
|
_, err := io.ReadFull(rand.Reader, u[:])
|
||||||
|
if err != nil {
|
||||||
|
if err == syscall.EPERM {
|
||||||
|
// EPERM represents an entropy pool exhaustion, a condition under
|
||||||
|
// which we backoff and retry.
|
||||||
|
if retries < maxretries {
|
||||||
|
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, 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:])
|
||||||
|
}
|
48
uuid/uuid_test.go
Normal file
48
uuid/uuid_test.go
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue