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.Assert.assertArrayEquals;
021import static org.junit.Assert.assertEquals;
022import static org.junit.Assert.assertNotNull;
023import static org.junit.Assert.assertTrue;
024
025import java.io.IOException;
026import java.util.HashMap;
027import java.util.List;
028import java.util.Map;
029import java.util.Optional;
030import java.util.concurrent.atomic.AtomicBoolean;
031import java.util.concurrent.atomic.AtomicInteger;
032import org.apache.hadoop.fs.FileSystem;
033import org.apache.hadoop.fs.Path;
034import org.apache.hadoop.hbase.Cell;
035import org.apache.hadoop.hbase.CellUtil;
036import org.apache.hadoop.hbase.CompareOperator;
037import org.apache.hadoop.hbase.CoprocessorEnvironment;
038import org.apache.hadoop.hbase.KeepDeletedCells;
039import org.apache.hadoop.hbase.client.Append;
040import org.apache.hadoop.hbase.client.CheckAndMutate;
041import org.apache.hadoop.hbase.client.CheckAndMutateResult;
042import org.apache.hadoop.hbase.client.Delete;
043import org.apache.hadoop.hbase.client.Durability;
044import org.apache.hadoop.hbase.client.Get;
045import org.apache.hadoop.hbase.client.Increment;
046import org.apache.hadoop.hbase.client.Mutation;
047import org.apache.hadoop.hbase.client.Put;
048import org.apache.hadoop.hbase.client.RegionInfo;
049import org.apache.hadoop.hbase.client.Result;
050import org.apache.hadoop.hbase.client.Scan;
051import org.apache.hadoop.hbase.filter.ByteArrayComparable;
052import org.apache.hadoop.hbase.filter.Filter;
053import org.apache.hadoop.hbase.io.FSDataInputStreamWrapper;
054import org.apache.hadoop.hbase.io.Reference;
055import org.apache.hadoop.hbase.io.hfile.CacheConfig;
056import org.apache.hadoop.hbase.regionserver.FlushLifeCycleTracker;
057import org.apache.hadoop.hbase.regionserver.InternalScanner;
058import org.apache.hadoop.hbase.regionserver.MiniBatchOperationInProgress;
059import org.apache.hadoop.hbase.regionserver.Region.Operation;
060import org.apache.hadoop.hbase.regionserver.RegionScanner;
061import org.apache.hadoop.hbase.regionserver.ScanOptions;
062import org.apache.hadoop.hbase.regionserver.ScanType;
063import org.apache.hadoop.hbase.regionserver.Store;
064import org.apache.hadoop.hbase.regionserver.StoreFile;
065import org.apache.hadoop.hbase.regionserver.StoreFileReader;
066import org.apache.hadoop.hbase.regionserver.compactions.CompactionLifeCycleTracker;
067import org.apache.hadoop.hbase.regionserver.compactions.CompactionRequest;
068import org.apache.hadoop.hbase.util.Bytes;
069import org.apache.hadoop.hbase.util.Pair;
070import org.apache.hadoop.hbase.wal.WALEdit;
071import org.apache.hadoop.hbase.wal.WALKey;
072
073/**
074 * A sample region observer that tests the RegionObserver interface. It works with
075 * TestRegionObserverInterface to provide the test case.
076 */
077public class SimpleRegionObserver implements RegionCoprocessor, RegionObserver {
078
079  final AtomicInteger ctBeforeDelete = new AtomicInteger(1);
080  final AtomicInteger ctPreOpen = new AtomicInteger(0);
081  final AtomicInteger ctPostOpen = new AtomicInteger(0);
082  final AtomicInteger ctPreClose = new AtomicInteger(0);
083  final AtomicInteger ctPostClose = new AtomicInteger(0);
084  final AtomicInteger ctPreFlush = new AtomicInteger(0);
085  final AtomicInteger ctPostFlush = new AtomicInteger(0);
086  final AtomicInteger ctPreCompactSelect = new AtomicInteger(0);
087  final AtomicInteger ctPostCompactSelect = new AtomicInteger(0);
088  final AtomicInteger ctPreCompact = new AtomicInteger(0);
089  final AtomicInteger ctPostCompact = new AtomicInteger(0);
090  final AtomicInteger ctPreGet = new AtomicInteger(0);
091  final AtomicInteger ctPostGet = new AtomicInteger(0);
092  final AtomicInteger ctPrePut = new AtomicInteger(0);
093  final AtomicInteger ctPostPut = new AtomicInteger(0);
094  final AtomicInteger ctPreDeleted = new AtomicInteger(0);
095  final AtomicInteger ctPrePrepareDeleteTS = new AtomicInteger(0);
096  final AtomicInteger ctPostDeleted = new AtomicInteger(0);
097  final AtomicInteger ctPreIncrement = new AtomicInteger(0);
098  final AtomicInteger ctPreIncrementAfterRowLock = new AtomicInteger(0);
099  final AtomicInteger ctPreAppend = new AtomicInteger(0);
100  final AtomicInteger ctPreAppendAfterRowLock = new AtomicInteger(0);
101  final AtomicInteger ctPostIncrement = new AtomicInteger(0);
102  final AtomicInteger ctPostAppend = new AtomicInteger(0);
103  final AtomicInteger ctPreCheckAndPut = new AtomicInteger(0);
104  final AtomicInteger ctPreCheckAndPutWithFilter = new AtomicInteger(0);
105  final AtomicInteger ctPreCheckAndPutAfterRowLock = new AtomicInteger(0);
106  final AtomicInteger ctPreCheckAndPutWithFilterAfterRowLock = new AtomicInteger(0);
107  final AtomicInteger ctPostCheckAndPut = new AtomicInteger(0);
108  final AtomicInteger ctPostCheckAndPutWithFilter = new AtomicInteger(0);
109  final AtomicInteger ctPreCheckAndDelete = new AtomicInteger(0);
110  final AtomicInteger ctPreCheckAndDeleteWithFilter = new AtomicInteger(0);
111  final AtomicInteger ctPreCheckAndDeleteAfterRowLock = new AtomicInteger(0);
112  final AtomicInteger ctPreCheckAndDeleteWithFilterAfterRowLock = new AtomicInteger(0);
113  final AtomicInteger ctPostCheckAndDelete = new AtomicInteger(0);
114  final AtomicInteger ctPostCheckAndDeleteWithFilter = new AtomicInteger(0);
115  final AtomicInteger ctPreCheckAndMutate = new AtomicInteger(0);
116  final AtomicInteger ctPreCheckAndMutateAfterRowLock = new AtomicInteger(0);
117  final AtomicInteger ctPostCheckAndMutate = new AtomicInteger(0);
118  final AtomicInteger ctPreScannerNext = new AtomicInteger(0);
119  final AtomicInteger ctPostScannerNext = new AtomicInteger(0);
120  final AtomicInteger ctPostScannerFilterRow = 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 ctPostScannerOpen = new AtomicInteger(0);
125  final AtomicInteger ctPreBulkLoadHFile = new AtomicInteger(0);
126  final AtomicInteger ctPostBulkLoadHFile = new AtomicInteger(0);
127  final AtomicInteger ctPreBatchMutate = new AtomicInteger(0);
128  final AtomicInteger ctPostBatchMutate = new AtomicInteger(0);
129  final AtomicInteger ctPreReplayWALs = new AtomicInteger(0);
130  final AtomicInteger ctPostReplayWALs = new AtomicInteger(0);
131  final AtomicInteger ctPreWALRestore = new AtomicInteger(0);
132  final AtomicInteger ctPostWALRestore = new AtomicInteger(0);
133  final AtomicInteger ctPreStoreFileReaderOpen = new AtomicInteger(0);
134  final AtomicInteger ctPostStoreFileReaderOpen = new AtomicInteger(0);
135  final AtomicInteger ctPostBatchMutateIndispensably = new AtomicInteger(0);
136  final AtomicInteger ctPostStartRegionOperation = new AtomicInteger(0);
137  final AtomicInteger ctPostCloseRegionOperation = new AtomicInteger(0);
138  final AtomicBoolean throwOnPostFlush = new AtomicBoolean(false);
139  final AtomicInteger ctPreWALAppend = new AtomicInteger(0);
140
141  static final String TABLE_SKIPPED = "SKIPPED_BY_PREWALRESTORE";
142  Map<String, byte[]> extendedAttributes = new HashMap<String, byte[]>();
143  static final byte[] WAL_EXTENDED_ATTRIBUTE_BYTES = Bytes.toBytes("foo");
144
145  public void setThrowOnPostFlush(Boolean val) {
146    throwOnPostFlush.set(val);
147  }
148
149  @Override
150  public Optional<RegionObserver> getRegionObserver() {
151    return Optional.of(this);
152  }
153
154  @Override
155  public void start(CoprocessorEnvironment e) throws IOException {
156  }
157
158  @Override
159  public void preOpen(ObserverContext<? extends RegionCoprocessorEnvironment> c) {
160    ctPreOpen.incrementAndGet();
161  }
162
163  @Override
164  public void postOpen(ObserverContext<? extends 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<? extends RegionCoprocessorEnvironment> c,
174    boolean abortRequested) {
175    ctPreClose.incrementAndGet();
176  }
177
178  @Override
179  public void postClose(ObserverContext<? extends RegionCoprocessorEnvironment> c,
180    boolean abortRequested) {
181    ctPostClose.incrementAndGet();
182  }
183
184  public boolean wasClosed() {
185    return ctPreClose.get() > 0 && ctPostClose.get() > 0;
186  }
187
188  @Override
189  public InternalScanner preFlush(ObserverContext<? extends RegionCoprocessorEnvironment> c,
190    Store store, InternalScanner scanner, FlushLifeCycleTracker tracker) throws IOException {
191    ctPreFlush.incrementAndGet();
192    return scanner;
193  }
194
195  @Override
196  public void postFlush(ObserverContext<? extends RegionCoprocessorEnvironment> c, Store store,
197    StoreFile resultFile, FlushLifeCycleTracker tracker) throws IOException {
198    ctPostFlush.incrementAndGet();
199    if (throwOnPostFlush.get()) {
200      throw new IOException("throwOnPostFlush is true in postFlush");
201    }
202  }
203
204  public boolean wasFlushed() {
205    return ctPreFlush.get() > 0 && ctPostFlush.get() > 0;
206  }
207
208  @Override
209  public void preCompactSelection(ObserverContext<? extends RegionCoprocessorEnvironment> c,
210    Store store, List<? extends StoreFile> candidates, CompactionLifeCycleTracker tracker)
211    throws IOException {
212    ctPreCompactSelect.incrementAndGet();
213  }
214
215  @Override
216  public void postCompactSelection(ObserverContext<? extends RegionCoprocessorEnvironment> c,
217    Store store, List<? extends StoreFile> selected, CompactionLifeCycleTracker tracker,
218    CompactionRequest request) {
219    ctPostCompactSelect.incrementAndGet();
220  }
221
222  @Override
223  public InternalScanner preCompact(ObserverContext<? extends RegionCoprocessorEnvironment> c,
224    Store store, InternalScanner scanner, ScanType scanType, CompactionLifeCycleTracker tracker,
225    CompactionRequest request) throws IOException {
226    ctPreCompact.incrementAndGet();
227    return scanner;
228  }
229
230  @Override
231  public void postCompact(ObserverContext<? extends RegionCoprocessorEnvironment> c, Store store,
232    StoreFile resultFile, CompactionLifeCycleTracker tracker, CompactionRequest request)
233    throws IOException {
234    ctPostCompact.incrementAndGet();
235  }
236
237  public boolean wasCompacted() {
238    return ctPreCompact.get() > 0 && ctPostCompact.get() > 0;
239  }
240
241  @Override
242  public void preScannerOpen(final ObserverContext<? extends RegionCoprocessorEnvironment> c,
243    final Scan scan) throws IOException {
244    ctPreScannerOpen.incrementAndGet();
245  }
246
247  @Override
248  public RegionScanner postScannerOpen(
249    final ObserverContext<? extends RegionCoprocessorEnvironment> c, final Scan scan,
250    final RegionScanner s) throws IOException {
251    ctPostScannerOpen.incrementAndGet();
252    return s;
253  }
254
255  @Override
256  public boolean preScannerNext(final ObserverContext<? extends RegionCoprocessorEnvironment> c,
257    final InternalScanner s, final List<Result> results, final int limit, final boolean hasMore)
258    throws IOException {
259    ctPreScannerNext.incrementAndGet();
260    return hasMore;
261  }
262
263  @Override
264  public boolean postScannerNext(final ObserverContext<? extends RegionCoprocessorEnvironment> c,
265    final InternalScanner s, final List<Result> results, final int limit, final boolean hasMore)
266    throws IOException {
267    ctPostScannerNext.incrementAndGet();
268    return hasMore;
269  }
270
271  @Override
272  public boolean postScannerFilterRow(
273    final ObserverContext<? extends RegionCoprocessorEnvironment> e, final InternalScanner s,
274    final Cell currentRow, final boolean hasMore) throws IOException {
275    ctPostScannerFilterRow.incrementAndGet();
276    return hasMore;
277  }
278
279  @Override
280  public void preScannerClose(final ObserverContext<? extends RegionCoprocessorEnvironment> c,
281    final InternalScanner s) throws IOException {
282    ctPreScannerClose.incrementAndGet();
283  }
284
285  @Override
286  public void postScannerClose(final ObserverContext<? extends RegionCoprocessorEnvironment> c,
287    final InternalScanner s) throws IOException {
288    ctPostScannerClose.incrementAndGet();
289  }
290
291  @Override
292  public void preGetOp(final ObserverContext<? extends RegionCoprocessorEnvironment> c,
293    final Get get, final List<Cell> results) throws IOException {
294    RegionCoprocessorEnvironment e = c.getEnvironment();
295    assertNotNull(e);
296    assertNotNull(e.getRegion());
297    assertNotNull(get);
298    assertNotNull(results);
299    ctPreGet.incrementAndGet();
300  }
301
302  @Override
303  public void postGetOp(final ObserverContext<? extends RegionCoprocessorEnvironment> c,
304    final Get get, final List<Cell> results) {
305    RegionCoprocessorEnvironment e = c.getEnvironment();
306    assertNotNull(e);
307    assertNotNull(e.getRegion());
308    assertNotNull(get);
309    assertNotNull(results);
310    if (
311      e.getRegion().getTableDescriptor().getTableName()
312        .equals(TestRegionObserverInterface.TEST_TABLE)
313    ) {
314      boolean foundA = false;
315      boolean foundB = false;
316      boolean foundC = false;
317      for (Cell kv : results) {
318        if (CellUtil.matchingFamily(kv, TestRegionObserverInterface.A)) {
319          foundA = true;
320        }
321        if (CellUtil.matchingFamily(kv, TestRegionObserverInterface.B)) {
322          foundB = true;
323        }
324        if (CellUtil.matchingFamily(kv, TestRegionObserverInterface.C)) {
325          foundC = true;
326        }
327      }
328      assertTrue(foundA);
329      assertTrue(foundB);
330      assertTrue(foundC);
331    }
332    ctPostGet.incrementAndGet();
333  }
334
335  @Override
336  public void prePut(final ObserverContext<? extends RegionCoprocessorEnvironment> c, final Put put,
337    final WALEdit edit, final Durability durability) throws IOException {
338    Map<byte[], List<Cell>> familyMap = put.getFamilyCellMap();
339    RegionCoprocessorEnvironment e = c.getEnvironment();
340    assertNotNull(e);
341    assertNotNull(e.getRegion());
342    assertNotNull(familyMap);
343    if (
344      e.getRegion().getTableDescriptor().getTableName()
345        .equals(TestRegionObserverInterface.TEST_TABLE)
346    ) {
347      List<Cell> cells = familyMap.get(TestRegionObserverInterface.A);
348      assertNotNull(cells);
349      assertNotNull(cells.get(0));
350      Cell cell = cells.get(0);
351      assertTrue(
352        Bytes.equals(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength(),
353          TestRegionObserverInterface.A, 0, TestRegionObserverInterface.A.length));
354      cells = familyMap.get(TestRegionObserverInterface.B);
355      assertNotNull(cells);
356      assertNotNull(cells.get(0));
357      cell = cells.get(0);
358      assertTrue(
359        Bytes.equals(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength(),
360          TestRegionObserverInterface.B, 0, TestRegionObserverInterface.B.length));
361      cells = familyMap.get(TestRegionObserverInterface.C);
362      assertNotNull(cells);
363      assertNotNull(cells.get(0));
364      cell = cells.get(0);
365      assertTrue(
366        Bytes.equals(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength(),
367          TestRegionObserverInterface.C, 0, TestRegionObserverInterface.C.length));
368    }
369    ctPrePut.incrementAndGet();
370  }
371
372  @Override
373  public void postPut(final ObserverContext<? extends RegionCoprocessorEnvironment> c,
374    final Put put, final WALEdit edit, final Durability durability) throws IOException {
375    Map<byte[], List<Cell>> familyMap = put.getFamilyCellMap();
376    RegionCoprocessorEnvironment e = c.getEnvironment();
377    assertNotNull(e);
378    assertNotNull(e.getRegion());
379    assertNotNull(familyMap);
380    List<Cell> cells = familyMap.get(TestRegionObserverInterface.A);
381    if (
382      e.getRegion().getTableDescriptor().getTableName()
383        .equals(TestRegionObserverInterface.TEST_TABLE)
384    ) {
385      assertNotNull(cells);
386      assertNotNull(cells.get(0));
387      // KeyValue v1 expectation. Cast for now until we go all Cell all the time. TODO
388      Cell cell = cells.get(0);
389      assertTrue(
390        Bytes.equals(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength(),
391          TestRegionObserverInterface.A, 0, TestRegionObserverInterface.A.length));
392      cells = familyMap.get(TestRegionObserverInterface.B);
393      assertNotNull(cells);
394      assertNotNull(cells.get(0));
395      // KeyValue v1 expectation. Cast for now until we go all Cell all the time. TODO
396      cell = cells.get(0);
397      assertTrue(
398        Bytes.equals(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength(),
399          TestRegionObserverInterface.B, 0, TestRegionObserverInterface.B.length));
400      cells = familyMap.get(TestRegionObserverInterface.C);
401      assertNotNull(cells);
402      assertNotNull(cells.get(0));
403      // KeyValue v1 expectation. Cast for now until we go all Cell all the time. TODO
404      cell = cells.get(0);
405      assertTrue(
406        Bytes.equals(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength(),
407          TestRegionObserverInterface.C, 0, TestRegionObserverInterface.C.length));
408    }
409    ctPostPut.incrementAndGet();
410  }
411
412  @Override
413  public void preDelete(final ObserverContext<? extends RegionCoprocessorEnvironment> c,
414    final Delete delete, final WALEdit edit, final Durability durability) throws IOException {
415    Map<byte[], List<Cell>> familyMap = delete.getFamilyCellMap();
416    RegionCoprocessorEnvironment e = c.getEnvironment();
417    assertNotNull(e);
418    assertNotNull(e.getRegion());
419    assertNotNull(familyMap);
420    if (ctBeforeDelete.get() > 0) {
421      ctPreDeleted.incrementAndGet();
422    }
423  }
424
425  @Override
426  public void prePrepareTimeStampForDeleteVersion(
427    ObserverContext<? extends RegionCoprocessorEnvironment> e, Mutation delete, Cell cell,
428    byte[] byteNow, Get get) throws IOException {
429    ctPrePrepareDeleteTS.incrementAndGet();
430  }
431
432  @Override
433  public void postDelete(final ObserverContext<? extends RegionCoprocessorEnvironment> c,
434    final Delete delete, final WALEdit edit, final Durability durability) throws IOException {
435    Map<byte[], List<Cell>> familyMap = delete.getFamilyCellMap();
436    RegionCoprocessorEnvironment e = c.getEnvironment();
437    assertNotNull(e);
438    assertNotNull(e.getRegion());
439    assertNotNull(familyMap);
440    ctBeforeDelete.set(0);
441    ctPostDeleted.incrementAndGet();
442  }
443
444  @Override
445  public void preBatchMutate(ObserverContext<? extends RegionCoprocessorEnvironment> c,
446    MiniBatchOperationInProgress<Mutation> miniBatchOp) throws IOException {
447    RegionCoprocessorEnvironment e = c.getEnvironment();
448    assertNotNull(e);
449    assertNotNull(e.getRegion());
450    assertNotNull(miniBatchOp);
451    ctPreBatchMutate.incrementAndGet();
452  }
453
454  @Override
455  public void postBatchMutate(final ObserverContext<? extends RegionCoprocessorEnvironment> c,
456    final MiniBatchOperationInProgress<Mutation> miniBatchOp) throws IOException {
457    RegionCoprocessorEnvironment e = c.getEnvironment();
458    assertNotNull(e);
459    assertNotNull(e.getRegion());
460    assertNotNull(miniBatchOp);
461    ctPostBatchMutate.incrementAndGet();
462  }
463
464  @Override
465  public void postStartRegionOperation(
466    final ObserverContext<? extends RegionCoprocessorEnvironment> ctx, Operation op)
467    throws IOException {
468    ctPostStartRegionOperation.incrementAndGet();
469  }
470
471  @Override
472  public void postCloseRegionOperation(
473    final ObserverContext<? extends RegionCoprocessorEnvironment> ctx, Operation op)
474    throws IOException {
475    if (ctPostStartRegionOperation.get() > 0) {
476      ctPostCloseRegionOperation.incrementAndGet();
477    }
478  }
479
480  @Override
481  public void postBatchMutateIndispensably(
482    final ObserverContext<? extends RegionCoprocessorEnvironment> ctx,
483    MiniBatchOperationInProgress<Mutation> miniBatchOp, final boolean success) throws IOException {
484    ctPostBatchMutateIndispensably.incrementAndGet();
485  }
486
487  @Override
488  public Result preIncrement(final ObserverContext<? extends RegionCoprocessorEnvironment> c,
489    final Increment increment) throws IOException {
490    ctPreIncrement.incrementAndGet();
491    return null;
492  }
493
494  @Override
495  public Result preIncrementAfterRowLock(ObserverContext<? extends RegionCoprocessorEnvironment> e,
496    Increment increment) throws IOException {
497    ctPreIncrementAfterRowLock.incrementAndGet();
498    return null;
499  }
500
501  @Override
502  public Result postIncrement(final ObserverContext<? extends RegionCoprocessorEnvironment> c,
503    final Increment increment, final Result result) throws IOException {
504    ctPostIncrement.incrementAndGet();
505    return result;
506  }
507
508  @Override
509  public boolean preCheckAndPut(ObserverContext<? extends RegionCoprocessorEnvironment> e,
510    byte[] row, byte[] family, byte[] qualifier, CompareOperator compareOp,
511    ByteArrayComparable comparator, Put put, boolean result) throws IOException {
512    ctPreCheckAndPut.incrementAndGet();
513    return true;
514  }
515
516  @Override
517  public boolean preCheckAndPut(ObserverContext<? extends RegionCoprocessorEnvironment> c,
518    byte[] row, Filter filter, Put put, boolean result) throws IOException {
519    ctPreCheckAndPutWithFilter.incrementAndGet();
520    return true;
521  }
522
523  @Override
524  public boolean preCheckAndPutAfterRowLock(
525    ObserverContext<? extends RegionCoprocessorEnvironment> e, byte[] row, byte[] family,
526    byte[] qualifier, CompareOperator compareOp, ByteArrayComparable comparator, Put put,
527    boolean result) throws IOException {
528    ctPreCheckAndPutAfterRowLock.incrementAndGet();
529    return true;
530  }
531
532  @Override
533  public boolean preCheckAndPutAfterRowLock(
534    ObserverContext<? extends RegionCoprocessorEnvironment> c, byte[] row, Filter filter, Put put,
535    boolean result) throws IOException {
536    ctPreCheckAndPutWithFilterAfterRowLock.incrementAndGet();
537    return true;
538  }
539
540  @Override
541  public boolean postCheckAndPut(ObserverContext<? extends RegionCoprocessorEnvironment> e,
542    byte[] row, byte[] family, byte[] qualifier, CompareOperator compareOp,
543    ByteArrayComparable comparator, Put put, boolean result) throws IOException {
544    ctPostCheckAndPut.incrementAndGet();
545    return true;
546  }
547
548  @Override
549  public boolean postCheckAndPut(ObserverContext<? extends RegionCoprocessorEnvironment> c,
550    byte[] row, Filter filter, Put put, boolean result) throws IOException {
551    ctPostCheckAndPutWithFilter.incrementAndGet();
552    return true;
553  }
554
555  @Override
556  public boolean preCheckAndDelete(ObserverContext<? extends RegionCoprocessorEnvironment> e,
557    byte[] row, byte[] family, byte[] qualifier, CompareOperator compareOp,
558    ByteArrayComparable comparator, Delete delete, boolean result) throws IOException {
559    ctPreCheckAndDelete.incrementAndGet();
560    return true;
561  }
562
563  @Override
564  public boolean preCheckAndDelete(ObserverContext<? extends RegionCoprocessorEnvironment> c,
565    byte[] row, Filter filter, Delete delete, boolean result) throws IOException {
566    ctPreCheckAndDeleteWithFilter.incrementAndGet();
567    return true;
568  }
569
570  @Override
571  public boolean preCheckAndDeleteAfterRowLock(
572    ObserverContext<? extends RegionCoprocessorEnvironment> e, byte[] row, byte[] family,
573    byte[] qualifier, CompareOperator compareOp, ByteArrayComparable comparator, Delete delete,
574    boolean result) throws IOException {
575    ctPreCheckAndDeleteAfterRowLock.incrementAndGet();
576    return true;
577  }
578
579  @Override
580  public boolean preCheckAndDeleteAfterRowLock(
581    ObserverContext<? extends RegionCoprocessorEnvironment> c, byte[] row, Filter filter,
582    Delete delete, boolean result) throws IOException {
583    ctPreCheckAndDeleteWithFilterAfterRowLock.incrementAndGet();
584    return true;
585  }
586
587  @Override
588  public boolean postCheckAndDelete(ObserverContext<? extends RegionCoprocessorEnvironment> e,
589    byte[] row, byte[] family, byte[] qualifier, CompareOperator compareOp,
590    ByteArrayComparable comparator, Delete delete, boolean result) throws IOException {
591    ctPostCheckAndDelete.incrementAndGet();
592    return true;
593  }
594
595  @Override
596  public boolean postCheckAndDelete(ObserverContext<? extends RegionCoprocessorEnvironment> e,
597    byte[] row, Filter filter, Delete delete, boolean result) throws IOException {
598    ctPostCheckAndDeleteWithFilter.incrementAndGet();
599    return true;
600  }
601
602  @Override
603  public CheckAndMutateResult preCheckAndMutate(
604    ObserverContext<? extends RegionCoprocessorEnvironment> c, CheckAndMutate checkAndMutate,
605    CheckAndMutateResult result) throws IOException {
606    ctPreCheckAndMutate.incrementAndGet();
607    return RegionObserver.super.preCheckAndMutate(c, checkAndMutate, result);
608  }
609
610  @Override
611  public CheckAndMutateResult preCheckAndMutateAfterRowLock(
612    ObserverContext<? extends RegionCoprocessorEnvironment> c, CheckAndMutate checkAndMutate,
613    CheckAndMutateResult result) throws IOException {
614    ctPreCheckAndMutateAfterRowLock.incrementAndGet();
615    return RegionObserver.super.preCheckAndMutateAfterRowLock(c, checkAndMutate, result);
616  }
617
618  @Override
619  public CheckAndMutateResult postCheckAndMutate(
620    ObserverContext<? extends RegionCoprocessorEnvironment> c, CheckAndMutate checkAndMutate,
621    CheckAndMutateResult result) throws IOException {
622    ctPostCheckAndMutate.incrementAndGet();
623    return RegionObserver.super.postCheckAndMutate(c, checkAndMutate, result);
624  }
625
626  @Override
627  public Result preAppendAfterRowLock(ObserverContext<? extends RegionCoprocessorEnvironment> e,
628    Append append) throws IOException {
629    ctPreAppendAfterRowLock.incrementAndGet();
630    return null;
631  }
632
633  @Override
634  public Result preAppend(ObserverContext<? extends RegionCoprocessorEnvironment> e, Append append)
635    throws IOException {
636    ctPreAppend.incrementAndGet();
637    return null;
638  }
639
640  @Override
641  public Result postAppend(ObserverContext<? extends RegionCoprocessorEnvironment> e, Append append,
642    Result result) throws IOException {
643    ctPostAppend.incrementAndGet();
644    return null;
645  }
646
647  @Override
648  public void preBulkLoadHFile(ObserverContext<? extends RegionCoprocessorEnvironment> ctx,
649    List<Pair<byte[], String>> familyPaths) throws IOException {
650    RegionCoprocessorEnvironment e = ctx.getEnvironment();
651    assertNotNull(e);
652    assertNotNull(e.getRegion());
653    if (
654      e.getRegion().getTableDescriptor().getTableName()
655        .equals(TestRegionObserverInterface.TEST_TABLE)
656    ) {
657      assertNotNull(familyPaths);
658      assertEquals(1, familyPaths.size());
659      assertArrayEquals(TestRegionObserverInterface.A, familyPaths.get(0).getFirst());
660      String familyPath = familyPaths.get(0).getSecond();
661      String familyName = Bytes.toString(TestRegionObserverInterface.A);
662      assertEquals(familyPath.substring(familyPath.length() - familyName.length() - 1),
663        "/" + familyName);
664    }
665    ctPreBulkLoadHFile.incrementAndGet();
666  }
667
668  @Override
669  public void postBulkLoadHFile(ObserverContext<? extends RegionCoprocessorEnvironment> ctx,
670    List<Pair<byte[], String>> familyPaths, Map<byte[], List<Path>> map) throws IOException {
671    RegionCoprocessorEnvironment e = ctx.getEnvironment();
672    assertNotNull(e);
673    assertNotNull(e.getRegion());
674    if (
675      e.getRegion().getTableDescriptor().getTableName()
676        .equals(TestRegionObserverInterface.TEST_TABLE)
677    ) {
678      assertNotNull(familyPaths);
679      assertEquals(1, familyPaths.size());
680      assertArrayEquals(TestRegionObserverInterface.A, familyPaths.get(0).getFirst());
681      String familyPath = familyPaths.get(0).getSecond();
682      String familyName = Bytes.toString(TestRegionObserverInterface.A);
683      assertEquals(familyPath.substring(familyPath.length() - familyName.length() - 1),
684        "/" + familyName);
685    }
686    ctPostBulkLoadHFile.incrementAndGet();
687  }
688
689  @Override
690  public void preReplayWALs(ObserverContext<? extends RegionCoprocessorEnvironment> env,
691    RegionInfo info, Path edits) throws IOException {
692    ctPreReplayWALs.incrementAndGet();
693  }
694
695  @Override
696  public void postReplayWALs(ObserverContext<? extends RegionCoprocessorEnvironment> env,
697    RegionInfo info, Path edits) throws IOException {
698    ctPostReplayWALs.incrementAndGet();
699  }
700
701  @Override
702  public void preWALRestore(ObserverContext<? extends RegionCoprocessorEnvironment> env,
703    RegionInfo info, WALKey logKey, WALEdit logEdit) throws IOException {
704    String tableName = logKey.getTableName().getNameAsString();
705    if (tableName.equals(TABLE_SKIPPED)) {
706      // skip recovery of TABLE_SKIPPED for testing purpose
707      env.bypass();
708      return;
709    }
710    ctPreWALRestore.incrementAndGet();
711  }
712
713  @Override
714  public void postWALRestore(ObserverContext<? extends RegionCoprocessorEnvironment> env,
715    RegionInfo info, WALKey logKey, WALEdit logEdit) throws IOException {
716    ctPostWALRestore.incrementAndGet();
717  }
718
719  @Override
720  public StoreFileReader preStoreFileReaderOpen(
721    ObserverContext<? extends RegionCoprocessorEnvironment> ctx, FileSystem fs, Path p,
722    FSDataInputStreamWrapper in, long size, CacheConfig cacheConf, Reference r,
723    StoreFileReader reader) throws IOException {
724    ctPreStoreFileReaderOpen.incrementAndGet();
725    return null;
726  }
727
728  @Override
729  public StoreFileReader postStoreFileReaderOpen(
730    ObserverContext<? extends RegionCoprocessorEnvironment> ctx, FileSystem fs, Path p,
731    FSDataInputStreamWrapper in, long size, CacheConfig cacheConf, Reference r,
732    StoreFileReader reader) throws IOException {
733    ctPostStoreFileReaderOpen.incrementAndGet();
734    return reader;
735  }
736
737  @Override
738  public void preStoreScannerOpen(ObserverContext<? extends RegionCoprocessorEnvironment> ctx,
739    Store store, ScanOptions options) throws IOException {
740    if (options.getScan().getTimeRange().isAllTime()) {
741      setScanOptions(options);
742    }
743  }
744
745  @Override
746  public void preCompactScannerOpen(ObserverContext<? extends RegionCoprocessorEnvironment> c,
747    Store store, ScanType scanType, ScanOptions options, CompactionLifeCycleTracker tracker,
748    CompactionRequest request) throws IOException {
749    setScanOptions(options);
750  }
751
752  public void preFlushScannerOpen(ObserverContext<? extends RegionCoprocessorEnvironment> c,
753    Store store, ScanOptions options, FlushLifeCycleTracker tracker) throws IOException {
754    setScanOptions(options);
755  }
756
757  public void preMemStoreCompactionCompactScannerOpen(
758    ObserverContext<? extends RegionCoprocessorEnvironment> c, Store store, ScanOptions options)
759    throws IOException {
760    setScanOptions(options);
761  }
762
763  private void setScanOptions(ScanOptions options) {
764    options.setMaxVersions(TestRegionCoprocessorHost.MAX_VERSIONS);
765    options.setMinVersions(TestRegionCoprocessorHost.MIN_VERSIONS);
766    options.setKeepDeletedCells(KeepDeletedCells.TRUE);
767    options.setTTL(TestRegionCoprocessorHost.TTL);
768    options.setTimeToPurgeDeletes(TestRegionCoprocessorHost.TIME_TO_PURGE_DELETES);
769  }
770
771  @Override
772  public void preWALAppend(ObserverContext<? extends RegionCoprocessorEnvironment> ctx, WALKey key,
773    WALEdit edit) throws IOException {
774    ctPreWALAppend.incrementAndGet();
775
776    key.addExtendedAttribute(Integer.toString(ctPreWALAppend.get()), Bytes.toBytes("foo"));
777  }
778
779  public boolean hadPreGet() {
780    return ctPreGet.get() > 0;
781  }
782
783  public boolean hadPostGet() {
784    return ctPostGet.get() > 0;
785  }
786
787  public boolean hadPrePut() {
788    return ctPrePut.get() > 0;
789  }
790
791  public boolean hadPostPut() {
792    return ctPostPut.get() > 0;
793  }
794
795  public boolean hadPreBatchMutate() {
796    return ctPreBatchMutate.get() > 0;
797  }
798
799  public int getPreBatchMutate() {
800    return ctPreBatchMutate.get();
801  }
802
803  public boolean hadPostBatchMutate() {
804    return ctPostBatchMutate.get() > 0;
805  }
806
807  public int getPostBatchMutate() {
808    return ctPostBatchMutate.get();
809  }
810
811  public boolean hadPostBatchMutateIndispensably() {
812    return ctPostBatchMutateIndispensably.get() > 0;
813  }
814
815  public int getPostBatchMutateIndispensably() {
816    return ctPostBatchMutateIndispensably.get();
817  }
818
819  public boolean hadPostStartRegionOperation() {
820    return ctPostStartRegionOperation.get() > 0;
821  }
822
823  public boolean hadPostCloseRegionOperation() {
824    return ctPostCloseRegionOperation.get() > 0;
825  }
826
827  public boolean hadDelete() {
828    return !(ctBeforeDelete.get() > 0);
829  }
830
831  public int getCtPostStartRegionOperation() {
832    return ctPostStartRegionOperation.get();
833  }
834
835  public int getCtPostCloseRegionOperation() {
836    return ctPostCloseRegionOperation.get();
837  }
838
839  public int getPreCheckAndPut() {
840    return ctPreCheckAndPut.get();
841  }
842
843  public int getPreCheckAndPutWithFilter() {
844    return ctPreCheckAndPutWithFilter.get();
845  }
846
847  public int getPreCheckAndPutAfterRowLock() {
848    return ctPreCheckAndPutAfterRowLock.get();
849  }
850
851  public int getPreCheckAndPutWithFilterAfterRowLock() {
852    return ctPreCheckAndPutWithFilterAfterRowLock.get();
853  }
854
855  public int getPostCheckAndPut() {
856    return ctPostCheckAndPut.get();
857  }
858
859  public int getPostCheckAndPutWithFilter() {
860    return ctPostCheckAndPutWithFilter.get();
861  }
862
863  public int getPreCheckAndDelete() {
864    return ctPreCheckAndDelete.get();
865  }
866
867  public int getPreCheckAndDeleteWithFilter() {
868    return ctPreCheckAndDeleteWithFilter.get();
869  }
870
871  public int getPreCheckAndDeleteAfterRowLock() {
872    return ctPreCheckAndDeleteAfterRowLock.get();
873  }
874
875  public int getPreCheckAndDeleteWithFilterAfterRowLock() {
876    return ctPreCheckAndDeleteWithFilterAfterRowLock.get();
877  }
878
879  public int getPostCheckAndDelete() {
880    return ctPostCheckAndDelete.get();
881  }
882
883  public int getPostCheckAndDeleteWithFilter() {
884    return ctPostCheckAndDeleteWithFilter.get();
885  }
886
887  public int getPreCheckAndMutate() {
888    return ctPreCheckAndMutate.get();
889  }
890
891  public int getPreCheckAndMutateAfterRowLock() {
892    return ctPreCheckAndMutateAfterRowLock.get();
893  }
894
895  public int getPostCheckAndMutate() {
896    return ctPostCheckAndMutate.get();
897  }
898
899  public boolean hadPreIncrement() {
900    return ctPreIncrement.get() > 0;
901  }
902
903  public boolean hadPreIncrementAfterRowLock() {
904    return ctPreIncrementAfterRowLock.get() > 0;
905  }
906
907  public boolean hadPostIncrement() {
908    return ctPostIncrement.get() > 0;
909  }
910
911  public boolean hadPreAppend() {
912    return ctPreAppend.get() > 0;
913  }
914
915  public boolean hadPreAppendAfterRowLock() {
916    return ctPreAppendAfterRowLock.get() > 0;
917  }
918
919  public boolean hadPostAppend() {
920    return ctPostAppend.get() > 0;
921  }
922
923  public boolean hadPrePreparedDeleteTS() {
924    return ctPrePrepareDeleteTS.get() > 0;
925  }
926
927  public boolean hadPreReplayWALs() {
928    return ctPreReplayWALs.get() > 0;
929  }
930
931  public boolean hadPostReplayWALs() {
932    return ctPostReplayWALs.get() > 0;
933  }
934
935  public boolean hadPreWALRestore() {
936    return ctPreWALRestore.get() > 0;
937  }
938
939  public boolean hadPostWALRestore() {
940    return ctPostWALRestore.get() > 0;
941  }
942
943  public boolean wasScannerNextCalled() {
944    return ctPreScannerNext.get() > 0 && ctPostScannerNext.get() > 0;
945  }
946
947  public boolean wasScannerFilterRowCalled() {
948    return ctPostScannerFilterRow.get() > 0;
949  }
950
951  public boolean wasScannerCloseCalled() {
952    return ctPreScannerClose.get() > 0 && ctPostScannerClose.get() > 0;
953  }
954
955  public boolean wasScannerOpenCalled() {
956    return ctPreScannerOpen.get() > 0 && ctPostScannerOpen.get() > 0;
957  }
958
959  public boolean hadDeleted() {
960    return ctPreDeleted.get() > 0 && ctPostDeleted.get() > 0;
961  }
962
963  public boolean hadPostBulkLoadHFile() {
964    return ctPostBulkLoadHFile.get() > 0;
965  }
966
967  public boolean hadPreBulkLoadHFile() {
968    return ctPreBulkLoadHFile.get() > 0;
969  }
970
971  public int getCtBeforeDelete() {
972    return ctBeforeDelete.get();
973  }
974
975  public int getCtPreOpen() {
976    return ctPreOpen.get();
977  }
978
979  public int getCtPostOpen() {
980    return ctPostOpen.get();
981  }
982
983  public int getCtPreClose() {
984    return ctPreClose.get();
985  }
986
987  public int getCtPostClose() {
988    return ctPostClose.get();
989  }
990
991  public int getCtPreFlush() {
992    return ctPreFlush.get();
993  }
994
995  public int getCtPostFlush() {
996    return ctPostFlush.get();
997  }
998
999  public int getCtPreCompactSelect() {
1000    return ctPreCompactSelect.get();
1001  }
1002
1003  public int getCtPostCompactSelect() {
1004    return ctPostCompactSelect.get();
1005  }
1006
1007  public int getCtPreCompact() {
1008    return ctPreCompact.get();
1009  }
1010
1011  public int getCtPostCompact() {
1012    return ctPostCompact.get();
1013  }
1014
1015  public int getCtPreGet() {
1016    return ctPreGet.get();
1017  }
1018
1019  public int getCtPostGet() {
1020    return ctPostGet.get();
1021  }
1022
1023  public int getCtPrePut() {
1024    return ctPrePut.get();
1025  }
1026
1027  public int getCtPostPut() {
1028    return ctPostPut.get();
1029  }
1030
1031  public int getCtPreDeleted() {
1032    return ctPreDeleted.get();
1033  }
1034
1035  public int getCtPostDeleted() {
1036    return ctPostDeleted.get();
1037  }
1038
1039  public int getCtPreIncrement() {
1040    return ctPreIncrement.get();
1041  }
1042
1043  public int getCtPostIncrement() {
1044    return ctPostIncrement.get();
1045  }
1046
1047  public int getCtPreReplayWALs() {
1048    return ctPreReplayWALs.get();
1049  }
1050
1051  public int getCtPostReplayWALs() {
1052    return ctPostReplayWALs.get();
1053  }
1054
1055  public int getCtPreWALRestore() {
1056    return ctPreWALRestore.get();
1057  }
1058
1059  public int getCtPostWALRestore() {
1060    return ctPostWALRestore.get();
1061  }
1062
1063  public int getCtPreWALAppend() {
1064    return ctPreWALAppend.get();
1065  }
1066
1067  public boolean wasStoreFileReaderOpenCalled() {
1068    return ctPreStoreFileReaderOpen.get() > 0 && ctPostStoreFileReaderOpen.get() > 0;
1069  }
1070}