pkg/authority/rule/authorization/handler.go (91 lines of code) (raw):
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You 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 authorization
import (
"reflect"
"sync"
"sync/atomic"
"github.com/apache/dubbo-admin/pkg/authority/rule/connection"
)
type Handler interface {
Add(key string, obj *Policy)
Get(key string) *Policy
Update(key string, newObj *Policy)
Delete(key string)
}
type Impl struct {
mutex *sync.Mutex
revision int64
storage *connection.Storage
cache map[string]*Policy
}
func NewHandler(storage *connection.Storage) *Impl {
return &Impl{
mutex: &sync.Mutex{},
storage: storage,
revision: 0,
cache: map[string]*Policy{},
}
}
func (i *Impl) Add(key string, obj *Policy) {
i.mutex.Lock()
defer i.mutex.Unlock()
if origin := i.cache[key]; reflect.DeepEqual(origin, obj) {
return
}
cloned := make(map[string]*Policy, len(i.cache)+1)
for k, v := range i.cache {
cloned[k] = v
}
cloned[key] = obj
i.cache = cloned
atomic.AddInt64(&i.revision, 1)
i.Notify()
}
func (i *Impl) Get(key string) *Policy {
i.mutex.Lock()
defer i.mutex.Unlock()
return i.cache[key]
}
func (i *Impl) Update(key string, newObj *Policy) {
i.mutex.Lock()
defer i.mutex.Unlock()
if origin := i.cache[key]; reflect.DeepEqual(origin, newObj) {
return
}
cloned := make(map[string]*Policy, len(i.cache))
for k, v := range i.cache {
cloned[k] = v
}
cloned[key] = newObj
i.cache = cloned
atomic.AddInt64(&i.revision, 1)
i.Notify()
}
func (i *Impl) Delete(key string) {
i.mutex.Lock()
defer i.mutex.Unlock()
if _, ok := i.cache[key]; !ok {
return
}
cloned := make(map[string]*Policy, len(i.cache)-1)
for k, v := range i.cache {
if k == key {
continue
}
cloned[k] = v
}
i.cache = cloned
atomic.AddInt64(&i.revision, 1)
i.Notify()
}
func (i *Impl) Notify() {
originRule := &Origin{
revision: i.revision,
data: i.cache,
}
i.storage.LatestRules[RuleType] = originRule
i.storage.Mutex.RLock()
defer i.storage.Mutex.RUnlock()
for _, c := range i.storage.Connection {
c.RawRuleQueue.Add(originRule)
}
}