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.client; 019 020import static org.junit.Assert.assertArrayEquals; 021import static org.junit.Assert.assertEquals; 022import static org.junit.Assert.assertNull; 023import static org.junit.Assert.assertThrows; 024 025import java.io.IOException; 026import org.apache.hadoop.hbase.DoNotRetryIOException; 027import org.apache.hadoop.hbase.HBaseClassTestRule; 028import org.apache.hadoop.hbase.TableName; 029import org.apache.hadoop.hbase.TableNotEnabledException; 030import org.apache.hadoop.hbase.TableNotFoundException; 031import org.apache.hadoop.hbase.regionserver.NoSuchColumnFamilyException; 032import org.apache.hadoop.hbase.regionserver.storefiletracker.StoreFileTrackerFactory; 033import org.apache.hadoop.hbase.testclassification.ClientTests; 034import org.apache.hadoop.hbase.testclassification.LargeTests; 035import org.apache.hadoop.hbase.util.Bytes; 036import org.apache.hadoop.hbase.util.FutureUtils; 037import org.junit.ClassRule; 038import org.junit.Test; 039import org.junit.experimental.categories.Category; 040import org.junit.runner.RunWith; 041import org.junit.runners.Parameterized; 042 043@RunWith(Parameterized.class) 044@Category({ LargeTests.class, ClientTests.class }) 045public class TestAsyncAdminModifyStoreFileTracker extends TestAsyncAdminBase { 046 047 @ClassRule 048 public static final HBaseClassTestRule CLASS_RULE = 049 HBaseClassTestRule.forClass(TestAsyncAdminModifyStoreFileTracker.class); 050 051 private static final String SRC_IMPL = "hbase.store.file-tracker.migration.src.impl"; 052 053 private static final String DST_IMPL = "hbase.store.file-tracker.migration.dst.impl"; 054 055 private void verifyModifyTableResult(TableName tableName, byte[] family, byte[] qual, byte[] row, 056 byte[] value, String sft) throws IOException { 057 TableDescriptor td = admin.getDescriptor(tableName).join(); 058 assertEquals(sft, td.getValue(StoreFileTrackerFactory.TRACKER_IMPL)); 059 // no migration related configs 060 assertNull(td.getValue(SRC_IMPL)); 061 assertNull(td.getValue(DST_IMPL)); 062 try (Table table = TEST_UTIL.getConnection().getTable(tableName)) { 063 assertArrayEquals(value, table.get(new Get(row)).getValue(family, qual)); 064 } 065 } 066 067 @Test 068 public void testModifyTableStoreFileTracker() throws IOException { 069 byte[] family = Bytes.toBytes("info"); 070 byte[] qual = Bytes.toBytes("q"); 071 byte[] row = Bytes.toBytes(0); 072 byte[] value = Bytes.toBytes(1); 073 try (Table table = TEST_UTIL.createTable(tableName, family)) { 074 table.put(new Put(row).addColumn(family, qual, value)); 075 } 076 // change to FILE 077 admin.modifyTableStoreFileTracker(tableName, StoreFileTrackerFactory.Trackers.FILE.name()) 078 .join(); 079 verifyModifyTableResult(tableName, family, qual, row, value, 080 StoreFileTrackerFactory.Trackers.FILE.name()); 081 082 // change to FILE again, should have no effect 083 admin.modifyTableStoreFileTracker(tableName, StoreFileTrackerFactory.Trackers.FILE.name()) 084 .join(); 085 verifyModifyTableResult(tableName, family, qual, row, value, 086 StoreFileTrackerFactory.Trackers.FILE.name()); 087 088 // change to MIGRATION, and then to FILE 089 admin.modifyTable(TableDescriptorBuilder.newBuilder(admin.getDescriptor(tableName).join()) 090 .setValue(StoreFileTrackerFactory.TRACKER_IMPL, 091 StoreFileTrackerFactory.Trackers.MIGRATION.name()) 092 .setValue(SRC_IMPL, StoreFileTrackerFactory.Trackers.FILE.name()) 093 .setValue(DST_IMPL, StoreFileTrackerFactory.Trackers.DEFAULT.name()).build()).join(); 094 admin.modifyTableStoreFileTracker(tableName, StoreFileTrackerFactory.Trackers.FILE.name()) 095 .join(); 096 verifyModifyTableResult(tableName, family, qual, row, value, 097 StoreFileTrackerFactory.Trackers.FILE.name()); 098 099 // change to MIGRATION, and then to DEFAULT 100 admin.modifyTable(TableDescriptorBuilder.newBuilder(admin.getDescriptor(tableName).join()) 101 .setValue(StoreFileTrackerFactory.TRACKER_IMPL, 102 StoreFileTrackerFactory.Trackers.MIGRATION.name()) 103 .setValue(SRC_IMPL, StoreFileTrackerFactory.Trackers.FILE.name()) 104 .setValue(DST_IMPL, StoreFileTrackerFactory.Trackers.DEFAULT.name()).build()).join(); 105 admin.modifyTableStoreFileTracker(tableName, StoreFileTrackerFactory.Trackers.DEFAULT.name()) 106 .join(); 107 verifyModifyTableResult(tableName, family, qual, row, value, 108 StoreFileTrackerFactory.Trackers.DEFAULT.name()); 109 } 110 111 private void verifyModifyColumnFamilyResult(TableName tableName, byte[] family, byte[] qual, 112 byte[] row, byte[] value, String sft) throws IOException { 113 TableDescriptor td = admin.getDescriptor(tableName).join(); 114 ColumnFamilyDescriptor cfd = td.getColumnFamily(family); 115 assertEquals(sft, cfd.getConfigurationValue(StoreFileTrackerFactory.TRACKER_IMPL)); 116 // no migration related configs 117 assertNull(cfd.getConfigurationValue(SRC_IMPL)); 118 assertNull(cfd.getConfigurationValue(DST_IMPL)); 119 assertNull(cfd.getValue(SRC_IMPL)); 120 assertNull(cfd.getValue(DST_IMPL)); 121 try (Table table = TEST_UTIL.getConnection().getTable(tableName)) { 122 assertArrayEquals(value, table.get(new Get(row)).getValue(family, qual)); 123 } 124 } 125 126 @Test 127 public void testModifyColumnFamilyStoreFileTracker() throws IOException { 128 byte[] family = Bytes.toBytes("info"); 129 byte[] qual = Bytes.toBytes("q"); 130 byte[] row = Bytes.toBytes(0); 131 byte[] value = Bytes.toBytes(1); 132 try (Table table = TEST_UTIL.createTable(tableName, family)) { 133 table.put(new Put(row).addColumn(family, qual, value)); 134 } 135 // change to FILE 136 admin.modifyColumnFamilyStoreFileTracker(tableName, family, 137 StoreFileTrackerFactory.Trackers.FILE.name()).join(); 138 verifyModifyColumnFamilyResult(tableName, family, qual, row, value, 139 StoreFileTrackerFactory.Trackers.FILE.name()); 140 141 // change to FILE again, should have no effect 142 admin.modifyColumnFamilyStoreFileTracker(tableName, family, 143 StoreFileTrackerFactory.Trackers.FILE.name()).join(); 144 verifyModifyColumnFamilyResult(tableName, family, qual, row, value, 145 StoreFileTrackerFactory.Trackers.FILE.name()); 146 147 // change to MIGRATION, and then to FILE 148 TableDescriptor current = admin.getDescriptor(tableName).join(); 149 admin.modifyTable(TableDescriptorBuilder.newBuilder(current) 150 .modifyColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder(current.getColumnFamily(family)) 151 .setConfiguration(StoreFileTrackerFactory.TRACKER_IMPL, 152 StoreFileTrackerFactory.Trackers.MIGRATION.name()) 153 .setConfiguration(SRC_IMPL, StoreFileTrackerFactory.Trackers.FILE.name()) 154 .setConfiguration(DST_IMPL, StoreFileTrackerFactory.Trackers.DEFAULT.name()).build()) 155 .build()).join(); 156 admin.modifyColumnFamilyStoreFileTracker(tableName, family, 157 StoreFileTrackerFactory.Trackers.FILE.name()).join(); 158 verifyModifyColumnFamilyResult(tableName, family, qual, row, value, 159 StoreFileTrackerFactory.Trackers.FILE.name()); 160 161 // change to MIGRATION, and then to DEFAULT 162 current = admin.getDescriptor(tableName).join(); 163 admin.modifyTable(TableDescriptorBuilder.newBuilder(current) 164 .modifyColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder(current.getColumnFamily(family)) 165 .setConfiguration(StoreFileTrackerFactory.TRACKER_IMPL, 166 StoreFileTrackerFactory.Trackers.MIGRATION.name()) 167 .setConfiguration(SRC_IMPL, StoreFileTrackerFactory.Trackers.FILE.name()) 168 .setConfiguration(DST_IMPL, StoreFileTrackerFactory.Trackers.DEFAULT.name()).build()) 169 .build()).join(); 170 admin.modifyColumnFamilyStoreFileTracker(tableName, family, 171 StoreFileTrackerFactory.Trackers.DEFAULT.name()).join(); 172 verifyModifyColumnFamilyResult(tableName, family, qual, row, value, 173 StoreFileTrackerFactory.Trackers.DEFAULT.name()); 174 } 175 176 @Test 177 public void testModifyStoreFileTrackerError() throws IOException { 178 byte[] family = Bytes.toBytes("info"); 179 TEST_UTIL.createTable(tableName, family).close(); 180 181 // table not exists 182 assertThrows(TableNotFoundException.class, 183 () -> FutureUtils.get(admin.modifyTableStoreFileTracker(TableName.valueOf("whatever"), 184 StoreFileTrackerFactory.Trackers.FILE.name()))); 185 // family not exists 186 assertThrows(NoSuchColumnFamilyException.class, 187 () -> FutureUtils.get(admin.modifyColumnFamilyStoreFileTracker(tableName, 188 Bytes.toBytes("not_exists"), StoreFileTrackerFactory.Trackers.FILE.name()))); 189 // to migration 190 assertThrows(DoNotRetryIOException.class, () -> FutureUtils.get(admin 191 .modifyTableStoreFileTracker(tableName, StoreFileTrackerFactory.Trackers.MIGRATION.name()))); 192 // disabled 193 admin.disableTable(tableName).join(); 194 assertThrows(TableNotEnabledException.class, () -> FutureUtils.get( 195 admin.modifyTableStoreFileTracker(tableName, StoreFileTrackerFactory.Trackers.FILE.name()))); 196 } 197}