consul/internal/controller/cache/index/index.go

97 lines
2.0 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package index
import (
"github.com/hashicorp/consul/proto-public/pbresource"
iradix "github.com/hashicorp/go-immutable-radix/v2"
)
type Index struct {
name string
required bool
indexer MultiIndexer
}
func New(name string, i Indexer, opts ...IndexOption) *Index {
if name == "" {
panic("all indexers must have a non-empty name")
}
if i == nil {
panic("no indexer was supplied when creating a new cache Index")
}
var multiIndexer MultiIndexer
switch v := i.(type) {
case SingleIndexer:
multiIndexer = singleIndexWrapper{indexer: v}
case MultiIndexer:
multiIndexer = v
default:
panic("The Indexer must also implement one of the SingleIndexer or MultiIndexer interfaces")
}
idx := &Index{
name: name,
indexer: multiIndexer,
}
for _, opt := range opts {
opt(idx)
}
return idx
}
func (i *Index) Name() string {
return i.name
}
// IndexedData combines the Index with an radix tree for index and resource storage.
func (i *Index) IndexedData() *IndexedData {
return &IndexedData{
Index: i,
tree: iradix.New[[]*pbresource.Resource](),
}
}
// IndexedData is a wrapper around an Index and an radix tree for index and resource storage.
type IndexedData struct {
*Index
tree *iradix.Tree[[]*pbresource.Resource]
}
func (i *IndexedData) Txn() Txn {
return &txn{
inner: i.tree.Txn(),
index: i,
dirty: false,
}
}
func (i *Index) fromArgs(args ...any) ([]byte, error) {
return i.indexer.FromArgs(args...)
}
func (i *Index) fromResource(r *pbresource.Resource) (bool, [][]byte, error) {
return i.indexer.FromResource(r)
}
type singleIndexWrapper struct {
indexer SingleIndexer
}
func (s singleIndexWrapper) FromArgs(args ...any) ([]byte, error) {
return s.indexer.FromArgs(args...)
}
func (s singleIndexWrapper) FromResource(r *pbresource.Resource) (bool, [][]byte, error) {
indexed, val, err := s.indexer.FromResource(r)
if err != nil || !indexed {
return false, nil, err
}
return true, [][]byte{val}, nil
}