| Index: appengine/cmd/dm/distributor/registry.go
|
| diff --git a/appengine/cmd/dm/distributor/registry.go b/appengine/cmd/dm/distributor/registry.go
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b441308ca6cb12b69fefad6cf3587e8f402bba47
|
| --- /dev/null
|
| +++ b/appengine/cmd/dm/distributor/registry.go
|
| @@ -0,0 +1,107 @@
|
| +// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +package distributor
|
| +
|
| +import (
|
| + "fmt"
|
| + "reflect"
|
| + "sync"
|
| +
|
| + "github.com/golang/protobuf/proto"
|
| + "github.com/luci/gae/service/info"
|
| + protos "github.com/luci/luci-go/appengine/cmd/dm/distributor/protos"
|
| + "golang.org/x/net/context"
|
| +)
|
| +
|
| +var registry = struct {
|
| + sync.RWMutex
|
| + data map[reflect.Type]Factory
|
| +}{data: map[reflect.Type]Factory{}}
|
| +
|
| +// Register enrolls a new distributor type in the registry. Calling
|
| +// this multiple times for the same proto Message will panic.
|
| +func Register(p proto.Message, factory Factory) {
|
| + if factory == nil {
|
| + panic("factory is nil")
|
| + }
|
| + if p == nil {
|
| + panic("proto.Message is nil")
|
| + }
|
| +
|
| + typ := reflect.TypeOf(p)
|
| +
|
| + registry.Lock()
|
| + defer registry.Unlock()
|
| + if _, ok := registry.data[typ]; ok {
|
| + panic(fmt.Errorf("trying to register %q twice", typ))
|
| + }
|
| + registry.data[typ] = factory
|
| +}
|
| +
|
| +// MakeDistributor builds a distributor instance that's configured with the
|
| +// provided config.
|
| +//
|
| +// The configuration for this distributor are obtained from luci-config at the
|
| +// time an Execution is started.
|
| +func MakeDistributor(c context.Context, cfg *Config) (D, error) {
|
| + typ := reflect.TypeOf(cfg.ImplConfig)
|
| +
|
| + registry.RLock()
|
| + fn, ok := registry.data[typ]
|
| + registry.RUnlock()
|
| +
|
| + if !ok {
|
| + return nil, fmt.Errorf("unknown distributor type %T", cfg.ImplConfig)
|
| + }
|
| +
|
| + return fn(c, cfg)
|
| +}
|
| +
|
| +// LoadConfiguration loads the named distributor configurtaion from luci-config,
|
| +// possibly using the in-memory or memcache version.
|
| +func LoadConfiguration(c context.Context, cfgName string) (ret *Config, err error) {
|
| + cfgVersion := ""
|
| + fullDMConfig := proto.Message(nil)
|
| + // TODO(riannucci): get config and version from luci-config in a fast cached way.
|
| +
|
| + configs := fullDMConfig.(*protos.Config)
|
| + cfg, ok := configs.DistributorConfigs[cfgName]
|
| + if !ok {
|
| + err = fmt.Errorf("unknown distributor configuration: %q", cfgName)
|
| + return
|
| + }
|
| + if alias := cfg.GetAlias(); alias != nil {
|
| + cfg, ok = configs.DistributorConfigs[alias.OtherConfig]
|
| + if !ok {
|
| + err = fmt.Errorf("unknown distributor configuration: %q (via alias %q)", cfgName, alias.OtherConfig)
|
| + return
|
| + }
|
| + if cfg.GetAlias() != nil {
|
| + err = fmt.Errorf("too many levels of indirection for alias %q (points to alias %q)", cfgName, alias.OtherConfig)
|
| + return
|
| + }
|
| + }
|
| +
|
| + dt := cfg.GetDistributorType()
|
| + if dt == nil {
|
| + err = fmt.Errorf("blank or unrecognized distributor_type")
|
| + return
|
| + }
|
| + dVal := reflect.ValueOf(dt)
|
| +
|
| + // All non-nil DistributorType's have a single field which is the actual oneof
|
| + // value.
|
| + implConfig := dVal.Field(0).Interface().(proto.Message)
|
| +
|
| + baseURL := fmt.Sprintf("https://%s/", info.Get(c).DefaultVersionHostname())
|
| + ret = &Config{
|
| + baseURL,
|
| + baseURL + handlerPath(cfgName),
|
| + cfgName,
|
| + cfgVersion,
|
| + implConfig,
|
| + }
|
| + return
|
| +}
|
|
|