Google Cloud Bigtable C++ Client  1.1.0
A C++ Client Library for Google Cloud Bigtable
table_admin_snippets.cc
Go to the documentation of this file.
1 // Copyright 2018 Google LLC
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 // http://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 //! [all code]
16 
17 //! [bigtable includes]
18 #include "google/cloud/bigtable/table.h"
19 #include "google/cloud/bigtable/table_admin.h"
20 //! [bigtable includes]
21 #include <google/protobuf/text_format.h>
22 #include <deque>
23 #include <list>
24 #include <sstream>
25 
26 namespace {
27 struct Usage {
28  std::string msg;
29 };
30 
31 char const* ConsumeArg(int& argc, char* argv[]) {
32  if (argc < 2) {
33  return nullptr;
34  }
35  char const* result = argv[1];
36  std::copy(argv + 2, argv + argc, argv + 1);
37  argc--;
38  return result;
39 }
40 
41 std::string command_usage;
42 
43 void PrintUsage(int, char* argv[], std::string const& msg) {
44  std::string const cmd = argv[0];
45  auto last_slash = std::string(cmd).find_last_of('/');
46  auto program = cmd.substr(last_slash + 1);
47  std::cerr << msg << "\nUsage: " << program << " <command> [arguments]\n\n"
48  << "Commands:\n"
49  << command_usage << "\n";
50 }
51 
52 void CreateTable(google::cloud::bigtable::TableAdmin admin, int argc,
53  char* argv[]) {
54  if (argc != 2) {
55  throw Usage{"create-table <project-id> <instance-id> <table-id>"};
56  }
57  std::string const table_id = ConsumeArg(argc, argv);
58 
59  //! [create table] [START bigtable_create_table]
60  namespace cbt = google::cloud::bigtable;
61  using google::cloud::StatusOr;
62  [](cbt::TableAdmin admin, std::string table_id) {
63  StatusOr<google::bigtable::admin::v2::Table> schema = admin.CreateTable(
64  table_id,
65  cbt::TableConfig({{"fam", cbt::GcRule::MaxNumVersions(10)},
66  {"foo", cbt::GcRule::MaxAge(std::chrono::hours(72))}},
67  {}));
68  if (!schema) {
69  throw std::runtime_error(schema.status().message());
70  }
71  std::cout << "Table successfully created: " << schema->DebugString()
72  << "\n";
73  }
74  //! [create table] [END bigtable_create_table]
75  (std::move(admin), table_id);
76 }
77 
78 void ListTables(google::cloud::bigtable::TableAdmin admin, int argc, char*[]) {
79  if (argc != 1) {
80  throw Usage{"list-tables <project-id> <instance-id>"};
81  }
82 
83  //! [list tables] [START bigtable_list_tables]
84  namespace cbt = google::cloud::bigtable;
85  using google::cloud::StatusOr;
86  [](cbt::TableAdmin admin) {
87  StatusOr<std::vector<google::bigtable::admin::v2::Table>> tables =
88  admin.ListTables(cbt::TableAdmin::NAME_ONLY);
89 
90  if (!tables) {
91  throw std::runtime_error(tables.status().message());
92  }
93  for (auto const& table : *tables) {
94  std::cout << table.name() << "\n";
95  }
96  }
97  //! [list tables] [END bigtable_list_tables]
98  (std::move(admin));
99 }
100 
101 void GetTable(google::cloud::bigtable::TableAdmin admin, int argc,
102  char* argv[]) {
103  if (argc != 2) {
104  throw Usage{"get-table <project-id> <instance-id> <table-id>"};
105  }
106  std::string const table_id = ConsumeArg(argc, argv);
107 
108  //! [get table] [START bigtable_get_table_metadata]
109  namespace cbt = google::cloud::bigtable;
110  using google::cloud::StatusOr;
111  [](cbt::TableAdmin admin, std::string table_id) {
112  StatusOr<google::bigtable::admin::v2::Table> table =
113  admin.GetTable(table_id, cbt::TableAdmin::FULL);
114  if (!table) {
115  throw std::runtime_error(table.status().message());
116  }
117  std::cout << table->name() << " details=\n" << table->DebugString() << "\n";
118  }
119  //! [get table] [END bigtable_get_table_metadata]
120  (std::move(admin), table_id);
121 }
122 
123 void CheckTableExists(google::cloud::bigtable::TableAdmin admin, int argc,
124  char* argv[]) {
125  if (argc != 2) {
126  throw Usage{"check-table-exists <project-id> <instance-id> <table-id>"};
127  }
128  std::string const table_id = ConsumeArg(argc, argv);
129 
130  //! [START bigtable_check_table_exists]
131  namespace cbt = google::cloud::bigtable;
132  using google::cloud::StatusOr;
133  [](cbt::TableAdmin admin, std::string table_id) {
134  StatusOr<google::bigtable::admin::v2::Table> table =
135  admin.GetTable(table_id, cbt::TableAdmin::NAME_ONLY);
136  if (!table) {
137  if (table.status().code() == google::cloud::StatusCode::kNotFound) {
138  throw std::runtime_error("Table " + table_id + " does not exist");
139  }
140  throw std::runtime_error(table.status().message());
141  }
142 
143  std::cout << "Table " << table->name() << " was found\n";
144  }
145  //! [END bigtable_check_table_exists]
146  (std::move(admin), table_id);
147 }
148 
149 void GetOrCreateTable(google::cloud::bigtable::TableAdmin admin, int argc,
150  char* argv[]) {
151  if (argc != 2) {
152  throw Usage{"get-or-create-table <project-id> <instance-id> <table-id>"};
153  }
154  std::string const table_id = ConsumeArg(argc, argv);
155 
156  // [START bigtable_get_or_create_table]
157  namespace cbt = google::cloud::bigtable;
158  using google::cloud::StatusOr;
159  [](cbt::TableAdmin admin, std::string table_id) {
160  StatusOr<google::bigtable::admin::v2::Table> table =
161  admin.GetTable(table_id, cbt::TableAdmin::FULL);
162  if (!table &&
163  table.status().code() == google::cloud::StatusCode::kNotFound) {
164  // The table does not exist, try to create the table.
165  table = admin.CreateTable(
166  table_id,
167  cbt::TableConfig({{"fam", cbt::GcRule::MaxNumVersions(10)}}, {}));
168  if (!table) {
169  throw std::runtime_error(table.status().message());
170  }
171  // The schema returned by a `CreateTable()` request does not include all
172  // the metadata for a table, we need to explicitly request the rest:
173  table = admin.GetTable(table_id, cbt::TableAdmin::FULL);
174  }
175  if (!table) {
176  throw std::runtime_error(table.status().message());
177  }
178  std::cout << "Table metadata: " << table->DebugString() << "\n";
179  }
180  // [END bigtable_get_or_create_table]
181  (std::move(admin), table_id);
182 }
183 
184 void DeleteTable(google::cloud::bigtable::TableAdmin admin, int argc,
185  char* argv[]) {
186  if (argc != 2) {
187  throw Usage{"delete-table <project-id> <instance-id> <table-id>"};
188  }
189  std::string const table_id = ConsumeArg(argc, argv);
190 
191  //! [delete table] [START bigtable_delete_table]
192  namespace cbt = google::cloud::bigtable;
193  [](cbt::TableAdmin admin, std::string table_id) {
194  google::cloud::Status status = admin.DeleteTable(table_id);
195  if (!status.ok()) {
196  throw std::runtime_error(status.message());
197  }
198  std::cout << "Table successfully deleted\n";
199  }
200  //! [delete table] [END bigtable_delete_table]
201  (std::move(admin), table_id);
202 }
203 
204 void ModifyTable(google::cloud::bigtable::TableAdmin admin, int argc,
205  char* argv[]) {
206  if (argc != 2) {
207  throw Usage{"modify-table <project-id> <instance-id> <table-id>"};
208  }
209  std::string const table_id = ConsumeArg(argc, argv);
210 
211  //! [modify table]
212  namespace cbt = google::cloud::bigtable;
213  using google::cloud::StatusOr;
214  [](cbt::TableAdmin admin, std::string table_id) {
215  StatusOr<google::bigtable::admin::v2::Table> schema =
216  admin.ModifyColumnFamilies(
217  table_id,
218  {cbt::ColumnFamilyModification::Drop("foo"),
219  cbt::ColumnFamilyModification::Update(
220  "fam", cbt::GcRule::Union(
221  cbt::GcRule::MaxNumVersions(5),
222  cbt::GcRule::MaxAge(std::chrono::hours(24 * 7)))),
223  cbt::ColumnFamilyModification::Create(
224  "bar", cbt::GcRule::Intersection(
225  cbt::GcRule::MaxNumVersions(3),
226  cbt::GcRule::MaxAge(std::chrono::hours(72))))});
227 
228  if (!schema) {
229  throw std::runtime_error(schema.status().message());
230  }
231  std::cout << "Schema modified to: " << schema->DebugString() << "\n";
232  }
233  //! [modify table]
234  (std::move(admin), table_id);
235 }
236 
237 void CreateMaxAgeFamily(google::cloud::bigtable::TableAdmin admin, int argc,
238  char* argv[]) {
239  if (argc != 3) {
240  throw Usage{
241  "create-max-age-family <project-id> <instance-id> <table-id>"
242  " <family-name>"};
243  }
244  std::string const table_id = ConsumeArg(argc, argv);
245  std::string const family_name = ConsumeArg(argc, argv);
246 
247  // [START bigtable_create_family_gc_max_age]
248  namespace cbt = google::cloud::bigtable;
249  using google::cloud::StatusOr;
250  [](cbt::TableAdmin admin, std::string table_id, std::string family_name) {
251  StatusOr<google::bigtable::admin::v2::Table> schema =
252  admin.ModifyColumnFamilies(
253  table_id,
254  {cbt::ColumnFamilyModification::Create(
255  family_name, cbt::GcRule::MaxAge(std::chrono::hours(5 * 24)))});
256 
257  if (!schema) {
258  throw std::runtime_error(schema.status().message());
259  }
260  std::cout << "Schema modified to: " << schema->DebugString() << "\n";
261  }
262  // [END bigtable_create_family_gc_max_age]
263  (std::move(admin), table_id, family_name);
264 }
265 
266 void CreateMaxVersionsFamily(google::cloud::bigtable::TableAdmin admin,
267  int argc, char* argv[]) {
268  if (argc != 3) {
269  throw Usage{
270  "create-max-versions-family <project-id> <instance-id> <table-id>"
271  " <family-name>"};
272  }
273  std::string const table_id = ConsumeArg(argc, argv);
274  std::string const family_name = ConsumeArg(argc, argv);
275 
276  // [START bigtable_create_family_gc_max_versions]
277  namespace cbt = google::cloud::bigtable;
278  using google::cloud::StatusOr;
279  [](cbt::TableAdmin admin, std::string table_id, std::string family_name) {
280  StatusOr<google::bigtable::admin::v2::Table> schema =
281  admin.ModifyColumnFamilies(
282  table_id, {cbt::ColumnFamilyModification::Create(
283  family_name, cbt::GcRule::MaxNumVersions(2))});
284 
285  if (!schema) {
286  throw std::runtime_error(schema.status().message());
287  }
288  std::cout << "Schema modified to: " << schema->DebugString() << "\n";
289  }
290  // [END bigtable_create_family_gc_max_versions]
291  (std::move(admin), table_id, family_name);
292 }
293 
294 void CreateUnionFamily(google::cloud::bigtable::TableAdmin admin, int argc,
295  char* argv[]) {
296  if (argc != 3) {
297  throw Usage{
298  "create-union-family <project-id> <instance-id> <table-id>"
299  " <family-name>"};
300  }
301  std::string const table_id = ConsumeArg(argc, argv);
302  std::string const family_name = ConsumeArg(argc, argv);
303 
304  // [START bigtable_create_family_gc_union]
305  namespace cbt = google::cloud::bigtable;
306  using google::cloud::StatusOr;
307  [](cbt::TableAdmin admin, std::string table_id, std::string family_name) {
308  StatusOr<google::bigtable::admin::v2::Table> schema =
309  admin.ModifyColumnFamilies(
310  table_id,
311  {cbt::ColumnFamilyModification::Create(
312  family_name,
313  cbt::GcRule::Union(
314  cbt::GcRule::MaxNumVersions(1),
315  cbt::GcRule::MaxAge(5 * std::chrono::hours(24))))});
316 
317  if (!schema) {
318  throw std::runtime_error(schema.status().message());
319  }
320  std::cout << "Schema modified to: " << schema->DebugString() << "\n";
321  }
322  // [END bigtable_create_family_gc_union]
323  (std::move(admin), table_id, family_name);
324 }
325 
326 void CreateIntersectionFamily(google::cloud::bigtable::TableAdmin admin,
327  int argc, char* argv[]) {
328  if (argc != 3) {
329  throw Usage{
330  "create-intersection-family <project-id> <instance-id> <table-id>"
331  " <family-name>"};
332  }
333  std::string const table_id = ConsumeArg(argc, argv);
334  std::string const family_name = ConsumeArg(argc, argv);
335 
336  // [START bigtable_create_family_gc_intersection]
337  namespace cbt = google::cloud::bigtable;
338  using google::cloud::StatusOr;
339  [](cbt::TableAdmin admin, std::string table_id, std::string family_name) {
340  StatusOr<google::bigtable::admin::v2::Table> schema =
341  admin.ModifyColumnFamilies(
342  table_id,
343  {cbt::ColumnFamilyModification::Create(
344  family_name,
345  cbt::GcRule::Intersection(
346  cbt::GcRule::MaxNumVersions(1),
347  cbt::GcRule::MaxAge(5 * std::chrono::hours(24))))});
348 
349  if (!schema) {
350  throw std::runtime_error(schema.status().message());
351  }
352  std::cout << "Schema modified to: " << schema->DebugString() << "\n";
353  }
354  // [END bigtable_create_family_gc_intersection]
355  (std::move(admin), table_id, family_name);
356 }
357 
358 void CreateNestedFamily(google::cloud::bigtable::TableAdmin admin, int argc,
359  char* argv[]) {
360  if (argc != 3) {
361  throw Usage{
362  "create-nested-family <project-id> <instance-id> <table-id>"
363  " <family-name>"};
364  }
365  std::string const table_id = ConsumeArg(argc, argv);
366  std::string const family_name = ConsumeArg(argc, argv);
367 
368  // [START bigtable_create_family_gc_nested]
369  namespace cbt = google::cloud::bigtable;
370  using google::cloud::StatusOr;
371  [](cbt::TableAdmin admin, std::string table_id, std::string family_name) {
372  StatusOr<google::bigtable::admin::v2::Table> schema =
373  admin.ModifyColumnFamilies(
374  table_id,
375  {cbt::ColumnFamilyModification::Create(
376  family_name,
377  cbt::GcRule::Union(
378  cbt::GcRule::MaxNumVersions(10),
379  cbt::GcRule::Intersection(
380  cbt::GcRule::MaxNumVersions(1),
381  cbt::GcRule::MaxAge(5 * std::chrono::hours(24)))))});
382 
383  if (!schema) {
384  throw std::runtime_error(schema.status().message());
385  }
386  std::cout << "Schema modified to: " << schema->DebugString() << "\n";
387  }
388  // [END bigtable_create_family_gc_nested]
389  (std::move(admin), table_id, family_name);
390 }
391 
392 void GetFamilyMetadata(google::cloud::bigtable::TableAdmin admin, int argc,
393  char* argv[]) {
394  if (argc != 3) {
395  throw Usage{
396  "get-family-metadata <project-id> <instance-id> <table-id>"
397  " <family-name>"};
398  }
399  std::string const table_id = ConsumeArg(argc, argv);
400  std::string const family_name = ConsumeArg(argc, argv);
401 
402  // [START bigtable_get_family_metadata] [START bigtable_get_family]
403  namespace cbt = google::cloud::bigtable;
404  using google::cloud::StatusOr;
405  [](cbt::TableAdmin admin, std::string table_id, std::string family_name) {
406  StatusOr<google::bigtable::admin::v2::Table> schema =
407  admin.GetTable(table_id, cbt::TableAdmin::FULL);
408 
409  if (!schema) {
410  throw std::runtime_error(schema.status().message());
411  }
412  auto pos = schema->column_families().find(family_name);
413  if (pos == schema->column_families().end()) {
414  std::cout << "Cannot find family <" << family_name << "> in table\n";
415  return;
416  }
417  std::cout << "Column family metadata for <" << family_name << "> is "
418  << pos->second.DebugString() << "\n";
419  }
420  // [END bigtable_get_family_metadata] [END bigtable_get_family]
421  (std::move(admin), table_id, family_name);
422 }
423 
424 void GetOrCreateFamily(google::cloud::bigtable::TableAdmin admin, int argc,
425  char* argv[]) {
426  if (argc != 3) {
427  throw Usage{
428  "get-or-create-family <project-id> <instance-id> <table-id>"
429  " <family-name>"};
430  }
431  std::string const table_id = ConsumeArg(argc, argv);
432  std::string const family_name = ConsumeArg(argc, argv);
433 
434  // [START bigtable_get_or_create_family]
435  namespace cbt = google::cloud::bigtable;
436  using google::cloud::StatusOr;
437  [](cbt::TableAdmin admin, std::string table_id, std::string family_name) {
438  StatusOr<google::bigtable::admin::v2::Table> schema =
439  admin.GetTable(table_id, cbt::TableAdmin::FULL);
440 
441  if (!schema) {
442  throw std::runtime_error(schema.status().message());
443  }
444  auto pos = schema->column_families().find(family_name);
445  if (pos == schema->column_families().end()) {
446  // Try to create the column family instead:
447  auto modified = admin.ModifyColumnFamilies(
448  table_id,
449  {cbt::ColumnFamilyModification::Create(
450  family_name, cbt::GcRule::MaxAge(std::chrono::hours(5 * 24)))});
451 
452  if (!modified) {
453  throw std::runtime_error(schema.status().message());
454  }
455  schema = *std::move(modified);
456  pos = schema->column_families().find(family_name);
457  }
458 
459  if (pos == schema->column_families().end()) {
460  throw std::runtime_error("GetOrCreateFamily failed");
461  }
462 
463  google::bigtable::admin::v2::ColumnFamily family = pos->second;
464  std::cout << "Column family name: " << pos->first
465  << "\nColumn family details: " << family.DebugString() << "\n";
466  }
467  // [END bigtable_get_or_create_family]
468  (std::move(admin), table_id, family_name);
469 }
470 
471 void DeleteColumnFamily(google::cloud::bigtable::TableAdmin admin, int argc,
472  char* argv[]) {
473  if (argc != 3) {
474  throw Usage{
475  "delete-column-family <project-id> <instance-id> <table-id>"
476  " <family-name>"};
477  }
478  std::string const table_id = ConsumeArg(argc, argv);
479  std::string const family_name = ConsumeArg(argc, argv);
480 
481  // [START bigtable_delete_family]
482  namespace cbt = google::cloud::bigtable;
483  using google::cloud::StatusOr;
484  [](cbt::TableAdmin admin, std::string table_id, std::string family_name) {
485  StatusOr<google::bigtable::admin::v2::Table> schema =
486  admin.ModifyColumnFamilies(
487  table_id, {cbt::ColumnFamilyModification::Drop(family_name)});
488 
489  if (!schema) {
490  throw std::runtime_error(schema.status().message());
491  }
492  std::cout << "Schema modified to: " << schema->DebugString() << "\n";
493  }
494  // [END bigtable_delete_family]
495  (std::move(admin), table_id, family_name);
496 }
497 
498 void CheckFamilyExists(google::cloud::bigtable::TableAdmin admin, int argc,
499  char* argv[]) {
500  if (argc != 3) {
501  throw Usage{
502  "check-family-exists <project-id> <instance-id> <table-id>"
503  " <family-name>"};
504  }
505  std::string const table_id = ConsumeArg(argc, argv);
506  std::string const family_name = ConsumeArg(argc, argv);
507 
508  // [START bigtable_check_family_exists]
509  namespace cbt = google::cloud::bigtable;
510  using google::cloud::StatusOr;
511  [](cbt::TableAdmin admin, std::string table_id, std::string family_name) {
512  StatusOr<google::bigtable::admin::v2::Table> schema =
513  admin.GetTable(table_id, cbt::TableAdmin::FULL);
514 
515  if (!schema) {
516  throw std::runtime_error(schema.status().message());
517  }
518  auto pos = schema->column_families().find(family_name);
519  if (pos == schema->column_families().end()) {
520  std::string msg =
521  "The column family <" + family_name + "> does not exist";
522  throw std::runtime_error(msg);
523  }
524  std::cout << "The column family <" << family_name << "> does exist\n";
525  }
526  // [END bigtable_check_family_exists]
527  (std::move(admin), table_id, family_name);
528 }
529 
530 void ListColumnFamilies(google::cloud::bigtable::TableAdmin admin, int argc,
531  char* argv[]) {
532  if (argc != 2) {
533  throw Usage{"list-column-families <project-id> <instance-id> <table-id>"};
534  }
535  std::string const table_id = ConsumeArg(argc, argv);
536 
537  // [START bigtable_list_column_families]
538  namespace cbt = google::cloud::bigtable;
539  using google::cloud::StatusOr;
540  [](cbt::TableAdmin admin, std::string table_id) {
541  StatusOr<google::bigtable::admin::v2::Table> schema =
542  admin.GetTable(table_id, cbt::TableAdmin::FULL);
543 
544  if (!schema) {
545  throw std::runtime_error(schema.status().message());
546  }
547  for (auto const& kv : schema->column_families()) {
548  std::string const& column_family_name = kv.first;
549  google::bigtable::admin::v2::ColumnFamily const& family = kv.second;
550  std::cout << "Column family name: " << column_family_name << "\n"
551  << "Column family metadata: " << family.DebugString() << "\n";
552  }
553  }
554  // [END bigtable_list_column_families]
555  (std::move(admin), table_id);
556 }
557 
558 void UpdateGcRule(google::cloud::bigtable::TableAdmin admin, int argc,
559  char* argv[]) {
560  if (argc != 3) {
561  throw Usage{
562  "update-gc-rule <project-id> <instance-id> <table-id>"
563  " <family-name>"};
564  }
565  std::string const table_id = ConsumeArg(argc, argv);
566  std::string const family_name = ConsumeArg(argc, argv);
567 
568  // [START bigtable_update_gc_rule]
569  namespace cbt = google::cloud::bigtable;
570  using google::cloud::StatusOr;
571  [](cbt::TableAdmin admin, std::string table_id, std::string family_name) {
572  StatusOr<google::bigtable::admin::v2::Table> schema =
573  admin.ModifyColumnFamilies(
574  table_id, {cbt::ColumnFamilyModification::Update(
575  family_name, cbt::GcRule::MaxNumVersions(1))});
576 
577  if (!schema) {
578  throw std::runtime_error(schema.status().message());
579  }
580  std::cout << "Schema modified to: " << schema->DebugString() << "\n";
581  }
582  // [END bigtable_update_gc_rule]
583  (std::move(admin), table_id, family_name);
584 }
585 
586 void DropAllRows(google::cloud::bigtable::TableAdmin admin, int argc,
587  char* argv[]) {
588  if (argc != 2) {
589  throw Usage{"drop-all-rows <project-id> <instance-id> <table-id>"};
590  }
591  std::string const table_id = ConsumeArg(argc, argv);
592 
593  //! [drop all rows]
594  // [START bigtable_truncate_table] [START bigtable_delete_rows]
595  namespace cbt = google::cloud::bigtable;
596  [](cbt::TableAdmin admin, std::string table_id) {
597  google::cloud::Status status = admin.DropAllRows(table_id);
598  if (!status.ok()) {
599  throw std::runtime_error(status.message());
600  }
601  std::cout << "All rows successfully deleted\n";
602  }
603  // [END bigtable_truncate_table] [END bigtable_delete_rows]
604  //! [drop all rows]
605  (std::move(admin), table_id);
606 }
607 
608 void DropRowsByPrefix(google::cloud::bigtable::TableAdmin admin, int argc,
609  char* argv[]) {
610  if (argc != 3) {
611  throw Usage{
612  "drop-rows-by-prefix <project-id> <instance-id> <table-id>"
613  " <prefix>"};
614  }
615  auto table_id = ConsumeArg(argc, argv);
616  auto prefix = ConsumeArg(argc, argv);
617 
618  //! [drop rows by prefix] [START bigtable_delete_rows_prefix]
619  namespace cbt = google::cloud::bigtable;
620  [](cbt::TableAdmin admin, std::string table_id, std::string prefix) {
621  google::cloud::Status status = admin.DropRowsByPrefix(table_id, prefix);
622  if (!status.ok()) {
623  throw std::runtime_error(status.message());
624  }
625  std::cout << "All rows starting with " << prefix
626  << " successfully deleted\n";
627  }
628  //! [drop rows by prefix] [END bigtable_delete_rows_prefix]
629  (std::move(admin), table_id, prefix);
630 }
631 
632 void WaitForConsistencyCheck(google::cloud::bigtable::TableAdmin admin,
633  int argc, char* argv[]) {
634  if (argc != 2) {
635  throw Usage{
636  "wait-for-consistency-check <project-id> <instance-id> <table-id>"};
637  }
638  auto table_id = ConsumeArg(argc, argv);
639 
640  //! [wait for consistency check]
641  namespace cbt = google::cloud::bigtable;
642  using google::cloud::future;
643  using google::cloud::StatusOr;
644  [](cbt::TableAdmin admin, std::string table_id) {
645  StatusOr<std::string> consistency_token =
646  admin.GenerateConsistencyToken(table_id);
647  if (!consistency_token) {
648  throw std::runtime_error(consistency_token.status().message());
649  }
650  future<StatusOr<cbt::Consistency>> consistent_future =
651  admin.WaitForConsistency(table_id, *consistency_token);
652  auto final = consistent_future.then(
653  [&consistency_token](future<StatusOr<cbt::Consistency>> f) {
654  auto is_consistent = f.get();
655  if (!is_consistent) {
656  throw std::runtime_error(is_consistent.status().message());
657  }
658  if (*is_consistent == cbt::Consistency::kConsistent) {
659  std::cout << "Table is consistent with token " << *consistency_token
660  << "\n";
661  } else {
662  std::cout
663  << "Table is not yet consistent, Please try again later with"
664  << " the same token (" << *consistency_token << ")\n";
665  }
666  });
667  final.get(); // simplify example by blocking until operation is done.
668  }
669  //! [wait for consistency check]
670  (std::move(admin), table_id);
671 }
672 
673 void CheckConsistency(google::cloud::bigtable::TableAdmin admin, int argc,
674  char* argv[]) {
675  if (argc != 3) {
676  throw Usage{
677  "check-consistency <project-id> <instance-id> <table-id> "
678  "<consistency_token>"};
679  }
680  auto table_id = ConsumeArg(argc, argv);
681  auto consistency_token = ConsumeArg(argc, argv);
682 
683  //! [check consistency]
684  namespace cbt = google::cloud::bigtable;
685  using google::cloud::StatusOr;
686  [](cbt::TableAdmin admin, std::string table_id,
687  std::string consistency_token) {
688  StatusOr<cbt::Consistency> result =
689  admin.CheckConsistency(table_id, consistency_token);
690  if (!result) {
691  throw std::runtime_error(result.status().message());
692  }
693  if (*result == cbt::Consistency::kConsistent) {
694  std::cout << "Table is consistent with token " << consistency_token
695  << "\n";
696  } else {
697  std::cout
698  << "Table is not yet consistent, Please try again later with the"
699  << " same token (" << consistency_token << ")\n";
700  }
701  }
702  //! [check consistency]
703  (std::move(admin), table_id, consistency_token);
704 }
705 
706 void GenerateConsistencyToken(google::cloud::bigtable::TableAdmin admin,
707  int argc, char* argv[]) {
708  if (argc != 2) {
709  throw Usage{
710  "generate-consistency-token <project-id> <instance-id> <table-id>"};
711  }
712  std::string const table_id = ConsumeArg(argc, argv);
713 
714  //! [generate consistency token]
715  namespace cbt = google::cloud::bigtable;
716  using google::cloud::StatusOr;
717  [](cbt::TableAdmin admin, std::string table_id) {
718  StatusOr<std::string> token = admin.GenerateConsistencyToken(table_id);
719  if (!token) {
720  throw std::runtime_error(token.status().message());
721  }
722  std::cout << "generated token is : " << *token << "\n";
723  }
724  //! [generate consistency token]
725  (std::move(admin), table_id);
726 }
727 
728 } // anonymous namespace
729 
730 int main(int argc, char* argv[]) try {
731  using CommandType =
732  std::function<void(google::cloud::bigtable::TableAdmin, int, char*[])>;
733 
734  std::map<std::string, CommandType> commands = {
735  {"create-table", &CreateTable},
736  {"list-tables", &ListTables},
737  {"get-table", &GetTable},
738  {"check-table-exists", &CheckTableExists},
739  {"get-or-create-table", &GetOrCreateTable},
740  {"delete-table", &DeleteTable},
741  {"modify-table", &ModifyTable},
742  {"create-max-age-family", &CreateMaxAgeFamily},
743  {"create-max-versions-family", &CreateMaxVersionsFamily},
744  {"create-union-family", &CreateUnionFamily},
745  {"create-intersection-family", &CreateIntersectionFamily},
746  {"create-nested-family", &CreateNestedFamily},
747  {"get-family-metadata", &GetFamilyMetadata},
748  {"get-or-create-family", &GetOrCreateFamily},
749  {"delete-column-family", &DeleteColumnFamily},
750  {"check-family-exists", &CheckFamilyExists},
751  {"list-column-families", &ListColumnFamilies},
752  {"update-gc-rule", &UpdateGcRule},
753  {"drop-all-rows", &DropAllRows},
754  {"drop-rows-by-prefix", &DropRowsByPrefix},
755  {"wait-for-consistency-check", &WaitForConsistencyCheck},
756  {"check-consistency", &CheckConsistency},
757  {"generate-consistency-token", &GenerateConsistencyToken},
758  };
759 
760  {
761  // Force each command to generate its Usage string, so we can provide a good
762  // usage string for the whole program. We need to create an TableAdmin
763  // object to do this, but that object is never used, it is passed to the
764  // commands, without any calls made to it.
765  google::cloud::bigtable::TableAdmin unused(
766  google::cloud::bigtable::CreateDefaultAdminClient(
767  "unused-project", google::cloud::bigtable::ClientOptions()),
768  "Unused-instance");
769  for (auto&& kv : commands) {
770  try {
771  int fake_argc = 0;
772  kv.second(unused, fake_argc, argv);
773  } catch (Usage const& u) {
774  command_usage += " ";
775  command_usage += u.msg;
776  command_usage += "\n";
777  } catch (...) {
778  // ignore other exceptions.
779  }
780  }
781  }
782 
783  if (argc < 4) {
784  PrintUsage(argc, argv, "Missing command and/or project-id/ or instance-id");
785  return 1;
786  }
787 
788  std::string const command_name = ConsumeArg(argc, argv);
789  std::string const project_id = ConsumeArg(argc, argv);
790  std::string const instance_id = ConsumeArg(argc, argv);
791 
792  auto command = commands.find(command_name);
793  if (commands.end() == command) {
794  PrintUsage(argc, argv, "Unknown command: " + command_name);
795  return 1;
796  }
797 
798  // Connect to the Cloud Bigtable admin endpoint.
799  //! [connect admin]
800  google::cloud::bigtable::TableAdmin admin(
801  google::cloud::bigtable::CreateDefaultAdminClient(
802  project_id, google::cloud::bigtable::ClientOptions()),
803  instance_id);
804  //! [connect admin]
805 
806  command->second(admin, argc, argv);
807 
808  return 0;
809 } catch (Usage const& ex) {
810  PrintUsage(argc, argv, ex.msg);
811  return 1;
812 } catch (std::exception const& ex) {
813  std::cerr << "Standard C++ exception raised: " << ex.what() << "\n";
814  return 1;
815 }
816 //! [all code]