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.assertArrayEquals; 021import static org.junit.jupiter.api.Assertions.assertEquals; 022import static org.junit.jupiter.api.Assertions.assertTrue; 023 024import java.io.IOException; 025import java.util.Arrays; 026import java.util.List; 027import java.util.Map; 028import java.util.NavigableMap; 029import java.util.Optional; 030import org.apache.hadoop.hbase.Cell; 031import org.apache.hadoop.hbase.HBaseTestingUtil; 032import org.apache.hadoop.hbase.TableName; 033import org.apache.hadoop.hbase.client.Append; 034import org.apache.hadoop.hbase.client.Get; 035import org.apache.hadoop.hbase.client.Put; 036import org.apache.hadoop.hbase.client.Result; 037import org.apache.hadoop.hbase.client.Row; 038import org.apache.hadoop.hbase.client.Table; 039import org.apache.hadoop.hbase.io.TimeRange; 040import org.apache.hadoop.hbase.procedure2.RemoteProcedureDispatcher; 041import org.apache.hadoop.hbase.testclassification.CoprocessorTests; 042import org.apache.hadoop.hbase.testclassification.MediumTests; 043import org.apache.hadoop.hbase.util.Bytes; 044import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; 045import org.apache.hadoop.hbase.util.ManualEnvironmentEdge; 046import org.junit.jupiter.api.AfterAll; 047import org.junit.jupiter.api.BeforeAll; 048import org.junit.jupiter.api.BeforeEach; 049import org.junit.jupiter.api.Tag; 050import org.junit.jupiter.api.Test; 051import org.junit.jupiter.api.TestInfo; 052 053@Tag(CoprocessorTests.TAG) 054@Tag(MediumTests.TAG) 055public class TestAppendTimeRange { 056 057 private String currentTestName; 058 059 private static final HBaseTestingUtil util = new HBaseTestingUtil(); 060 private static final ManualEnvironmentEdge mee = new ManualEnvironmentEdge(); 061 062 private static final byte[] TEST_FAMILY = Bytes.toBytes("f1"); 063 064 private static final byte[] ROW = Bytes.toBytes("aaa"); 065 066 private static final byte[] QUAL = Bytes.toBytes("col1"); 067 068 private static final byte[] VALUE = Bytes.toBytes("1"); 069 070 @BeforeAll 071 public static void setupBeforeClass() throws Exception { 072 util.getConfiguration().set(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY, 073 MyObserver.class.getName()); 074 // Make general delay zero rather than default. Timing is off in this 075 // test that depends on an evironment edge that is manually moved forward. 076 util.getConfiguration().setInt(RemoteProcedureDispatcher.DISPATCH_DELAY_CONF_KEY, 0); 077 util.startMiniCluster(); 078 EnvironmentEdgeManager.injectEdge(mee); 079 } 080 081 @AfterAll 082 public static void tearDownAfterClass() throws Exception { 083 util.shutdownMiniCluster(); 084 } 085 086 @BeforeEach 087 public void setUp(TestInfo testInfo) { 088 currentTestName = testInfo.getTestMethod().get().getName(); 089 } 090 091 public static class MyObserver implements RegionCoprocessor, RegionObserver { 092 private static TimeRange tr10 = null; 093 private static TimeRange tr2 = null; 094 095 @Override 096 public Optional<RegionObserver> getRegionObserver() { 097 return Optional.of(this); 098 } 099 100 @Override 101 public Result preAppend(final ObserverContext<? extends RegionCoprocessorEnvironment> e, 102 final Append append) throws IOException { 103 NavigableMap<byte[], List<Cell>> map = append.getFamilyCellMap(); 104 for (Map.Entry<byte[], List<Cell>> entry : map.entrySet()) { 105 for (Cell cell : entry.getValue()) { 106 String appendStr = 107 Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()); 108 if (appendStr.equals("b")) { 109 tr10 = append.getTimeRange(); 110 } else if (appendStr.equals("c") && !append.getTimeRange().isAllTime()) { 111 tr2 = append.getTimeRange(); 112 } 113 } 114 } 115 return null; 116 } 117 } 118 119 @Test 120 public void testHTableInterfaceMethods() throws Exception { 121 try (Table table = util.createTable(TableName.valueOf(currentTestName), TEST_FAMILY)) { 122 table.put(new Put(ROW).addColumn(TEST_FAMILY, QUAL, VALUE)); 123 long time = EnvironmentEdgeManager.currentTime(); 124 mee.setValue(time); 125 table.put(new Put(ROW).addColumn(TEST_FAMILY, QUAL, Bytes.toBytes("a"))); 126 checkRowValue(table, ROW, Bytes.toBytes("a")); 127 128 time = EnvironmentEdgeManager.currentTime(); 129 mee.setValue(time); 130 TimeRange range10 = TimeRange.between(1, time + 10); 131 table.append(new Append(ROW).addColumn(TEST_FAMILY, QUAL, Bytes.toBytes("b")) 132 .setTimeRange(range10.getMin(), range10.getMax())); 133 checkRowValue(table, ROW, Bytes.toBytes("ab")); 134 assertEquals(MyObserver.tr10.getMin(), range10.getMin()); 135 assertEquals(MyObserver.tr10.getMax(), range10.getMax()); 136 time = EnvironmentEdgeManager.currentTime(); 137 mee.setValue(time); 138 TimeRange range2 = TimeRange.between(1, time + 20); 139 List<Row> actions = Arrays.asList(new Row[] { 140 new Append(ROW).addColumn(TEST_FAMILY, QUAL, Bytes.toBytes("c")) 141 .setTimeRange(range2.getMin(), range2.getMax()), 142 new Append(ROW).addColumn(TEST_FAMILY, QUAL, Bytes.toBytes("c")) 143 .setTimeRange(range2.getMin(), range2.getMax()) }); 144 Object[] results1 = new Object[actions.size()]; 145 table.batch(actions, results1); 146 assertEquals(MyObserver.tr2.getMin(), range2.getMin()); 147 assertEquals(MyObserver.tr2.getMax(), range2.getMax()); 148 for (Object r2 : results1) { 149 assertTrue(r2 instanceof Result); 150 } 151 checkRowValue(table, ROW, Bytes.toBytes("abcc")); 152 } 153 } 154 155 private void checkRowValue(Table table, byte[] row, byte[] expectedValue) throws IOException { 156 Get get = new Get(row).addColumn(TEST_FAMILY, QUAL); 157 Result result = table.get(get); 158 byte[] actualValue = result.getValue(TEST_FAMILY, QUAL); 159 assertArrayEquals(expectedValue, actualValue); 160 } 161}