1   /**
2    * Copyright 2010 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  
21  package org.apache.hadoop.hbase.coprocessor;
22  
23  import static org.junit.Assert.assertNotNull;
24  import static org.junit.Assert.assertTrue;
25  
26  import java.io.IOException;
27  import java.util.List;
28  import java.util.Map;
29  import java.util.Arrays;
30  
31  import com.google.common.collect.ImmutableList;
32  import org.apache.commons.logging.Log;
33  import org.apache.commons.logging.LogFactory;
34  import org.apache.hadoop.hbase.KeyValue;
35  import org.apache.hadoop.hbase.client.Get;
36  import org.apache.hadoop.hbase.client.Put;
37  import org.apache.hadoop.hbase.client.Delete;
38  import org.apache.hadoop.hbase.client.Increment;
39  import org.apache.hadoop.hbase.client.Result;
40  import org.apache.hadoop.hbase.client.Scan;
41  import org.apache.hadoop.hbase.regionserver.HRegion;
42  import org.apache.hadoop.hbase.regionserver.InternalScanner;
43  import org.apache.hadoop.hbase.regionserver.RegionScanner;
44  import org.apache.hadoop.hbase.regionserver.Store;
45  import org.apache.hadoop.hbase.regionserver.StoreFile;
46  import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
47  import org.apache.hadoop.hbase.util.Bytes;
48  
49  /**
50   * A sample region observer that tests the RegionObserver interface.
51   * It works with TestRegionObserverInterface to provide the test case.
52   */
53  public class SimpleRegionObserver extends BaseRegionObserver {
54    static final Log LOG = LogFactory.getLog(TestRegionObserverInterface.class);
55  
56    boolean beforeDelete = true;
57    boolean scannerOpened = false;
58    boolean hadPreOpen;
59    boolean hadPostOpen;
60    boolean hadPreClose;
61    boolean hadPostClose;
62    boolean hadPreFlush;
63    boolean hadPostFlush;
64    boolean hadPreSplit;
65    boolean hadPostSplit;
66    boolean hadPreCompactSelect;
67    boolean hadPostCompactSelect;
68    boolean hadPreCompact;
69    boolean hadPostCompact;
70    boolean hadPreGet = false;
71    boolean hadPostGet = false;
72    boolean hadPrePut = false;
73    boolean hadPostPut = false;
74    boolean hadPreDeleted = false;
75    boolean hadPostDeleted = false;
76    boolean hadPreGetClosestRowBefore = false;
77    boolean hadPostGetClosestRowBefore = false;
78    boolean hadPreIncrement = false;
79    boolean hadPostIncrement = false;
80    boolean hadPreWALRestored = false;
81    boolean hadPostWALRestored = false;
82    boolean hadPreScannerNext = false;
83    boolean hadPostScannerNext = false;
84    boolean hadPreScannerClose = false;
85    boolean hadPostScannerClose = false;
86    boolean hadPreScannerOpen = false;
87    boolean hadPostScannerOpen = false;
88  
89    @Override
90    public void preOpen(ObserverContext<RegionCoprocessorEnvironment> c) {
91      hadPreOpen = true;
92    }
93  
94    @Override
95    public void postOpen(ObserverContext<RegionCoprocessorEnvironment> c) {
96      hadPostOpen = true;
97    }
98  
99    public boolean wasOpened() {
100     return hadPreOpen && hadPostOpen;
101   }
102 
103   @Override
104   public void preClose(ObserverContext<RegionCoprocessorEnvironment> c, boolean abortRequested) {
105     hadPreClose = true;
106   }
107 
108   @Override
109   public void postClose(ObserverContext<RegionCoprocessorEnvironment> c, boolean abortRequested) {
110     hadPostClose = true;
111   }
112 
113   public boolean wasClosed() {
114     return hadPreClose && hadPostClose;
115   }
116 
117   @Override
118   public void preFlush(ObserverContext<RegionCoprocessorEnvironment> c) {
119     hadPreFlush = true;
120   }
121 
122   @Override
123   public void postFlush(ObserverContext<RegionCoprocessorEnvironment> c) {
124     hadPostFlush = true;
125   }
126 
127   public boolean wasFlushed() {
128     return hadPreFlush && hadPostFlush;
129   }
130 
131   @Override
132   public void preSplit(ObserverContext<RegionCoprocessorEnvironment> c) {
133     hadPreSplit = true;
134   }
135 
136   @Override
137   public void postSplit(ObserverContext<RegionCoprocessorEnvironment> c, HRegion l, HRegion r) {
138     hadPostSplit = true;
139   }
140 
141   public boolean wasSplit() {
142     return hadPreSplit && hadPostSplit;
143   }
144 
145   @Override
146   public void preCompactSelection(ObserverContext<RegionCoprocessorEnvironment> c,
147       Store store, List<StoreFile> candidates) {
148     hadPreCompactSelect = true;
149   }
150 
151   @Override
152   public void postCompactSelection(ObserverContext<RegionCoprocessorEnvironment> c,
153       Store store, ImmutableList<StoreFile> selected) {
154     hadPostCompactSelect = true;
155   }
156 
157   @Override
158   public InternalScanner preCompact(ObserverContext<RegionCoprocessorEnvironment> e,
159       Store store, InternalScanner scanner) {
160     hadPreCompact = true;
161     return scanner;
162   }
163 
164   @Override
165   public void postCompact(ObserverContext<RegionCoprocessorEnvironment> e,
166       Store store, StoreFile resultFile) {
167     hadPostCompact = true;
168   }
169 
170   public boolean wasCompacted() {
171     return hadPreCompact && hadPostCompact;
172   }
173 
174   @Override
175   public RegionScanner preScannerOpen(final ObserverContext<RegionCoprocessorEnvironment> c,
176       final Scan scan,
177       final RegionScanner s) throws IOException {
178     hadPreScannerOpen = true;
179     return null;
180   }
181 
182   @Override
183   public RegionScanner postScannerOpen(final ObserverContext<RegionCoprocessorEnvironment> c,
184       final Scan scan, final RegionScanner s)
185       throws IOException {
186     hadPostScannerOpen = true;
187     return s;
188   }
189 
190   @Override
191   public boolean preScannerNext(final ObserverContext<RegionCoprocessorEnvironment> c,
192       final InternalScanner s, final List<Result> results,
193       final int limit, final boolean hasMore) throws IOException {
194     hadPreScannerNext = true;
195     return hasMore;
196   }
197 
198   @Override
199   public boolean postScannerNext(final ObserverContext<RegionCoprocessorEnvironment> c,
200       final InternalScanner s, final List<Result> results, final int limit,
201       final boolean hasMore) throws IOException {
202     hadPostScannerNext = true;
203     return hasMore;
204   }
205 
206   @Override
207   public void preScannerClose(final ObserverContext<RegionCoprocessorEnvironment> c,
208       final InternalScanner s) throws IOException {
209     hadPreScannerClose = true;
210   }
211 
212   @Override
213   public void postScannerClose(final ObserverContext<RegionCoprocessorEnvironment> c,
214       final InternalScanner s) throws IOException {
215     hadPostScannerClose = true;
216   }
217 
218   @Override
219   public void preGet(final ObserverContext<RegionCoprocessorEnvironment> c, final Get get,
220       final List<KeyValue> results) throws IOException {
221     RegionCoprocessorEnvironment e = c.getEnvironment();
222     assertNotNull(e);
223     assertNotNull(e.getRegion());
224     assertNotNull(get);
225     assertNotNull(results);
226     hadPreGet = true;
227   }
228 
229   @Override
230   public void postGet(final ObserverContext<RegionCoprocessorEnvironment> c, final Get get,
231       final List<KeyValue> results) {
232     RegionCoprocessorEnvironment e = c.getEnvironment();
233     assertNotNull(e);
234     assertNotNull(e.getRegion());
235     assertNotNull(get);
236     assertNotNull(results);
237     if (Arrays.equals(e.getRegion().getTableDesc().getName(),
238         TestRegionObserverInterface.TEST_TABLE)) {
239       boolean foundA = false;
240       boolean foundB = false;
241       boolean foundC = false;
242       for (KeyValue kv: results) {
243         if (Bytes.equals(kv.getFamily(), TestRegionObserverInterface.A)) {
244           foundA = true;
245         }
246         if (Bytes.equals(kv.getFamily(), TestRegionObserverInterface.B)) {
247           foundB = true;
248         }
249         if (Bytes.equals(kv.getFamily(), TestRegionObserverInterface.C)) {
250           foundC = true;
251         }
252       }
253       assertTrue(foundA);
254       assertTrue(foundB);
255       assertTrue(foundC);
256     }
257     hadPostGet = true;
258   }
259 
260   @Override
261   public void prePut(final ObserverContext<RegionCoprocessorEnvironment> c, 
262       final Put put, final WALEdit edit,
263       final boolean writeToWAL) throws IOException {
264     Map<byte[], List<KeyValue>> familyMap  = put.getFamilyMap();
265     RegionCoprocessorEnvironment e = c.getEnvironment();
266     assertNotNull(e);
267     assertNotNull(e.getRegion());
268     assertNotNull(familyMap);
269     if (Arrays.equals(e.getRegion().getTableDesc().getName(),
270         TestRegionObserverInterface.TEST_TABLE)) {
271       List<KeyValue> kvs = familyMap.get(TestRegionObserverInterface.A);
272       assertNotNull(kvs);
273       assertNotNull(kvs.get(0));
274       assertTrue(Bytes.equals(kvs.get(0).getQualifier(),
275           TestRegionObserverInterface.A));
276       kvs = familyMap.get(TestRegionObserverInterface.B);
277       assertNotNull(kvs);
278       assertNotNull(kvs.get(0));
279       assertTrue(Bytes.equals(kvs.get(0).getQualifier(),
280           TestRegionObserverInterface.B));
281       kvs = familyMap.get(TestRegionObserverInterface.C);
282       assertNotNull(kvs);
283       assertNotNull(kvs.get(0));
284       assertTrue(Bytes.equals(kvs.get(0).getQualifier(),
285           TestRegionObserverInterface.C));
286     }
287     hadPrePut = true;
288   }
289 
290   @Override
291   public void postPut(final ObserverContext<RegionCoprocessorEnvironment> c,
292       final Put put, final WALEdit edit,
293       final boolean writeToWAL) throws IOException {
294     Map<byte[], List<KeyValue>> familyMap  = put.getFamilyMap();
295     RegionCoprocessorEnvironment e = c.getEnvironment();
296     assertNotNull(e);
297     assertNotNull(e.getRegion());
298     assertNotNull(familyMap);
299     List<KeyValue> kvs = familyMap.get(TestRegionObserverInterface.A);
300     if (Arrays.equals(e.getRegion().getTableDesc().getName(),
301         TestRegionObserverInterface.TEST_TABLE)) {
302       assertNotNull(kvs);
303       assertNotNull(kvs.get(0));
304       assertTrue(Bytes.equals(kvs.get(0).getQualifier(),
305           TestRegionObserverInterface.A));
306       kvs = familyMap.get(TestRegionObserverInterface.B);
307       assertNotNull(kvs);
308       assertNotNull(kvs.get(0));
309       assertTrue(Bytes.equals(kvs.get(0).getQualifier(),
310           TestRegionObserverInterface.B));
311       kvs = familyMap.get(TestRegionObserverInterface.C);
312       assertNotNull(kvs);
313       assertNotNull(kvs.get(0));
314       assertTrue(Bytes.equals(kvs.get(0).getQualifier(),
315           TestRegionObserverInterface.C));
316     }
317     hadPostPut = true;
318   }
319 
320   @Override
321   public void preDelete(final ObserverContext<RegionCoprocessorEnvironment> c, 
322       final Delete delete, final WALEdit edit,
323       final boolean writeToWAL) throws IOException {
324     Map<byte[], List<KeyValue>> familyMap  = delete.getFamilyMap();
325     RegionCoprocessorEnvironment e = c.getEnvironment();
326     assertNotNull(e);
327     assertNotNull(e.getRegion());
328     assertNotNull(familyMap);
329     if (beforeDelete) {
330       hadPreDeleted = true;
331     }
332   }
333 
334   @Override
335   public void postDelete(final ObserverContext<RegionCoprocessorEnvironment> c, 
336       final Delete delete, final WALEdit edit,
337       final boolean writeToWAL) throws IOException {
338     Map<byte[], List<KeyValue>> familyMap  = delete.getFamilyMap();
339     RegionCoprocessorEnvironment e = c.getEnvironment();
340     assertNotNull(e);
341     assertNotNull(e.getRegion());
342     assertNotNull(familyMap);
343     beforeDelete = false;
344     hadPostDeleted = true;
345   }
346 
347   @Override
348   public void preGetClosestRowBefore(final ObserverContext<RegionCoprocessorEnvironment> c,
349       final byte[] row, final byte[] family, final Result result)
350       throws IOException {
351     RegionCoprocessorEnvironment e = c.getEnvironment();
352     assertNotNull(e);
353     assertNotNull(e.getRegion());
354     assertNotNull(row);
355     assertNotNull(result);
356     if (beforeDelete) {
357       hadPreGetClosestRowBefore = true;
358     }
359   }
360 
361   @Override
362   public void postGetClosestRowBefore(final ObserverContext<RegionCoprocessorEnvironment> c,
363       final byte[] row, final byte[] family, final Result result)
364       throws IOException {
365     RegionCoprocessorEnvironment e = c.getEnvironment();
366     assertNotNull(e);
367     assertNotNull(e.getRegion());
368     assertNotNull(row);
369     assertNotNull(result);
370     hadPostGetClosestRowBefore = true;
371   }
372 
373   @Override
374   public void preIncrement(final ObserverContext<RegionCoprocessorEnvironment> c,
375       final Increment increment, final Result result) throws IOException {
376     hadPreIncrement = true;
377   }
378 
379   @Override
380   public void postIncrement(final ObserverContext<RegionCoprocessorEnvironment> c,
381       final Increment increment, final Result result) throws IOException {
382     hadPostIncrement = true;
383   }
384 
385   public boolean hadPreGet() {
386     return hadPreGet;
387   }
388 
389   public boolean hadPostGet() {
390     return hadPostGet;
391   }
392 
393   public boolean hadPrePut() {
394     return hadPrePut;
395   }
396 
397   public boolean hadPostPut() {
398     return hadPostPut;
399   }
400   public boolean hadDelete() {
401     return !beforeDelete;
402   }
403 
404   public boolean hadPreIncrement() {
405     return hadPreIncrement;
406   }
407 
408   public boolean hadPostIncrement() {
409     return hadPostIncrement;
410   }
411 
412   public boolean hadPreWALRestored() {
413     return hadPreWALRestored;
414   }
415 
416   public boolean hadPostWALRestored() {
417     return hadPostWALRestored;
418   }
419   public boolean wasScannerNextCalled() {
420     return hadPreScannerNext && hadPostScannerNext;
421   }
422   public boolean wasScannerCloseCalled() {
423     return hadPreScannerClose && hadPostScannerClose;
424   }
425   public boolean wasScannerOpenCalled() {
426     return hadPreScannerOpen && hadPostScannerOpen;
427   }
428   public boolean hadDeleted() {
429     return hadPreDeleted && hadPostDeleted;
430   }
431 }