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