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,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019
020package org.apache.hadoop.hbase.coprocessor;
021
022import java.io.IOException;
023import java.util.ArrayList;
024import java.util.List;
025import java.util.Map;
026
027import org.apache.hadoop.fs.FileSystem;
028import org.apache.hadoop.fs.Path;
029import org.apache.hadoop.hbase.Cell;
030import org.apache.hadoop.hbase.CompareOperator;
031import org.apache.hadoop.hbase.HBaseInterfaceAudience;
032import org.apache.hadoop.hbase.client.Append;
033import org.apache.hadoop.hbase.client.Delete;
034import org.apache.hadoop.hbase.client.Durability;
035import org.apache.hadoop.hbase.client.Get;
036import org.apache.hadoop.hbase.client.Increment;
037import org.apache.hadoop.hbase.client.Mutation;
038import org.apache.hadoop.hbase.client.Put;
039import org.apache.hadoop.hbase.client.RegionInfo;
040import org.apache.hadoop.hbase.client.Result;
041import org.apache.hadoop.hbase.client.Scan;
042import org.apache.hadoop.hbase.filter.ByteArrayComparable;
043import org.apache.hadoop.hbase.filter.Filter;
044import org.apache.hadoop.hbase.io.FSDataInputStreamWrapper;
045import org.apache.hadoop.hbase.io.Reference;
046import org.apache.hadoop.hbase.io.hfile.CacheConfig;
047import org.apache.hadoop.hbase.regionserver.FlushLifeCycleTracker;
048import org.apache.hadoop.hbase.regionserver.InternalScanner;
049import org.apache.hadoop.hbase.regionserver.MiniBatchOperationInProgress;
050import org.apache.hadoop.hbase.regionserver.OperationStatus;
051import org.apache.hadoop.hbase.regionserver.Region;
052import org.apache.hadoop.hbase.regionserver.Region.Operation;
053import org.apache.hadoop.hbase.regionserver.RegionScanner;
054import org.apache.hadoop.hbase.regionserver.ScanOptions;
055import org.apache.hadoop.hbase.regionserver.ScanType;
056import org.apache.hadoop.hbase.regionserver.Store;
057import org.apache.hadoop.hbase.regionserver.StoreFile;
058import org.apache.hadoop.hbase.regionserver.StoreFileReader;
059import org.apache.hadoop.hbase.regionserver.compactions.CompactionLifeCycleTracker;
060import org.apache.hadoop.hbase.regionserver.compactions.CompactionRequest;
061import org.apache.hadoop.hbase.regionserver.querymatcher.DeleteTracker;
062import org.apache.hadoop.hbase.util.Pair;
063import org.apache.hadoop.hbase.wal.WALEdit;
064import org.apache.hadoop.hbase.wal.WALKey;
065import org.apache.yetus.audience.InterfaceAudience;
066import org.apache.yetus.audience.InterfaceStability;
067
068/**
069 * Coprocessors implement this interface to observe and mediate client actions on the region.
070 * <p>
071 * Since most implementations will be interested in only a subset of hooks, this class uses
072 * 'default' functions to avoid having to add unnecessary overrides. When the functions are
073 * non-empty, it's simply to satisfy the compiler by returning value of expected (non-void) type. It
074 * is done in a way that these default definitions act as no-op. So our suggestion to implementation
075 * would be to not call these 'default' methods from overrides.
076 * <p>
077 * <h3>Exception Handling</h3><br>
078 * For all functions, exception handling is done as follows:
079 * <ul>
080 * <li>Exceptions of type {@link IOException} are reported back to client.</li>
081 * <li>For any other kind of exception:
082 * <ul>
083 * <li>If the configuration {@link CoprocessorHost#ABORT_ON_ERROR_KEY} is set to true, then the
084 * server aborts.</li>
085 * <li>Otherwise, coprocessor is removed from the server and
086 * {@link org.apache.hadoop.hbase.DoNotRetryIOException} is returned to the client.</li>
087 * </ul>
088 * </li>
089 * </ul>
090 * <p>
091 * <h3>For Split Related Hooks</h3> <br>
092 * In hbase2/AMv2, master runs splits, so the split related hooks are moved to
093 * {@link MasterObserver}.
094 * <p>
095 * <h3>Increment Column Value</h3><br>
096 * We do not call this hook anymore.
097 */
098@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC)
099@InterfaceStability.Evolving
100// TODO as method signatures need to break, update to
101// ObserverContext<? extends RegionCoprocessorEnvironment>
102// so we can use additional environment state that isn't exposed to coprocessors.
103public interface RegionObserver {
104  /** Mutation type for postMutationBeforeWAL hook */
105  enum MutationType {
106    APPEND, INCREMENT
107  }
108
109  /**
110   * Called before the region is reported as open to the master.
111   * @param c the environment provided by the region server
112   */
113  default void preOpen(ObserverContext<RegionCoprocessorEnvironment> c) throws IOException {}
114
115  /**
116   * Called after the region is reported as open to the master.
117   * @param c the environment provided by the region server
118   */
119  default void postOpen(ObserverContext<RegionCoprocessorEnvironment> c) {}
120
121  /**
122   * Called before the memstore is flushed to disk.
123   * @param c the environment provided by the region server
124   * @param tracker tracker used to track the life cycle of a flush
125   */
126  default void preFlush(final ObserverContext<RegionCoprocessorEnvironment> c,
127      FlushLifeCycleTracker tracker) throws IOException {}
128
129  /**
130   * Called before we open store scanner for flush. You can use the {@code options} to change max
131   * versions and TTL for the scanner being opened.
132   * @param c the environment provided by the region server
133   * @param store the store where flush is being requested
134   * @param options used to change max versions and TTL for the scanner being opened
135   */
136  default void preFlushScannerOpen(ObserverContext<RegionCoprocessorEnvironment> c, Store store,
137      ScanOptions options,FlushLifeCycleTracker tracker) throws IOException {}
138
139  /**
140   * Called before a Store's memstore is flushed to disk.
141   * @param c the environment provided by the region server
142   * @param store the store where flush is being requested
143   * @param scanner the scanner over existing data used in the memstore
144   * @param tracker tracker used to track the life cycle of a flush
145   * @return the scanner to use during flush. Should not be {@code null} unless the implementation
146   *         is writing new store files on its own.
147   */
148  default InternalScanner preFlush(ObserverContext<RegionCoprocessorEnvironment> c, Store store,
149      InternalScanner scanner, FlushLifeCycleTracker tracker) throws IOException {
150    return scanner;
151  }
152
153  /**
154   * Called after the memstore is flushed to disk.
155   * @param c the environment provided by the region server
156   * @param tracker tracker used to track the life cycle of a flush
157   * @throws IOException if an error occurred on the coprocessor
158   */
159  default void postFlush(ObserverContext<RegionCoprocessorEnvironment> c,
160      FlushLifeCycleTracker tracker) throws IOException {}
161
162  /**
163   * Called after a Store's memstore is flushed to disk.
164   * @param c the environment provided by the region server
165   * @param store the store being flushed
166   * @param resultFile the new store file written out during compaction
167   * @param tracker tracker used to track the life cycle of a flush
168   */
169  default void postFlush(ObserverContext<RegionCoprocessorEnvironment> c, Store store,
170      StoreFile resultFile, FlushLifeCycleTracker tracker) throws IOException {}
171
172  /**
173   * Called before in memory compaction started.
174   * @param c the environment provided by the region server
175   * @param store the store where in memory compaction is being requested
176   */
177  default void preMemStoreCompaction(ObserverContext<RegionCoprocessorEnvironment> c, Store store)
178      throws IOException {}
179
180  /**
181   * Called before we open store scanner for in memory compaction. You can use the {@code options}
182   * to change max versions and TTL for the scanner being opened. Notice that this method will only
183   * be called when you use {@code eager} mode. For {@code basic} mode we will not drop any cells
184   * thus we do not open a store scanner.
185   * @param c the environment provided by the region server
186   * @param store the store where in memory compaction is being requested
187   * @param options used to change max versions and TTL for the scanner being opened
188   */
189  default void preMemStoreCompactionCompactScannerOpen(
190      ObserverContext<RegionCoprocessorEnvironment> c, Store store, ScanOptions options)
191      throws IOException {}
192
193  /**
194   * Called before we do in memory compaction. Notice that this method will only be called when you
195   * use {@code eager} mode. For {@code basic} mode we will not drop any cells thus there is no
196   * {@link InternalScanner}.
197   * @param c the environment provided by the region server
198   * @param store the store where in memory compaction is being executed
199   * @param scanner the scanner over existing data used in the memstore segments being compact
200   * @return the scanner to use during in memory compaction. Must be non-null.
201   */
202  default InternalScanner preMemStoreCompactionCompact(
203      ObserverContext<RegionCoprocessorEnvironment> c, Store store, InternalScanner scanner)
204      throws IOException {
205    return scanner;
206  }
207
208  /**
209   * Called after the in memory compaction is finished.
210   * @param c the environment provided by the region server
211   * @param store the store where in memory compaction is being executed
212   */
213  default void postMemStoreCompaction(ObserverContext<RegionCoprocessorEnvironment> c, Store store)
214      throws IOException {}
215
216  /**
217   * Called prior to selecting the {@link StoreFile StoreFiles} to compact from the list of
218   * available candidates. To alter the files used for compaction, you may mutate the passed in list
219   * of candidates. If you remove all the candidates then the compaction will be canceled.
220   * <p>Supports Coprocessor 'bypass' -- 'bypass' is how this method indicates that it changed
221   * the passed in <code>candidates</code>.
222   * If 'bypass' is set, we skip out on calling any subsequent chained coprocessors.
223   * @param c the environment provided by the region server
224   * @param store the store where compaction is being requested
225   * @param candidates the store files currently available for compaction
226   * @param tracker tracker used to track the life cycle of a compaction
227   */
228  default void preCompactSelection(ObserverContext<RegionCoprocessorEnvironment> c, Store store,
229      List<? extends StoreFile> candidates, CompactionLifeCycleTracker tracker)
230      throws IOException {}
231
232  /**
233   * Called after the {@link StoreFile}s to compact have been selected from the available
234   * candidates.
235   * @param c the environment provided by the region server
236   * @param store the store being compacted
237   * @param selected the store files selected to compact
238   * @param tracker tracker used to track the life cycle of a compaction
239   * @param request the requested compaction
240   */
241  default void postCompactSelection(ObserverContext<RegionCoprocessorEnvironment> c, Store store,
242      List<? extends StoreFile> selected, CompactionLifeCycleTracker tracker,
243      CompactionRequest request) {}
244
245  /**
246   * Called before we open store scanner for compaction. You can use the {@code options} to change max
247   * versions and TTL for the scanner being opened.
248   * @param c the environment provided by the region server
249   * @param store the store being compacted
250   * @param scanType type of Scan
251   * @param options used to change max versions and TTL for the scanner being opened
252   * @param tracker tracker used to track the life cycle of a compaction
253   * @param request the requested compaction
254   */
255  default void preCompactScannerOpen(ObserverContext<RegionCoprocessorEnvironment> c, Store store,
256      ScanType scanType, ScanOptions options, CompactionLifeCycleTracker tracker,
257      CompactionRequest request) throws IOException {}
258
259  /**
260   * Called prior to writing the {@link StoreFile}s selected for compaction into a new
261   * {@code StoreFile}.
262   * <p>
263   * To override or modify the compaction process, implementing classes can wrap the provided
264   * {@link InternalScanner} with a custom implementation that is returned from this method. The
265   * custom scanner can then inspect {@link org.apache.hadoop.hbase.Cell}s from the wrapped scanner,
266   * applying its own policy to what gets written.
267   * @param c the environment provided by the region server
268   * @param store the store being compacted
269   * @param scanner the scanner over existing data used in the store file rewriting
270   * @param scanType type of Scan
271   * @param tracker tracker used to track the life cycle of a compaction
272   * @param request the requested compaction
273   * @return the scanner to use during compaction. Should not be {@code null} unless the
274   *         implementation is writing new store files on its own.
275   */
276  default InternalScanner preCompact(ObserverContext<RegionCoprocessorEnvironment> c, Store store,
277      InternalScanner scanner, ScanType scanType, CompactionLifeCycleTracker tracker,
278      CompactionRequest request) throws IOException {
279    return scanner;
280  }
281
282  /**
283   * Called after compaction has completed and the new store file has been moved in to place.
284   * @param c the environment provided by the region server
285   * @param store the store being compacted
286   * @param resultFile the new store file written out during compaction
287   * @param tracker used to track the life cycle of a compaction
288   * @param request the requested compaction
289   */
290  default void postCompact(ObserverContext<RegionCoprocessorEnvironment> c, Store store,
291      StoreFile resultFile, CompactionLifeCycleTracker tracker, CompactionRequest request)
292      throws IOException {}
293
294  /**
295   * Called before the region is reported as closed to the master.
296   * @param c the environment provided by the region server
297   * @param abortRequested true if the region server is aborting
298   */
299  default void preClose(ObserverContext<RegionCoprocessorEnvironment> c, boolean abortRequested)
300      throws IOException {}
301
302  /**
303   * Called after the region is reported as closed to the master.
304   * @param c the environment provided by the region server
305   * @param abortRequested true if the region server is aborting
306   */
307  default void postClose(ObserverContext<RegionCoprocessorEnvironment> c, boolean abortRequested) {}
308
309  /**
310   * Called before the client performs a Get
311   * <p>
312   * Call CoprocessorEnvironment#bypass to skip default actions.
313   * If 'bypass' is set, we skip out on calling any subsequent chained coprocessors.
314   * @param c the environment provided by the region server
315   * @param get the Get request
316   * @param result The result to return to the client if default processing
317   * is bypassed. Can be modified. Will not be used if default processing
318   * is not bypassed.
319   */
320  default void preGetOp(ObserverContext<RegionCoprocessorEnvironment> c, Get get, List<Cell> result)
321      throws IOException {}
322
323  /**
324   * Called after the client performs a Get
325   * <p>
326   * Note: Do not retain references to any Cells in 'result' beyond the life of this invocation.
327   * If need a Cell reference for later use, copy the cell and use that.
328   * @param c the environment provided by the region server
329   * @param get the Get request
330   * @param result the result to return to the client, modify as necessary
331   */
332  default void postGetOp(ObserverContext<RegionCoprocessorEnvironment> c, Get get,
333      List<Cell> result) throws IOException {}
334
335  /**
336   * Called before the client tests for existence using a Get.
337   * <p>
338   * Call CoprocessorEnvironment#bypass to skip default actions.
339   * If 'bypass' is set, we skip out on calling any subsequent chained coprocessors.
340   * @param c the environment provided by the region server
341   * @param get the Get request
342   * @param exists the result returned by the region server
343   * @return the value to return to the client if bypassing default processing
344   */
345  default boolean preExists(ObserverContext<RegionCoprocessorEnvironment> c, Get get,
346      boolean exists) throws IOException {
347    return exists;
348  }
349
350  /**
351   * Called after the client tests for existence using a Get.
352   * @param c the environment provided by the region server
353   * @param get the Get request
354   * @param exists the result returned by the region server
355   * @return the result to return to the client
356   */
357  default boolean postExists(ObserverContext<RegionCoprocessorEnvironment> c, Get get,
358      boolean exists) throws IOException {
359    return exists;
360  }
361
362  /**
363   * Called before the client stores a value.
364   * <p>
365   * Call CoprocessorEnvironment#bypass to skip default actions.
366   * If 'bypass' is set, we skip out on calling any subsequent chained coprocessors.
367   * <p>
368   * Note: Do not retain references to any Cells in 'put' beyond the life of this invocation.
369   * If need a Cell reference for later use, copy the cell and use that.
370   * @param c the environment provided by the region server
371   * @param put The Put object
372   * @param edit The WALEdit object that will be written to the wal
373   * @param durability Persistence guarantee for this Put
374   */
375  default void prePut(ObserverContext<RegionCoprocessorEnvironment> c, Put put, WALEdit edit,
376      Durability durability) throws IOException {}
377
378  /**
379   * Called after the client stores a value.
380   * <p>
381   * Note: Do not retain references to any Cells in 'put' beyond the life of this invocation.
382   * If need a Cell reference for later use, copy the cell and use that.
383   * @param c the environment provided by the region server
384   * @param put The Put object
385   * @param edit The WALEdit object for the wal
386   * @param durability Persistence guarantee for this Put
387   */
388  default void postPut(ObserverContext<RegionCoprocessorEnvironment> c, Put put, WALEdit edit,
389      Durability durability) throws IOException {}
390
391  /**
392   * Called before the client deletes a value.
393   * <p>
394   * Call CoprocessorEnvironment#bypass to skip default actions.
395   * If 'bypass' is set, we skip out on calling any subsequent chained coprocessors.
396   * <p>
397   * Note: Do not retain references to any Cells in 'delete' beyond the life of this invocation.
398   * If need a Cell reference for later use, copy the cell and use that.
399   * @param c the environment provided by the region server
400   * @param delete The Delete object
401   * @param edit The WALEdit object for the wal
402   * @param durability Persistence guarantee for this Delete
403   */
404  default void preDelete(ObserverContext<RegionCoprocessorEnvironment> c, Delete delete,
405      WALEdit edit, Durability durability) throws IOException {}
406
407  /**
408   * Called before the server updates the timestamp for version delete with latest timestamp.
409   * <p>
410   * Call CoprocessorEnvironment#bypass to skip default actions.
411   * If 'bypass' is set, we skip out on calling any subsequent chained coprocessors.
412   * @param c the environment provided by the region server
413   * @param mutation - the parent mutation associated with this delete cell
414   * @param cell - The deleteColumn with latest version cell
415   * @param byteNow - timestamp bytes
416   * @param get - the get formed using the current cell's row. Note that the get does not specify
417   *          the family and qualifier
418   * @deprecated Since hbase-2.0.0. No replacement. To be removed in hbase-3.0.0 and replaced
419   * with something that doesn't expose IntefaceAudience.Private classes.
420   */
421  @Deprecated
422  default void prePrepareTimeStampForDeleteVersion(ObserverContext<RegionCoprocessorEnvironment> c,
423      Mutation mutation, Cell cell, byte[] byteNow, Get get) throws IOException {}
424
425  /**
426   * Called after the client deletes a value.
427   * <p>
428   * Note: Do not retain references to any Cells in 'delete' beyond the life of this invocation.
429   * If need a Cell reference for later use, copy the cell and use that.
430   * @param c the environment provided by the region server
431   * @param delete The Delete object
432   * @param edit The WALEdit object for the wal
433   * @param durability Persistence guarantee for this Delete
434   */
435  default void postDelete(ObserverContext<RegionCoprocessorEnvironment> c, Delete delete,
436      WALEdit edit, Durability durability) throws IOException {}
437
438  /**
439   * This will be called for every batch mutation operation happening at the server. This will be
440   * called after acquiring the locks on the mutating rows and after applying the proper timestamp
441   * for each Mutation at the server. The batch may contain Put/Delete. By setting OperationStatus
442   * of Mutations ({@link MiniBatchOperationInProgress#setOperationStatus(int, OperationStatus)}),
443   * {@link RegionObserver} can make Region to skip these Mutations.
444   * <p>
445   * Note: Do not retain references to any Cells in Mutations beyond the life of this invocation.
446   * If need a Cell reference for later use, copy the cell and use that.
447   * @param c the environment provided by the region server
448   * @param miniBatchOp batch of Mutations getting applied to region.
449   */
450  default void preBatchMutate(ObserverContext<RegionCoprocessorEnvironment> c,
451      MiniBatchOperationInProgress<Mutation> miniBatchOp) throws IOException {}
452
453  /**
454   * This will be called after applying a batch of Mutations on a region. The Mutations are added to
455   * memstore and WAL. The difference of this one with
456   * {@link #postPut(ObserverContext, Put, WALEdit, Durability) }
457   * and {@link #postDelete(ObserverContext, Delete, WALEdit, Durability) } is
458   * this hook will be executed before the mvcc transaction completion.
459   * <p>
460   * Note: Do not retain references to any Cells in Mutations beyond the life of this invocation.
461   * If need a Cell reference for later use, copy the cell and use that.
462   * @param c the environment provided by the region server
463   * @param miniBatchOp batch of Mutations applied to region. Coprocessors are discouraged from
464   *                    manipulating its state.
465   */
466  // Coprocessors can do a form of bypass by changing state in miniBatchOp.
467  default void postBatchMutate(ObserverContext<RegionCoprocessorEnvironment> c,
468      MiniBatchOperationInProgress<Mutation> miniBatchOp) throws IOException {}
469
470  /**
471   * This will be called for region operations where read lock is acquired in
472   * {@link Region#startRegionOperation()}.
473   * @param ctx
474   * @param operation The operation is about to be taken on the region
475   */
476  default void postStartRegionOperation(ObserverContext<RegionCoprocessorEnvironment> ctx,
477      Operation operation) throws IOException {}
478
479  /**
480   * Called after releasing read lock in {@link Region#closeRegionOperation()}.
481   * @param ctx
482   * @param operation
483   */
484  default void postCloseRegionOperation(ObserverContext<RegionCoprocessorEnvironment> ctx,
485      Operation operation) throws IOException {}
486
487  /**
488   * Called after the completion of batch put/delete and will be called even if the batch operation
489   * fails.
490   * <p>
491   * Note: Do not retain references to any Cells in Mutations beyond the life of this invocation.
492   * If need a Cell reference for later use, copy the cell and use that.
493   * @param ctx
494   * @param miniBatchOp
495   * @param success true if batch operation is successful otherwise false.
496   */
497  default void postBatchMutateIndispensably(ObserverContext<RegionCoprocessorEnvironment> ctx,
498      MiniBatchOperationInProgress<Mutation> miniBatchOp, boolean success) throws IOException {}
499
500  /**
501   * Called before checkAndPut.
502   * <p>
503   * Call CoprocessorEnvironment#bypass to skip default actions.
504   * If 'bypass' is set, we skip out on calling any subsequent chained coprocessors.
505   * <p>
506   * Note: Do not retain references to any Cells in 'put' beyond the life of this invocation.
507   * If need a Cell reference for later use, copy the cell and use that.
508   * @param c the environment provided by the region server
509   * @param row row to check
510   * @param family column family
511   * @param qualifier column qualifier
512   * @param op the comparison operation
513   * @param comparator the comparator
514   * @param put data to put if check succeeds
515   * @param result the default value of the result
516   * @return the return value to return to client if bypassing default processing
517   */
518  default boolean preCheckAndPut(ObserverContext<RegionCoprocessorEnvironment> c, byte[] row,
519      byte[] family, byte[] qualifier, CompareOperator op, ByteArrayComparable comparator, Put put,
520      boolean result) throws IOException {
521    return result;
522  }
523
524  /**
525   * Called before checkAndPut.
526   * <p>
527   * Call CoprocessorEnvironment#bypass to skip default actions.
528   * If 'bypass' is set, we skip out on calling any subsequent chained coprocessors.
529   * <p>
530   * Note: Do not retain references to any Cells in 'put' beyond the life of this invocation.
531   * If need a Cell reference for later use, copy the cell and use that.
532   * @param c the environment provided by the region server
533   * @param row row to check
534   * @param filter filter
535   * @param put data to put if check succeeds
536   * @param result the default value of the result
537   * @return the return value to return to client if bypassing default processing
538   */
539  default boolean preCheckAndPut(ObserverContext<RegionCoprocessorEnvironment> c, byte[] row,
540    Filter filter, Put put, boolean result) throws IOException {
541    return result;
542  }
543
544  /**
545   * Called before checkAndPut but after acquiring rowlock.
546   * <p>
547   * <b>Note:</b> Caution to be taken for not doing any long time operation in this hook.
548   * Row will be locked for longer time. Trying to acquire lock on another row, within this,
549   * can lead to potential deadlock.
550   * <p>
551   * Call CoprocessorEnvironment#bypass to skip default actions.
552   * If 'bypass' is set, we skip out on calling any subsequent chained coprocessors.
553   * <p>
554   * Note: Do not retain references to any Cells in 'put' beyond the life of this invocation.
555   * If need a Cell reference for later use, copy the cell and use that.
556   * @param c the environment provided by the region server
557   * @param row row to check
558   * @param family column family
559   * @param qualifier column qualifier
560   * @param op the comparison operation
561   * @param comparator the comparator
562   * @param put data to put if check succeeds
563   * @param result the default value of the result
564   * @return the return value to return to client if bypassing default processing
565   */
566  default boolean preCheckAndPutAfterRowLock(ObserverContext<RegionCoprocessorEnvironment> c,
567      byte[] row, byte[] family, byte[] qualifier, CompareOperator op,
568      ByteArrayComparable comparator, Put put, boolean result) throws IOException {
569    return result;
570  }
571
572  /**
573   * Called before checkAndPut but after acquiring rowlock.
574   * <p>
575   * <b>Note:</b> Caution to be taken for not doing any long time operation in this hook.
576   * Row will be locked for longer time. Trying to acquire lock on another row, within this,
577   * can lead to potential deadlock.
578   * <p>
579   * Call CoprocessorEnvironment#bypass to skip default actions.
580   * If 'bypass' is set, we skip out on calling any subsequent chained coprocessors.
581   * <p>
582   * Note: Do not retain references to any Cells in 'put' beyond the life of this invocation.
583   * If need a Cell reference for later use, copy the cell and use that.
584   * @param c the environment provided by the region server
585   * @param row row to check
586   * @param filter filter
587   * @param put data to put if check succeeds
588   * @param result the default value of the result
589   * @return the return value to return to client if bypassing default processing
590   */
591  default boolean preCheckAndPutAfterRowLock(ObserverContext<RegionCoprocessorEnvironment> c,
592    byte[] row, Filter filter, Put put, boolean result) throws IOException {
593    return result;
594  }
595
596  /**
597   * Called after checkAndPut
598   * <p>
599   * Note: Do not retain references to any Cells in 'put' beyond the life of this invocation.
600   * If need a Cell reference for later use, copy the cell and use that.
601   * @param c the environment provided by the region server
602   * @param row row to check
603   * @param family column family
604   * @param qualifier column qualifier
605   * @param op the comparison operation
606   * @param comparator the comparator
607   * @param put data to put if check succeeds
608   * @param result from the checkAndPut
609   * @return the possibly transformed return value to return to client
610   */
611  default boolean postCheckAndPut(ObserverContext<RegionCoprocessorEnvironment> c, byte[] row,
612      byte[] family, byte[] qualifier, CompareOperator op, ByteArrayComparable comparator, Put put,
613      boolean result) throws IOException {
614    return result;
615  }
616
617  /**
618   * Called after checkAndPut
619   * <p>
620   * Note: Do not retain references to any Cells in 'put' beyond the life of this invocation.
621   * If need a Cell reference for later use, copy the cell and use that.
622   * @param c the environment provided by the region server
623   * @param row row to check
624   * @param filter filter
625   * @param put data to put if check succeeds
626   * @param result from the checkAndPut
627   * @return the possibly transformed return value to return to client
628   */
629  default boolean postCheckAndPut(ObserverContext<RegionCoprocessorEnvironment> c, byte[] row,
630    Filter filter, Put put, boolean result) throws IOException {
631    return result;
632  }
633
634  /**
635   * Called before checkAndDelete.
636   * <p>
637   * Call CoprocessorEnvironment#bypass to skip default actions.
638   * If 'bypass' is set, we skip out on calling any subsequent chained coprocessors.
639   * <p>
640   * Note: Do not retain references to any Cells in 'delete' beyond the life of this invocation.
641   * If need a Cell reference for later use, copy the cell and use that.
642   * @param c the environment provided by the region server
643   * @param row row to check
644   * @param family column family
645   * @param qualifier column qualifier
646   * @param op the comparison operation
647   * @param comparator the comparator
648   * @param delete delete to commit if check succeeds
649   * @param result the default value of the result
650   * @return the value to return to client if bypassing default processing
651   */
652  default boolean preCheckAndDelete(ObserverContext<RegionCoprocessorEnvironment> c, byte[] row,
653      byte[] family, byte[] qualifier, CompareOperator op, ByteArrayComparable comparator,
654      Delete delete, boolean result) throws IOException {
655    return result;
656  }
657
658  /**
659   * Called before checkAndDelete.
660   * <p>
661   * Call CoprocessorEnvironment#bypass to skip default actions.
662   * If 'bypass' is set, we skip out on calling any subsequent chained coprocessors.
663   * <p>
664   * Note: Do not retain references to any Cells in 'delete' beyond the life of this invocation.
665   * If need a Cell reference for later use, copy the cell and use that.
666   * @param c the environment provided by the region server
667   * @param row row to check
668   * @param filter column family
669   * @param delete delete to commit if check succeeds
670   * @param result the default value of the result
671   * @return the value to return to client if bypassing default processing
672   */
673  default boolean preCheckAndDelete(ObserverContext<RegionCoprocessorEnvironment> c, byte[] row,
674    Filter filter, Delete delete, boolean result) throws IOException {
675    return result;
676  }
677
678  /**
679   * Called before checkAndDelete but after acquiring rowock.
680   * <p>
681   * <b>Note:</b> Caution to be taken for not doing any long time operation in this hook.
682   * Row will be locked for longer time. Trying to acquire lock on another row, within this,
683   * can lead to potential deadlock.
684   * <p>
685   * Call CoprocessorEnvironment#bypass to skip default actions.
686   * If 'bypass' is set, we skip out on calling any subsequent chained coprocessors.
687   * <p>
688   * Note: Do not retain references to any Cells in 'delete' beyond the life of this invocation.
689   * If need a Cell reference for later use, copy the cell and use that.
690   * @param c the environment provided by the region server
691   * @param row row to check
692   * @param family column family
693   * @param qualifier column qualifier
694   * @param op the comparison operation
695   * @param comparator the comparator
696   * @param delete delete to commit if check succeeds
697   * @param result the default value of the result
698   * @return the value to return to client if bypassing default processing
699   */
700  default boolean preCheckAndDeleteAfterRowLock(ObserverContext<RegionCoprocessorEnvironment> c,
701      byte[] row, byte[] family, byte[] qualifier, CompareOperator op,
702      ByteArrayComparable comparator, Delete delete, boolean result) throws IOException {
703    return result;
704  }
705
706  /**
707   * Called before checkAndDelete but after acquiring rowock.
708   * <p>
709   * <b>Note:</b> Caution to be taken for not doing any long time operation in this hook.
710   * Row will be locked for longer time. Trying to acquire lock on another row, within this,
711   * can lead to potential deadlock.
712   * <p>
713   * Call CoprocessorEnvironment#bypass to skip default actions.
714   * If 'bypass' is set, we skip out on calling any subsequent chained coprocessors.
715   * <p>
716   * Note: Do not retain references to any Cells in 'delete' beyond the life of this invocation.
717   * If need a Cell reference for later use, copy the cell and use that.
718   * @param c the environment provided by the region server
719   * @param row row to check
720   * @param filter filter
721   * @param delete delete to commit if check succeeds
722   * @param result the default value of the result
723   * @return the value to return to client if bypassing default processing
724   */
725  default boolean preCheckAndDeleteAfterRowLock(ObserverContext<RegionCoprocessorEnvironment> c,
726    byte[] row, Filter filter, Delete delete, boolean result) throws IOException {
727    return result;
728  }
729
730  /**
731   * Called after checkAndDelete
732   * <p>
733   * Note: Do not retain references to any Cells in 'delete' beyond the life of this invocation.
734   * If need a Cell reference for later use, copy the cell and use that.
735   * @param c the environment provided by the region server
736   * @param row row to check
737   * @param family column family
738   * @param qualifier column qualifier
739   * @param op the comparison operation
740   * @param comparator the comparator
741   * @param delete delete to commit if check succeeds
742   * @param result from the CheckAndDelete
743   * @return the possibly transformed returned value to return to client
744   */
745  default boolean postCheckAndDelete(ObserverContext<RegionCoprocessorEnvironment> c, byte[] row,
746      byte[] family, byte[] qualifier, CompareOperator op, ByteArrayComparable comparator,
747      Delete delete, boolean result) throws IOException {
748    return result;
749  }
750
751  /**
752   * Called after checkAndDelete
753   * <p>
754   * Note: Do not retain references to any Cells in 'delete' beyond the life of this invocation.
755   * If need a Cell reference for later use, copy the cell and use that.
756   * @param c the environment provided by the region server
757   * @param row row to check
758   * @param filter filter
759   * @param delete delete to commit if check succeeds
760   * @param result from the CheckAndDelete
761   * @return the possibly transformed returned value to return to client
762   */
763  default boolean postCheckAndDelete(ObserverContext<RegionCoprocessorEnvironment> c, byte[] row,
764    Filter filter, Delete delete, boolean result) throws IOException {
765    return result;
766  }
767
768  /**
769   * Called before Append.
770   * <p>
771   * Call CoprocessorEnvironment#bypass to skip default actions.
772   * If 'bypass' is set, we skip out on calling any subsequent chained coprocessors.
773   * <p>
774   * Note: Do not retain references to any Cells in 'append' beyond the life of this invocation.
775   * If need a Cell reference for later use, copy the cell and use that.
776   * @param c the environment provided by the region server
777   * @param append Append object
778   * @return result to return to the client if bypassing default processing
779   */
780  default Result preAppend(ObserverContext<RegionCoprocessorEnvironment> c, Append append)
781      throws IOException {
782    return null;
783  }
784
785  /**
786   * Called before Append but after acquiring rowlock.
787   * <p>
788   * <b>Note:</b> Caution to be taken for not doing any long time operation in this hook.
789   * Row will be locked for longer time. Trying to acquire lock on another row, within this,
790   * can lead to potential deadlock.
791   * <p>
792   * Call CoprocessorEnvironment#bypass to skip default actions.
793   * If 'bypass' is set, we skip out on calling any subsequent chained coprocessors.
794   * <p>
795   * Note: Do not retain references to any Cells in 'append' beyond the life of this invocation.
796   * If need a Cell reference for later use, copy the cell and use that.
797   * @param c the environment provided by the region server
798   * @param append Append object
799   * @return result to return to the client if bypassing default processing
800   */
801  default Result preAppendAfterRowLock(ObserverContext<RegionCoprocessorEnvironment> c,
802      Append append) throws IOException {
803    return null;
804  }
805
806  /**
807   * Called after Append
808   * <p>
809   * Note: Do not retain references to any Cells in 'append' beyond the life of this invocation.
810   * If need a Cell reference for later use, copy the cell and use that.
811   * @param c the environment provided by the region server
812   * @param append Append object
813   * @param result the result returned by increment
814   * @return the result to return to the client
815   */
816  default Result postAppend(ObserverContext<RegionCoprocessorEnvironment> c, Append append,
817      Result result) throws IOException {
818    return result;
819  }
820
821  /**
822   * Called before Increment.
823   * <p>
824   * Call CoprocessorEnvironment#bypass to skip default actions.
825   * If 'bypass' is set, we skip out on calling any subsequent chained coprocessors.
826   * <p>
827   * Note: Do not retain references to any Cells in 'increment' beyond the life of this invocation.
828   * If need a Cell reference for later use, copy the cell and use that.
829   * @param c the environment provided by the region server
830   * @param increment increment object
831   * @return result to return to the client if bypassing default processing
832   */
833  default Result preIncrement(ObserverContext<RegionCoprocessorEnvironment> c, Increment increment)
834      throws IOException {
835    return null;
836  }
837
838  /**
839   * Called before Increment but after acquiring rowlock.
840   * <p>
841   * <b>Note:</b> Caution to be taken for not doing any long time operation in this hook.
842   * Row will be locked for longer time. Trying to acquire lock on another row, within this,
843   * can lead to potential deadlock.
844   * <p>
845   * Call CoprocessorEnvironment#bypass to skip default actions.
846   * If 'bypass' is set, we skip out on calling any subsequent chained coprocessors.
847   * <p>
848   * Note: Do not retain references to any Cells in 'increment' beyond the life of this invocation.
849   * If need a Cell reference for later use, copy the cell and use that.
850   *
851   * @param c
852   *          the environment provided by the region server
853   * @param increment
854   *          increment object
855   * @return result to return to the client if bypassing default processing
856   *           if an error occurred on the coprocessor
857   */
858  default Result preIncrementAfterRowLock(ObserverContext<RegionCoprocessorEnvironment> c,
859      Increment increment) throws IOException {
860    return null;
861  }
862
863  /**
864   * Called after increment
865   * <p>
866   * Note: Do not retain references to any Cells in 'increment' beyond the life of this invocation.
867   * If need a Cell reference for later use, copy the cell and use that.
868   * @param c the environment provided by the region server
869   * @param increment increment object
870   * @param result the result returned by increment
871   * @return the result to return to the client
872   */
873  default Result postIncrement(ObserverContext<RegionCoprocessorEnvironment> c, Increment increment,
874      Result result) throws IOException {
875    return result;
876  }
877
878  /**
879   * Called before the client opens a new scanner.
880   * <p>
881   * Note: Do not retain references to any Cells returned by scanner, beyond the life of this
882   * invocation. If need a Cell reference for later use, copy the cell and use that.
883   * @param c the environment provided by the region server
884   * @param scan the Scan specification
885   */
886  default void preScannerOpen(ObserverContext<RegionCoprocessorEnvironment> c, Scan scan)
887      throws IOException {
888  }
889
890  /**
891   * Called after the client opens a new scanner.
892   * <p>
893   * Note: Do not retain references to any Cells returned by scanner, beyond the life of this
894   * invocation. If need a Cell reference for later use, copy the cell and use that.
895   * @param c the environment provided by the region server
896   * @param scan the Scan specification
897   * @param s if not null, the base scanner
898   * @return the scanner instance to use
899   */
900  default RegionScanner postScannerOpen(ObserverContext<RegionCoprocessorEnvironment> c, Scan scan,
901      RegionScanner s) throws IOException {
902    return s;
903  }
904
905  /**
906   * Called before the client asks for the next row on a scanner.
907   * <p>
908   * Call CoprocessorEnvironment#bypass to skip default actions.
909   * If 'bypass' is set, we skip out on calling any subsequent chained coprocessors.
910   * <p>
911   * Note: Do not retain references to any Cells returned by scanner, beyond the life of this
912   * invocation. If need a Cell reference for later use, copy the cell and use that.
913   * @param c the environment provided by the region server
914   * @param s the scanner
915   * @param result The result to return to the client if default processing
916   * is bypassed. Can be modified. Will not be returned if default processing
917   * is not bypassed.
918   * @param limit the maximum number of results to return
919   * @param hasNext the 'has more' indication
920   * @return 'has more' indication that should be sent to client
921   */
922  default boolean preScannerNext(ObserverContext<RegionCoprocessorEnvironment> c, InternalScanner s,
923      List<Result> result, int limit, boolean hasNext) throws IOException {
924    return hasNext;
925  }
926
927  /**
928   * Called after the client asks for the next row on a scanner.
929   * <p>
930   * Note: Do not retain references to any Cells returned by scanner, beyond the life of this
931   * invocation. If need a Cell reference for later use, copy the cell and use that.
932   * @param c the environment provided by the region server
933   * @param s the scanner
934   * @param result the result to return to the client, can be modified
935   * @param limit the maximum number of results to return
936   * @param hasNext the 'has more' indication
937   * @return 'has more' indication that should be sent to client
938   */
939  default boolean postScannerNext(ObserverContext<RegionCoprocessorEnvironment> c,
940      InternalScanner s, List<Result> result, int limit, boolean hasNext) throws IOException {
941    return hasNext;
942  }
943
944  /**
945   * This will be called by the scan flow when the current scanned row is being filtered out by the
946   * filter. The filter may be filtering out the row via any of the below scenarios
947   * <ol>
948   * <li>
949   * <code>boolean filterRowKey(byte [] buffer, int offset, int length)</code> returning true</li>
950   * <li>
951   * <code>boolean filterRow()</code> returning true</li>
952   * <li>
953   * <code>default void filterRow(List&lt;KeyValue&gt; kvs)</code> removing all the kvs from
954   * the passed List</li>
955   * </ol>
956   * <p>
957   * Note: Do not retain references to any Cells returned by scanner, beyond the life of this
958   * invocation. If need a Cell reference for later use, copy the cell and use that.
959   * @param c the environment provided by the region server
960   * @param s the scanner
961   * @param curRowCell The cell in the current row which got filtered out
962   * @param hasMore the 'has more' indication
963   * @return whether more rows are available for the scanner or not
964   */
965  default boolean postScannerFilterRow(ObserverContext<RegionCoprocessorEnvironment> c,
966      InternalScanner s, Cell curRowCell, boolean hasMore) throws IOException {
967    return hasMore;
968  }
969
970  /**
971   * Called before the client closes a scanner.
972   * <p>
973   * Call CoprocessorEnvironment#bypass to skip default actions.
974   * If 'bypass' is set, we skip out on calling any subsequent chained coprocessors.
975   * @param c the environment provided by the region server
976   * @param s the scanner
977   */
978  default void preScannerClose(ObserverContext<RegionCoprocessorEnvironment> c, InternalScanner s)
979      throws IOException {}
980
981  /**
982   * Called after the client closes a scanner.
983   * @param ctx the environment provided by the region server
984   * @param s the scanner
985   */
986  default void postScannerClose(ObserverContext<RegionCoprocessorEnvironment> ctx,
987      InternalScanner s) throws IOException {}
988
989  /**
990   * Called before a store opens a new scanner.
991   * <p>
992   * This hook is called when a "user" scanner is opened. Use {@code preFlushScannerOpen} and
993   * {@code preCompactScannerOpen} to inject flush/compaction.
994   * <p>
995   * Notice that, this method is used to change the inherent max versions and TTL for a Store. For
996   * example, you can change the max versions option for a {@link Scan} object to 10 in
997   * {@code preScannerOpen}, but if the max versions config on the Store is 1, then you still can
998   * only read 1 version. You need also to inject here to change the max versions to 10 if you want
999   * to get more versions.
1000   * @param ctx the environment provided by the region server
1001   * @param store the store which we want to get scanner from
1002   * @param options used to change max versions and TTL for the scanner being opened
1003   * @see #preFlushScannerOpen(ObserverContext, Store, ScanOptions, FlushLifeCycleTracker)
1004   * @see #preCompactScannerOpen(ObserverContext, Store, ScanType, ScanOptions,
1005   *      CompactionLifeCycleTracker, CompactionRequest)
1006   */
1007  default void preStoreScannerOpen(ObserverContext<RegionCoprocessorEnvironment> ctx, Store store,
1008      ScanOptions options) throws IOException {}
1009
1010  /**
1011   * Called before replaying WALs for this region.
1012   * Calling {@link org.apache.hadoop.hbase.coprocessor.ObserverContext#bypass()} has no
1013   * effect in this hook.
1014   * @param ctx the environment provided by the region server
1015   * @param info the RegionInfo for this region
1016   * @param edits the file of recovered edits
1017   */
1018  // todo: what about these?
1019  default void preReplayWALs(ObserverContext<? extends RegionCoprocessorEnvironment> ctx,
1020    RegionInfo info, Path edits) throws IOException {}
1021
1022  /**
1023   * Called after replaying WALs for this region.
1024   * @param ctx the environment provided by the region server
1025   * @param info the RegionInfo for this region
1026   * @param edits the file of recovered edits
1027   */
1028  default void postReplayWALs(ObserverContext<? extends RegionCoprocessorEnvironment> ctx,
1029    RegionInfo info, Path edits) throws IOException {}
1030
1031  /**
1032   * Called before a {@link WALEdit}
1033   * replayed for this region.
1034   * @param ctx the environment provided by the region server
1035   */
1036  default void preWALRestore(ObserverContext<? extends RegionCoprocessorEnvironment> ctx,
1037    RegionInfo info, WALKey logKey, WALEdit logEdit) throws IOException {}
1038
1039  /**
1040   * Called after a {@link WALEdit}
1041   * replayed for this region.
1042   * @param ctx the environment provided by the region server
1043   */
1044  default void postWALRestore(ObserverContext<? extends RegionCoprocessorEnvironment> ctx,
1045    RegionInfo info, WALKey logKey, WALEdit logEdit) throws IOException {}
1046
1047  /**
1048   * Called before bulkLoadHFile. Users can create a StoreFile instance to
1049   * access the contents of a HFile.
1050   *
1051   * @param ctx the environment provided by the region server
1052   * @param familyPaths pairs of { CF, HFile path } submitted for bulk load. Adding
1053   * or removing from this list will add or remove HFiles to be bulk loaded.
1054   */
1055  default void preBulkLoadHFile(ObserverContext<RegionCoprocessorEnvironment> ctx,
1056    List<Pair<byte[], String>> familyPaths) throws IOException {}
1057
1058  /**
1059   * Called before moving bulk loaded hfile to region directory.
1060   *
1061   * @param ctx the environment provided by the region server
1062   * @param family column family
1063   * @param pairs List of pairs of { HFile location in staging dir, HFile path in region dir }
1064   * Each pair are for the same hfile.
1065   */
1066  default void preCommitStoreFile(ObserverContext<RegionCoprocessorEnvironment> ctx, byte[] family,
1067      List<Pair<Path, Path>> pairs) throws IOException {}
1068
1069  /**
1070   * Called after moving bulk loaded hfile to region directory.
1071   *
1072   * @param ctx the environment provided by the region server
1073   * @param family column family
1074   * @param srcPath Path to file before the move
1075   * @param dstPath Path to file after the move
1076   */
1077  default void postCommitStoreFile(ObserverContext<RegionCoprocessorEnvironment> ctx, byte[] family,
1078      Path srcPath, Path dstPath) throws IOException {}
1079
1080  /**
1081   * Called after bulkLoadHFile.
1082   *
1083   * @param ctx the environment provided by the region server
1084   * @param stagingFamilyPaths pairs of { CF, HFile path } submitted for bulk load
1085   * @param finalPaths Map of CF to List of file paths for the loaded files
1086   *   if the Map is not null, the bulkLoad was successful. Otherwise the bulk load failed.
1087   *   bulkload is done by the time this hook is called.
1088   */
1089  default void postBulkLoadHFile(ObserverContext<RegionCoprocessorEnvironment> ctx,
1090      List<Pair<byte[], String>> stagingFamilyPaths, Map<byte[], List<Path>> finalPaths)
1091          throws IOException {
1092  }
1093
1094  /**
1095   * Called before creation of Reader for a store file.
1096   * Calling {@link org.apache.hadoop.hbase.coprocessor.ObserverContext#bypass()} has no
1097   * effect in this hook.
1098   *
1099   * @param ctx the environment provided by the region server
1100   * @param fs fileystem to read from
1101   * @param p path to the file
1102   * @param in {@link FSDataInputStreamWrapper}
1103   * @param size Full size of the file
1104   * @param cacheConf
1105   * @param r original reference file. This will be not null only when reading a split file.
1106   * @param reader the base reader, if not {@code null}, from previous RegionObserver in the chain
1107   * @return a Reader instance to use instead of the base reader if overriding
1108   * default behavior, null otherwise
1109   * @deprecated For Phoenix only, StoreFileReader is not a stable interface.
1110   */
1111  @Deprecated
1112  // Passing InterfaceAudience.Private args FSDataInputStreamWrapper, CacheConfig and Reference.
1113  // This is fine as the hook is deprecated any way.
1114  default StoreFileReader preStoreFileReaderOpen(ObserverContext<RegionCoprocessorEnvironment> ctx,
1115      FileSystem fs, Path p, FSDataInputStreamWrapper in, long size, CacheConfig cacheConf,
1116      Reference r, StoreFileReader reader) throws IOException {
1117    return reader;
1118  }
1119
1120  /**
1121   * Called after the creation of Reader for a store file.
1122   *
1123   * @param ctx the environment provided by the region server
1124   * @param fs fileystem to read from
1125   * @param p path to the file
1126   * @param in {@link FSDataInputStreamWrapper}
1127   * @param size Full size of the file
1128   * @param cacheConf
1129   * @param r original reference file. This will be not null only when reading a split file.
1130   * @param reader the base reader instance
1131   * @return The reader to use
1132   * @deprecated For Phoenix only, StoreFileReader is not a stable interface.
1133   */
1134  @Deprecated
1135  // Passing InterfaceAudience.Private args FSDataInputStreamWrapper, CacheConfig and Reference.
1136  // This is fine as the hook is deprecated any way.
1137  default StoreFileReader postStoreFileReaderOpen(ObserverContext<RegionCoprocessorEnvironment> ctx,
1138      FileSystem fs, Path p, FSDataInputStreamWrapper in, long size, CacheConfig cacheConf,
1139      Reference r, StoreFileReader reader) throws IOException {
1140    return reader;
1141  }
1142
1143  /**
1144   * Called after a new cell has been created during an increment operation, but before
1145   * it is committed to the WAL or memstore.
1146   * Calling {@link org.apache.hadoop.hbase.coprocessor.ObserverContext#bypass()} has no
1147   * effect in this hook.
1148   * @param ctx the environment provided by the region server
1149   * @param opType the operation type
1150   * @param mutation the current mutation
1151   * @param oldCell old cell containing previous value
1152   * @param newCell the new cell containing the computed value
1153   * @return the new cell, possibly changed
1154   * @deprecated since 2.2.0 and will be removedin 4.0.0. Use
1155   *   {@link #postIncrementBeforeWAL(ObserverContext, Mutation, List)} or
1156   *   {@link #postAppendBeforeWAL(ObserverContext, Mutation, List)} instead.
1157   * @see #postIncrementBeforeWAL(ObserverContext, Mutation, List)
1158   * @see #postAppendBeforeWAL(ObserverContext, Mutation, List)
1159   * @see <a href="https://issues.apache.org/jira/browse/HBASE-21643">HBASE-21643</a>
1160   */
1161  @Deprecated
1162  default Cell postMutationBeforeWAL(ObserverContext<RegionCoprocessorEnvironment> ctx,
1163      MutationType opType, Mutation mutation, Cell oldCell, Cell newCell) throws IOException {
1164    return newCell;
1165  }
1166
1167  /**
1168   * Called after a list of new cells has been created during an increment operation, but before
1169   * they are committed to the WAL or memstore.
1170   *
1171   * @param ctx       the environment provided by the region server
1172   * @param mutation  the current mutation
1173   * @param cellPairs a list of cell pair. The first cell is old cell which may be null.
1174   *                  And the second cell is the new cell.
1175   * @return a list of cell pair, possibly changed.
1176   */
1177  default List<Pair<Cell, Cell>> postIncrementBeforeWAL(
1178      ObserverContext<RegionCoprocessorEnvironment> ctx, Mutation mutation,
1179      List<Pair<Cell, Cell>> cellPairs) throws IOException {
1180    List<Pair<Cell, Cell>> resultPairs = new ArrayList<>(cellPairs.size());
1181    for (Pair<Cell, Cell> pair : cellPairs) {
1182      resultPairs.add(new Pair<>(pair.getFirst(),
1183          postMutationBeforeWAL(ctx, MutationType.INCREMENT, mutation, pair.getFirst(),
1184              pair.getSecond())));
1185    }
1186    return resultPairs;
1187  }
1188
1189  /**
1190   * Called after a list of new cells has been created during an append operation, but before
1191   * they are committed to the WAL or memstore.
1192   *
1193   * @param ctx       the environment provided by the region server
1194   * @param mutation  the current mutation
1195   * @param cellPairs a list of cell pair. The first cell is old cell which may be null.
1196   *                  And the second cell is the new cell.
1197   * @return a list of cell pair, possibly changed.
1198   */
1199  default List<Pair<Cell, Cell>> postAppendBeforeWAL(
1200      ObserverContext<RegionCoprocessorEnvironment> ctx, Mutation mutation,
1201      List<Pair<Cell, Cell>> cellPairs) throws IOException {
1202    List<Pair<Cell, Cell>> resultPairs = new ArrayList<>(cellPairs.size());
1203    for (Pair<Cell, Cell> pair : cellPairs) {
1204      resultPairs.add(new Pair<>(pair.getFirst(),
1205          postMutationBeforeWAL(ctx, MutationType.INCREMENT, mutation, pair.getFirst(),
1206              pair.getSecond())));
1207    }
1208    return resultPairs;
1209  }
1210
1211  /**
1212   * Called after the ScanQueryMatcher creates ScanDeleteTracker. Implementing
1213   * this hook would help in creating customised DeleteTracker and returning
1214   * the newly created DeleteTracker
1215   * <p>
1216   * Warn: This is used by internal coprocessors. Should not be implemented by user coprocessors
1217   * @param ctx the environment provided by the region server
1218   * @param delTracker the deleteTracker that is created by the QueryMatcher
1219   * @return the Delete Tracker
1220   * @deprecated Since 2.0 with out any replacement and will be removed in 3.0
1221   */
1222  @Deprecated
1223  default DeleteTracker postInstantiateDeleteTracker(
1224      ObserverContext<RegionCoprocessorEnvironment> ctx, DeleteTracker delTracker)
1225      throws IOException {
1226    return delTracker;
1227  }
1228
1229  /**
1230   * Called just before the WAL Entry is appended to the WAL. Implementing this hook allows
1231   * coprocessors to add extended attributes to the WALKey that then get persisted to the
1232   * WAL, and are available to replication endpoints to use in processing WAL Entries.
1233   * @param ctx the environment provided by the region server
1234   * @param key the WALKey associated with a particular append to a WAL
1235   */
1236  default void preWALAppend(ObserverContext<RegionCoprocessorEnvironment> ctx, WALKey key,
1237                            WALEdit edit)
1238    throws IOException {
1239  }
1240}