зеркало из https://github.com/github/vitess-gh.git
221 строка
6.5 KiB
Go
221 строка
6.5 KiB
Go
/*
|
|
Copyright 2019 The Vitess Authors.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package throttler
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
"sync"
|
|
|
|
"vitess.io/vitess/go/vt/log"
|
|
|
|
throttlerdatapb "vitess.io/vitess/go/vt/proto/throttlerdata"
|
|
)
|
|
|
|
// GlobalManager is the per-process manager which manages all active throttlers.
|
|
var GlobalManager = newManager()
|
|
|
|
// Manager defines the public interface of the throttler manager. It is used
|
|
// for example by the different RPC implementations.
|
|
type Manager interface {
|
|
// MaxRates returns the max rate of all known throttlers.
|
|
MaxRates() map[string]int64
|
|
|
|
// SetMaxRate sets the max rate on all known throttlers.
|
|
// It returns the names of the updated throttlers.
|
|
SetMaxRate(rate int64) []string
|
|
|
|
// GetConfiguration returns the configuration of the MaxReplicationlag module
|
|
// for the given throttler or all throttlers if "throttlerName" is empty.
|
|
GetConfiguration(throttlerName string) (map[string]*throttlerdatapb.Configuration, error)
|
|
|
|
// UpdateConfiguration (partially) updates the configuration of the
|
|
// MaxReplicationlag module for the given throttler or all throttlers if
|
|
// "throttlerName" is empty.
|
|
// If "copyZeroValues" is true, fields with zero values will be copied
|
|
// as well.
|
|
// The function returns the names of the updated throttlers.
|
|
UpdateConfiguration(throttlerName string, configuration *throttlerdatapb.Configuration, copyZeroValues bool) ([]string, error)
|
|
|
|
// ResetConfiguration resets the configuration of the MaxReplicationlag module
|
|
// to the initial configuration for the given throttler or all throttlers if
|
|
// "throttlerName" is empty.
|
|
// The function returns the names of the updated throttlers.
|
|
ResetConfiguration(throttlerName string) ([]string, error)
|
|
}
|
|
|
|
// managerImpl controls multiple throttlers and also aggregates their
|
|
// statistics. It implements the "Manager" interface.
|
|
type managerImpl struct {
|
|
// mu guards all fields in this group.
|
|
mu sync.Mutex
|
|
// throttlers tracks all running throttlers (by their name).
|
|
throttlers map[string]*Throttler
|
|
}
|
|
|
|
func newManager() *managerImpl {
|
|
return &managerImpl{
|
|
throttlers: make(map[string]*Throttler),
|
|
}
|
|
}
|
|
|
|
func (m *managerImpl) registerThrottler(name string, throttler *Throttler) error {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
|
|
if _, ok := m.throttlers[name]; ok {
|
|
return fmt.Errorf("registerThrottler(): throttler with name '%v' is already registered", name)
|
|
}
|
|
m.throttlers[name] = throttler
|
|
return nil
|
|
}
|
|
|
|
func (m *managerImpl) unregisterThrottler(name string) {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
|
|
if _, ok := m.throttlers[name]; !ok {
|
|
log.Errorf("unregisterThrottler(): throttler with name '%v' is not registered", name)
|
|
return
|
|
}
|
|
delete(m.throttlers, name)
|
|
}
|
|
|
|
// MaxRates returns the max rate of all known throttlers.
|
|
func (m *managerImpl) MaxRates() map[string]int64 {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
|
|
rates := make(map[string]int64, len(m.throttlers))
|
|
for name, t := range m.throttlers {
|
|
rates[name] = t.MaxRate()
|
|
}
|
|
return rates
|
|
}
|
|
|
|
// SetMaxRate sets the max rate on all known throttlers.
|
|
func (m *managerImpl) SetMaxRate(rate int64) []string {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
|
|
for _, t := range m.throttlers {
|
|
t.SetMaxRate(rate)
|
|
}
|
|
return m.throttlerNamesLocked()
|
|
}
|
|
|
|
// GetConfiguration implements the "Manager" interface.
|
|
func (m *managerImpl) GetConfiguration(throttlerName string) (map[string]*throttlerdatapb.Configuration, error) {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
|
|
configurations := make(map[string]*throttlerdatapb.Configuration)
|
|
|
|
if throttlerName != "" {
|
|
t, ok := m.throttlers[throttlerName]
|
|
if !ok {
|
|
return nil, fmt.Errorf("throttler: %v does not exist", throttlerName)
|
|
}
|
|
configurations[throttlerName] = t.GetConfiguration()
|
|
return configurations, nil
|
|
}
|
|
|
|
for name, t := range m.throttlers {
|
|
configurations[name] = t.GetConfiguration()
|
|
}
|
|
return configurations, nil
|
|
}
|
|
|
|
// UpdateConfiguration implements the "Manager" interface.
|
|
func (m *managerImpl) UpdateConfiguration(throttlerName string, configuration *throttlerdatapb.Configuration, copyZeroValues bool) ([]string, error) {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
|
|
// Note: The calls to t.UpdateConfiguration() below return no error but the
|
|
// called protobuf library functions may panic. This is fine because the
|
|
// throttler RPC service has a panic handler which will catch this.
|
|
|
|
if throttlerName != "" {
|
|
t, ok := m.throttlers[throttlerName]
|
|
if !ok {
|
|
return nil, fmt.Errorf("throttler: %v does not exist", throttlerName)
|
|
}
|
|
if err := t.UpdateConfiguration(configuration, copyZeroValues); err != nil {
|
|
return nil, fmt.Errorf("failed to update throttler: %v err: %v", throttlerName, err)
|
|
}
|
|
return []string{throttlerName}, nil
|
|
}
|
|
|
|
for name, t := range m.throttlers {
|
|
if err := t.UpdateConfiguration(configuration, copyZeroValues); err != nil {
|
|
return nil, fmt.Errorf("failed to update throttler: %v err: %v", name, err)
|
|
}
|
|
}
|
|
return m.throttlerNamesLocked(), nil
|
|
}
|
|
|
|
// ResetConfiguration implements the "Manager" interface.
|
|
func (m *managerImpl) ResetConfiguration(throttlerName string) ([]string, error) {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
|
|
if throttlerName != "" {
|
|
t, ok := m.throttlers[throttlerName]
|
|
if !ok {
|
|
return nil, fmt.Errorf("throttler: %v does not exist", throttlerName)
|
|
}
|
|
t.ResetConfiguration()
|
|
return []string{throttlerName}, nil
|
|
}
|
|
|
|
for _, t := range m.throttlers {
|
|
t.ResetConfiguration()
|
|
}
|
|
return m.throttlerNamesLocked(), nil
|
|
}
|
|
|
|
// Throttlers returns the sorted list of active throttlers.
|
|
func (m *managerImpl) Throttlers() []string {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
|
|
return m.throttlerNamesLocked()
|
|
}
|
|
|
|
func (m *managerImpl) throttlerNamesLocked() []string {
|
|
var names []string
|
|
for k := range m.throttlers {
|
|
names = append(names, k)
|
|
}
|
|
sort.Strings(names)
|
|
return names
|
|
}
|
|
|
|
// Log returns the most recent changes of the MaxReplicationLag module.
|
|
// There will be one result for each processed replication lag record.
|
|
func (m *managerImpl) Log(throttlerName string) ([]result, error) {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
|
|
t, ok := m.throttlers[throttlerName]
|
|
if !ok {
|
|
return nil, fmt.Errorf("throttler: %v does not exist", throttlerName)
|
|
}
|
|
|
|
return t.Log(), nil
|
|
}
|