View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  
20  package org.apache.hadoop.hbase.coprocessor;
21  
22  import static org.junit.Assert.assertArrayEquals;
23  import static org.junit.Assert.assertEquals;
24  import static org.junit.Assert.assertNotNull;
25  import static org.junit.Assert.assertTrue;
26  
27  import java.io.IOException;
28  import java.util.List;
29  import java.util.Map;
30  import java.util.NavigableSet;
31  import java.util.concurrent.atomic.AtomicBoolean;
32  import java.util.concurrent.atomic.AtomicInteger;
33  
34  import org.apache.commons.logging.Log;
35  import org.apache.commons.logging.LogFactory;
36  import org.apache.hadoop.fs.FileSystem;
37  import org.apache.hadoop.fs.Path;
38  import org.apache.hadoop.hbase.Cell;
39  import org.apache.hadoop.hbase.CellUtil;
40  import org.apache.hadoop.hbase.CoprocessorEnvironment;
41  import org.apache.hadoop.hbase.HRegionInfo;
42  import org.apache.hadoop.hbase.KeyValue;
43  import org.apache.hadoop.hbase.client.Append;
44  import org.apache.hadoop.hbase.client.Delete;
45  import org.apache.hadoop.hbase.client.Durability;
46  import org.apache.hadoop.hbase.client.Get;
47  import org.apache.hadoop.hbase.client.Increment;
48  import org.apache.hadoop.hbase.client.Mutation;
49  import org.apache.hadoop.hbase.client.Put;
50  import org.apache.hadoop.hbase.client.Result;
51  import org.apache.hadoop.hbase.client.Scan;
52  import org.apache.hadoop.hbase.filter.ByteArrayComparable;
53  import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
54  import org.apache.hadoop.hbase.io.FSDataInputStreamWrapper;
55  import org.apache.hadoop.hbase.io.Reference;
56  import org.apache.hadoop.hbase.io.hfile.CacheConfig;
57  import org.apache.hadoop.hbase.regionserver.HRegion;
58  import org.apache.hadoop.hbase.regionserver.HRegion.Operation;
59  import org.apache.hadoop.hbase.regionserver.InternalScanner;
60  import org.apache.hadoop.hbase.regionserver.KeyValueScanner;
61  import org.apache.hadoop.hbase.regionserver.Leases;
62  import org.apache.hadoop.hbase.regionserver.MiniBatchOperationInProgress;
63  import org.apache.hadoop.hbase.regionserver.RegionScanner;
64  import org.apache.hadoop.hbase.regionserver.ScanType;
65  import org.apache.hadoop.hbase.regionserver.Store;
66  import org.apache.hadoop.hbase.regionserver.StoreFile;
67  import org.apache.hadoop.hbase.regionserver.StoreFile.Reader;
68  import org.apache.hadoop.hbase.regionserver.wal.HLogKey;
69  import org.apache.hadoop.hbase.wal.WALKey;
70  import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
71  import org.apache.hadoop.hbase.util.Bytes;
72  import org.apache.hadoop.hbase.util.Pair;
73  
74  import com.google.common.collect.ImmutableList;
75  
76  /**
77   * A sample region observer that tests the RegionObserver interface.
78   * It works with TestRegionObserverInterface to provide the test case.
79   */
80  public class SimpleRegionObserver extends BaseRegionObserver {
81    static final Log LOG = LogFactory.getLog(TestRegionObserverInterface.class);
82  
83    final AtomicInteger ctBeforeDelete = new AtomicInteger(1);
84    final AtomicInteger ctPreOpen = new AtomicInteger(0);
85    final AtomicInteger ctPostOpen = new AtomicInteger(0);
86    final AtomicInteger ctPreClose = new AtomicInteger(0);
87    final AtomicInteger ctPostClose = new AtomicInteger(0);
88    final AtomicInteger ctPreFlush = new AtomicInteger(0);
89    final AtomicInteger ctPreFlushScannerOpen = new AtomicInteger(0);
90    final AtomicInteger ctPostFlush = new AtomicInteger(0);
91    final AtomicInteger ctPreSplit = new AtomicInteger(0);
92    final AtomicInteger ctPostSplit = new AtomicInteger(0);
93    final AtomicInteger ctPreCompactSelect = new AtomicInteger(0);
94    final AtomicInteger ctPostCompactSelect = new AtomicInteger(0);
95    final AtomicInteger ctPreCompactScanner = new AtomicInteger(0);
96    final AtomicInteger ctPreCompact = new AtomicInteger(0);
97    final AtomicInteger ctPostCompact = new AtomicInteger(0);
98    final AtomicInteger ctPreGet = new AtomicInteger(0);
99    final AtomicInteger ctPostGet = new AtomicInteger(0);
100   final AtomicInteger ctPrePut = new AtomicInteger(0);
101   final AtomicInteger ctPostPut = new AtomicInteger(0);
102   final AtomicInteger ctPreDeleted = new AtomicInteger(0);
103   final AtomicInteger ctPrePrepareDeleteTS = new AtomicInteger(0);
104   final AtomicInteger ctPostDeleted = new AtomicInteger(0);
105   final AtomicInteger ctPreGetClosestRowBefore = new AtomicInteger(0);
106   final AtomicInteger ctPostGetClosestRowBefore = new AtomicInteger(0);
107   final AtomicInteger ctPreIncrement = new AtomicInteger(0);
108   final AtomicInteger ctPreIncrementAfterRowLock = new AtomicInteger(0);
109   final AtomicInteger ctPreAppend = new AtomicInteger(0);
110   final AtomicInteger ctPreAppendAfterRowLock = new AtomicInteger(0);
111   final AtomicInteger ctPostIncrement = new AtomicInteger(0);
112   final AtomicInteger ctPostAppend = new AtomicInteger(0);
113   final AtomicInteger ctPreCheckAndPut = new AtomicInteger(0);
114   final AtomicInteger ctPreCheckAndPutAfterRowLock = new AtomicInteger(0);
115   final AtomicInteger ctPostCheckAndPut = new AtomicInteger(0);
116   final AtomicInteger ctPreCheckAndDelete = new AtomicInteger(0);
117   final AtomicInteger ctPreCheckAndDeleteAfterRowLock = new AtomicInteger(0);
118   final AtomicInteger ctPostCheckAndDelete = new AtomicInteger(0);
119   final AtomicInteger ctPreScannerNext = new AtomicInteger(0);
120   final AtomicInteger ctPostScannerNext = new AtomicInteger(0);
121   final AtomicInteger ctPreScannerClose = new AtomicInteger(0);
122   final AtomicInteger ctPostScannerClose = new AtomicInteger(0);
123   final AtomicInteger ctPreScannerOpen = new AtomicInteger(0);
124   final AtomicInteger ctPreStoreScannerOpen = new AtomicInteger(0);
125   final AtomicInteger ctPostScannerOpen = new AtomicInteger(0);
126   final AtomicInteger ctPreBulkLoadHFile = new AtomicInteger(0);
127   final AtomicInteger ctPostBulkLoadHFile = new AtomicInteger(0);
128   final AtomicInteger ctPreBatchMutate = new AtomicInteger(0);
129   final AtomicInteger ctPostBatchMutate = new AtomicInteger(0);
130   final AtomicInteger ctPreWALRestore = new AtomicInteger(0);
131   final AtomicInteger ctPostWALRestore = new AtomicInteger(0);
132   final AtomicInteger ctPreWALRestoreDeprecated = new AtomicInteger(0);
133   final AtomicInteger ctPostWALRestoreDeprecated = new AtomicInteger(0);
134   final AtomicInteger ctPreSplitBeforePONR = new AtomicInteger(0);
135   final AtomicInteger ctPreSplitAfterPONR = new AtomicInteger(0);
136   final AtomicInteger ctPreStoreFileReaderOpen = new AtomicInteger(0);
137   final AtomicInteger ctPostStoreFileReaderOpen = new AtomicInteger(0);
138   final AtomicInteger ctPostBatchMutateIndispensably = new AtomicInteger(0);
139   final AtomicInteger ctPostStartRegionOperation = new AtomicInteger(0);
140   final AtomicInteger ctPostCloseRegionOperation = new AtomicInteger(0);
141   final AtomicBoolean throwOnPostFlush = new AtomicBoolean(false);
142   static final String TABLE_SKIPPED = "SKIPPED_BY_PREWALRESTORE";
143 
144   public void setThrowOnPostFlush(Boolean val){
145     throwOnPostFlush.set(val);
146   }
147 
148   @Override
149   public void start(CoprocessorEnvironment e) throws IOException {
150     // this only makes sure that leases and locks are available to coprocessors
151     // from external packages
152     RegionCoprocessorEnvironment re = (RegionCoprocessorEnvironment)e;
153     Leases leases = re.getRegionServerServices().getLeases();
154     leases.createLease(re.getRegion().getRegionNameAsString(), 2000, null);
155     leases.cancelLease(re.getRegion().getRegionNameAsString());
156   }
157 
158   @Override
159   public void preOpen(ObserverContext<RegionCoprocessorEnvironment> c) {
160     ctPreOpen.incrementAndGet();
161   }
162 
163   @Override
164   public void postOpen(ObserverContext<RegionCoprocessorEnvironment> c) {
165     ctPostOpen.incrementAndGet();
166   }
167 
168   public boolean wasOpened() {
169     return ctPreOpen.get() > 0 && ctPostOpen.get() > 0;
170   }
171 
172   @Override
173   public void preClose(ObserverContext<RegionCoprocessorEnvironment> c, boolean abortRequested) {
174     ctPreClose.incrementAndGet();
175   }
176 
177   @Override
178   public void postClose(ObserverContext<RegionCoprocessorEnvironment> c, boolean abortRequested) {
179     ctPostClose.incrementAndGet();
180   }
181 
182   public boolean wasClosed() {
183     return ctPreClose.get() > 0 && ctPostClose.get() > 0;
184   }
185 
186   @Override
187   public InternalScanner preFlush(ObserverContext<RegionCoprocessorEnvironment> c,
188       Store store, InternalScanner scanner) throws IOException {
189     ctPreFlush.incrementAndGet();
190     return scanner;
191   }
192 
193   @Override
194   public InternalScanner preFlushScannerOpen(final ObserverContext<RegionCoprocessorEnvironment> c,
195       Store store, KeyValueScanner memstoreScanner, InternalScanner s) throws IOException {
196     ctPreFlushScannerOpen.incrementAndGet();
197     return null;
198   }
199 
200   @Override
201   public void postFlush(ObserverContext<RegionCoprocessorEnvironment> c,
202       Store store, StoreFile resultFile) throws IOException {
203     ctPostFlush.incrementAndGet();
204     if (throwOnPostFlush.get()){
205       throw new IOException("throwOnPostFlush is true in postFlush");
206     }
207   }
208 
209   public boolean wasFlushed() {
210     return ctPreFlush.get() > 0 && ctPostFlush.get() > 0;
211   }
212 
213   @Override
214   public void preSplit(ObserverContext<RegionCoprocessorEnvironment> c) {
215     ctPreSplit.incrementAndGet();
216   }
217 
218   @Override
219   public void preSplitBeforePONR(
220       ObserverContext<RegionCoprocessorEnvironment> ctx, byte[] splitKey,
221       List<Mutation> metaEntries) throws IOException {
222     ctPreSplitBeforePONR.incrementAndGet();
223   }
224   
225   @Override
226   public void preSplitAfterPONR(
227       ObserverContext<RegionCoprocessorEnvironment> ctx) throws IOException {
228     ctPreSplitAfterPONR.incrementAndGet();
229   }
230   
231   @Override
232   public void postSplit(ObserverContext<RegionCoprocessorEnvironment> c, HRegion l, HRegion r) {
233     ctPostSplit.incrementAndGet();
234   }
235 
236   public boolean wasSplit() {
237     return ctPreSplit.get() > 0 && ctPostSplit.get() > 0;
238   }
239 
240   @Override
241   public void preCompactSelection(ObserverContext<RegionCoprocessorEnvironment> c,
242       Store store, List<StoreFile> candidates) {
243     ctPreCompactSelect.incrementAndGet();
244   }
245 
246   @Override
247   public void postCompactSelection(ObserverContext<RegionCoprocessorEnvironment> c,
248       Store store, ImmutableList<StoreFile> selected) {
249     ctPostCompactSelect.incrementAndGet();
250   }
251 
252   @Override
253   public InternalScanner preCompact(ObserverContext<RegionCoprocessorEnvironment> e,
254       Store store, InternalScanner scanner, ScanType scanType) {
255     ctPreCompact.incrementAndGet();
256     return scanner;
257   }
258 
259   @Override
260   public InternalScanner preCompactScannerOpen(
261       final ObserverContext<RegionCoprocessorEnvironment> c,
262       Store store, List<? extends KeyValueScanner> scanners, ScanType scanType, long earliestPutTs,
263       InternalScanner s) throws IOException {
264     ctPreCompactScanner.incrementAndGet();
265     return null;
266   }
267 
268   @Override
269   public void postCompact(ObserverContext<RegionCoprocessorEnvironment> e,
270       Store store, StoreFile resultFile) {
271     ctPostCompact.incrementAndGet();
272   }
273 
274   public boolean wasCompacted() {
275     return ctPreCompact.get() > 0 && ctPostCompact.get() > 0;
276   }
277 
278   @Override
279   public RegionScanner preScannerOpen(final ObserverContext<RegionCoprocessorEnvironment> c,
280       final Scan scan,
281       final RegionScanner s) throws IOException {
282     ctPreScannerOpen.incrementAndGet();
283     return null;
284   }
285 
286   @Override
287   public KeyValueScanner preStoreScannerOpen(final ObserverContext<RegionCoprocessorEnvironment> c,
288       final Store store, final Scan scan, final NavigableSet<byte[]> targetCols,
289       final KeyValueScanner s) throws IOException {
290     ctPreStoreScannerOpen.incrementAndGet();
291     return null;
292   }
293 
294   @Override
295   public RegionScanner postScannerOpen(final ObserverContext<RegionCoprocessorEnvironment> c,
296       final Scan scan, final RegionScanner s)
297       throws IOException {
298     ctPostScannerOpen.incrementAndGet();
299     return s;
300   }
301 
302   @Override
303   public boolean preScannerNext(final ObserverContext<RegionCoprocessorEnvironment> c,
304       final InternalScanner s, final List<Result> results,
305       final int limit, final boolean hasMore) throws IOException {
306     ctPreScannerNext.incrementAndGet();
307     return hasMore;
308   }
309 
310   @Override
311   public boolean postScannerNext(final ObserverContext<RegionCoprocessorEnvironment> c,
312       final InternalScanner s, final List<Result> results, final int limit,
313       final boolean hasMore) throws IOException {
314     ctPostScannerNext.incrementAndGet();
315     return hasMore;
316   }
317 
318   @Override
319   public void preScannerClose(final ObserverContext<RegionCoprocessorEnvironment> c,
320       final InternalScanner s) throws IOException {
321     ctPreScannerClose.incrementAndGet();
322   }
323 
324   @Override
325   public void postScannerClose(final ObserverContext<RegionCoprocessorEnvironment> c,
326       final InternalScanner s) throws IOException {
327     ctPostScannerClose.incrementAndGet();
328   }
329 
330   @Override
331   public void preGetOp(final ObserverContext<RegionCoprocessorEnvironment> c, final Get get,
332       final List<Cell> results) throws IOException {
333     RegionCoprocessorEnvironment e = c.getEnvironment();
334     assertNotNull(e);
335     assertNotNull(e.getRegion());
336     assertNotNull(get);
337     assertNotNull(results);
338     ctPreGet.incrementAndGet();
339   }
340 
341   @Override
342   public void postGetOp(final ObserverContext<RegionCoprocessorEnvironment> c, final Get get,
343       final List<Cell> results) {
344     RegionCoprocessorEnvironment e = c.getEnvironment();
345     assertNotNull(e);
346     assertNotNull(e.getRegion());
347     assertNotNull(get);
348     assertNotNull(results);
349     if (e.getRegion().getTableDesc().getTableName().equals(
350         TestRegionObserverInterface.TEST_TABLE)) {
351       boolean foundA = false;
352       boolean foundB = false;
353       boolean foundC = false;
354       for (Cell kv: results) {
355         if (CellUtil.matchingFamily(kv, TestRegionObserverInterface.A)) {
356           foundA = true;
357         }
358         if (CellUtil.matchingFamily(kv, TestRegionObserverInterface.B)) {
359           foundB = true;
360         }
361         if (CellUtil.matchingFamily(kv, TestRegionObserverInterface.C)) {
362           foundC = true;
363         }
364       }
365       assertTrue(foundA);
366       assertTrue(foundB);
367       assertTrue(foundC);
368     }
369     ctPostGet.incrementAndGet();
370   }
371 
372   @Override
373   public void prePut(final ObserverContext<RegionCoprocessorEnvironment> c, 
374       final Put put, final WALEdit edit,
375       final Durability durability) throws IOException {
376     Map<byte[], List<Cell>> familyMap  = put.getFamilyCellMap();
377     RegionCoprocessorEnvironment e = c.getEnvironment();
378     assertNotNull(e);
379     assertNotNull(e.getRegion());
380     assertNotNull(familyMap);
381     if (e.getRegion().getTableDesc().getTableName().equals(
382         TestRegionObserverInterface.TEST_TABLE)) {
383       List<Cell> cells = familyMap.get(TestRegionObserverInterface.A);
384       assertNotNull(cells);
385       assertNotNull(cells.get(0));
386       KeyValue kv = (KeyValue)cells.get(0);
387       assertTrue(Bytes.equals(kv.getQualifier(),
388           TestRegionObserverInterface.A));
389       cells = familyMap.get(TestRegionObserverInterface.B);
390       assertNotNull(cells);
391       assertNotNull(cells.get(0));
392       kv = (KeyValue)cells.get(0);
393       assertTrue(Bytes.equals(kv.getQualifier(),
394           TestRegionObserverInterface.B));
395       cells = familyMap.get(TestRegionObserverInterface.C);
396       assertNotNull(cells);
397       assertNotNull(cells.get(0));
398       kv = (KeyValue)cells.get(0);
399       assertTrue(Bytes.equals(kv.getQualifier(),
400           TestRegionObserverInterface.C));
401     }
402     ctPrePut.incrementAndGet();
403   }
404 
405   @Override
406   public void postPut(final ObserverContext<RegionCoprocessorEnvironment> c,
407       final Put put, final WALEdit edit,
408       final Durability durability) throws IOException {
409     Map<byte[], List<Cell>> familyMap  = put.getFamilyCellMap();
410     RegionCoprocessorEnvironment e = c.getEnvironment();
411     assertNotNull(e);
412     assertNotNull(e.getRegion());
413     assertNotNull(familyMap);
414     List<Cell> cells = familyMap.get(TestRegionObserverInterface.A);
415     if (e.getRegion().getTableDesc().getTableName().equals(
416         TestRegionObserverInterface.TEST_TABLE)) {
417       assertNotNull(cells);
418       assertNotNull(cells.get(0));
419       // KeyValue v1 expectation.  Cast for now until we go all Cell all the time. TODO
420       KeyValue kv = (KeyValue)cells.get(0);
421       assertTrue(Bytes.equals(kv.getQualifier(), TestRegionObserverInterface.A));
422       cells = familyMap.get(TestRegionObserverInterface.B);
423       assertNotNull(cells);
424       assertNotNull(cells.get(0));
425       // KeyValue v1 expectation.  Cast for now until we go all Cell all the time. TODO
426       kv = (KeyValue)cells.get(0);
427       assertTrue(Bytes.equals(kv.getQualifier(), TestRegionObserverInterface.B));
428       cells = familyMap.get(TestRegionObserverInterface.C);
429       assertNotNull(cells);
430       assertNotNull(cells.get(0));
431       // KeyValue v1 expectation.  Cast for now until we go all Cell all the time. TODO
432       kv = (KeyValue)cells.get(0);
433       assertTrue(Bytes.equals(kv.getQualifier(), TestRegionObserverInterface.C));
434     }
435     ctPostPut.incrementAndGet();
436   }
437 
438   @Override
439   public void preDelete(final ObserverContext<RegionCoprocessorEnvironment> c, 
440       final Delete delete, final WALEdit edit,
441       final Durability durability) throws IOException {
442     Map<byte[], List<Cell>> familyMap  = delete.getFamilyCellMap();
443     RegionCoprocessorEnvironment e = c.getEnvironment();
444     assertNotNull(e);
445     assertNotNull(e.getRegion());
446     assertNotNull(familyMap);
447     if (ctBeforeDelete.get() > 0) {
448       ctPreDeleted.incrementAndGet();
449     }
450   }
451 
452   @Override
453   public void prePrepareTimeStampForDeleteVersion(ObserverContext<RegionCoprocessorEnvironment> e,
454       Mutation delete, Cell cell, byte[] byteNow, Get get) throws IOException {
455     ctPrePrepareDeleteTS.incrementAndGet();
456   }
457 
458   @Override
459   public void postDelete(final ObserverContext<RegionCoprocessorEnvironment> c, 
460       final Delete delete, final WALEdit edit,
461       final Durability durability) throws IOException {
462     Map<byte[], List<Cell>> familyMap  = delete.getFamilyCellMap();
463     RegionCoprocessorEnvironment e = c.getEnvironment();
464     assertNotNull(e);
465     assertNotNull(e.getRegion());
466     assertNotNull(familyMap);
467     ctBeforeDelete.set(0);
468     ctPostDeleted.incrementAndGet();
469   }
470   
471   @Override
472   public void preBatchMutate(ObserverContext<RegionCoprocessorEnvironment> c,
473       MiniBatchOperationInProgress<Mutation> miniBatchOp) throws IOException {
474     RegionCoprocessorEnvironment e = c.getEnvironment();
475     assertNotNull(e);
476     assertNotNull(e.getRegion());
477     assertNotNull(miniBatchOp);
478     ctPreBatchMutate.incrementAndGet();
479   }
480 
481   @Override
482   public void postBatchMutate(final ObserverContext<RegionCoprocessorEnvironment> c,
483       final MiniBatchOperationInProgress<Mutation> miniBatchOp) throws IOException {
484     RegionCoprocessorEnvironment e = c.getEnvironment();
485     assertNotNull(e);
486     assertNotNull(e.getRegion());
487     assertNotNull(miniBatchOp);
488     ctPostBatchMutate.incrementAndGet();
489   }
490 
491   @Override
492   public void postStartRegionOperation(final ObserverContext<RegionCoprocessorEnvironment> ctx,
493       Operation op) throws IOException {
494     ctPostStartRegionOperation.incrementAndGet();
495   }
496 
497   @Override
498   public void postCloseRegionOperation(final ObserverContext<RegionCoprocessorEnvironment> ctx,
499       Operation op) throws IOException {
500     if (ctPostStartRegionOperation.get() > 0) {
501       ctPostCloseRegionOperation.incrementAndGet();
502     }
503   }
504 
505   @Override
506   public void postBatchMutateIndispensably(final ObserverContext<RegionCoprocessorEnvironment> ctx,
507       MiniBatchOperationInProgress<Mutation> miniBatchOp, final boolean success) throws IOException {
508     ctPostBatchMutateIndispensably.incrementAndGet();
509   }
510 
511   @Override
512   public void preGetClosestRowBefore(final ObserverContext<RegionCoprocessorEnvironment> c,
513       final byte[] row, final byte[] family, final Result result)
514       throws IOException {
515     RegionCoprocessorEnvironment e = c.getEnvironment();
516     assertNotNull(e);
517     assertNotNull(e.getRegion());
518     assertNotNull(row);
519     assertNotNull(result);
520     if (ctBeforeDelete.get() > 0) {
521       ctPreGetClosestRowBefore.incrementAndGet();
522     }
523   }
524 
525   @Override
526   public void postGetClosestRowBefore(final ObserverContext<RegionCoprocessorEnvironment> c,
527       final byte[] row, final byte[] family, final Result result)
528       throws IOException {
529     RegionCoprocessorEnvironment e = c.getEnvironment();
530     assertNotNull(e);
531     assertNotNull(e.getRegion());
532     assertNotNull(row);
533     assertNotNull(result);
534     ctPostGetClosestRowBefore.incrementAndGet();
535   }
536 
537   @Override
538   public Result preIncrement(final ObserverContext<RegionCoprocessorEnvironment> c,
539       final Increment increment) throws IOException {
540     ctPreIncrement.incrementAndGet();
541     return null;
542   }
543 
544   @Override
545   public Result preIncrementAfterRowLock(ObserverContext<RegionCoprocessorEnvironment> e,
546       Increment increment) throws IOException {
547     ctPreIncrementAfterRowLock.incrementAndGet();
548     return null;
549   }
550 
551   @Override
552   public Result postIncrement(final ObserverContext<RegionCoprocessorEnvironment> c,
553       final Increment increment, final Result result) throws IOException {
554     ctPostIncrement.incrementAndGet();
555     return result;
556   }
557 
558   @Override
559   public boolean preCheckAndPut(ObserverContext<RegionCoprocessorEnvironment> e, byte[] row,
560       byte[] family, byte[] qualifier, CompareOp compareOp, ByteArrayComparable comparator,
561       Put put, boolean result) throws IOException {
562     ctPreCheckAndPut.incrementAndGet();
563     return true;
564   }
565 
566   @Override
567   public boolean preCheckAndPutAfterRowLock(ObserverContext<RegionCoprocessorEnvironment> e,
568       byte[] row, byte[] family, byte[] qualifier, CompareOp compareOp,
569       ByteArrayComparable comparator, Put put, boolean result) throws IOException {
570     ctPreCheckAndPutAfterRowLock.incrementAndGet();
571     return true;
572   }
573 
574   @Override
575   public boolean postCheckAndPut(ObserverContext<RegionCoprocessorEnvironment> e, byte[] row,
576       byte[] family, byte[] qualifier, CompareOp compareOp, ByteArrayComparable comparator,
577       Put put, boolean result) throws IOException {
578     ctPostCheckAndPut.incrementAndGet();
579     return true;
580   }
581 
582   @Override
583   public boolean preCheckAndDelete(ObserverContext<RegionCoprocessorEnvironment> e, byte[] row,
584       byte[] family, byte[] qualifier, CompareOp compareOp, ByteArrayComparable comparator,
585       Delete delete, boolean result) throws IOException {
586     ctPreCheckAndDelete.incrementAndGet();
587     return true;
588   }
589 
590   @Override
591   public boolean preCheckAndDeleteAfterRowLock(ObserverContext<RegionCoprocessorEnvironment> e,
592       byte[] row, byte[] family, byte[] qualifier, CompareOp compareOp,
593       ByteArrayComparable comparator, Delete delete, boolean result) throws IOException {
594     ctPreCheckAndDeleteAfterRowLock.incrementAndGet();
595     return true;
596   }
597 
598   @Override
599   public boolean postCheckAndDelete(ObserverContext<RegionCoprocessorEnvironment> e, byte[] row,
600       byte[] family, byte[] qualifier, CompareOp compareOp, ByteArrayComparable comparator,
601       Delete delete, boolean result) throws IOException {
602     ctPostCheckAndDelete.incrementAndGet();
603     return true;
604   }
605 
606   @Override
607   public Result preAppendAfterRowLock(ObserverContext<RegionCoprocessorEnvironment> e, 
608       Append append) throws IOException {
609     ctPreAppendAfterRowLock.incrementAndGet();
610     return null;
611   }
612 
613   @Override
614   public Result preAppend(ObserverContext<RegionCoprocessorEnvironment> e, Append append)
615       throws IOException {
616     ctPreAppend.incrementAndGet();
617     return null;
618   }
619 
620   @Override
621   public Result postAppend(ObserverContext<RegionCoprocessorEnvironment> e, Append append,
622       Result result) throws IOException {
623     ctPostAppend.incrementAndGet();
624     return null;
625   }
626 
627   @Override
628   public void preBulkLoadHFile(ObserverContext<RegionCoprocessorEnvironment> ctx,
629                                List<Pair<byte[], String>> familyPaths) throws IOException {
630     RegionCoprocessorEnvironment e = ctx.getEnvironment();
631     assertNotNull(e);
632     assertNotNull(e.getRegion());
633     if (e.getRegion().getTableDesc().getTableName().equals(
634         TestRegionObserverInterface.TEST_TABLE)) {
635       assertNotNull(familyPaths);
636       assertEquals(1,familyPaths.size());
637       assertArrayEquals(familyPaths.get(0).getFirst(), TestRegionObserverInterface.A);
638       String familyPath = familyPaths.get(0).getSecond();
639       String familyName = Bytes.toString(TestRegionObserverInterface.A);
640       assertEquals(familyPath.substring(familyPath.length()-familyName.length()-1),"/"+familyName);
641     }
642     ctPreBulkLoadHFile.incrementAndGet();
643   }
644 
645   @Override
646   public boolean postBulkLoadHFile(ObserverContext<RegionCoprocessorEnvironment> ctx,
647       List<Pair<byte[], String>> familyPaths, boolean hasLoaded) throws IOException {
648     RegionCoprocessorEnvironment e = ctx.getEnvironment();
649     assertNotNull(e);
650     assertNotNull(e.getRegion());
651     if (e.getRegion().getTableDesc().getTableName().equals(
652         TestRegionObserverInterface.TEST_TABLE)) {
653       assertNotNull(familyPaths);
654       assertEquals(1,familyPaths.size());
655       assertArrayEquals(familyPaths.get(0).getFirst(), TestRegionObserverInterface.A);
656       String familyPath = familyPaths.get(0).getSecond();
657       String familyName = Bytes.toString(TestRegionObserverInterface.A);
658       assertEquals(familyPath.substring(familyPath.length()-familyName.length()-1),"/"+familyName);
659     }
660     ctPostBulkLoadHFile.incrementAndGet();
661     return hasLoaded;
662   }
663 
664   @Override
665   public void preWALRestore(ObserverContext<? extends RegionCoprocessorEnvironment> env,
666       HRegionInfo info, WALKey logKey, WALEdit logEdit) throws IOException {
667     String tableName = logKey.getTablename().getNameAsString();
668     if (tableName.equals(TABLE_SKIPPED)) {
669       // skip recovery of TABLE_SKIPPED for testing purpose
670       env.bypass();
671       return;
672     }
673     ctPreWALRestore.incrementAndGet();
674   }
675 
676   @Override
677   public void preWALRestore(ObserverContext<RegionCoprocessorEnvironment> env, HRegionInfo info,
678                             HLogKey logKey, WALEdit logEdit) throws IOException {
679     preWALRestore(env, info, (WALKey)logKey, logEdit);
680     ctPreWALRestoreDeprecated.incrementAndGet();
681   }
682 
683   @Override
684   public void postWALRestore(ObserverContext<? extends RegionCoprocessorEnvironment> env,
685                              HRegionInfo info, WALKey logKey, WALEdit logEdit) throws IOException {
686     ctPostWALRestore.incrementAndGet();
687   }
688 
689   @Override
690   public void postWALRestore(ObserverContext<RegionCoprocessorEnvironment> env,
691                              HRegionInfo info, HLogKey logKey, WALEdit logEdit) throws IOException {
692     postWALRestore(env, info, (WALKey)logKey, logEdit);
693     ctPostWALRestoreDeprecated.incrementAndGet();
694   }
695 
696   @Override
697   public Reader preStoreFileReaderOpen(ObserverContext<RegionCoprocessorEnvironment> ctx,
698       FileSystem fs, Path p, FSDataInputStreamWrapper in, long size, CacheConfig cacheConf,
699       Reference r, Reader reader) throws IOException {
700     ctPreStoreFileReaderOpen.incrementAndGet();
701     return null;
702   }
703 
704   @Override
705   public Reader postStoreFileReaderOpen(ObserverContext<RegionCoprocessorEnvironment> ctx,
706       FileSystem fs, Path p, FSDataInputStreamWrapper in, long size, CacheConfig cacheConf,
707       Reference r, Reader reader) throws IOException {
708     ctPostStoreFileReaderOpen.incrementAndGet();
709     return reader;
710   }
711 
712   public boolean hadPreGet() {
713     return ctPreGet.get() > 0;
714   }
715 
716   public boolean hadPostGet() {
717     return ctPostGet.get() > 0;
718   }
719 
720   public boolean hadPrePut() {
721     return ctPrePut.get() > 0;
722   }
723 
724   public boolean hadPostPut() {
725     return ctPostPut.get() > 0;
726   }
727   
728   public boolean hadPreBatchMutate() {
729     return ctPreBatchMutate.get() > 0;
730   }
731 
732   public boolean hadPostBatchMutate() {
733     return ctPostBatchMutate.get() > 0;
734   }
735 
736   public boolean hadPostBatchMutateIndispensably() {
737     return ctPostBatchMutateIndispensably.get() > 0;
738   }
739 
740   public boolean hadPostStartRegionOperation() {
741     return ctPostStartRegionOperation.get() > 0;
742   }
743 
744   public boolean hadPostCloseRegionOperation() {
745     return ctPostCloseRegionOperation.get() > 0;
746   }
747 
748   public boolean hadDelete() {
749     return !(ctBeforeDelete.get() > 0);
750   }
751 
752   public int getCtPostStartRegionOperation() {
753     return ctPostStartRegionOperation.get();
754   }
755 
756   public int getCtPostCloseRegionOperation() {
757     return ctPostCloseRegionOperation.get();
758   }
759 
760   public boolean hadPreCheckAndPut() {
761     return ctPreCheckAndPut.get() > 0;
762   }
763 
764   public boolean hadPreCheckAndPutAfterRowLock() {
765     return ctPreCheckAndPutAfterRowLock.get() > 0;
766   }
767 
768   public boolean hadPostCheckAndPut() {
769     return ctPostCheckAndPut.get() > 0;
770   }
771 
772   public boolean hadPreCheckAndDelete() {
773     return ctPreCheckAndDelete.get() > 0;
774   }
775 
776   public boolean hadPreCheckAndDeleteAfterRowLock() {
777     return ctPreCheckAndDeleteAfterRowLock.get() > 0;
778   }
779 
780   public boolean hadPostCheckAndDelete() {
781     return ctPostCheckAndDelete.get() > 0;
782   }
783 
784   public boolean hadPreIncrement() {
785     return ctPreIncrement.get() > 0;
786   }
787   
788   public boolean hadPreIncrementAfterRowLock() {
789     return ctPreIncrementAfterRowLock.get() > 0;
790   }
791 
792   public boolean hadPostIncrement() {
793     return ctPostIncrement.get() > 0;
794   }
795 
796   public boolean hadPreAppend() {
797     return ctPreAppend.get() > 0;
798   }
799 
800   public boolean hadPreAppendAfterRowLock() {
801     return ctPreAppendAfterRowLock.get() > 0;
802   }
803 
804   public boolean hadPostAppend() {
805     return ctPostAppend.get() > 0;
806   }
807 
808   public boolean hadPrePreparedDeleteTS() {
809     return ctPrePrepareDeleteTS.get() > 0;
810   }
811   
812   public boolean hadPreWALRestore() {
813     return ctPreWALRestore.get() > 0;
814   }
815 
816   public boolean hadPostWALRestore() {
817     return ctPostWALRestore.get() > 0;
818   }
819 
820   public boolean wasScannerNextCalled() {
821     return ctPreScannerNext.get() > 0 && ctPostScannerNext.get() > 0;
822   }
823   public boolean wasScannerCloseCalled() {
824     return ctPreScannerClose.get() > 0 && ctPostScannerClose.get() > 0;
825   }
826   public boolean wasScannerOpenCalled() {
827     return ctPreScannerOpen.get() > 0 && ctPostScannerOpen.get() > 0;
828   }
829   public boolean hadDeleted() {
830     return ctPreDeleted.get() > 0 && ctPostDeleted.get() > 0;
831   }
832 
833   public boolean hadPostBulkLoadHFile() {
834     return ctPostBulkLoadHFile.get() > 0;
835   }
836 
837   public boolean hadPreBulkLoadHFile() {
838     return ctPreBulkLoadHFile.get() > 0;
839   }
840 
841 
842   public int getCtBeforeDelete() {
843     return ctBeforeDelete.get();
844   }
845 
846   public int getCtPreOpen() {
847     return ctPreOpen.get();
848   }
849 
850   public int getCtPostOpen() {
851     return ctPostOpen.get();
852   }
853 
854   public int getCtPreClose() {
855     return ctPreClose.get();
856   }
857 
858   public int getCtPostClose() {
859     return ctPostClose.get();
860   }
861 
862   public int getCtPreFlush() {
863     return ctPreFlush.get();
864   }
865 
866   public int getCtPreFlushScannerOpen() {
867     return ctPreFlushScannerOpen.get();
868   }
869 
870   public int getCtPostFlush() {
871     return ctPostFlush.get();
872   }
873 
874   public int getCtPreSplit() {
875     return ctPreSplit.get();
876   }
877   
878   public int getCtPreSplitBeforePONR() {
879     return ctPreSplitBeforePONR.get();
880   }
881 
882   public int getCtPreSplitAfterPONR() {
883     return ctPreSplitAfterPONR.get();
884   }
885 
886   public int getCtPostSplit() {
887     return ctPostSplit.get();
888   }
889 
890   public int getCtPreCompactSelect() {
891     return ctPreCompactSelect.get();
892   }
893 
894   public int getCtPostCompactSelect() {
895     return ctPostCompactSelect.get();
896   }
897 
898   public int getCtPreCompactScanner() {
899     return ctPreCompactScanner.get();
900   }
901 
902   public int getCtPreCompact() {
903     return ctPreCompact.get();
904   }
905 
906   public int getCtPostCompact() {
907     return ctPostCompact.get();
908   }
909 
910   public int getCtPreGet() {
911     return ctPreGet.get();
912   }
913 
914   public int getCtPostGet() {
915     return ctPostGet.get();
916   }
917 
918   public int getCtPrePut() {
919     return ctPrePut.get();
920   }
921 
922   public int getCtPostPut() {
923     return ctPostPut.get();
924   }
925 
926   public int getCtPreDeleted() {
927     return ctPreDeleted.get();
928   }
929 
930   public int getCtPostDeleted() {
931     return ctPostDeleted.get();
932   }
933 
934   public int getCtPreGetClosestRowBefore() {
935     return ctPreGetClosestRowBefore.get();
936   }
937 
938   public int getCtPostGetClosestRowBefore() {
939     return ctPostGetClosestRowBefore.get();
940   }
941 
942   public int getCtPreIncrement() {
943     return ctPreIncrement.get();
944   }
945 
946   public int getCtPostIncrement() {
947     return ctPostIncrement.get();
948   }
949 
950   public int getCtPreWALRestore() {
951     return ctPreWALRestore.get();
952   }
953 
954   public int getCtPostWALRestore() {
955     return ctPostWALRestore.get();
956   }
957 
958   public int getCtPreWALRestoreDeprecated() {
959     return ctPreWALRestoreDeprecated.get();
960   }
961 
962   public int getCtPostWALRestoreDeprecated() {
963     return ctPostWALRestoreDeprecated.get();
964   }
965 
966   public boolean wasStoreFileReaderOpenCalled() {
967     return ctPreStoreFileReaderOpen.get() > 0 && ctPostStoreFileReaderOpen.get() > 0;
968   }
969 
970   /**
971    * This implementation should trigger our legacy support because it does not directly
972    * implement the newer API calls.
973    */
974   public static class Legacy extends SimpleRegionObserver {
975   }
976 }