mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Revendor go-memdb to floridoo/go-memdb's fork (608dda3b1410a73eaf3ac8b517c9ae7ebab6aa87)
We are temporarily using a fork containing a PR that hasn't been merged upstream yet. Signed-off-by: Andrea Luzzardi <aluzzardi@gmail.com>
This commit is contained in:
parent
da499758b8
commit
9322636c89
4 changed files with 175 additions and 87 deletions
|
@ -108,7 +108,7 @@ github.com/google/certificate-transparency d90e65c3a07988180c5b1ece71791c0b65068
|
||||||
golang.org/x/crypto 3fbbcd23f1cb824e69491a5930cfeff09b12f4d2
|
golang.org/x/crypto 3fbbcd23f1cb824e69491a5930cfeff09b12f4d2
|
||||||
golang.org/x/time a4bde12657593d5e90d0533a3e4fd95e635124cb
|
golang.org/x/time a4bde12657593d5e90d0533a3e4fd95e635124cb
|
||||||
github.com/mreiferson/go-httpclient 63fe23f7434723dc904c901043af07931f293c47
|
github.com/mreiferson/go-httpclient 63fe23f7434723dc904c901043af07931f293c47
|
||||||
github.com/hashicorp/go-memdb 98f52f52d7a476958fa9da671354d270c50661a7
|
github.com/hashicorp/go-memdb 608dda3b1410a73eaf3ac8b517c9ae7ebab6aa87 https://github.com/floridoo/go-memdb
|
||||||
github.com/hashicorp/go-immutable-radix 8e8ed81f8f0bf1bdd829593fdd5c29922c1ea990
|
github.com/hashicorp/go-immutable-radix 8e8ed81f8f0bf1bdd829593fdd5c29922c1ea990
|
||||||
github.com/hashicorp/golang-lru a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4
|
github.com/hashicorp/golang-lru a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4
|
||||||
github.com/coreos/pkg fa29b1d70f0beaddd4c7021607cc3c3be8ce94b8
|
github.com/coreos/pkg fa29b1d70f0beaddd4c7021607cc3c3be8ce94b8
|
||||||
|
|
124
vendor/github.com/hashicorp/go-memdb/index.go
generated
vendored
124
vendor/github.com/hashicorp/go-memdb/index.go
generated
vendored
|
@ -9,15 +9,27 @@ import (
|
||||||
|
|
||||||
// Indexer is an interface used for defining indexes
|
// Indexer is an interface used for defining indexes
|
||||||
type Indexer interface {
|
type Indexer interface {
|
||||||
// FromObject is used to extract an index value from an
|
|
||||||
// object or to indicate that the index value is missing.
|
|
||||||
FromObject(raw interface{}) (bool, []byte, error)
|
|
||||||
|
|
||||||
// ExactFromArgs is used to build an exact index lookup
|
// ExactFromArgs is used to build an exact index lookup
|
||||||
// based on arguments
|
// based on arguments
|
||||||
FromArgs(args ...interface{}) ([]byte, error)
|
FromArgs(args ...interface{}) ([]byte, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SingleIndexer is an interface used for defining indexes
|
||||||
|
// generating a single entry per object
|
||||||
|
type SingleIndexer interface {
|
||||||
|
// FromObject is used to extract an index value from an
|
||||||
|
// object or to indicate that the index value is missing.
|
||||||
|
FromObject(raw interface{}) (bool, []byte, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MultiIndexer is an interface used for defining indexes
|
||||||
|
// generating multiple entries per object
|
||||||
|
type MultiIndexer interface {
|
||||||
|
// FromObject is used to extract index values from an
|
||||||
|
// object or to indicate that the index value is missing.
|
||||||
|
FromObject(raw interface{}) (bool, [][]byte, error)
|
||||||
|
}
|
||||||
|
|
||||||
// PrefixIndexer can optionally be implemented for any
|
// PrefixIndexer can optionally be implemented for any
|
||||||
// indexes that support prefix based iteration. This may
|
// indexes that support prefix based iteration. This may
|
||||||
// not apply to all indexes.
|
// not apply to all indexes.
|
||||||
|
@ -88,6 +100,79 @@ func (s *StringFieldIndex) PrefixFromArgs(args ...interface{}) ([]byte, error) {
|
||||||
return val, nil
|
return val, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StringSliceFieldIndex is used to extract a field from an object
|
||||||
|
// using reflection and builds an index on that field.
|
||||||
|
type StringSliceFieldIndex struct {
|
||||||
|
Field string
|
||||||
|
Lowercase bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StringSliceFieldIndex) FromObject(obj interface{}) (bool, [][]byte, error) {
|
||||||
|
v := reflect.ValueOf(obj)
|
||||||
|
v = reflect.Indirect(v) // Dereference the pointer if any
|
||||||
|
|
||||||
|
fv := v.FieldByName(s.Field)
|
||||||
|
if !fv.IsValid() {
|
||||||
|
return false, nil,
|
||||||
|
fmt.Errorf("field '%s' for %#v is invalid", s.Field, obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
if fv.Kind() != reflect.Slice || fv.Type().Elem().Kind() != reflect.String {
|
||||||
|
return false, nil, fmt.Errorf("field '%s' is not a string slice", s.Field)
|
||||||
|
}
|
||||||
|
|
||||||
|
length := fv.Len()
|
||||||
|
vals := make([][]byte, 0, length)
|
||||||
|
for i := 0; i < fv.Len(); i++ {
|
||||||
|
val := fv.Index(i).String()
|
||||||
|
if val == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Lowercase {
|
||||||
|
val = strings.ToLower(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the null character as a terminator
|
||||||
|
val += "\x00"
|
||||||
|
vals = append(vals, []byte(val))
|
||||||
|
}
|
||||||
|
if len(vals) == 0 {
|
||||||
|
return false, nil, nil
|
||||||
|
}
|
||||||
|
return true, vals, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StringSliceFieldIndex) FromArgs(args ...interface{}) ([]byte, error) {
|
||||||
|
if len(args) != 1 {
|
||||||
|
return nil, fmt.Errorf("must provide only a single argument")
|
||||||
|
}
|
||||||
|
arg, ok := args[0].(string)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("argument must be a string: %#v", args[0])
|
||||||
|
}
|
||||||
|
if s.Lowercase {
|
||||||
|
arg = strings.ToLower(arg)
|
||||||
|
}
|
||||||
|
// Add the null character as a terminator
|
||||||
|
arg += "\x00"
|
||||||
|
return []byte(arg), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StringSliceFieldIndex) PrefixFromArgs(args ...interface{}) ([]byte, error) {
|
||||||
|
val, err := s.FromArgs(args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strip the null terminator, the rest is a prefix
|
||||||
|
n := len(val)
|
||||||
|
if n > 0 {
|
||||||
|
return val[:n-1], nil
|
||||||
|
}
|
||||||
|
return val, nil
|
||||||
|
}
|
||||||
|
|
||||||
// UUIDFieldIndex is used to extract a field from an object
|
// UUIDFieldIndex is used to extract a field from an object
|
||||||
// using reflection and builds an index on that field by treating
|
// using reflection and builds an index on that field by treating
|
||||||
// it as a UUID. This is an optimization to using a StringFieldIndex
|
// it as a UUID. This is an optimization to using a StringFieldIndex
|
||||||
|
@ -270,7 +355,11 @@ type CompoundIndex struct {
|
||||||
|
|
||||||
func (c *CompoundIndex) FromObject(raw interface{}) (bool, []byte, error) {
|
func (c *CompoundIndex) FromObject(raw interface{}) (bool, []byte, error) {
|
||||||
var out []byte
|
var out []byte
|
||||||
for i, idx := range c.Indexes {
|
for i, idxRaw := range c.Indexes {
|
||||||
|
idx, ok := idxRaw.(SingleIndexer)
|
||||||
|
if !ok {
|
||||||
|
return false, nil, fmt.Errorf("sub-index %d error: %s", i, "sub-index must be a SingleIndexer")
|
||||||
|
}
|
||||||
ok, val, err := idx.FromObject(raw)
|
ok, val, err := idx.FromObject(raw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, fmt.Errorf("sub-index %d error: %v", i, err)
|
return false, nil, fmt.Errorf("sub-index %d error: %v", i, err)
|
||||||
|
@ -291,40 +380,17 @@ func (c *CompoundIndex) FromArgs(args ...interface{}) ([]byte, error) {
|
||||||
if len(args) != len(c.Indexes) {
|
if len(args) != len(c.Indexes) {
|
||||||
return nil, fmt.Errorf("less arguments than index fields")
|
return nil, fmt.Errorf("less arguments than index fields")
|
||||||
}
|
}
|
||||||
var out []byte
|
return c.PrefixFromArgs(args...)
|
||||||
for i, arg := range args {
|
|
||||||
val, err := c.Indexes[i].FromArgs(arg)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("sub-index %d error: %v", i, err)
|
|
||||||
}
|
|
||||||
out = append(out, val...)
|
|
||||||
}
|
|
||||||
return out, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CompoundIndex) PrefixFromArgs(args ...interface{}) ([]byte, error) {
|
func (c *CompoundIndex) PrefixFromArgs(args ...interface{}) ([]byte, error) {
|
||||||
if len(args) > len(c.Indexes) {
|
|
||||||
return nil, fmt.Errorf("more arguments than index fields")
|
|
||||||
}
|
|
||||||
var out []byte
|
var out []byte
|
||||||
for i, arg := range args {
|
for i, arg := range args {
|
||||||
if i+1 < len(args) {
|
|
||||||
val, err := c.Indexes[i].FromArgs(arg)
|
val, err := c.Indexes[i].FromArgs(arg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("sub-index %d error: %v", i, err)
|
return nil, fmt.Errorf("sub-index %d error: %v", i, err)
|
||||||
}
|
}
|
||||||
out = append(out, val...)
|
out = append(out, val...)
|
||||||
} else {
|
|
||||||
prefixIndexer, ok := c.Indexes[i].(PrefixIndexer)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("sub-index %d does not support prefix scanning", i)
|
|
||||||
}
|
|
||||||
val, err := prefixIndexer.PrefixFromArgs(arg)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("sub-index %d error: %v", i, err)
|
|
||||||
}
|
|
||||||
out = append(out, val...)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
9
vendor/github.com/hashicorp/go-memdb/schema.go
generated
vendored
9
vendor/github.com/hashicorp/go-memdb/schema.go
generated
vendored
|
@ -46,6 +46,9 @@ func (s *TableSchema) Validate() error {
|
||||||
if !s.Indexes["id"].Unique {
|
if !s.Indexes["id"].Unique {
|
||||||
return fmt.Errorf("id index must be unique")
|
return fmt.Errorf("id index must be unique")
|
||||||
}
|
}
|
||||||
|
if _, ok := s.Indexes["id"].Indexer.(SingleIndexer); !ok {
|
||||||
|
return fmt.Errorf("id index must be a SingleIndexer")
|
||||||
|
}
|
||||||
for name, index := range s.Indexes {
|
for name, index := range s.Indexes {
|
||||||
if name != index.Name {
|
if name != index.Name {
|
||||||
return fmt.Errorf("index name mis-match for '%s'", name)
|
return fmt.Errorf("index name mis-match for '%s'", name)
|
||||||
|
@ -72,5 +75,11 @@ func (s *IndexSchema) Validate() error {
|
||||||
if s.Indexer == nil {
|
if s.Indexer == nil {
|
||||||
return fmt.Errorf("missing index function for '%s'", s.Name)
|
return fmt.Errorf("missing index function for '%s'", s.Name)
|
||||||
}
|
}
|
||||||
|
switch s.Indexer.(type) {
|
||||||
|
case SingleIndexer:
|
||||||
|
case MultiIndexer:
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("indexer for '%s' must be a SingleIndexer or MultiIndexer", s.Name)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
93
vendor/github.com/hashicorp/go-memdb/txn.go
generated
vendored
93
vendor/github.com/hashicorp/go-memdb/txn.go
generated
vendored
|
@ -148,7 +148,8 @@ func (txn *Txn) Insert(table string, obj interface{}) error {
|
||||||
|
|
||||||
// Get the primary ID of the object
|
// Get the primary ID of the object
|
||||||
idSchema := tableSchema.Indexes[id]
|
idSchema := tableSchema.Indexes[id]
|
||||||
ok, idVal, err := idSchema.Indexer.FromObject(obj)
|
idIndexer := idSchema.Indexer.(SingleIndexer)
|
||||||
|
ok, idVal, err := idIndexer.FromObject(obj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to build primary index: %v", err)
|
return fmt.Errorf("failed to build primary index: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -167,7 +168,19 @@ func (txn *Txn) Insert(table string, obj interface{}) error {
|
||||||
indexTxn := txn.writableIndex(table, name)
|
indexTxn := txn.writableIndex(table, name)
|
||||||
|
|
||||||
// Determine the new index value
|
// Determine the new index value
|
||||||
ok, val, err := indexSchema.Indexer.FromObject(obj)
|
var (
|
||||||
|
ok bool
|
||||||
|
vals [][]byte
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
switch indexer := indexSchema.Indexer.(type) {
|
||||||
|
case SingleIndexer:
|
||||||
|
var val []byte
|
||||||
|
ok, val, err = indexer.FromObject(obj)
|
||||||
|
vals = [][]byte{val}
|
||||||
|
case MultiIndexer:
|
||||||
|
ok, vals, err = indexer.FromObject(obj)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to build index '%s': %v", name, err)
|
return fmt.Errorf("failed to build index '%s': %v", name, err)
|
||||||
}
|
}
|
||||||
|
@ -176,16 +189,31 @@ func (txn *Txn) Insert(table string, obj interface{}) error {
|
||||||
// This is done by appending the primary key which must
|
// This is done by appending the primary key which must
|
||||||
// be unique anyways.
|
// be unique anyways.
|
||||||
if ok && !indexSchema.Unique {
|
if ok && !indexSchema.Unique {
|
||||||
val = append(val, idVal...)
|
for i := range vals {
|
||||||
|
vals[i] = append(vals[i], idVal...)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle the update by deleting from the index first
|
// Handle the update by deleting from the index first
|
||||||
if update {
|
if update {
|
||||||
okExist, valExist, err := indexSchema.Indexer.FromObject(existing)
|
var (
|
||||||
|
okExist bool
|
||||||
|
valsExist [][]byte
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
switch indexer := indexSchema.Indexer.(type) {
|
||||||
|
case SingleIndexer:
|
||||||
|
var valExist []byte
|
||||||
|
okExist, valExist, err = indexer.FromObject(existing)
|
||||||
|
valsExist = [][]byte{valExist}
|
||||||
|
case MultiIndexer:
|
||||||
|
okExist, valsExist, err = indexer.FromObject(existing)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to build index '%s': %v", name, err)
|
return fmt.Errorf("failed to build index '%s': %v", name, err)
|
||||||
}
|
}
|
||||||
if okExist {
|
if okExist {
|
||||||
|
for i, valExist := range valsExist {
|
||||||
// Handle non-unique index by computing a unique index.
|
// Handle non-unique index by computing a unique index.
|
||||||
// This is done by appending the primary key which must
|
// This is done by appending the primary key which must
|
||||||
// be unique anyways.
|
// be unique anyways.
|
||||||
|
@ -196,11 +224,12 @@ func (txn *Txn) Insert(table string, obj interface{}) error {
|
||||||
// If we are writing to the same index with the same value,
|
// If we are writing to the same index with the same value,
|
||||||
// we can avoid the delete as the insert will overwrite the
|
// we can avoid the delete as the insert will overwrite the
|
||||||
// value anyways.
|
// value anyways.
|
||||||
if !bytes.Equal(valExist, val) {
|
if i >= len(vals) || !bytes.Equal(valExist, vals[i]) {
|
||||||
indexTxn.Delete(valExist)
|
indexTxn.Delete(valExist)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If there is no index value, either this is an error or an expected
|
// If there is no index value, either this is an error or an expected
|
||||||
// case and we can skip updating
|
// case and we can skip updating
|
||||||
|
@ -213,8 +242,10 @@ func (txn *Txn) Insert(table string, obj interface{}) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the value of the index
|
// Update the value of the index
|
||||||
|
for _, val := range vals {
|
||||||
indexTxn.Insert(val, obj)
|
indexTxn.Insert(val, obj)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,7 +264,8 @@ func (txn *Txn) Delete(table string, obj interface{}) error {
|
||||||
|
|
||||||
// Get the primary ID of the object
|
// Get the primary ID of the object
|
||||||
idSchema := tableSchema.Indexes[id]
|
idSchema := tableSchema.Indexes[id]
|
||||||
ok, idVal, err := idSchema.Indexer.FromObject(obj)
|
idIndexer := idSchema.Indexer.(SingleIndexer)
|
||||||
|
ok, idVal, err := idIndexer.FromObject(obj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to build primary index: %v", err)
|
return fmt.Errorf("failed to build primary index: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -253,7 +285,19 @@ func (txn *Txn) Delete(table string, obj interface{}) error {
|
||||||
indexTxn := txn.writableIndex(table, name)
|
indexTxn := txn.writableIndex(table, name)
|
||||||
|
|
||||||
// Handle the update by deleting from the index first
|
// Handle the update by deleting from the index first
|
||||||
ok, val, err := indexSchema.Indexer.FromObject(existing)
|
var (
|
||||||
|
ok bool
|
||||||
|
vals [][]byte
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
switch indexer := indexSchema.Indexer.(type) {
|
||||||
|
case SingleIndexer:
|
||||||
|
var val []byte
|
||||||
|
ok, val, err = indexer.FromObject(existing)
|
||||||
|
vals = [][]byte{val}
|
||||||
|
case MultiIndexer:
|
||||||
|
ok, vals, err = indexer.FromObject(existing)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to build index '%s': %v", name, err)
|
return fmt.Errorf("failed to build index '%s': %v", name, err)
|
||||||
}
|
}
|
||||||
|
@ -261,12 +305,14 @@ func (txn *Txn) Delete(table string, obj interface{}) error {
|
||||||
// Handle non-unique index by computing a unique index.
|
// Handle non-unique index by computing a unique index.
|
||||||
// This is done by appending the primary key which must
|
// This is done by appending the primary key which must
|
||||||
// be unique anyways.
|
// be unique anyways.
|
||||||
|
for _, val := range vals {
|
||||||
if !indexSchema.Unique {
|
if !indexSchema.Unique {
|
||||||
val = append(val, idVal...)
|
val = append(val, idVal...)
|
||||||
}
|
}
|
||||||
indexTxn.Delete(val)
|
indexTxn.Delete(val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,39 +380,6 @@ func (txn *Txn) First(table, index string, args ...interface{}) (interface{}, er
|
||||||
return value, nil
|
return value, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// LongestPrefix is used to fetch the longest prefix match for the given
|
|
||||||
// constraints on the index. Note that this will not work with the memdb
|
|
||||||
// StringFieldIndex because it adds null terminators which prevent the
|
|
||||||
// algorithm from correctly finding a match (it will get to right before the
|
|
||||||
// null and fail to find a leaf node). This should only be used where the prefix
|
|
||||||
// given is capable of matching indexed entries directly, which typically only
|
|
||||||
// applies to a custom indexer. See the unit test for an example.
|
|
||||||
func (txn *Txn) LongestPrefix(table, index string, args ...interface{}) (interface{}, error) {
|
|
||||||
// Enforce that this only works on prefix indexes.
|
|
||||||
if !strings.HasSuffix(index, "_prefix") {
|
|
||||||
return nil, fmt.Errorf("must use '%s_prefix' on index", index)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the index value.
|
|
||||||
indexSchema, val, err := txn.getIndexValue(table, index, args...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// This algorithm only makes sense against a unique index, otherwise the
|
|
||||||
// index keys will have the IDs appended to them.
|
|
||||||
if !indexSchema.Unique {
|
|
||||||
return nil, fmt.Errorf("index '%s' is not unique", index)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the longest prefix match with the given index.
|
|
||||||
indexTxn := txn.readableIndex(table, indexSchema.Name)
|
|
||||||
if _, value, ok := indexTxn.Root().LongestPrefix(val); ok {
|
|
||||||
return value, nil
|
|
||||||
}
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// getIndexValue is used to get the IndexSchema and the value
|
// getIndexValue is used to get the IndexSchema and the value
|
||||||
// used to scan the index given the parameters. This handles prefix based
|
// used to scan the index given the parameters. This handles prefix based
|
||||||
// scans when the index has the "_prefix" suffix. The index must support
|
// scans when the index has the "_prefix" suffix. The index must support
|
||||||
|
|
Loading…
Add table
Reference in a new issue