1   /*
2    * Copyright 2011 The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  package org.apache.hadoop.hbase.coprocessor;
21  
22  import java.io.IOException;
23  import java.util.ArrayList;
24  import java.util.List;
25  import java.util.Map;
26  
27  import org.apache.hadoop.conf.Configuration;
28  import org.apache.hadoop.hbase.*;
29  import org.apache.hadoop.hbase.client.Delete;
30  import org.apache.hadoop.hbase.client.Get;
31  import org.apache.hadoop.hbase.client.HTable;
32  import org.apache.hadoop.hbase.client.Put;
33  import org.apache.hadoop.hbase.client.Result;
34  import org.apache.hadoop.hbase.coprocessor.BaseRegionObserver;
35  import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
36  import org.apache.hadoop.hbase.coprocessor.ObserverContext;
37  import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
38  import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
39  import org.apache.hadoop.hbase.util.Bytes;
40  import org.junit.AfterClass;
41  import org.junit.BeforeClass;
42  import org.junit.Test;
43  import org.junit.experimental.categories.Category;
44  
45  import static org.junit.Assert.assertEquals;
46  
47  @Category(MediumTests.class)
48  public class TestRegionObserverBypass {
49    private static HBaseTestingUtility util;
50    private static final byte[] tableName = Bytes.toBytes("test");
51    private static final byte[] dummy = Bytes.toBytes("dummy");
52    private static final byte[] row1 = Bytes.toBytes("r1");
53    private static final byte[] row2 = Bytes.toBytes("r2");
54    private static final byte[] row3 = Bytes.toBytes("r3");
55    private static final byte[] test = Bytes.toBytes("test");
56  
57    @BeforeClass
58    public static void setUpBeforeClass() throws Exception {
59      Configuration conf = HBaseConfiguration.create();
60      conf.setStrings(CoprocessorHost.USER_REGION_COPROCESSOR_CONF_KEY,
61          TestCoprocessor.class.getName());
62      util = new HBaseTestingUtility(conf);
63      util.startMiniCluster();
64      util.createTable(tableName, new byte[][] {dummy, test});
65    }
66  
67    @AfterClass
68    public static void tearDownAfterClass() throws Exception {
69      util.shutdownMiniCluster();
70    }
71  
72    /**
73     * do a single put that is bypassed by a RegionObserver
74     * @throws Exception
75     */
76    @Test
77    public void testSimple() throws Exception {
78      HTable t = new HTable(util.getConfiguration(), tableName);
79      Put p = new Put(row1);
80      p.add(test,dummy,dummy);
81      // before HBASE-4331, this would throw an exception
82      t.put(p);
83      checkRowAndDelete(t,row1,0);
84      t.close();
85    }
86  
87    /**
88     * Test various multiput operations.
89     * @throws Exception
90     */
91    @Test
92    public void testMulti() throws Exception {
93      HTable t = new HTable(util.getConfiguration(), tableName);
94      List<Put> puts = new ArrayList<Put>();
95      Put p = new Put(row1);
96      p.add(dummy,dummy,dummy);
97      puts.add(p);
98      p = new Put(row2);
99      p.add(test,dummy,dummy);
100     puts.add(p);
101     p = new Put(row3);
102     p.add(test,dummy,dummy);
103     puts.add(p);
104     // before HBASE-4331, this would throw an exception
105     t.put(puts);
106     checkRowAndDelete(t,row1,1);
107     checkRowAndDelete(t,row2,0);
108     checkRowAndDelete(t,row3,0);
109 
110     puts.clear();
111     p = new Put(row1);
112     p.add(test,dummy,dummy);
113     puts.add(p);
114     p = new Put(row2);
115     p.add(test,dummy,dummy);
116     puts.add(p);
117     p = new Put(row3);
118     p.add(test,dummy,dummy);
119     puts.add(p);
120     // before HBASE-4331, this would throw an exception
121     t.put(puts);
122     checkRowAndDelete(t,row1,0);
123     checkRowAndDelete(t,row2,0);
124     checkRowAndDelete(t,row3,0);
125 
126     puts.clear();
127     p = new Put(row1);
128     p.add(test,dummy,dummy);
129     puts.add(p);
130     p = new Put(row2);
131     p.add(test,dummy,dummy);
132     puts.add(p);
133     p = new Put(row3);
134     p.add(dummy,dummy,dummy);
135     puts.add(p);
136     // this worked fine even before HBASE-4331
137     t.put(puts);
138     checkRowAndDelete(t,row1,0);
139     checkRowAndDelete(t,row2,0);
140     checkRowAndDelete(t,row3,1);
141 
142     puts.clear();
143     p = new Put(row1);
144     p.add(dummy,dummy,dummy);
145     puts.add(p);
146     p = new Put(row2);
147     p.add(test,dummy,dummy);
148     puts.add(p);
149     p = new Put(row3);
150     p.add(dummy,dummy,dummy);
151     puts.add(p);
152     // this worked fine even before HBASE-4331
153     t.put(puts);
154     checkRowAndDelete(t,row1,1);
155     checkRowAndDelete(t,row2,0);
156     checkRowAndDelete(t,row3,1);
157 
158     puts.clear();
159     p = new Put(row1);
160     p.add(test,dummy,dummy);
161     puts.add(p);
162     p = new Put(row2);
163     p.add(dummy,dummy,dummy);
164     puts.add(p);
165     p = new Put(row3);
166     p.add(test,dummy,dummy);
167     puts.add(p);
168     // before HBASE-4331, this would throw an exception
169     t.put(puts);
170     checkRowAndDelete(t,row1,0);
171     checkRowAndDelete(t,row2,1);
172     checkRowAndDelete(t,row3,0);
173     t.close();
174   }
175 
176   private void checkRowAndDelete(HTable t, byte[] row, int count) throws IOException {
177     Get g = new Get(row);
178     Result r = t.get(g);
179     assertEquals(count, r.size());
180     Delete d = new Delete(row);
181     t.delete(d);
182   }
183 
184   public static class TestCoprocessor extends BaseRegionObserver {
185     @Override
186     public void prePut(final ObserverContext<RegionCoprocessorEnvironment> e,
187         final Put put, final WALEdit edit, final boolean writeToWAL)
188         throws IOException {
189       Map<byte[], List<KeyValue>> familyMap = put.getFamilyMap();
190       if (familyMap.containsKey(test)) {
191         e.bypass();
192       }
193     }
194   }
195 
196   @org.junit.Rule
197   public org.apache.hadoop.hbase.ResourceCheckerJUnitRule cu =
198     new org.apache.hadoop.hbase.ResourceCheckerJUnitRule();
199 }
200