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