| // Copyright 2016 The etcd 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 v3rpc |
| |
| import ( |
| "context" |
| |
| "go.etcd.io/etcd/etcdserver" |
| "go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes" |
| pb "go.etcd.io/etcd/etcdserver/etcdserverpb" |
| "go.etcd.io/etcd/pkg/types" |
| ) |
| |
| type quotaKVServer struct { |
| pb.KVServer |
| qa quotaAlarmer |
| } |
| |
| type quotaAlarmer struct { |
| q etcdserver.Quota |
| a Alarmer |
| id types.ID |
| } |
| |
| // check whether request satisfies the quota. If there is not enough space, |
| // ignore request and raise the free space alarm. |
| func (qa *quotaAlarmer) check(ctx context.Context, r interface{}) error { |
| if qa.q.Available(r) { |
| return nil |
| } |
| req := &pb.AlarmRequest{ |
| MemberID: uint64(qa.id), |
| Action: pb.AlarmRequest_ACTIVATE, |
| Alarm: pb.AlarmType_NOSPACE, |
| } |
| qa.a.Alarm(ctx, req) |
| return rpctypes.ErrGRPCNoSpace |
| } |
| |
| func NewQuotaKVServer(s *etcdserver.EtcdServer) pb.KVServer { |
| return "aKVServer{ |
| NewKVServer(s), |
| quotaAlarmer{etcdserver.NewBackendQuota(s, "kv"), s, s.ID()}, |
| } |
| } |
| |
| func (s *quotaKVServer) Put(ctx context.Context, r *pb.PutRequest) (*pb.PutResponse, error) { |
| if err := s.qa.check(ctx, r); err != nil { |
| return nil, err |
| } |
| return s.KVServer.Put(ctx, r) |
| } |
| |
| func (s *quotaKVServer) Txn(ctx context.Context, r *pb.TxnRequest) (*pb.TxnResponse, error) { |
| if err := s.qa.check(ctx, r); err != nil { |
| return nil, err |
| } |
| return s.KVServer.Txn(ctx, r) |
| } |
| |
| type quotaLeaseServer struct { |
| pb.LeaseServer |
| qa quotaAlarmer |
| } |
| |
| func (s *quotaLeaseServer) LeaseGrant(ctx context.Context, cr *pb.LeaseGrantRequest) (*pb.LeaseGrantResponse, error) { |
| if err := s.qa.check(ctx, cr); err != nil { |
| return nil, err |
| } |
| return s.LeaseServer.LeaseGrant(ctx, cr) |
| } |
| |
| func NewQuotaLeaseServer(s *etcdserver.EtcdServer) pb.LeaseServer { |
| return "aLeaseServer{ |
| NewLeaseServer(s), |
| quotaAlarmer{etcdserver.NewBackendQuota(s, "lease"), s, s.ID()}, |
| } |
| } |