001/**
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements.  See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership.  The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License.  You may obtain a copy of the License at
010 *
011 *     http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 */
019package org.apache.hadoop.hbase.client;
020
021import java.io.Closeable;
022import java.io.IOException;
023import java.util.Collections;
024import java.util.List;
025import java.util.Map;
026import java.util.TreeMap;
027import java.util.concurrent.TimeUnit;
028import org.apache.commons.lang3.NotImplementedException;
029import org.apache.hadoop.conf.Configuration;
030import org.apache.hadoop.hbase.Cell;
031import org.apache.hadoop.hbase.CompareOperator;
032import org.apache.hadoop.hbase.TableName;
033import org.apache.hadoop.hbase.client.coprocessor.Batch;
034import org.apache.hadoop.hbase.client.coprocessor.Batch.Callback;
035import org.apache.hadoop.hbase.filter.Filter;
036import org.apache.hadoop.hbase.io.TimeRange;
037import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel;
038import org.apache.hadoop.hbase.util.Bytes;
039import org.apache.yetus.audience.InterfaceAudience;
040
041import org.apache.hbase.thirdparty.com.google.protobuf.Descriptors;
042import org.apache.hbase.thirdparty.com.google.protobuf.Message;
043import org.apache.hbase.thirdparty.com.google.protobuf.Service;
044import org.apache.hbase.thirdparty.com.google.protobuf.ServiceException;
045
046/**
047 * Used to communicate with a single HBase table.
048 * Obtain an instance from a {@link Connection} and call {@link #close()} afterwards.
049 *
050 * <p><code>Table</code> can be used to get, put, delete or scan data from a table.
051 * @see ConnectionFactory
052 * @see Connection
053 * @see Admin
054 * @see RegionLocator
055 * @since 0.99.0
056 */
057@InterfaceAudience.Public
058public interface Table extends Closeable {
059  /**
060   * Gets the fully qualified table name instance of this table.
061   */
062  TableName getName();
063
064  /**
065   * Returns the {@link org.apache.hadoop.conf.Configuration} object used by this instance.
066   * <p>
067   * The reference returned is not a copy, so any change made to it will
068   * affect this instance.
069   */
070  Configuration getConfiguration();
071
072  /**
073   * Gets the {@link org.apache.hadoop.hbase.client.TableDescriptor table descriptor} for this table.
074   * @throws java.io.IOException if a remote or network exception occurs.
075   */
076  TableDescriptor getDescriptor() throws IOException;
077
078  /**
079   * Gets the {@link RegionLocator} for this table.
080   */
081  RegionLocator getRegionLocator() throws IOException;
082
083  /**
084   * Test for the existence of columns in the table, as specified by the Get.
085   * <p>
086   *
087   * This will return true if the Get matches one or more keys, false if not.
088   * <p>
089   *
090   * This is a server-side call so it prevents any data from being transfered to
091   * the client.
092   *
093   * @param get the Get
094   * @return true if the specified Get matches one or more keys, false if not
095   * @throws IOException e
096   */
097  default boolean exists(Get get) throws IOException {
098    return exists(Collections.singletonList(get))[0];
099  }
100
101  /**
102   * Test for the existence of columns in the table, as specified by the Gets.
103   * <p>
104   *
105   * This will return an array of booleans. Each value will be true if the related Get matches
106   * one or more keys, false if not.
107   * <p>
108   *
109   * This is a server-side call so it prevents any data from being transferred to
110   * the client.
111   *
112   * @param gets the Gets
113   * @return Array of boolean.  True if the specified Get matches one or more keys, false if not.
114   * @throws IOException e
115   */
116  default boolean[] exists(List<Get> gets) throws IOException {
117    throw new NotImplementedException("Add an implementation!");
118  }
119
120  /**
121   * Method that does a batch call on Deletes, Gets, Puts, Increments, Appends, RowMutations.
122   * The ordering of execution of the actions is not defined. Meaning if you do a Put and a
123   * Get in the same {@link #batch} call, you will not necessarily be
124   * guaranteed that the Get returns what the Put had put.
125   *
126   * @param actions list of Get, Put, Delete, Increment, Append, RowMutations.
127   * @param results Empty Object[], same size as actions. Provides access to partial
128   *                results, in case an exception is thrown. A null in the result array means that
129   *                the call for that action failed, even after retries. The order of the objects
130   *                in the results array corresponds to the order of actions in the request list.
131   * @throws IOException
132   * @since 0.90.0
133   */
134  default void batch(final List<? extends Row> actions, final Object[] results) throws IOException,
135    InterruptedException {
136    throw new NotImplementedException("Add an implementation!");
137  }
138
139  /**
140   * Same as {@link #batch(List, Object[])}, but with a callback.
141   * @since 0.96.0
142   * @deprecated since 3.0.0, will removed in 4.0.0. Please use the batch related methods in
143   *             {@link AsyncTable} directly if you want to use callback. We reuse the callback for
144   *             coprocessor here, and the problem is that for batch operation, the
145   *             {@link AsyncTable} does not tell us the region, so in this method we need an extra
146   *             locating after we get the result, which is not good.
147   */
148  @Deprecated
149  default <R> void batchCallback(final List<? extends Row> actions, final Object[] results,
150      final Batch.Callback<R> callback) throws IOException, InterruptedException {
151    throw new NotImplementedException("Add an implementation!");
152  }
153
154  /**
155   * Extracts certain cells from a given row.
156   * @param get The object that specifies what data to fetch and from which row.
157   * @return The data coming from the specified row, if it exists.  If the row
158   *   specified doesn't exist, the {@link Result} instance returned won't
159   *   contain any {@link org.apache.hadoop.hbase.KeyValue}, as indicated by
160   *   {@link Result#isEmpty()}.
161   * @throws IOException if a remote or network exception occurs.
162   * @since 0.20.0
163   */
164  default Result get(Get get) throws IOException {
165    return get(Collections.singletonList(get))[0];
166  }
167
168  /**
169   * Extracts specified cells from the given rows, as a batch.
170   *
171   * @param gets The objects that specify what data to fetch and from which rows.
172   * @return The data coming from the specified rows, if it exists.  If the row specified doesn't
173   *   exist, the {@link Result} instance returned won't contain any
174   *   {@link org.apache.hadoop.hbase.Cell}s, as indicated by {@link Result#isEmpty()}. If there
175   *   are any failures even after retries, there will be a <code>null</code> in the results' array
176   *   for  those Gets, AND an exception will be thrown. The ordering of the Result array
177   *   corresponds to  the order of the list of passed in Gets.
178   * @throws IOException if a remote or network exception occurs.
179   * @since 0.90.0
180   * @apiNote {@link #put(List)} runs pre-flight validations on the input list on client.
181   *          Currently {@link #get(List)} doesn't run any validations on the client-side,
182   *          currently there is no need, but this may change in the future. An
183   *          {@link IllegalArgumentException} will be thrown in this case.
184   */
185  default Result[] get(List<Get> gets) throws IOException {
186    throw new NotImplementedException("Add an implementation!");
187  }
188
189  /**
190   * Returns a scanner on the current table as specified by the {@link Scan}
191   * object.
192   * Note that the passed {@link Scan}'s start row and caching properties
193   * maybe changed.
194   *
195   * @param scan A configured {@link Scan} object.
196   * @return A scanner.
197   * @throws IOException if a remote or network exception occurs.
198   * @since 0.20.0
199   */
200  default ResultScanner getScanner(Scan scan) throws IOException {
201    throw new NotImplementedException("Add an implementation!");
202  }
203
204  /**
205   * Gets a scanner on the current table for the given family.
206   *
207   * @param family The column family to scan.
208   * @return A scanner.
209   * @throws IOException if a remote or network exception occurs.
210   * @since 0.20.0
211   */
212  default ResultScanner getScanner(byte[] family) throws IOException {
213    throw new NotImplementedException("Add an implementation!");
214  }
215
216  /**
217   * Gets a scanner on the current table for the given family and qualifier.
218   *
219   * @param family The column family to scan.
220   * @param qualifier The column qualifier to scan.
221   * @return A scanner.
222   * @throws IOException if a remote or network exception occurs.
223   * @since 0.20.0
224   */
225  default ResultScanner getScanner(byte[] family, byte[] qualifier) throws IOException {
226    throw new NotImplementedException("Add an implementation!");
227  }
228
229  /**
230   * Puts some data in the table.
231   *
232   * @param put The data to put.
233   * @throws IOException if a remote or network exception occurs.
234   * @since 0.20.0
235   */
236  default void put(Put put) throws IOException {
237    put(Collections.singletonList(put));
238  }
239
240  /**
241   * Batch puts the specified data into the table.
242   * <p>
243   * This can be used for group commit, or for submitting user defined batches. Before sending
244   * a batch of mutations to the server, the client runs a few validations on the input list. If an
245   * error is found, for example, a mutation was supplied but was missing it's column an
246   * {@link IllegalArgumentException} will be thrown and no mutations will be applied. If there
247   * are any failures even after retries, a {@link RetriesExhaustedWithDetailsException} will be
248   * thrown. RetriesExhaustedWithDetailsException contains lists of failed mutations and
249   * corresponding remote exceptions. The ordering of mutations and exceptions in the
250   * encapsulating exception corresponds to the order of the input list of Put requests.
251   *
252   * @param puts The list of mutations to apply.
253   * @throws IOException if a remote or network exception occurs.
254   * @since 0.20.0
255   */
256  default void put(List<Put> puts) throws IOException {
257    throw new NotImplementedException("Add an implementation!");
258  }
259
260  /**
261   * Deletes the specified cells/row.
262   *
263   * @param delete The object that specifies what to delete.
264   * @throws IOException if a remote or network exception occurs.
265   * @since 0.20.0
266   */
267  default void delete(Delete delete) throws IOException {
268    throw new NotImplementedException("Add an implementation!");
269  }
270
271  /**
272   * Batch Deletes the specified cells/rows from the table.
273   * <p>
274   * If a specified row does not exist, {@link Delete} will report as though sucessful
275   * delete; no exception will be thrown. If there are any failures even after retries,
276   * a {@link RetriesExhaustedWithDetailsException} will be thrown.
277   * RetriesExhaustedWithDetailsException contains lists of failed {@link Delete}s and
278   * corresponding remote exceptions.
279   *
280   * @param deletes List of things to delete. The input list gets modified by this
281   * method. All successfully applied {@link Delete}s in the list are removed (in particular it
282   * gets re-ordered, so the order in which the elements are inserted in the list gives no
283   * guarantee as to the order in which the {@link Delete}s are executed).
284   * @throws IOException if a remote or network exception occurs. In that case
285   * the {@code deletes} argument will contain the {@link Delete} instances
286   * that have not be successfully applied.
287   * @since 0.20.1
288   * @apiNote In 3.0.0 version, the input list {@code deletes} will no longer be modified. Also,
289   *          {@link #put(List)} runs pre-flight validations on the input list on client. Currently
290   *          {@link #delete(List)} doesn't run validations on the client, there is no need
291   *          currently, but this may change in the future. An * {@link IllegalArgumentException}
292   *          will be thrown in this case.
293   */
294  default void delete(List<Delete> deletes) throws IOException {
295    throw new NotImplementedException("Add an implementation!");
296  }
297
298  /**
299   * Atomically checks if a row/family/qualifier value matches the expected value. If it does, it
300   * adds the Put/Delete/RowMutations.
301   * <p>
302   * Use the returned {@link CheckAndMutateBuilder} to construct your request and then execute it.
303   * This is a fluent style API, the code is like:
304   *
305   * <pre>
306   * <code>
307   * table.checkAndMutate(row, family).qualifier(qualifier).ifNotExists().thenPut(put);
308   * </code>
309   * </pre>
310   *
311   * @deprecated Since 3.0.0, will be removed in 4.0.0. For internal test use only, do not use it
312   *   any more.
313   */
314  @Deprecated
315  default CheckAndMutateBuilder checkAndMutate(byte[] row, byte[] family) {
316    throw new NotImplementedException("Add an implementation!");
317  }
318
319  /**
320   * A helper class for sending checkAndMutate request.
321   *
322   * @deprecated Since 3.0.0, will be removed in 4.0.0. For internal test use only, do not use it
323   *   any more.
324   */
325  @Deprecated
326  interface CheckAndMutateBuilder {
327
328    /**
329     * @param qualifier column qualifier to check.
330     */
331    CheckAndMutateBuilder qualifier(byte[] qualifier);
332
333    /**
334     * @param timeRange timeRange to check
335     */
336    CheckAndMutateBuilder timeRange(TimeRange timeRange);
337
338    /**
339     * Check for lack of column.
340     */
341    CheckAndMutateBuilder ifNotExists();
342
343    /**
344     * Check for equality.
345     * @param value the expected value
346     */
347    default CheckAndMutateBuilder ifEquals(byte[] value) {
348      return ifMatches(CompareOperator.EQUAL, value);
349    }
350
351    /**
352     * @param compareOp comparison operator to use
353     * @param value the expected value
354     */
355    CheckAndMutateBuilder ifMatches(CompareOperator compareOp, byte[] value);
356
357    /**
358     * @param put data to put if check succeeds
359     * @return {@code true} if the new put was executed, {@code false} otherwise.
360     */
361    boolean thenPut(Put put) throws IOException;
362
363    /**
364     * @param delete data to delete if check succeeds
365     * @return {@code true} if the new delete was executed, {@code false} otherwise.
366     */
367    boolean thenDelete(Delete delete) throws IOException;
368
369    /**
370     * @param mutation mutations to perform if check succeeds
371     * @return true if the new mutation was executed, false otherwise.
372     */
373    boolean thenMutate(RowMutations mutation) throws IOException;
374  }
375
376  /**
377   * Atomically checks if a row matches the specified filter. If it does, it adds the
378   * Put/Delete/RowMutations.
379   * <p>
380   * Use the returned {@link CheckAndMutateWithFilterBuilder} to construct your request and then
381   * execute it. This is a fluent style API, the code is like:
382   *
383   * <pre>
384   * <code>
385   * table.checkAndMutate(row, filter).thenPut(put);
386   * </code>
387   * </pre>
388   *
389   * @deprecated Since 3.0.0, will be removed in 4.0.0. For internal test use only, do not use it
390   *   any more.
391   */
392  @Deprecated
393  default CheckAndMutateWithFilterBuilder checkAndMutate(byte[] row, Filter filter) {
394    throw new NotImplementedException("Add an implementation!");
395  }
396
397  /**
398   * A helper class for sending checkAndMutate request with a filter.
399   *
400   * @deprecated Since 3.0.0, will be removed in 4.0.0. For internal test use only, do not use it
401   *   any more.
402   */
403  @Deprecated
404  interface CheckAndMutateWithFilterBuilder {
405
406    /**
407     * @param timeRange timeRange to check
408     */
409    CheckAndMutateWithFilterBuilder timeRange(TimeRange timeRange);
410
411    /**
412     * @param put data to put if check succeeds
413     * @return {@code true} if the new put was executed, {@code false} otherwise.
414     */
415    boolean thenPut(Put put) throws IOException;
416
417    /**
418     * @param delete data to delete if check succeeds
419     * @return {@code true} if the new delete was executed, {@code false} otherwise.
420     */
421    boolean thenDelete(Delete delete) throws IOException;
422
423    /**
424     * @param mutation mutations to perform if check succeeds
425     * @return true if the new mutation was executed, false otherwise.
426     */
427    boolean thenMutate(RowMutations mutation) throws IOException;
428  }
429
430  /**
431   * checkAndMutate that atomically checks if a row matches the specified condition. If it does,
432   * it performs the specified action.
433   *
434   * @param checkAndMutate The CheckAndMutate object.
435   * @return A CheckAndMutateResult object that represents the result for the CheckAndMutate.
436   * @throws IOException if a remote or network exception occurs.
437   */
438  default CheckAndMutateResult checkAndMutate(CheckAndMutate checkAndMutate) throws IOException {
439    return checkAndMutate(Collections.singletonList(checkAndMutate)).get(0);
440  }
441
442  /**
443   * Batch version of checkAndMutate. The specified CheckAndMutates are batched only in the sense
444   * that they are sent to a RS in one RPC, but each CheckAndMutate operation is still executed
445   * atomically (and thus, each may fail independently of others).
446   *
447   * @param checkAndMutates The list of CheckAndMutate.
448   * @return A list of CheckAndMutateResult objects that represents the result for each
449   *   CheckAndMutate.
450   * @throws IOException if a remote or network exception occurs.
451   */
452  default List<CheckAndMutateResult> checkAndMutate(List<CheckAndMutate> checkAndMutates)
453    throws IOException {
454    throw new NotImplementedException("Add an implementation!");
455  }
456
457  /**
458   * Performs multiple mutations atomically on a single row. Currently
459   * {@link Put} and {@link Delete} are supported.
460   *
461   * @param rm object that specifies the set of mutations to perform atomically
462   * @throws IOException
463   */
464  default void mutateRow(final RowMutations rm) throws IOException {
465    throw new NotImplementedException("Add an implementation!");
466  }
467
468  /**
469   * Appends values to one or more columns within a single row.
470   * <p>
471   * This operation guaranteed atomicity to readers. Appends are done
472   * under a single row lock, so write operations to a row are synchronized, and
473   * readers are guaranteed to see this operation fully completed.
474   *
475   * @param append object that specifies the columns and values to be appended
476   * @throws IOException e
477   * @return values of columns after the append operation (maybe null)
478   */
479  default Result append(final Append append) throws IOException {
480    throw new NotImplementedException("Add an implementation!");
481  }
482
483  /**
484   * Increments one or more columns within a single row.
485   * <p>
486   * This operation ensures atomicity to readers. Increments are done
487   * under a single row lock, so write operations to a row are synchronized, and
488   * readers are guaranteed to see this operation fully completed.
489   *
490   * @param increment object that specifies the columns and amounts to be used
491   *                  for the increment operations
492   * @throws IOException e
493   * @return values of columns after the increment
494   */
495  default Result increment(final Increment increment) throws IOException {
496    throw new NotImplementedException("Add an implementation!");
497  }
498
499  /**
500   * See {@link #incrementColumnValue(byte[], byte[], byte[], long, Durability)}
501   * <p>
502   * The {@link Durability} is defaulted to {@link Durability#SYNC_WAL}.
503   * @param row The row that contains the cell to increment.
504   * @param family The column family of the cell to increment.
505   * @param qualifier The column qualifier of the cell to increment.
506   * @param amount The amount to increment the cell with (or decrement, if the
507   * amount is negative).
508   * @return The new value, post increment.
509   * @throws IOException if a remote or network exception occurs.
510   */
511  default long incrementColumnValue(byte[] row, byte[] family, byte[] qualifier, long amount)
512      throws IOException {
513    Increment increment = new Increment(row).addColumn(family, qualifier, amount);
514    Cell cell = increment(increment).getColumnLatestCell(family, qualifier);
515    return Bytes.toLong(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());
516  }
517
518  /**
519   * Atomically increments a column value. If the column value already exists
520   * and is not a big-endian long, this could throw an exception. If the column
521   * value does not yet exist it is initialized to <code>amount</code> and
522   * written to the specified column.
523   *
524   * <p>Setting durability to {@link Durability#SKIP_WAL} means that in a fail
525   * scenario you will lose any increments that have not been flushed.
526   * @param row The row that contains the cell to increment.
527   * @param family The column family of the cell to increment.
528   * @param qualifier The column qualifier of the cell to increment.
529   * @param amount The amount to increment the cell with (or decrement, if the
530   * amount is negative).
531   * @param durability The persistence guarantee for this increment.
532   * @return The new value, post increment.
533   * @throws IOException if a remote or network exception occurs.
534   */
535  default long incrementColumnValue(byte[] row, byte[] family, byte[] qualifier,
536    long amount, Durability durability) throws IOException {
537    Increment increment = new Increment(row)
538        .addColumn(family, qualifier, amount)
539        .setDurability(durability);
540    Cell cell = increment(increment).getColumnLatestCell(family, qualifier);
541    return Bytes.toLong(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());
542  }
543
544  /**
545   * Releases any resources held or pending changes in internal buffers.
546   *
547   * @throws IOException if a remote or network exception occurs.
548   */
549  @Override
550  default void close() throws IOException {
551    throw new NotImplementedException("Add an implementation!");
552  }
553
554  /**
555   * Creates and returns a {@link org.apache.hbase.thirdparty.com.google.protobuf.RpcChannel}
556   * instance connected to the table region containing the specified row. The row given does not
557   * actually have to exist. Whichever region would contain the row based on start and end keys will
558   * be used. Note that the {@code row} parameter is also not passed to the coprocessor handler
559   * registered for this protocol, unless the {@code row} is separately passed as an argument in the
560   * service request. The parameter here is only used to locate the region used to handle the call.
561   * <p/>
562   * The obtained {@link org.apache.hbase.thirdparty.com.google.protobuf.RpcChannel} instance can be
563   * used to access a published coprocessor {@link Service} using standard protobuf service
564   * invocations:
565   * <p/>
566   * <div style="background-color: #cccccc; padding: 2px"> <blockquote>
567   * <pre>
568   * CoprocessorRpcChannel channel = myTable.coprocessorService(rowkey);
569   * MyService.BlockingInterface service = MyService.newBlockingStub(channel);
570   * MyCallRequest request = MyCallRequest.newBuilder()
571   *     ...
572   *     .build();
573   * MyCallResponse response = service.myCall(null, request);
574   * </pre>
575   * </blockquote>
576   * </div>
577   * @param row The row key used to identify the remote region location
578   * @return A CoprocessorRpcChannel instance
579   * @deprecated since 3.0.0, will removed in 4.0.0. This is too low level, please stop using it any
580   *             more. Use the coprocessorService methods in {@link AsyncTable} instead.
581   * @see Connection#toAsyncConnection()
582   */
583  @Deprecated
584  default CoprocessorRpcChannel coprocessorService(byte[] row) {
585    throw new NotImplementedException("Add an implementation!");
586  }
587
588  /**
589   * Creates an instance of the given {@link Service} subclass for each table region spanning the
590   * range from the {@code startKey} row to {@code endKey} row (inclusive), and invokes the passed
591   * {@link org.apache.hadoop.hbase.client.coprocessor.Batch.Call#call} method with each
592   * {@link Service} instance.
593   * @param service the protocol buffer {@code Service} implementation to call
594   * @param startKey start region selection with region containing this row. If {@code null}, the
595   *          selection will start with the first table region.
596   * @param endKey select regions up to and including the region containing this row. If
597   *          {@code null}, selection will continue through the last table region.
598   * @param callable this instance's
599   *          {@link org.apache.hadoop.hbase.client.coprocessor.Batch.Call#call} method will be
600   *          invoked once per table region, using the {@link Service} instance connected to that
601   *          region.
602   * @param <T> the {@link Service} subclass to connect to
603   * @param <R> Return type for the {@code callable} parameter's
604   *          {@link org.apache.hadoop.hbase.client.coprocessor.Batch.Call#call} method
605   * @return a map of result values keyed by region name
606   * @deprecated since 3.0.0, will removed in 4.0.0. The batch call here references the blocking
607   *             interface for of a protobuf stub, so it is not possible to do it in an asynchronous
608   *             way, even if now we are building the {@link Table} implementation based on the
609   *             {@link AsyncTable}, which is not good. Use the coprocessorService methods in
610   *             {@link AsyncTable} directly instead.
611   * @see Connection#toAsyncConnection()
612   */
613  @Deprecated
614  default <T extends Service, R> Map<byte[], R> coprocessorService(final Class<T> service,
615      byte[] startKey, byte[] endKey, final Batch.Call<T, R> callable)
616      throws ServiceException, Throwable {
617    Map<byte[], R> results =
618      Collections.synchronizedMap(new TreeMap<byte[], R>(Bytes.BYTES_COMPARATOR));
619    coprocessorService(service, startKey, endKey, callable, new Batch.Callback<R>() {
620      @Override
621      public void update(byte[] region, byte[] row, R value) {
622        if (region != null) {
623          results.put(region, value);
624        }
625      }
626    });
627    return results;
628  }
629
630  /**
631   * Creates an instance of the given {@link Service} subclass for each table region spanning the
632   * range from the {@code startKey} row to {@code endKey} row (inclusive), and invokes the passed
633   * {@link org.apache.hadoop.hbase.client.coprocessor.Batch.Call#call} method with each
634   * {@link Service} instance.
635   * <p/>
636   * The given
637   * {@link org.apache.hadoop.hbase.client.coprocessor.Batch.Callback#update(byte[],byte[],Object)}
638   * method will be called with the return value from each region's
639   * {@link org.apache.hadoop.hbase.client.coprocessor.Batch.Call#call} invocation.
640   * @param service the protocol buffer {@code Service} implementation to call
641   * @param startKey start region selection with region containing this row. If {@code null}, the
642   *          selection will start with the first table region.
643   * @param endKey select regions up to and including the region containing this row. If
644   *          {@code null}, selection will continue through the last table region.
645   * @param callable this instance's
646   *          {@link org.apache.hadoop.hbase.client.coprocessor.Batch.Call#call} method will be
647   *          invoked once per table region, using the {@link Service} instance connected to that
648   *          region.
649   * @param <T> the {@link Service} subclass to connect to
650   * @param <R> Return type for the {@code callable} parameter's
651   *          {@link org.apache.hadoop.hbase.client.coprocessor.Batch.Call#call} method
652   * @deprecated since 3.0.0, will removed in 4.0.0. The batch call here references the blocking
653   *             interface for of a protobuf stub, so it is not possible to do it in an asynchronous
654   *             way, even if now we are building the {@link Table} implementation based on the
655   *             {@link AsyncTable}, which is not good. Use the coprocessorService methods in
656   *             {@link AsyncTable} directly instead.
657   * @see Connection#toAsyncConnection()
658   */
659  @Deprecated
660  default <T extends Service, R> void coprocessorService(final Class<T> service, byte[] startKey,
661      byte[] endKey, final Batch.Call<T, R> callable, final Batch.Callback<R> callback)
662      throws ServiceException, Throwable {
663    throw new NotImplementedException("Add an implementation!");
664  }
665
666  /**
667   * Creates an instance of the given {@link Service} subclass for each table region spanning the
668   * range from the {@code startKey} row to {@code endKey} row (inclusive), all the invocations to
669   * the same region server will be batched into one call. The coprocessor service is invoked
670   * according to the service instance, method name and parameters.
671   * @param methodDescriptor the descriptor for the protobuf service method to call.
672   * @param request the method call parameters
673   * @param startKey start region selection with region containing this row. If {@code null}, the
674   *          selection will start with the first table region.
675   * @param endKey select regions up to and including the region containing this row. If
676   *          {@code null}, selection will continue through the last table region.
677   * @param responsePrototype the proto type of the response of the method in Service.
678   * @param <R> the response type for the coprocessor Service method
679   * @return a map of result values keyed by region name
680   * @deprecated since 3.0.0, will removed in 4.0.0. The batch call here references the blocking
681   *             interface for of a protobuf stub, so it is not possible to do it in an asynchronous
682   *             way, even if now we are building the {@link Table} implementation based on the
683   *             {@link AsyncTable}, which is not good. Use the coprocessorService methods in
684   *             {@link AsyncTable} directly instead.
685   * @see Connection#toAsyncConnection()
686   */
687  @Deprecated
688  default <R extends Message> Map<byte[], R> batchCoprocessorService(
689      Descriptors.MethodDescriptor methodDescriptor, Message request, byte[] startKey,
690      byte[] endKey, R responsePrototype) throws ServiceException, Throwable {
691    final Map<byte[], R> results =
692      Collections.synchronizedMap(new TreeMap<byte[], R>(Bytes.BYTES_COMPARATOR));
693    batchCoprocessorService(methodDescriptor, request, startKey, endKey, responsePrototype,
694      new Callback<R>() {
695        @Override
696        public void update(byte[] region, byte[] row, R result) {
697          if (region != null) {
698            results.put(region, result);
699          }
700        }
701      });
702    return results;
703  }
704
705  /**
706   * Creates an instance of the given {@link Service} subclass for each table region spanning the
707   * range from the {@code startKey} row to {@code endKey} row (inclusive), all the invocations to
708   * the same region server will be batched into one call. The coprocessor service is invoked
709   * according to the service instance, method name and parameters.
710   * <p/>
711   * The given
712   * {@link org.apache.hadoop.hbase.client.coprocessor.Batch.Callback#update(byte[],byte[],Object)}
713   * method will be called with the return value from each region's invocation.
714   * @param methodDescriptor the descriptor for the protobuf service method to call.
715   * @param request the method call parameters
716   * @param startKey start region selection with region containing this row. If {@code null}, the
717   *          selection will start with the first table region.
718   * @param endKey select regions up to and including the region containing this row. If
719   *          {@code null}, selection will continue through the last table region.
720   * @param responsePrototype the proto type of the response of the method in Service.
721   * @param callback callback to invoke with the response for each region
722   * @param <R> the response type for the coprocessor Service method
723   * @deprecated since 3.0.0, will removed in 4.0.0. The batch call here references the blocking
724   *             interface for of a protobuf stub, so it is not possible to do it in an asynchronous
725   *             way, even if now we are building the {@link Table} implementation based on the
726   *             {@link AsyncTable}, which is not good. Use the coprocessorService methods in
727   *             {@link AsyncTable} directly instead.
728   * @see Connection#toAsyncConnection()
729   */
730  @Deprecated
731  default <R extends Message> void batchCoprocessorService(
732      Descriptors.MethodDescriptor methodDescriptor, Message request, byte[] startKey,
733      byte[] endKey, R responsePrototype, Batch.Callback<R> callback)
734      throws ServiceException, Throwable {
735    throw new NotImplementedException("Add an implementation!");
736  }
737
738  /**
739   * Get timeout of each rpc request in this Table instance. It will be overridden by a more
740   * specific rpc timeout config such as readRpcTimeout or writeRpcTimeout.
741   * @see #getReadRpcTimeout(TimeUnit)
742   * @see #getWriteRpcTimeout(TimeUnit)
743   * @param unit the unit of time the timeout to be represented in
744   * @return rpc timeout in the specified time unit
745   */
746  default long getRpcTimeout(TimeUnit unit) {
747    throw new NotImplementedException("Add an implementation!");
748  }
749
750  /**
751   * Get timeout of each rpc read request in this Table instance.
752   * @param unit the unit of time the timeout to be represented in
753   * @return read rpc timeout in the specified time unit
754   */
755  default long getReadRpcTimeout(TimeUnit unit) {
756    throw new NotImplementedException("Add an implementation!");
757  }
758
759  /**
760   * Get timeout of each rpc write request in this Table instance.
761   * @param unit the unit of time the timeout to be represented in
762   * @return write rpc timeout in the specified time unit
763   */
764  default long getWriteRpcTimeout(TimeUnit unit) {
765    throw new NotImplementedException("Add an implementation!");
766  }
767
768  /**
769   * Get timeout of each operation in Table instance.
770   * @param unit the unit of time the timeout to be represented in
771   * @return operation rpc timeout in the specified time unit
772   */
773  default long getOperationTimeout(TimeUnit unit) {
774    throw new NotImplementedException("Add an implementation!");
775  }
776}