/* * * Copyright 2019 gRPC 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 wrr import ( "sync" "google.golang.org/grpc/internal/grpcrand" ) // weightedItem is a wrapped weighted item that is used to implement weighted random algorithm. type weightedItem struct { Item interface{} Weight int64 } // randomWRR is a struct that contains weighted items implement weighted random algorithm. type randomWRR struct { mu sync.RWMutex items []*weightedItem sumOfWeights int64 } // NewRandom creates a new WRR with random. func NewRandom() WRR { return &randomWRR{} } var grpcrandInt63n = grpcrand.Int63n func (rw *randomWRR) Next() (item interface{}) { rw.mu.RLock() defer rw.mu.RUnlock() if rw.sumOfWeights == 0 { return nil } // Random number in [0, sum). randomWeight := grpcrandInt63n(rw.sumOfWeights) for _, item := range rw.items { randomWeight = randomWeight - item.Weight if randomWeight < 0 { return item.Item } } return rw.items[len(rw.items)-1].Item } func (rw *randomWRR) Add(item interface{}, weight int64) { rw.mu.Lock() defer rw.mu.Unlock() rItem := &weightedItem{Item: item, Weight: weight} rw.items = append(rw.items, rItem) rw.sumOfWeights += weight }