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.constraint; 019 020import java.io.IOException; 021import java.util.ArrayList; 022import java.util.List; 023import java.util.Optional; 024import org.apache.hadoop.hbase.CoprocessorEnvironment; 025import org.apache.hadoop.hbase.client.Durability; 026import org.apache.hadoop.hbase.client.Put; 027import org.apache.hadoop.hbase.client.TableDescriptor; 028import org.apache.hadoop.hbase.coprocessor.ObserverContext; 029import org.apache.hadoop.hbase.coprocessor.RegionCoprocessor; 030import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment; 031import org.apache.hadoop.hbase.coprocessor.RegionObserver; 032import org.apache.hadoop.hbase.wal.WALEdit; 033import org.apache.yetus.audience.InterfaceAudience; 034import org.slf4j.Logger; 035import org.slf4j.LoggerFactory; 036 037/*** 038 * Processes multiple {@link Constraint Constraints} on a given table. 039 * <p> 040 * This is an ease of use mechanism - all the functionality here could be implemented on any given 041 * system by a coprocessor. 042 */ 043@InterfaceAudience.Private 044public class ConstraintProcessor implements RegionCoprocessor, RegionObserver { 045 046 private static final Logger LOG = LoggerFactory.getLogger(ConstraintProcessor.class); 047 048 private final ClassLoader classloader; 049 050 private List<? extends Constraint> constraints = new ArrayList<>(); 051 052 @Override 053 public Optional<RegionObserver> getRegionObserver() { 054 return Optional.of(this); 055 } 056 057 /** 058 * Create the constraint processor. 059 * <p> 060 * Stores the current classloader. 061 */ 062 public ConstraintProcessor() { 063 classloader = this.getClass().getClassLoader(); 064 } 065 066 @Override 067 public void start(CoprocessorEnvironment environment) { 068 // make sure we are on a region server 069 if (!(environment instanceof RegionCoprocessorEnvironment)) { 070 throw new IllegalArgumentException( 071 "Constraints only act on regions - started in an environment that was not a region"); 072 } 073 RegionCoprocessorEnvironment env = (RegionCoprocessorEnvironment) environment; 074 TableDescriptor desc = env.getRegion().getTableDescriptor(); 075 // load all the constraints from the HTD 076 try { 077 this.constraints = Constraints.getConstraints(desc, classloader); 078 } catch (IOException e) { 079 throw new IllegalArgumentException(e); 080 } 081 082 if (LOG.isInfoEnabled()) { 083 LOG.info("Finished loading " + constraints.size() + " user Constraints on table: " 084 + desc.getTableName()); 085 } 086 087 } 088 089 @Override 090 public void prePut(ObserverContext<? extends RegionCoprocessorEnvironment> e, Put put, 091 WALEdit edit, Durability durability) throws IOException { 092 // check the put against the stored constraints 093 for (Constraint c : constraints) { 094 c.check(put); 095 } 096 // if we made it here, then the Put is valid 097 } 098}