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.coprocessor; 019 020import static org.junit.jupiter.api.Assertions.assertEquals; 021 022import java.io.IOException; 023import java.util.Optional; 024import org.apache.hadoop.conf.Configuration; 025import org.apache.hadoop.hbase.HBaseTestingUtil; 026import org.apache.hadoop.hbase.TableName; 027import org.apache.hadoop.hbase.client.Admin; 028import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor; 029import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; 030import org.apache.hadoop.hbase.client.TableDescriptor; 031import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 032import org.apache.hadoop.hbase.testclassification.CoprocessorTests; 033import org.apache.hadoop.hbase.testclassification.MediumTests; 034import org.apache.hadoop.hbase.util.Bytes; 035import org.junit.jupiter.api.AfterAll; 036import org.junit.jupiter.api.BeforeAll; 037import org.junit.jupiter.api.Tag; 038import org.junit.jupiter.api.Test; 039 040@Tag(CoprocessorTests.TAG) 041@Tag(MediumTests.TAG) 042public class TestMasterObserverToModifyTableSchema { 043 044 private static HBaseTestingUtil UTIL = new HBaseTestingUtil(); 045 private static TableName TABLENAME = TableName.valueOf("TestTable"); 046 047 @BeforeAll 048 public static void setupBeforeClass() throws Exception { 049 Configuration conf = UTIL.getConfiguration(); 050 conf.set(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY, 051 OnlyOneVersionAllowedMasterObserver.class.getName()); 052 UTIL.startMiniCluster(1); 053 } 054 055 @AfterAll 056 public static void tearDownAfterClass() throws Exception { 057 UTIL.shutdownMiniCluster(); 058 } 059 060 @Test 061 public void testMasterObserverToModifyTableSchema() throws IOException { 062 TableDescriptorBuilder builder = TableDescriptorBuilder.newBuilder(TABLENAME); 063 for (int i = 1; i <= 3; i++) { 064 builder.setColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes("cf" + i)) 065 .setMaxVersions(i).build()); 066 } 067 try (Admin admin = UTIL.getAdmin()) { 068 admin.createTable(builder.build()); 069 assertOneVersion(admin.getDescriptor(TABLENAME)); 070 071 builder.modifyColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes("cf1")) 072 .setMaxVersions(Integer.MAX_VALUE).build()); 073 admin.modifyTable(builder.build()); 074 assertOneVersion(admin.getDescriptor(TABLENAME)); 075 } 076 } 077 078 private void assertOneVersion(TableDescriptor td) { 079 for (ColumnFamilyDescriptor cfd : td.getColumnFamilies()) { 080 assertEquals(1, cfd.getMaxVersions()); 081 } 082 } 083 084 public static class OnlyOneVersionAllowedMasterObserver 085 implements MasterCoprocessor, MasterObserver { 086 087 @Override 088 public Optional<MasterObserver> getMasterObserver() { 089 return Optional.of(this); 090 } 091 092 @Override 093 public TableDescriptor preCreateTableRegionsInfos( 094 ObserverContext<MasterCoprocessorEnvironment> ctx, TableDescriptor desc) throws IOException { 095 TableDescriptorBuilder builder = TableDescriptorBuilder.newBuilder(desc); 096 for (ColumnFamilyDescriptor cfd : desc.getColumnFamilies()) { 097 builder.modifyColumnFamily( 098 ColumnFamilyDescriptorBuilder.newBuilder(cfd).setMaxVersions(1).build()); 099 } 100 return builder.build(); 101 } 102 103 @Override 104 public TableDescriptor preModifyTable(ObserverContext<MasterCoprocessorEnvironment> env, 105 TableName tableName, final TableDescriptor currentDescriptor, 106 final TableDescriptor newDescriptor) throws IOException { 107 TableDescriptorBuilder builder = TableDescriptorBuilder.newBuilder(newDescriptor); 108 for (ColumnFamilyDescriptor cfd : newDescriptor.getColumnFamilies()) { 109 builder.modifyColumnFamily( 110 ColumnFamilyDescriptorBuilder.newBuilder(cfd).setMaxVersions(1).build()); 111 } 112 return builder.build(); 113 } 114 } 115}