state: fix prefix index with the new pattern

Prefix queries are generally being used to match part of a partial
index. We can support these indexes by using a function that accept
different types for each subset of the index.

What I found interesting is that in the generic StringFieldIndexer the
implementation for PrefixFromArgs would remove the trailing null, but
at least in these 2 cases we actually want a null terminated string.
We simply want fewer components in the string.
This commit is contained in:
Daniel Nephin 2021-02-12 16:52:09 -05:00
parent d90845f26d
commit 627c469f08
5 changed files with 19 additions and 7 deletions

View File

@ -28,7 +28,7 @@ const (
minUUIDLookupLen = 2
)
// Query is type used to query any single value index that may include an
// Query is a type used to query any single value index that may include an
// enterprise identifier.
type Query struct {
Value string

View File

@ -103,6 +103,17 @@ func indexFromServiceNode(raw interface{}) ([]byte, error) {
return b.Bytes(), nil
}
func prefixIndexFromQuery(arg interface{}) ([]byte, error) {
var b indexBuilder
switch v := arg.(type) {
case Query:
b.String(strings.ToLower(v.Value))
return b.Bytes(), nil
}
return nil, fmt.Errorf("unexpected type %T for NodeServiceQuery prefix index", arg)
}
func serviceIndexName(name string, _ *structs.EnterpriseMeta) string {
return fmt.Sprintf("service.%s", name)
}

View File

@ -72,9 +72,10 @@ func servicesTableSchema() *memdb.TableSchema {
Name: indexID,
AllowMissing: false,
Unique: true,
Indexer: indexerSingle{
readIndex: readIndex(indexFromNodeServiceQuery),
writeIndex: writeIndex(indexFromServiceNode),
Indexer: indexerSingleWithPrefix{
readIndex: readIndex(indexFromNodeServiceQuery),
writeIndex: writeIndex(indexFromServiceNode),
prefixIndex: prefixIndex(prefixIndexFromQuery),
},
},
indexNode: {

View File

@ -53,7 +53,7 @@ func (f readIndex) FromArgs(args ...interface{}) ([]byte, error) {
var errMissingValueForIndex = fmt.Errorf("object is missing a value for this index")
// writeIndex implements memdb.SingleIndexer. It is used so that a function
// writeIndex implements memdb.SingleIndexer. It exists so that a function
// can be used to provide this interface.
//
// Instead of a bool return value, writeIndex expects errMissingValueForIndex to
@ -69,7 +69,7 @@ func (f writeIndex) FromObject(raw interface{}) (bool, []byte, error) {
return err == nil, v, err
}
// writeIndexMulti implements memdb.MultiIndexer. It is used so that a function
// writeIndexMulti implements memdb.MultiIndexer. It exists so that a function
// can be used to provide this interface.
//
// Instead of a bool return value, writeIndexMulti expects errMissingValueForIndex to

View File

@ -150,7 +150,7 @@ table=services
index=connect allow-missing
indexer=github.com/hashicorp/consul/agent/consul/state.IndexConnectService
index=id unique
indexer=github.com/hashicorp/consul/agent/consul/state.indexerSingle readIndex=github.com/hashicorp/consul/agent/consul/state.indexFromNodeServiceQuery writeIndex=github.com/hashicorp/consul/agent/consul/state.indexFromServiceNode
indexer=github.com/hashicorp/consul/agent/consul/state.indexerSingleWithPrefix readIndex=github.com/hashicorp/consul/agent/consul/state.indexFromNodeServiceQuery writeIndex=github.com/hashicorp/consul/agent/consul/state.indexFromServiceNode prefixIndex=github.com/hashicorp/consul/agent/consul/state.prefixIndexFromQuery
index=kind
indexer=github.com/hashicorp/consul/agent/consul/state.IndexServiceKind
index=node