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.HBaseConfiguration;
29  import org.apache.hadoop.hbase.HBaseTestingUtility;
30  import org.apache.hadoop.hbase.KeyValue;
31  import org.apache.hadoop.hbase.client.Delete;
32  import org.apache.hadoop.hbase.client.Get;
33  import org.apache.hadoop.hbase.client.HTable;
34  import org.apache.hadoop.hbase.client.Put;
35  import org.apache.hadoop.hbase.client.Result;
36  import org.apache.hadoop.hbase.coprocessor.BaseRegionObserver;
37  import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
38  import org.apache.hadoop.hbase.coprocessor.ObserverContext;
39  import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
40  import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
41  import org.apache.hadoop.hbase.util.Bytes;
42  import org.junit.AfterClass;
43  import org.junit.BeforeClass;
44  import org.junit.Test;
45  
46  import static org.junit.Assert.assertEquals;
47  
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    }
85  
86    /**
87     * Test various multiput operations.
88     * @throws Exception
89     */
90    @Test
91    public void testMulti() throws Exception {
92      HTable t = new HTable(util.getConfiguration(), tableName);
93      List<Put> puts = new ArrayList<Put>();
94      Put p = new Put(row1);
95      p.add(dummy,dummy,dummy);
96      puts.add(p);
97      p = new Put(row2);
98      p.add(test,dummy,dummy);
99      puts.add(p);
100     p = new Put(row3);
101     p.add(test,dummy,dummy);
102     puts.add(p);
103     // before HBASE-4331, this would throw an exception
104     t.put(puts);
105     checkRowAndDelete(t,row1,1);
106     checkRowAndDelete(t,row2,0);
107     checkRowAndDelete(t,row3,0);
108 
109     puts.clear();
110     p = new Put(row1);
111     p.add(test,dummy,dummy);
112     puts.add(p);
113     p = new Put(row2);
114     p.add(test,dummy,dummy);
115     puts.add(p);
116     p = new Put(row3);
117     p.add(test,dummy,dummy);
118     puts.add(p);
119     // before HBASE-4331, this would throw an exception
120     t.put(puts);
121     checkRowAndDelete(t,row1,0);
122     checkRowAndDelete(t,row2,0);
123     checkRowAndDelete(t,row3,0);
124 
125     puts.clear();
126     p = new Put(row1);
127     p.add(test,dummy,dummy);
128     puts.add(p);
129     p = new Put(row2);
130     p.add(test,dummy,dummy);
131     puts.add(p);
132     p = new Put(row3);
133     p.add(dummy,dummy,dummy);
134     puts.add(p);
135     // this worked fine even before HBASE-4331
136     t.put(puts);
137     checkRowAndDelete(t,row1,0);
138     checkRowAndDelete(t,row2,0);
139     checkRowAndDelete(t,row3,1);
140 
141     puts.clear();
142     p = new Put(row1);
143     p.add(dummy,dummy,dummy);
144     puts.add(p);
145     p = new Put(row2);
146     p.add(test,dummy,dummy);
147     puts.add(p);
148     p = new Put(row3);
149     p.add(dummy,dummy,dummy);
150     puts.add(p);
151     // this worked fine even before HBASE-4331
152     t.put(puts);
153     checkRowAndDelete(t,row1,1);
154     checkRowAndDelete(t,row2,0);
155     checkRowAndDelete(t,row3,1);
156 
157     puts.clear();
158     p = new Put(row1);
159     p.add(test,dummy,dummy);
160     puts.add(p);
161     p = new Put(row2);
162     p.add(dummy,dummy,dummy);
163     puts.add(p);
164     p = new Put(row3);
165     p.add(test,dummy,dummy);
166     puts.add(p);
167     // before HBASE-4331, this would throw an exception
168     t.put(puts);
169     checkRowAndDelete(t,row1,0);
170     checkRowAndDelete(t,row2,1);
171     checkRowAndDelete(t,row3,0);
172   }
173 
174   private void checkRowAndDelete(HTable t, byte[] row, int count) throws IOException {
175     Get g = new Get(row);
176     Result r = t.get(g);
177     assertEquals(count, r.size());
178     Delete d = new Delete(row);
179     t.delete(d);
180   }
181 
182   public static class TestCoprocessor extends BaseRegionObserver {
183     @Override
184     public void prePut(final ObserverContext<RegionCoprocessorEnvironment> e,
185         final Put put, final WALEdit edit, final boolean writeToWAL)
186         throws IOException {
187       Map<byte[], List<KeyValue>> familyMap = put.getFamilyMap();
188       if (familyMap.containsKey(test)) {
189         e.bypass();
190       }
191     }
192   }
193 }