001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to you under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.hadoop.hbase.quotas;
018
019import org.apache.hadoop.hbase.TableName;
020import org.apache.yetus.audience.InterfaceAudience;
021import org.apache.yetus.audience.InterfaceStability;
022import org.apache.hadoop.hbase.quotas.SpaceQuotaSnapshot.SpaceQuotaStatus;
023import org.apache.hadoop.hbase.quotas.policies.DefaultViolationPolicyEnforcement;
024import org.apache.hadoop.hbase.quotas.policies.DisableTableViolationPolicyEnforcement;
025import org.apache.hadoop.hbase.quotas.policies.MissingSnapshotViolationPolicyEnforcement;
026import org.apache.hadoop.hbase.quotas.policies.NoInsertsViolationPolicyEnforcement;
027import org.apache.hadoop.hbase.quotas.policies.NoWritesCompactionsViolationPolicyEnforcement;
028import org.apache.hadoop.hbase.quotas.policies.NoWritesViolationPolicyEnforcement;
029import org.apache.hadoop.hbase.regionserver.RegionServerServices;
030
031/**
032 * A factory class for instantiating {@link SpaceViolationPolicyEnforcement} instances.
033 */
034@InterfaceAudience.Private
035@InterfaceStability.Evolving
036public class SpaceViolationPolicyEnforcementFactory {
037
038  private static final SpaceViolationPolicyEnforcementFactory INSTANCE =
039      new SpaceViolationPolicyEnforcementFactory();
040
041  private SpaceViolationPolicyEnforcementFactory() {}
042
043  /**
044   * Returns an instance of this factory.
045   */
046  public static SpaceViolationPolicyEnforcementFactory getInstance() {
047    return INSTANCE;
048  }
049
050  /**
051   * Constructs the appropriate {@link SpaceViolationPolicyEnforcement} for tables that are
052   * in violation of their space quota.
053   */
054  public SpaceViolationPolicyEnforcement create(
055      RegionServerServices rss, TableName tableName, SpaceQuotaSnapshot snapshot) {
056    SpaceViolationPolicyEnforcement enforcement;
057    SpaceQuotaStatus status = snapshot.getQuotaStatus();
058    if (!status.isInViolation()) {
059      throw new IllegalArgumentException(tableName + " is not in violation. Snapshot=" + snapshot);
060    }
061    switch (status.getPolicy().get()) {
062      case DISABLE:
063        enforcement = new DisableTableViolationPolicyEnforcement();
064        break;
065      case NO_WRITES_COMPACTIONS:
066        enforcement = new NoWritesCompactionsViolationPolicyEnforcement();
067        break;
068      case NO_WRITES:
069        enforcement = new NoWritesViolationPolicyEnforcement();
070        break;
071      case NO_INSERTS:
072        enforcement = new NoInsertsViolationPolicyEnforcement();
073        break;
074      default:
075        throw new IllegalArgumentException("Unhandled SpaceViolationPolicy: " + status.getPolicy());
076    }
077    enforcement.initialize(rss, tableName, snapshot);
078    return enforcement;
079  }
080
081  /**
082   * Creates the "default" {@link SpaceViolationPolicyEnforcement} for a table that isn't in
083   * violation. This is used to have uniform policy checking for tables in and not quotas. This
084   * policy will still verify that new bulk loads do not exceed the configured quota limit.
085   *
086   * @param rss RegionServerServices instance the policy enforcement should use.
087   * @param tableName The target HBase table.
088   * @param snapshot The current quota snapshot for the {@code tableName}, can be null.
089   */
090  public SpaceViolationPolicyEnforcement createWithoutViolation(
091      RegionServerServices rss, TableName tableName, SpaceQuotaSnapshot snapshot) {
092    if (snapshot == null) {
093      // If we have no snapshot, this is equivalent to no quota for this table.
094      // We should do use the (singleton instance) of this policy to do nothing.
095      return MissingSnapshotViolationPolicyEnforcement.getInstance();
096    }
097    // We have a snapshot which means that there is a quota set on this table, but it's not in
098    // violation of that quota. We need to construct a policy for this table.
099    SpaceQuotaStatus status = snapshot.getQuotaStatus();
100    if (status.isInViolation()) {
101      throw new IllegalArgumentException(
102          tableName + " is in violation. Logic error. Snapshot=" + snapshot);
103    }
104    // We have a unique size snapshot to use. Create an instance for this tablename + snapshot.
105    DefaultViolationPolicyEnforcement enforcement = new DefaultViolationPolicyEnforcement();
106    enforcement.initialize(rss, tableName, snapshot);
107    return enforcement;
108  }
109}