View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to you under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    * http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.hadoop.hbase.quotas.policies;
18  
19  import java.io.IOException;
20  import java.util.List;
21  import java.util.Objects;
22  
23  import org.apache.hadoop.fs.FileStatus;
24  import org.apache.hadoop.fs.FileSystem;
25  import org.apache.hadoop.fs.Path;
26  import org.apache.hadoop.hbase.classification.InterfaceAudience;
27  import org.apache.hadoop.hbase.client.Mutation;
28  import org.apache.hadoop.hbase.quotas.SpaceLimitingException;
29  import org.apache.hadoop.hbase.quotas.SpaceQuotaSnapshot;
30  import org.apache.hadoop.hbase.quotas.SpaceViolationPolicyEnforcement;
31  
32  /**
33   * The default implementation for {@link SpaceViolationPolicyEnforcement}. This is done because all
34   * tables, whether or not they're in violation now, should be checking bulk loads to proactively
35   * catch a swell of files that would push the table into violation.
36   */
37  @InterfaceAudience.Private
38  public class DefaultViolationPolicyEnforcement extends AbstractViolationPolicyEnforcement {
39  
40    @Override
41    public void enable() throws IOException {}
42  
43    @Override
44    public void disable() throws IOException {}
45  
46    @Override
47    public String getPolicyName() {
48      return "BulkLoadVerifying";
49    }
50  
51    @Override
52    public void check(Mutation m) throws SpaceLimitingException {}
53  
54    @Override
55    public boolean shouldCheckBulkLoads() {
56      // Reference check. The singleton is used when no quota exists to check against
57      return SpaceQuotaSnapshot.getNoSuchSnapshot() != quotaSnapshot;
58    }
59  
60    @Override
61    public void checkBulkLoad(FileSystem fs, List<String> paths) throws SpaceLimitingException {
62      // Compute the amount of space that could be used to save some arithmetic in the for-loop
63      final long sizeAvailableForBulkLoads = quotaSnapshot.getLimit() - quotaSnapshot.getUsage();
64      long size = 0L;
65      for (String path : paths) {
66        size += addSingleFile(fs, path);
67        if (size > sizeAvailableForBulkLoads) {
68          break;
69        }
70      }
71      if (size > sizeAvailableForBulkLoads) {
72        throw new SpaceLimitingException(getPolicyName(), "Bulk load of " + paths
73            + " is disallowed because the file(s) exceed the limits of a space quota.");
74      }
75    }
76  
77    private long addSingleFile(FileSystem fs, String path) throws SpaceLimitingException {
78      final FileStatus status;
79      try {
80        status = fs.getFileStatus(new Path(Objects.requireNonNull(path)));
81      } catch (IOException e) {
82        throw new SpaceLimitingException(
83            getPolicyName(), "Could not verify length of file to bulk load", e);
84      }
85      if (!status.isFile()) {
86        throw new IllegalArgumentException(path + " is not a file.");
87      }
88      return status.getLen();
89    }
90  }