View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
3    * agreements. See the NOTICE file distributed with this work for additional information regarding
4    * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
5    * "License"); you may not use this file except in compliance with the License. You may obtain a
6    * copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable
7    * law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
8    * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
9    * for the specific language governing permissions and limitations under the License.
10   */
11  
12  package org.apache.hadoop.hbase.quotas;
13  
14  import java.io.Closeable;
15  import java.io.IOException;
16  import java.util.Iterator;
17  import java.util.LinkedList;
18  import java.util.Queue;
19  
20  import org.apache.commons.logging.Log;
21  import org.apache.commons.logging.LogFactory;
22  import org.apache.hadoop.conf.Configuration;
23  import org.apache.hadoop.hbase.TableName;
24  import org.apache.hadoop.hbase.classification.InterfaceAudience;
25  import org.apache.hadoop.hbase.classification.InterfaceStability;
26  import org.apache.hadoop.hbase.client.Connection;
27  import org.apache.hadoop.hbase.client.ConnectionFactory;
28  import org.apache.hadoop.hbase.client.Result;
29  import org.apache.hadoop.hbase.client.ResultScanner;
30  import org.apache.hadoop.hbase.client.Scan;
31  import org.apache.hadoop.hbase.client.Table;
32  import org.apache.hadoop.hbase.protobuf.generated.QuotaProtos.Quotas;
33  import org.apache.hadoop.util.StringUtils;
34  
35  /**
36   * Scanner to iterate over the quota settings.
37   */
38  @InterfaceAudience.Public
39  @InterfaceStability.Evolving
40  public final class QuotaRetriever implements Closeable, Iterable<QuotaSettings> {
41    private static final Log LOG = LogFactory.getLog(QuotaRetriever.class);
42  
43    private final Queue<QuotaSettings> cache = new LinkedList<QuotaSettings>();
44    private ResultScanner scanner;
45    /**
46     * Connection to use. Could pass one in and have this class use it but this class wants to be
47     * standalone.
48     */
49    private Connection connection;
50    private Table table;
51  
52    private QuotaRetriever() {
53    }
54  
55    void init(final Configuration conf, final Scan scan) throws IOException {
56      this.connection = ConnectionFactory.createConnection(conf);
57      this.table = this.connection.getTable(QuotaTableUtil.QUOTA_TABLE_NAME);
58      try {
59        scanner = table.getScanner(scan);
60      } catch (IOException e) {
61        try {
62          close();
63        } catch (IOException ioe) {
64          LOG.warn("Failed getting scanner and then failed close on cleanup", e);
65        }
66        throw e;
67      }
68    }
69  
70    public void close() throws IOException {
71      if (this.table != null) {
72        this.table.close();
73        this.table = null;
74      }
75      if (this.connection != null) {
76        this.connection.close();
77        this.connection = null;
78      }
79    }
80  
81    public QuotaSettings next() throws IOException {
82      if (cache.isEmpty()) {
83        Result result = scanner.next();
84        if (result == null) return null;
85  
86        QuotaTableUtil.parseResult(result, new QuotaTableUtil.QuotasVisitor() {
87          @Override
88          public void visitUserQuotas(String userName, Quotas quotas) {
89            cache.addAll(QuotaSettingsFactory.fromUserQuotas(userName, quotas));
90          }
91  
92          @Override
93          public void visitUserQuotas(String userName, TableName table, Quotas quotas) {
94            cache.addAll(QuotaSettingsFactory.fromUserQuotas(userName, table, quotas));
95          }
96  
97          @Override
98          public void visitUserQuotas(String userName, String namespace, Quotas quotas) {
99            cache.addAll(QuotaSettingsFactory.fromUserQuotas(userName, namespace, quotas));
100         }
101 
102         @Override
103         public void visitTableQuotas(TableName tableName, Quotas quotas) {
104           cache.addAll(QuotaSettingsFactory.fromTableQuotas(tableName, quotas));
105         }
106 
107         @Override
108         public void visitNamespaceQuotas(String namespace, Quotas quotas) {
109           cache.addAll(QuotaSettingsFactory.fromNamespaceQuotas(namespace, quotas));
110         }
111       });
112     }
113     return cache.poll();
114   }
115 
116   @Override
117   public Iterator<QuotaSettings> iterator() {
118     return new Iter();
119   }
120 
121   private class Iter implements Iterator<QuotaSettings> {
122     private QuotaSettings cache;
123 
124     public Iter() {
125       try {
126         cache = QuotaRetriever.this.next();
127       } catch (IOException e) {
128         LOG.warn(StringUtils.stringifyException(e));
129       }
130     }
131 
132     @Override
133     public boolean hasNext() {
134       return cache != null;
135     }
136 
137     @Override
138     public QuotaSettings next() {
139       QuotaSettings result = cache;
140       try {
141         cache = QuotaRetriever.this.next();
142       } catch (IOException e) {
143         LOG.warn(StringUtils.stringifyException(e));
144       }
145       return result;
146     }
147 
148     @Override
149     public void remove() {
150       throw new RuntimeException("remove() not supported");
151     }
152   }
153 
154   /**
155    * Open a QuotaRetriever with no filter, all the quota settings will be returned.
156    * @param conf Configuration object to use.
157    * @return the QuotaRetriever
158    * @throws IOException if a remote or network exception occurs
159    */
160   public static QuotaRetriever open(final Configuration conf) throws IOException {
161     return open(conf, null);
162   }
163 
164   /**
165    * Open a QuotaRetriever with the specified filter.
166    * @param conf Configuration object to use.
167    * @param filter the QuotaFilter
168    * @return the QuotaRetriever
169    * @throws IOException if a remote or network exception occurs
170    */
171   public static QuotaRetriever open(final Configuration conf, final QuotaFilter filter)
172       throws IOException {
173     Scan scan = QuotaTableUtil.makeScan(filter);
174     QuotaRetriever scanner = new QuotaRetriever();
175     scanner.init(conf, scan);
176     return scanner;
177   }
178 }