Google Cloud Bigtable C++ Client  1.35.0
A C++ Client Library for Google Cloud Bigtable
table.h
Go to the documentation of this file.
1 // Copyright 2017 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_BIGTABLE_TABLE_H
16 #define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_BIGTABLE_TABLE_H
17 
18 #include "google/cloud/bigtable/async_row_reader.h"
19 #include "google/cloud/bigtable/completion_queue.h"
20 #include "google/cloud/bigtable/data_client.h"
21 #include "google/cloud/bigtable/filters.h"
22 #include "google/cloud/bigtable/idempotent_mutation_policy.h"
23 #include "google/cloud/bigtable/mutations.h"
24 #include "google/cloud/bigtable/read_modify_write_rule.h"
25 #include "google/cloud/bigtable/row_key_sample.h"
26 #include "google/cloud/bigtable/row_reader.h"
27 #include "google/cloud/bigtable/row_set.h"
28 #include "google/cloud/bigtable/rpc_backoff_policy.h"
29 #include "google/cloud/bigtable/rpc_retry_policy.h"
30 #include "google/cloud/bigtable/version.h"
31 #include "google/cloud/future.h"
32 #include "google/cloud/grpc_error_delegate.h"
33 #include "google/cloud/status.h"
34 #include "google/cloud/status_or.h"
35 #include "absl/meta/type_traits.h"
36 #include <string>
37 #include <vector>
38 
39 namespace google {
40 namespace cloud {
41 namespace bigtable {
43 /// The branch taken by a Table::CheckAndMutateRow operation.
44 enum class MutationBranch {
45  /// The predicate provided to CheckAndMutateRow did not match and the
46  /// `false_mutations` (if any) were applied.
48  /// The predicate provided to CheckAndMutateRow matched and the
49  /// `true_mutations` (if any) were applied.
51 };
52 
53 class MutationBatcher;
54 
55 /**
56  * Return the full table name.
57  *
58  * The full table name is:
59  *
60  * `projects/<PROJECT_ID>/instances/<INSTANCE_ID>/tables/<table_id>`
61  *
62  * Where the project id and instance id come from the @p client parameter.
63  */
64 inline std::string TableName(std::shared_ptr<DataClient> const& client,
65  std::string const& table_id) {
66  return InstanceName(client) + "/tables/" + table_id;
67 }
68 
69 /**
70  * The main interface to interact with data in a Cloud Bigtable table.
71  *
72  * This class provides member functions to:
73  * - read specific rows: `Table::ReadRow()`
74  * - scan a ranges of rows: `Table::ReadRows()`
75  * - update or create a single row: `Table::Apply()`
76  * - update or modify multiple rows: `Table::BulkApply()`
77  * - update a row based on previous values: `Table::CheckAndMutateRow()`
78  * - to atomically append data and/or increment multiple values in a row:
79  * `Table::ReadModifyWriteRow()`
80  * - to sample the row keys: `Table::SampleRows()`.
81  *
82  * The class deals with the most common transient failures, and retries the
83  * underlying RPC calls subject to the policies configured by the application.
84  * These policies are documented in `Table::Table()`.
85  *
86  * @par Thread-safety
87  * Instances of this class created via copy-construction or copy-assignment
88  * share the underlying pool of connections. Access to these copies via multiple
89  * threads is guaranteed to work. Two threads operating concurrently on the same
90  * instance of this class is not guaranteed to work.
91  *
92  * @par Cost
93  * Creating a new object of type `Table` is comparable to creating a few objects
94  * of type `std::string` or a few objects of type `std::shared_ptr<int>`. The
95  * class represents a shallow handle to a remote object.
96  *
97  * @par Error Handling
98  * This class uses `StatusOr<T>` to report errors. When an operation fails to
99  * perform its work the returned `StatusOr<T>` contains the error details. If
100  * the `ok()` member function in the `StatusOr<T>` returns `true` then it
101  * contains the expected result. Operations that do not return a value simply
102  * return a `google::cloud::Status` indicating success or the details of the
103  * error Please consult the [`StatusOr<T>`
104  * documentation](#google::cloud::StatusOr) for more details.
105  *
106  * @code
107  * namespace cbt = google::cloud::bigtable;
108  * cbt::Table = ...;
109  * google::cloud::StatusOr<std::pair<bool, cbt::Row>> row = table.ReadRow(...);
110  *
111  * if (!row) {
112  * std::cerr << "Error reading row\n";
113  * return;
114  * }
115  *
116  * // Use "row" as a smart pointer here, e.g.:
117  * if (!row->first) {
118  * std::cout << "Contacting the server was successful, but the row does not"
119  * << " exist\n";
120  * return;
121  * }
122  * std::cout << "The row has " << row->second.cells().size() << " cells\n";
123  * @endcode
124  *
125  * In addition, the @ref index "main page" contains examples using `StatusOr<T>`
126  * to handle errors.
127  *
128  * @par Retry, Backoff, and Idempotency Policies
129  * The library automatically retries requests that fail with transient errors,
130  * and uses [truncated exponential backoff][backoff-link] to backoff between
131  * retries. The default policies are to continue retrying for up to 10 minutes.
132  * On each transient failure the backoff period is doubled, starting with an
133  * initial backoff of 100 milliseconds. The backoff period growth is truncated
134  * at 60 seconds. The default idempotency policy is to only retry idempotent
135  * operations. Note that most operations that change state are **not**
136  * idempotent.
137  *
138  * The application can override these policies when constructing objects of this
139  * class. The documentation for the constructors show examples of this in
140  * action.
141  *
142  * [backoff-link]: https://cloud.google.com/storage/docs/exponential-backoff
143  *
144  * @see https://cloud.google.com/bigtable/ for an overview of Cloud Bigtable.
145  *
146  * @see https://cloud.google.com/bigtable/docs/overview for an overview of the
147  * Cloud Bigtable data model.
148  *
149  * @see https://cloud.google.com/bigtable/docs/instances-clusters-nodes for an
150  * introduction of the main APIs into Cloud Bigtable.
151  *
152  * @see https://cloud.google.com/bigtable/docs/reference/service-apis-overview
153  * for an overview of the underlying Cloud Bigtable API.
154  *
155  * @see #google::cloud::StatusOr for a description of the error reporting class
156  * used by this library.
157  *
158  * @see `LimitedTimeRetryPolicy` and `LimitedErrorCountRetryPolicy` for
159  * alternative retry policies.
160  *
161  * @see `ExponentialBackoffPolicy` to configure different parameters for the
162  * exponential backoff policy.
163  *
164  * @see `SafeIdempotentMutationPolicy` and `AlwaysRetryMutationPolicy` for
165  * alternative idempotency policies.
166  */
167 class Table {
168  private:
169  // We need to eliminate some function overloads from resolution, and that
170  // requires a bit of infrastructure in the private section.
171 
172  /// A meta function to check if @p P is a valid Policy type.
173  template <typename P>
174  struct ValidPolicy
175  : absl::disjunction<std::is_base_of<RPCBackoffPolicy, P>,
176  std::is_base_of<RPCRetryPolicy, P>,
177  std::is_base_of<IdempotentMutationPolicy, P>> {};
178 
179  /// A meta function to check if all the @p Policies are valid policy types.
180  template <typename... Policies>
181  struct ValidPolicies : absl::conjunction<ValidPolicy<Policies>...> {};
182 
183  public:
184  /**
185  * Constructor with default policies.
186  *
187  * @param client how to communicate with Cloud Bigtable, including
188  * credentials, the project id, and the instance id.
189  * @param table_id the table id within the instance defined by client. The
190  * full table name is `client->instance_name() + '/tables/' + table_id`.
191  */
192  Table(std::shared_ptr<DataClient> client, std::string const& table_id)
193  : Table(std::move(client), std::string{}, table_id) {}
194 
195  /**
196  * Constructor with default policies.
197  *
198  * @param client how to communicate with Cloud Bigtable, including
199  * credentials, the project id, and the instance id.
200  * @param app_profile_id the app_profile_id needed for using the replication
201  * API.
202  * @param table_id the table id within the instance defined by client. The
203  * full table name is `client->instance_name() + '/tables/' + table_id`.
204  *
205  * @par Example
206  * @snippet bigtable_hello_app_profile.cc cbt namespace
207  *
208  * @par Example Using AppProfile
209  * @snippet bigtable_hello_app_profile.cc read with app profile
210  */
211  Table(std::shared_ptr<DataClient> client, std::string app_profile_id,
212  std::string const& table_id)
213  : client_(std::move(client)),
214  app_profile_id_(std::move(app_profile_id)),
215  table_name_(TableName(client_, table_id)),
216  table_id_(table_id),
217  rpc_retry_policy_prototype_(
218  bigtable::DefaultRPCRetryPolicy(internal::kBigtableLimits)),
219  rpc_backoff_policy_prototype_(
220  bigtable::DefaultRPCBackoffPolicy(internal::kBigtableLimits)),
221  metadata_update_policy_(
222  MetadataUpdatePolicy(table_name_, MetadataParamTypes::TABLE_NAME)),
223  idempotent_mutation_policy_(
225  background_threads_(client_->BackgroundThreadsFactory()()) {}
226 
227  /**
228  * Constructor with explicit policies.
229  *
230  * The policies are passed by value, because this makes it easy for
231  * applications to create them.
232  *
233  * @par Example
234  * @code
235  * using namespace std::chrono_literals; // assuming C++14.
236  * auto client = bigtable::MakeClient(...); // details omitted
237  * bigtable::Table table(client, "my-table",
238  * // Allow up to 20 minutes to retry operations
239  * bigtable::LimitedTimeRetryPolicy(20min),
240  * // Start with 50 milliseconds backoff, grow
241  * // exponentially to 5 minutes.
242  * bigtable::ExponentialBackoffPolicy(50ms, 5min),
243  * // Only retry idempotent mutations.
244  * bigtable::SafeIdempotentMutationPolicy());
245  * @endcode
246  *
247  * @param client how to communicate with Cloud Bigtable, including
248  * credentials, the project id, and the instance id.
249  * @param table_id the table id within the instance defined by client. The
250  * full table name is `client->instance_name() + "/tables/" + table_id`.
251  * @param policies the set of policy overrides for this object.
252  * @tparam Policies the types of the policies to override, the types must
253  * derive from one of the following types:
254  *
255  * - `IdempotentMutationPolicy` which mutations are retried. Use
256  * `SafeIdempotentMutationPolicy` to only retry idempotent operations,
257  * use `AlwaysRetryMutationPolicy` to retry all operations. Read the
258  * caveats in the class definition to understand the downsides of the
259  * latter. You can also create your own policies that decide which
260  * mutations to retry.
261  * - `RPCBackoffPolicy` how to backoff from a failed RPC. Currently only
262  * `ExponentialBackoffPolicy` is implemented. You can also create your
263  * own policies that backoff using a different algorithm.
264  * - `RPCRetryPolicy` for how long to retry failed RPCs. Use
265  * `LimitedErrorCountRetryPolicy` to limit the number of failures
266  * allowed. Use `LimitedTimeRetryPolicy` to bound the time for any
267  * request. You can also create your own policies that combine time and
268  * error counts.
269  *
270  * @see SafeIdempotentMutationPolicy, AlwaysRetryMutationPolicy,
271  * ExponentialBackoffPolicy, LimitedErrorCountRetryPolicy,
272  * LimitedTimeRetryPolicy.
273  *
274  * @par Idempotency Policy Example
275  * @snippet data_snippets.cc apply relaxed idempotency
276  *
277  * @par Modified Retry Policy Example
278  * @snippet data_snippets.cc apply custom retry
279  */
280  template <
281  typename... Policies,
282  typename std::enable_if<ValidPolicies<Policies...>::value, int>::type = 0>
283  Table(std::shared_ptr<DataClient> client, std::string const& table_id,
284  Policies&&... policies)
285  : Table(std::move(client), table_id) {
286  ChangePolicies(std::forward<Policies>(policies)...);
287  }
288 
289  /**
290  * Constructor with explicit policies.
291  *
292  * The policies are passed by value, because this makes it easy for
293  * applications to create them.
294  *
295  * @par Example
296  * @code
297  * using namespace std::chrono_literals; // assuming C++14.
298  * auto client = bigtable::MakeClient(...); // details omitted
299  * bigtable::Table table(client, "app_id", "my-table",
300  * // Allow up to 20 minutes to retry operations
301  * bigtable::LimitedTimeRetryPolicy(20min),
302  * // Start with 50 milliseconds backoff, grow
303  * // exponentially to 5 minutes.
304  * bigtable::ExponentialBackoffPolicy(50ms, 5min),
305  * // Only retry idempotent mutations.
306  * bigtable::SafeIdempotentMutationPolicy());
307  * @endcode
308  *
309  * @param client how to communicate with Cloud Bigtable, including
310  * credentials, the project id, and the instance id.
311  * @param app_profile_id the app_profile_id needed for using the replication
312  * API.
313  * @param table_id the table id within the instance defined by client. The
314  * full table name is `client->instance_name() + "/tables/" + table_id`.
315  * @param policies the set of policy overrides for this object.
316  * @tparam Policies the types of the policies to override, the types must
317  * derive from one of the following types:
318  * - `IdempotentMutationPolicy` which mutations are retried. Use
319  * `SafeIdempotentMutationPolicy` to only retry idempotent operations,
320  * use `AlwaysRetryMutationPolicy` to retry all operations. Read the
321  * caveats in the class definition to understand the downsides of the
322  * latter. You can also create your own policies that decide which
323  * mutations to retry.
324  * - `RPCBackoffPolicy` how to backoff from a failed RPC. Currently only
325  * `ExponentialBackoffPolicy` is implemented. You can also create your
326  * own policies that backoff using a different algorithm.
327  * - `RPCRetryPolicy` for how long to retry failed RPCs. Use
328  * `LimitedErrorCountRetryPolicy` to limit the number of failures
329  * allowed. Use `LimitedTimeRetryPolicy` to bound the time for any
330  * request. You can also create your own policies that combine time and
331  * error counts.
332  *
333  * @see SafeIdempotentMutationPolicy, AlwaysRetryMutationPolicy,
334  * ExponentialBackoffPolicy, LimitedErrorCountRetryPolicy,
335  * LimitedTimeRetryPolicy.
336  *
337  * @par Idempotency Policy Example
338  * @snippet data_snippets.cc apply relaxed idempotency
339  *
340  * @par Modified Retry Policy Example
341  * @snippet data_snippets.cc apply custom retry
342  */
343  template <
344  typename... Policies,
345  typename std::enable_if<ValidPolicies<Policies...>::value, int>::type = 0>
346  Table(std::shared_ptr<DataClient> client, std::string app_profile_id,
347  std::string const& table_id, Policies&&... policies)
348  : Table(std::move(client), std::move(app_profile_id), table_id) {
349  ChangePolicies(std::forward<Policies>(policies)...);
350  }
351 
352  std::string const& table_name() const { return table_name_; }
353  std::string const& app_profile_id() const { return app_profile_id_; }
354  std::string const& project_id() const { return client_->project_id(); }
355  std::string const& instance_id() const { return client_->instance_id(); }
356  std::string const& table_id() const { return table_id_; }
357 
358  /**
359  * Attempts to apply the mutation to a row.
360  *
361  * @param mut the mutation. Note that this function takes ownership (and
362  * then discards) the data in the mutation. In general, a
363  * `SingleRowMutation` can be used to modify and/or delete multiple cells,
364  * across different columns and column families.
365  *
366  * @return status of the operation.
367  *
368  * @par Idempotency
369  * This operation is idempotent if the provided mutations are idempotent. Note
370  * that `google::cloud::bigtable::SetCell()` without an explicit timestamp is
371  * **not** an idempotent operation.
372  *
373  * @par Thread-safety
374  * Two threads concurrently calling this member function on the same instance
375  * of this class are **not** guaranteed to work.
376  *
377  * @par Example
378  * @snippet data_snippets.cc apply
379  */
381 
382  /**
383  * Makes asynchronous attempts to apply the mutation to a row.
384  *
385  * @warning This is an early version of the asynchronous APIs for Cloud
386  * Bigtable. These APIs might be changed in backward-incompatible ways. It
387  * is not subject to any SLA or deprecation policy.
388  *
389  * @param mut the mutation. Note that this function takes ownership
390  * (and then discards) the data in the mutation. In general, a
391  * `SingleRowMutation` can be used to modify and/or delete
392  * multiple cells, across different columns and column families.
393  *
394  * @par Idempotency
395  * This operation is idempotent if the provided mutations are idempotent. Note
396  * that `google::cloud::bigtable::SetCell()` without an explicit timestamp is
397  * **not** an idempotent operation.
398  *
399  * @par Example
400  * @snippet data_async_snippets.cc async-apply
401  */
403 
404  /**
405  * Attempts to apply mutations to multiple rows.
406  *
407  * These mutations are applied in bulk, in a single `MutateRowsRequest` RPC.
408  * Failures are handled on a per mutation basis. If the result of a mutation
409  * is a permanent (non-retryable) error, or if a non-idempotent mutation fails
410  * for any reason, the mutation will not be retried. Only idempotent mutations
411  * that encounter transient (retryable) errors can be retried. These mutations
412  * are collected and retried in bulk. This function will continue to retry any
413  * remaining errors until this class's retry policy is exhausted.
414  *
415  * It is possible that some mutations may not be attempted at all. These
416  * mutations are considered failing and will be returned.
417  *
418  * @note The retry policy is only impacted by the result of the gRPC stream.
419  * Let's say you have a `LimitedErrorCountRetryPolicy` of 2. If an
420  * idempotent mutation fails with a retryable error and the stream itself
421  * succeeds, it may be retried more than 2 times. Only when the stream
422  * fails twice will we give up and consider the mutation to be failed.
423  *
424  * @note This function takes ownership (and then discards) the data in the
425  * mutation. In general, a `BulkMutation` can modify multiple rows, and
426  * the modifications for each row can change (or create) multiple cells,
427  * across different columns and column families.
428  *
429  * @param mut the mutations
430  * @returns a list of failed mutations
431  *
432  * @par Idempotency
433  * This operation is idempotent if the provided mutations are idempotent. Note
434  * that `google::cloud::bigtable::SetCell()` without an explicit timestamp is
435  * **not** an idempotent operation.
436  *
437  * @par Thread-safety
438  * Two threads concurrently calling this member function on the same instance
439  * of this class are **not** guaranteed to work. Consider copying the object
440  * and using different copies in each thread.
441  *
442  * @par Example
443  * @snippet data_snippets.cc bulk apply
444  */
446 
447  /**
448  * Makes asynchronous attempts to apply mutations to multiple rows.
449  *
450  * These mutations are applied in bulk, in a single `MutateRowsRequest` RPC.
451  * Failures are handled on a per mutation basis. If the result of a mutation
452  * is a permanent (non-retryable) error, or if a non-idempotent mutation fails
453  * for any reason, the mutation will not be retried. Only idempotent mutations
454  * that encounter transient (retryable) errors can be retried. These mutations
455  * are collected and retried in bulk. This function will continue to retry any
456  * remaining errors until this class's retry policy is exhausted.
457  *
458  * It is possible that some mutations may not be attempted at all. These
459  * mutations are considered failing and will be returned.
460  *
461  * @note The retry policy is only impacted by the result of the gRPC stream.
462  * Let's say you have a `LimitedErrorCountRetryPolicy` of 2. If an
463  * idempotent mutation fails with a retryable error and the stream itself
464  * succeeds, it may be retried more than 2 times. Only when the stream
465  * fails twice will we give up and consider the mutation to be failed.
466  *
467  * @note This function takes ownership (and then discards) the data in the
468  * mutation. In general, a `BulkMutation` can modify multiple rows, and
469  * the modifications for each row can change (or create) multiple cells,
470  * across different columns and column families.
471  *
472  * @param mut the mutations
473  * @returns a future to be filled with a list of failed mutations, when the
474  * operation is complete.
475  *
476  * @par Idempotency
477  * This operation is idempotent if the provided mutations are idempotent. Note
478  * that `google::cloud::bigtable::SetCell()` without an explicit timestamp is
479  * **not** an idempotent operation.
480  *
481  * @par Thread-safety
482  * Two threads concurrently calling this member function on the same instance
483  * of this class are **not** guaranteed to work. Consider copying the object
484  * and using different copies in each thread.
485  *
486  * @par Example
487  * @snippet data_async_snippets.cc bulk async-bulk-apply
488  */
490 
491  /**
492  * Reads a set of rows from the table.
493  *
494  * @param row_set the rows to read from.
495  * @param filter is applied on the server-side to data in the rows.
496  *
497  * @par Idempotency
498  * This is a read-only operation and therefore it is always idempotent.
499  *
500  * @par Thread-safety
501  * Two threads concurrently calling this member function on the same instance
502  * of this class are **not** guaranteed to work. Consider copying the object
503  * and using different copies in each thread. The values returned by
504  * different calls are independent with respect to thread-safety, please see
505  * the `RowReader` documentation for more details.
506  *
507  * @par Example
508  * @snippet read_snippets.cc read rows
509  */
510  RowReader ReadRows(RowSet row_set, Filter filter);
511 
512  /**
513  * Reads a limited set of rows from the table.
514  *
515  * @param row_set the rows to read from.
516  * @param rows_limit the maximum number of rows to read. Cannot be a negative
517  * number or zero. Use `ReadRows(RowSet, Filter)` to read all matching
518  * rows.
519  * @param filter is applied on the server-side to data in the rows.
520  *
521  * @par Idempotency
522  * This is a read-only operation and therefore it is always idempotent.
523  *
524  * @par Thread-safety
525  * Two threads concurrently calling this member function on the same instance
526  * of this class are **not** guaranteed to work. Consider copying the object
527  * and using different copies in each thread. The values returned by
528  * different calls are independent with respect to thread-safety, please see
529  * the `RowReader` documentation for more details.
530  *
531  * @par Example
532  * @snippet read_snippets.cc read rows with limit
533  */
534  RowReader ReadRows(RowSet row_set, std::int64_t rows_limit, Filter filter);
535 
536  /**
537  * Read and return a single row from the table.
538  *
539  * @param row_key the row to read.
540  * @param filter a filter expression, can be used to select a subset of the
541  * column families and columns in the row.
542  * @returns a tuple, the first element is a boolean, with value `false` if the
543  * row does not exist. If the first element is `true` the second element
544  * has the contents of the Row. Note that the contents may be empty
545  * if the filter expression removes all column families and columns.
546  *
547  * @par Idempotency
548  * This is a read-only operation and therefore it is always idempotent.
549  *
550  * @par Thread-safety
551  * Two threads concurrently calling this member function on the same instance
552  * of this class are **not** guaranteed to work. Consider copying the object
553  * and using different copies in each thread.
554  *
555  * @par Example
556  * @snippet read_snippets.cc read row
557  */
558  StatusOr<std::pair<bool, Row>> ReadRow(std::string row_key, Filter filter);
559 
560  /**
561  * Atomic test-and-set for a row using filter expressions.
562  *
563  * Atomically check the value of a row using a filter expression. If the
564  * expression passes (meaning at least one element is returned by it), one
565  * set of mutations is applied. If the filter does not pass, a different set
566  * of mutations is applied. The changes are atomically applied in the server.
567  *
568  * @param row_key the row to modify.
569  * @param filter the filter expression.
570  * @param true_mutations the mutations for the "filter passed" case.
571  * @param false_mutations the mutations for the "filter did not pass" case.
572  * @returns true if the filter passed.
573  *
574  * @par Idempotency
575  * This operation is always treated as non-idempotent.
576  *
577  * @par Thread-safety
578  * Two threads concurrently calling this member function on the same instance
579  * of this class are **not** guaranteed to work. Consider copying the object
580  * and using different copies in each thread.
581  *
582  * @par Check for Value Example
583  * @snippet data_snippets.cc check and mutate
584  *
585  * @par Check for Cell Presence Example
586  * @snippet data_snippets.cc check and mutate not present
587  */
589  std::string row_key, Filter filter, std::vector<Mutation> true_mutations,
590  std::vector<Mutation> false_mutations);
591 
592  /**
593  * Make an asynchronous request to conditionally mutate a row.
594  *
595  * @warning This is an early version of the asynchronous APIs for Cloud
596  * Bigtable. These APIs might be changed in backward-incompatible ways. It
597  * is not subject to any SLA or deprecation policy.
598  *
599  * @param row_key the row key on which the conditional mutation will be
600  * performed
601  * @param filter the condition, depending on which the mutation will be
602  * performed
603  * @param true_mutations the mutations which will be performed if @p filter is
604  * true
605  * @param false_mutations the mutations which will be performed if @p filter
606  * is false
607  *
608  * @par Idempotency
609  * This operation is always treated as non-idempotent.
610  *
611  * @par Thread-safety
612  * Two threads concurrently calling this member function on the same instance
613  * of this class are **not** guaranteed to work. Consider copying the object
614  * and using different copies in each thread.
615  *
616  * @par Example
617  * @snippet data_async_snippets.cc async check and mutate
618  */
620  std::string row_key, Filter filter, std::vector<Mutation> true_mutations,
621  std::vector<Mutation> false_mutations);
622 
623  /**
624  * Sample of the row keys in the table, including approximate data sizes.
625  *
626  * @note The sample may only include one element for small tables. In
627  * addition, the sample may include row keys that do not exist on the
628  * table, and may include the empty row key to indicate "end of table".
629  *
630  * @par Idempotency
631  * This operation is always treated as idempotent.
632  *
633  * @par Thread-safety
634  * Two threads concurrently calling this member function on the same instance
635  * of this class are **not** guaranteed to work. Consider copying the object
636  * and using different copies in each thread.
637  *
638  * @par Examples
639  * @snippet data_snippets.cc sample row keys
640  */
641  StatusOr<std::vector<bigtable::RowKeySample>> SampleRows();
642 
643  /**
644  * Asynchronously obtains a sample of the row keys in the table, including
645  * approximate data sizes.
646  *
647  * @returns a future, that becomes satisfied when the operation completes.
648  *
649  * @note The sample may only include one element for small tables. In
650  * addition, the sample may include row keys that do not exist on the
651  * table, and may include the empty row key to indicate "end of table".
652  *
653  * @par Idempotency
654  * This operation is always treated as idempotent.
655  *
656  * @par Thread-safety
657  * Two threads concurrently calling this member function on the same instance
658  * of this class are **not** guaranteed to work. Consider copying the object
659  * and using different copies in each thread.
660  *
661  * @par Examples
662  * @snippet data_async_snippets.cc async sample row keys
663  */
664  future<StatusOr<std::vector<bigtable::RowKeySample>>> AsyncSampleRows();
665 
666  /**
667  * Atomically read and modify the row in the server, returning the
668  * resulting row
669  *
670  * @tparam Args this is zero or more ReadModifyWriteRules to apply on a row
671  * @param row_key the row to read
672  * @param rule to modify the row. Two types of rules are applied here
673  * AppendValue which will read the existing value and append the
674  * text provided to the value.
675  * IncrementAmount which will read the existing uint64 big-endian-int
676  * and add the value provided.
677  * Both rules accept the family and column identifier to modify.
678  * @param rules is the zero or more ReadModifyWriteRules to apply on a row.
679  * @returns the new contents of all modified cells.
680  *
681  * @par Idempotency
682  * This operation is always treated as non-idempotent.
683  *
684  * @par Thread-safety
685  * Two threads concurrently calling this member function on the same instance
686  * of this class are **not** guaranteed to work. Consider copying the object
687  * and using different copies in each thread.
688  *
689  * @par Example
690  * @snippet data_snippets.cc read modify write
691  */
692  template <typename... Args>
693  StatusOr<Row> ReadModifyWriteRow(std::string row_key,
695  Args&&... rules) {
696  ::google::bigtable::v2::ReadModifyWriteRowRequest request;
697  request.set_row_key(std::move(row_key));
698 
699  // Generate a better compile time error message than the default one
700  // if the types do not match
701  static_assert(
702  absl::conjunction<
703  std::is_convertible<Args, bigtable::ReadModifyWriteRule>...>::value,
704  "The arguments passed to ReadModifyWriteRow(row_key,...) must be "
705  "convertible to bigtable::ReadModifyWriteRule");
706 
707  *request.add_rules() = std::move(rule).as_proto();
708  AddRules(request, std::forward<Args>(rules)...);
709  return ReadModifyWriteRowImpl(std::move(request));
710  }
711 
712  /**
713  * Make an asynchronous request to atomically read and modify a row.
714  *
715  * @warning This is an early version of the asynchronous APIs for Cloud
716  * Bigtable. These APIs might be changed in backward-incompatible ways. It
717  * is not subject to any SLA or deprecation policy.
718  *
719  * @param row_key the row key on which modification will be performed
720  *
721  * @param rule to modify the row. Two types of rules are applied here
722  * AppendValue which will read the existing value and append the
723  * text provided to the value.
724  * IncrementAmount which will read the existing uint64 big-endian-int
725  * and add the value provided.
726  * Both rules accept the family and column identifier to modify.
727  * @param rules is the zero or more ReadModifyWriteRules to apply on a row.
728  * @returns a future, that becomes satisfied when the operation completes,
729  * at that point the future has the contents of all modified cells.
730  *
731  * @par Idempotency
732  * This operation is always treated as non-idempotent.
733  *
734  * @par Thread-safety
735  * Two threads concurrently calling this member function on the same instance
736  * of this class are **not** guaranteed to work.
737  *
738  * @par Example
739  * @snippet data_async_snippets.cc async read modify write
740  */
741  template <typename... Args>
743  std::string row_key, bigtable::ReadModifyWriteRule rule,
744  Args&&... rules) {
745  ::google::bigtable::v2::ReadModifyWriteRowRequest request;
746  request.set_row_key(std::move(row_key));
747 
748  // Generate a better compile time error message than the default one
749  // if the types do not match
750  static_assert(
751  absl::conjunction<
752  std::is_convertible<Args, bigtable::ReadModifyWriteRule>...>::value,
753  "The arguments passed to AsyncReadModifyWriteRow(row_key,...) must be "
754  "convertible to bigtable::ReadModifyWriteRule");
755 
756  *request.add_rules() = std::move(rule).as_proto();
757  AddRules(request, std::forward<Args>(rules)...);
758  return AsyncReadModifyWriteRowImpl(std::move(request));
759  }
760 
761  /**
762  * Asynchronously reads a set of rows from the table.
763  *
764  * @warning This is an early version of the asynchronous APIs for Cloud
765  * Bigtable. These APIs might be changed in backward-incompatible ways. It
766  * is not subject to any SLA or deprecation policy.
767  *
768  * @param on_row the callback to be invoked on each successfully read row; it
769  * should be invocable with `Row` and return a future<bool>; the returned
770  * `future<bool>` should be satisfied with `true` when the user is ready
771  * to receive the next callback and with `false` when the user doesn't
772  * want any more rows; if `on_row` throws, the results are undefined
773  * @param on_finish the callback to be invoked when the stream is closed; it
774  * should be invocable with `Status` and not return anything; it will
775  * always be called as the last callback; if `on_finish` throws, the
776  * results are undefined
777  * @param row_set the rows to read from.
778  * @param filter is applied on the server-side to data in the rows.
779  *
780  * @tparam RowFunctor the type of the @p on_row callback.
781  * @tparam FinishFunctor the type of the @p on_finish callback.
782  *
783  * @par Thread-safety
784  * Two threads concurrently calling this member function on the same instance
785  * of this class are **not** guaranteed to work. Consider copying the object
786  * and using different copies in each thread.
787  *
788  * @par Example
789  * @snippet data_async_snippets.cc async read rows
790  */
791  template <typename RowFunctor, typename FinishFunctor>
792  void AsyncReadRows(RowFunctor on_row, FinishFunctor on_finish, RowSet row_set,
793  Filter filter) {
794  AsyncReadRows(std::move(on_row), std::move(on_finish), std::move(row_set),
795  AsyncRowReader<RowFunctor, FinishFunctor>::NO_ROWS_LIMIT,
796  std::move(filter));
797  }
798 
799  /**
800  * Asynchronously reads a set of rows from the table.
801  *
802  * @warning This is an early version of the asynchronous APIs for Cloud
803  * Bigtable. These APIs might be changed in backward-incompatible ways. It
804  * is not subject to any SLA or deprecation policy.
805  *
806  * @param on_row the callback to be invoked on each successfully read row; it
807  * should be invocable with `Row` and return a future<bool>; the returned
808  * `future<bool>` should be satisfied with `true` when the user is ready
809  * to receive the next callback and with `false` when the user doesn't
810  * want any more rows; if `on_row` throws, the results are undefined
811  * @param on_finish the callback to be invoked when the stream is closed; it
812  * should be invocable with `Status` and not return anything; it will
813  * always be called as the last callback; if `on_finish` throws, the
814  * results are undefined
815  * @param row_set the rows to read from.
816  * @param rows_limit the maximum number of rows to read. Cannot be a negative
817  * number or zero. Use `AsyncReadRows(RowSet, Filter)` to
818  * read all matching rows.
819  * @param filter is applied on the server-side to data in the rows.
820  *
821  * @tparam RowFunctor the type of the @p on_row callback.
822  * @tparam FinishFunctor the type of the @p on_finish callback.
823  *
824  * @par Thread-safety
825  * Two threads concurrently calling this member function on the same instance
826  * of this class are **not** guaranteed to work. Consider copying the object
827  * and using different copies in each thread. The callbacks passed to this
828  * function may be executed on any thread running the provided completion
829  * queue.
830  *
831  * @par Example
832  * @snippet data_async_snippets.cc async read rows with limit
833  */
834  template <typename RowFunctor, typename FinishFunctor>
835  void AsyncReadRows(RowFunctor on_row, FinishFunctor on_finish, RowSet row_set,
836  std::int64_t rows_limit, Filter filter) {
837  AsyncRowReader<RowFunctor, FinishFunctor>::Create(
838  background_threads_->cq(), client_, app_profile_id_, table_name_,
839  std::move(on_row), std::move(on_finish), std::move(row_set), rows_limit,
840  std::move(filter), clone_rpc_retry_policy(), clone_rpc_backoff_policy(),
841  metadata_update_policy_,
842  absl::make_unique<bigtable::internal::ReadRowsParserFactory>());
843  }
844 
845  /**
846  * Asynchronously read and return a single row from the table.
847  *
848  * @warning This is an early version of the asynchronous APIs for Cloud
849  * Bigtable. These APIs might be changed in backward-incompatible ways. It
850  * is not subject to any SLA or deprecation policy.
851  *
852  * @param row_key the row to read.
853  * @param filter a filter expression, can be used to select a subset of the
854  * column families and columns in the row.
855  * @returns a future satisfied when the operation completes, fails
856  * permanently or keeps failing transiently, but the retry policy has been
857  * exhausted. The future will return a tuple. The first element is a
858  * boolean, with value `false` if the row does not exist. If the first
859  * element is `true` the second element has the contents of the Row. Note
860  * that the contents may be empty if the filter expression removes all
861  * column families and columns.
862  *
863  * @par Idempotency
864  * This is a read-only operation and therefore it is always idempotent.
865  *
866  * @par Thread-safety
867  * Two threads concurrently calling this member function on the same instance
868  * of this class are **not** guaranteed to work. Consider copying the object
869  * and using different copies in each thread.
870  *
871  * @par Example
872  * @snippet data_async_snippets.cc async read row
873  */
874  future<StatusOr<std::pair<bool, Row>>> AsyncReadRow(std::string row_key,
875  Filter filter);
876 
877  private:
878  /**
879  * Send request ReadModifyWriteRowRequest to modify the row and get it back
880  */
881  StatusOr<Row> ReadModifyWriteRowImpl(
882  ::google::bigtable::v2::ReadModifyWriteRowRequest request);
883 
884  future<StatusOr<Row>> AsyncReadModifyWriteRowImpl(
885  ::google::bigtable::v2::ReadModifyWriteRowRequest request);
886 
887  void AddRules(google::bigtable::v2::ReadModifyWriteRowRequest&) {
888  // no-op for empty list
889  }
890 
891  template <typename... Args>
892  void AddRules(google::bigtable::v2::ReadModifyWriteRowRequest& request,
893  bigtable::ReadModifyWriteRule rule, Args&&... args) {
894  *request.add_rules() = std::move(rule).as_proto();
895  AddRules(request, std::forward<Args>(args)...);
896  }
897 
898  std::unique_ptr<RPCRetryPolicy> clone_rpc_retry_policy() {
899  return rpc_retry_policy_prototype_->clone();
900  }
901 
902  std::unique_ptr<RPCBackoffPolicy> clone_rpc_backoff_policy() {
903  return rpc_backoff_policy_prototype_->clone();
904  }
905 
906  MetadataUpdatePolicy clone_metadata_update_policy() {
907  return metadata_update_policy_;
908  }
909 
910  std::unique_ptr<IdempotentMutationPolicy> clone_idempotent_mutation_policy() {
911  return idempotent_mutation_policy_->clone();
912  }
913 
914  //@{
915  /// @name Helper functions to implement constructors with changed policies.
916  void ChangePolicy(RPCRetryPolicy const& policy) {
917  rpc_retry_policy_prototype_ = policy.clone();
918  }
919 
920  void ChangePolicy(RPCBackoffPolicy const& policy) {
921  rpc_backoff_policy_prototype_ = policy.clone();
922  }
923 
924  void ChangePolicy(IdempotentMutationPolicy const& policy) {
925  idempotent_mutation_policy_ = policy.clone();
926  }
927 
928  template <typename Policy, typename... Policies>
929  void ChangePolicies(Policy&& policy, Policies&&... policies) {
930  ChangePolicy(policy);
931  ChangePolicies(std::forward<Policies>(policies)...);
932  }
933  void ChangePolicies() {}
934  //@}
935 
936  friend class MutationBatcher;
937  std::shared_ptr<DataClient> client_;
938  std::string app_profile_id_;
939  std::string table_name_;
940  std::string table_id_;
941  std::shared_ptr<RPCRetryPolicy const> rpc_retry_policy_prototype_;
942  std::shared_ptr<RPCBackoffPolicy const> rpc_backoff_policy_prototype_;
943  MetadataUpdatePolicy metadata_update_policy_;
944  std::shared_ptr<IdempotentMutationPolicy> idempotent_mutation_policy_;
945  std::shared_ptr<BackgroundThreads> background_threads_;
946 };
947 
949 } // namespace bigtable
950 } // namespace cloud
951 } // namespace google
952 
953 #endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_BIGTABLE_TABLE_H