diff --git a/dfget/core/locator/locator.go b/dfget/core/locator/locator.go new file mode 100644 index 000000000..65ca9f883 --- /dev/null +++ b/dfget/core/locator/locator.go @@ -0,0 +1,65 @@ +/* + * Copyright The Dragonfly 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 locator + +// SupernodeLocator defines the way how to get available supernodes. +// Developers can implement their own locator more flexibly , not just get the +// supernode list from configuration or CLI. +type SupernodeLocator interface { + // Get returns the current selected supernode, it should be idempotent. + Get() *Supernode + + // Next chooses the next available supernode for retrying or other + // purpose. The current supernode should be set as this result. + Next() *Supernode + + // GetGroup returns the group. + GetGroup(name string) *SupernodeGroup + + // All returns all the supernodes. + All() []*SupernodeGroup + + // Report records the metrics of the current supernode in order to choose a + // more appropriate supernode for the next time if necessary. + Report(ip string, metrics *SupernodeMetrics) + + // Refresh refreshes all the supernodes. + Refresh() bool +} + +// SupernodeGroup groups supernodes which has same attributes. +type SupernodeGroup struct { + Name string + Nodes []*Supernode + + // Infos stores other information that user can customized. + Infos map[string]string +} + +// Supernode basic information of supernodes. +type Supernode struct { + Schema string + IP string + Port int + Weight int + Metrics *SupernodeMetrics +} + +// SupernodeMetrics the metrics used for locator to choose supernode. +type SupernodeMetrics struct { + Metrics map[string]interface{} +} diff --git a/dfget/core/locator/static_locator.go b/dfget/core/locator/static_locator.go new file mode 100644 index 000000000..013c8d056 --- /dev/null +++ b/dfget/core/locator/static_locator.go @@ -0,0 +1,76 @@ +/* + * Copyright The Dragonfly 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 locator + +import ( + "go.uber.org/atomic" +) + +type StaticLocator struct { + idx atomic.Int32 + Group *SupernodeGroup +} + +// NewStaticLocator constructs StaticLocator which uses the nodes passed from +// configuration or CLI. +func NewStaticLocator(nodes []string) *StaticLocator { + // TODO: initialize Group + return &StaticLocator{} +} + +func (s *StaticLocator) Get() *Supernode { + if s.Group == nil { + return nil + } + idx := int(s.idx.Load()) + if idx >= len(s.Group.Nodes) { + return nil + } + return s.Group.Nodes[idx] +} + +func (s *StaticLocator) Next() *Supernode { + if s.Group == nil || int(s.idx.Load()) >= len(s.Group.Nodes) { + return nil + } + idx := int(s.idx.Inc()) + if idx >= len(s.Group.Nodes) { + return nil + } + return s.Group.Nodes[idx] +} + +func (s *StaticLocator) GetGroup(name string) *SupernodeGroup { + return s.Group +} + +func (s *StaticLocator) All() []*SupernodeGroup { + if s.Group == nil { + return []*SupernodeGroup{} + } + return []*SupernodeGroup{s.Group} +} + +func (s *StaticLocator) Report(ip string, metrics *SupernodeMetrics) { + // unnecessary to implement this method + return +} + +func (s *StaticLocator) Refresh() bool { + s.idx.Store(0) + return true +}