View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.hadoop.hbase.quotas;
20  
21  import java.util.List;
22  
23  import org.apache.hadoop.hbase.classification.InterfaceAudience;
24  import org.apache.hadoop.hbase.classification.InterfaceStability;
25  import org.apache.hadoop.hbase.client.Mutation;
26  import org.apache.hadoop.hbase.client.Result;
27  
28  /**
29   * Interface that allows to check the quota available for an operation.
30   */
31  @InterfaceAudience.Private
32  @InterfaceStability.Evolving
33  public interface OperationQuota {
34    public enum OperationType { MUTATE, GET, SCAN }
35  
36    /**
37     * Keeps track of the average data size of operations like get, scan, mutate
38     */
39    public class AvgOperationSize {
40      private final long[] sizeSum;
41      private final long[] count;
42  
43      public AvgOperationSize() {
44        int size = OperationType.values().length;
45        sizeSum = new long[size];
46        count = new long[size];
47        for (int i = 0; i < size; ++i) {
48          sizeSum[i] = 0;
49          count[i] = 0;
50        }
51      }
52  
53      public void addOperationSize(OperationType type, long size) {
54        if (size > 0) {
55          int index = type.ordinal();
56          sizeSum[index] += size;
57          count[index]++;
58        }
59      }
60  
61      public long getAvgOperationSize(OperationType type) {
62        int index = type.ordinal();
63        return count[index] > 0 ? sizeSum[index] / count[index] : 0;
64      }
65  
66      public long getOperationSize(OperationType type) {
67        return sizeSum[type.ordinal()];
68      }
69  
70      public void addGetResult(final Result result) {
71        long size = QuotaUtil.calculateResultSize(result);
72        addOperationSize(OperationType.GET, size);
73      }
74  
75      public void addScanResult(final List<Result> results) {
76        long size = QuotaUtil.calculateResultSize(results);
77        addOperationSize(OperationType.SCAN, size);
78      }
79  
80      public void addMutation(final Mutation mutation) {
81        long size = QuotaUtil.calculateMutationSize(mutation);
82        addOperationSize(OperationType.MUTATE, size);
83      }
84    }
85  
86    /**
87     * Checks if it is possible to execute the specified operation.
88     * The quota will be estimated based on the number of operations to perform
89     * and the average size accumulated during time.
90     *
91     * @param numWrites number of write operation that will be performed
92     * @param numReads number of small-read operation that will be performed
93     * @param numScans number of long-read operation that will be performed
94     * @throws ThrottlingException if the operation cannot be performed
95     */
96    void checkQuota(int numWrites, int numReads, int numScans)
97      throws ThrottlingException;
98  
99    /** Cleanup method on operation completion */
100   void close();
101 
102   /**
103    * Add a get result. This will be used to calculate the exact quota and
104    * have a better short-read average size for the next time.
105    */
106   void addGetResult(Result result);
107 
108   /**
109    * Add a scan result. This will be used to calculate the exact quota and
110    * have a better long-read average size for the next time.
111    */
112   void addScanResult(List<Result> results);
113 
114   /**
115    * Add a mutation result. This will be used to calculate the exact quota and
116    * have a better mutation average size for the next time.
117    */
118   void addMutation(Mutation mutation);
119 
120   /** @return the number of bytes available to read to avoid exceeding the quota */
121   long getReadAvailable();
122 
123   /** @return the number of bytes available to write to avoid exceeding the quota */
124   long getWriteAvailable();
125 
126   /** @return the average data size of the specified operation */
127   long getAvgOperationSize(OperationType type);
128 }