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    @Override
71    public void close() throws IOException {
72      if (this.table != null) {
73        this.table.close();
74        this.table = null;
75      }
76      if (this.connection != null) {
77        this.connection.close();
78        this.connection = null;
79      }
80    }
81  
82    public QuotaSettings next() throws IOException {
83      if (cache.isEmpty()) {
84        Result result = scanner.next();
85        if (result == null) return null;
86  
87        QuotaTableUtil.parseResult(result, new QuotaTableUtil.QuotasVisitor() {
88          @Override
89          public void visitUserQuotas(String userName, Quotas quotas) {
90            cache.addAll(QuotaSettingsFactory.fromUserQuotas(userName, quotas));
91          }
92  
93          @Override
94          public void visitUserQuotas(String userName, TableName table, Quotas quotas) {
95            cache.addAll(QuotaSettingsFactory.fromUserQuotas(userName, table, quotas));
96          }
97  
98          @Override
99          public void visitUserQuotas(String userName, String namespace, Quotas quotas) {
100           cache.addAll(QuotaSettingsFactory.fromUserQuotas(userName, namespace, quotas));
101         }
102 
103         @Override
104         public void visitTableQuotas(TableName tableName, Quotas quotas) {
105           cache.addAll(QuotaSettingsFactory.fromTableQuotas(tableName, quotas));
106         }
107 
108         @Override
109         public void visitNamespaceQuotas(String namespace, Quotas quotas) {
110           cache.addAll(QuotaSettingsFactory.fromNamespaceQuotas(namespace, quotas));
111         }
112       });
113     }
114     return cache.poll();
115   }
116 
117   @Override
118   public Iterator<QuotaSettings> iterator() {
119     return new Iter();
120   }
121 
122   private class Iter implements Iterator<QuotaSettings> {
123     private QuotaSettings cache;
124 
125     public Iter() {
126       try {
127         cache = QuotaRetriever.this.next();
128       } catch (IOException e) {
129         LOG.warn(StringUtils.stringifyException(e));
130       }
131     }
132 
133     @Override
134     public boolean hasNext() {
135       return cache != null;
136     }
137 
138     @Override
139     public QuotaSettings next() {
140       QuotaSettings result = cache;
141       try {
142         cache = QuotaRetriever.this.next();
143       } catch (IOException e) {
144         LOG.warn(StringUtils.stringifyException(e));
145       }
146       return result;
147     }
148 
149     @Override
150     public void remove() {
151       throw new RuntimeException("remove() not supported");
152     }
153   }
154 
155   /**
156    * Open a QuotaRetriever with no filter, all the quota settings will be returned.
157    * @param conf Configuration object to use.
158    * @return the QuotaRetriever
159    * @throws IOException if a remote or network exception occurs
160    */
161   public static QuotaRetriever open(final Configuration conf) throws IOException {
162     return open(conf, null);
163   }
164 
165   /**
166    * Open a QuotaRetriever with the specified filter.
167    * @param conf Configuration object to use.
168    * @param filter the QuotaFilter
169    * @return the QuotaRetriever
170    * @throws IOException if a remote or network exception occurs
171    */
172   public static QuotaRetriever open(final Configuration conf, final QuotaFilter filter)
173       throws IOException {
174     Scan scan = QuotaTableUtil.makeScan(filter);
175     QuotaRetriever scanner = new QuotaRetriever();
176     scanner.init(conf, scan);
177     return scanner;
178   }
179 }