1 // Copyright 2020 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 #include "google/cloud/bigtable/examples/bigtable_examples_common.h"
16 #include "google/cloud/bigtable/table.h"
17 #include "google/cloud/bigtable/table_admin.h"
18 #include "google/cloud/internal/getenv.h"
19 #include "google/cloud/internal/random.h"
20 #include "google/cloud/testing_util/crash_handler.h"
21 #include <chrono>
22 #include <sstream>
23 
24 namespace {
25 
26 using google::cloud::bigtable::examples::Usage;
27 using std::chrono::microseconds;
28 using std::chrono::milliseconds;
29 
FilterLimitRowSample(google::cloud::bigtable::Table table,std::vector<std::string> const &)30 void FilterLimitRowSample(google::cloud::bigtable::Table table,
31                           std::vector<std::string> const&) {
32   //! [START bigtable_filters_limit_row_sample]
33   namespace cbt = google::cloud::bigtable;
34   using google::cloud::StatusOr;
35   [](cbt::Table table) {
36     // Filter the results, only include rows with a given probability
37     cbt::Filter filter = cbt::Filter::RowSample(0.75);
38 
39     // Read and print the rows.
40     for (StatusOr<cbt::Row> const& row :
41          table.ReadRows(cbt::RowSet(cbt::RowRange::InfiniteRange()), filter)) {
42       if (!row) throw std::runtime_error(row.status().message());
43       std::cout << row->row_key() << " = ";
44       for (auto const& cell : row->cells()) {
45         std::cout << "[" << cell.family_name() << ", "
46                   << cell.column_qualifier() << ", " << cell.value() << "],";
47       }
48       std::cout << "\n";
49     }
50   }
51   //! [END bigtable_filters_limit_row_sample]
52   (std::move(table));
53 }
54 
FilterLimitRowRegex(google::cloud::bigtable::Table table,std::vector<std::string> const &)55 void FilterLimitRowRegex(google::cloud::bigtable::Table table,
56                          std::vector<std::string> const&) {
57   //! [START bigtable_filters_limit_row_regex]
58   namespace cbt = google::cloud::bigtable;
59   using google::cloud::StatusOr;
60   [](cbt::Table table) {
61     // Create the range of rows to read.
62     auto range = cbt::RowRange::Range("key-000010", "key-000030");
63     // Filter the results, only include rows where row_key matchs given regular
64     // expression
65     cbt::Filter filter = cbt::Filter::RowKeysRegex("key.*9$");
66     // Read and print the rows.
67     for (StatusOr<cbt::Row> const& row : table.ReadRows(range, filter)) {
68       if (!row) throw std::runtime_error(row.status().message());
69       std::cout << row->row_key() << " = ";
70       for (auto const& cell : row->cells()) {
71         std::cout << "[" << cell.family_name() << ", "
72                   << cell.column_qualifier() << ", " << cell.value() << "],";
73       }
74       std::cout << "\n";
75     }
76   }
77   //! [END bigtable_filters_limit_row_regex]
78   (std::move(table));
79 }
80 
FilterLimitCellsPerColumn(google::cloud::bigtable::Table table,std::vector<std::string> const &)81 void FilterLimitCellsPerColumn(google::cloud::bigtable::Table table,
82                                std::vector<std::string> const&) {
83   //! [START bigtable_filters_limit_cells_per_col]
84   namespace cbt = google::cloud::bigtable;
85   using google::cloud::StatusOr;
86   [](cbt::Table table) {
87     // Create the range of rows to read.
88     auto range = cbt::RowRange::Range("key-000010", "key-000020");
89     // Filter the results, only include limited cells
90     cbt::Filter filter = cbt::Filter::Latest(2);
91     // Read and print the rows.
92     for (StatusOr<cbt::Row> const& row : table.ReadRows(range, filter)) {
93       if (!row) throw std::runtime_error(row.status().message());
94       std::cout << row->row_key() << " = ";
95       for (auto const& cell : row->cells()) {
96         std::cout << "[" << cell.family_name() << ", "
97                   << cell.column_qualifier() << ", " << cell.value() << "],";
98       }
99       std::cout << "\n";
100     }
101   }
102   //! [END bigtable_filters_limit_cells_per_col]
103   (std::move(table));
104 }
105 
FilterLimitCellsPerRow(google::cloud::bigtable::Table table,std::vector<std::string> const &)106 void FilterLimitCellsPerRow(google::cloud::bigtable::Table table,
107                             std::vector<std::string> const&) {
108   //! [START bigtable_filters_limit_cells_per_row]
109   namespace cbt = google::cloud::bigtable;
110   using google::cloud::StatusOr;
111   [](cbt::Table table) {
112     // Create the range of rows to read.
113     auto range = cbt::RowRange::Range("key-000010", "key-000020");
114     // Filter the results, only include limited cells per row
115     cbt::Filter filter = cbt::Filter::CellsRowLimit(2);
116     // Read and print the rows.
117     for (StatusOr<cbt::Row> const& row : table.ReadRows(range, filter)) {
118       if (!row) throw std::runtime_error(row.status().message());
119       std::cout << row->row_key() << " = ";
120       for (auto const& cell : row->cells()) {
121         std::cout << "[" << cell.family_name() << ", "
122                   << cell.column_qualifier() << ", " << cell.value() << "],";
123       }
124       std::cout << "\n";
125     }
126   }
127   //! [END bigtable_filters_limit_cells_per_row]
128   (std::move(table));
129 }
130 
FilterLimitCellsPerRowOfset(google::cloud::bigtable::Table table,std::vector<std::string> const &)131 void FilterLimitCellsPerRowOfset(google::cloud::bigtable::Table table,
132                                  std::vector<std::string> const&) {
133   //! [START bigtable_filters_limit_cells_per_row_offset]
134   namespace cbt = google::cloud::bigtable;
135   using google::cloud::StatusOr;
136   [](cbt::Table table) {
137     // Create the range of rows to read.
138     auto range = cbt::RowRange::Range("key-000010", "key-000020");
139     cbt::Filter filter = cbt::Filter::CellsRowOffset(2);
140     // Read and print the rows.
141     for (StatusOr<cbt::Row> const& row : table.ReadRows(range, filter)) {
142       if (!row) throw std::runtime_error(row.status().message());
143       std::cout << row->row_key() << " = ";
144       for (auto const& cell : row->cells()) {
145         std::cout << "[" << cell.family_name() << ", "
146                   << cell.column_qualifier() << ", " << cell.value() << "],";
147       }
148       std::cout << "\n";
149     }
150   }
151   //! [END bigtable_filters_limit_cells_per_row_offset]
152   (std::move(table));
153 }
154 
FilterLimitColFamilyRegex(google::cloud::bigtable::Table table,std::vector<std::string> const &)155 void FilterLimitColFamilyRegex(google::cloud::bigtable::Table table,
156                                std::vector<std::string> const&) {
157   //! [START bigtable_filters_limit_col_family_regex]
158   namespace cbt = google::cloud::bigtable;
159   using google::cloud::StatusOr;
160   [](cbt::Table table) {
161     // Create the range of rows to read.
162     auto range = cbt::RowRange::Range("key-000011", "key-000015");
163     cbt::Filter filter = cbt::Filter::FamilyRegex("fam-1.*");
164     // Read and print the rows.
165     for (StatusOr<cbt::Row> const& row : table.ReadRows(range, filter)) {
166       if (!row) throw std::runtime_error(row.status().message());
167       std::cout << row->row_key() << " = ";
168       for (auto const& cell : row->cells()) {
169         std::cout << "[" << cell.family_name() << ", "
170                   << cell.column_qualifier() << ", " << cell.value() << "],";
171       }
172       std::cout << "\n";
173     }
174   }
175   //! [END bigtable_filters_limit_col_family_regex]
176   (std::move(table));
177 }
178 
FilterLimitColQualifierRegex(google::cloud::bigtable::Table table,std::vector<std::string> const &)179 void FilterLimitColQualifierRegex(google::cloud::bigtable::Table table,
180                                   std::vector<std::string> const&) {
181   //! [START bigtable_filters_limit_col_qualifier_regex]
182   namespace cbt = google::cloud::bigtable;
183   using google::cloud::StatusOr;
184   [](cbt::Table table) {
185     // Create the range of rows to read.
186     auto range = cbt::RowRange::Range("key-000011", "key-000015");
187     cbt::Filter filter = cbt::Filter::ColumnRegex("col-[a,b].*$");
188     // Read and print the rows.
189     for (StatusOr<cbt::Row> const& row : table.ReadRows(range, filter)) {
190       if (!row) throw std::runtime_error(row.status().message());
191       std::cout << row->row_key() << " = ";
192       for (auto const& cell : row->cells()) {
193         std::cout << "[" << cell.family_name() << ", "
194                   << cell.column_qualifier() << ", " << cell.value() << "],";
195       }
196       std::cout << "\n";
197     }
198   }
199   //! [END bigtable_filters_limit_col_qualifier_regex]
200   (std::move(table));
201 }
202 
FilterLimitColRange(google::cloud::bigtable::Table table,std::vector<std::string> const &)203 void FilterLimitColRange(google::cloud::bigtable::Table table,
204                          std::vector<std::string> const&) {
205   //! [START bigtable_filters_limit_col_range]
206   namespace cbt = google::cloud::bigtable;
207   using google::cloud::StatusOr;
208   [](cbt::Table table) {
209     // Create the range of rows to read.
210     auto range = cbt::RowRange::Range("key-000011", "key-000015");
211     cbt::Filter filter = cbt::Filter::ColumnRange("fam-0", "col-a", "col-c");
212     // Read and print the rows.
213     for (StatusOr<cbt::Row> const& row : table.ReadRows(range, filter)) {
214       if (!row) throw std::runtime_error(row.status().message());
215       std::cout << row->row_key() << " = ";
216       for (auto const& cell : row->cells()) {
217         std::cout << "[" << cell.family_name() << ", "
218                   << cell.column_qualifier() << ", " << cell.value() << "],";
219       }
220       std::cout << "\n";
221     }
222   }
223   //! [END bigtable_filters_limit_col_range]
224   (std::move(table));
225 }
226 
FilterLimitValueRange(google::cloud::bigtable::Table table,std::vector<std::string> const &)227 void FilterLimitValueRange(google::cloud::bigtable::Table table,
228                            std::vector<std::string> const&) {
229   //! [START bigtable_filters_limit_value_range]
230   namespace cbt = google::cloud::bigtable;
231   using google::cloud::StatusOr;
232   [](cbt::Table table) {
233     // Create the range of rows to read.
234     auto range = cbt::RowRange::Range("key-000011", "key-000015");
235     cbt::Filter filter = cbt::Filter::ValueRange("value-0", "value-2");
236     // Read and print the rows.
237     for (StatusOr<cbt::Row> const& row : table.ReadRows(range, filter)) {
238       if (!row) throw std::runtime_error(row.status().message());
239       std::cout << row->row_key() << " = ";
240       for (auto const& cell : row->cells()) {
241         std::cout << "[" << cell.family_name() << ", "
242                   << cell.column_qualifier() << ", " << cell.value() << "],";
243       }
244       std::cout << "\n";
245     }
246   }
247   //! [END bigtable_filters_limit_value_range]
248   (std::move(table));
249 }
250 
FilterLimitValueRegex(google::cloud::bigtable::Table table,std::vector<std::string> const &)251 void FilterLimitValueRegex(google::cloud::bigtable::Table table,
252                            std::vector<std::string> const&) {
253   //! [START bigtable_filters_limit_value_regex]
254   namespace cbt = google::cloud::bigtable;
255   using google::cloud::StatusOr;
256   [](cbt::Table table) {
257     // Create the range of rows to read.
258     auto range = cbt::RowRange::Range("key-000011", "key-000015");
259     cbt::Filter filter = cbt::Filter::ValueRegex("value-0.*");
260     // Read and print the rows.
261     for (StatusOr<cbt::Row> const& row : table.ReadRows(range, filter)) {
262       if (!row) throw std::runtime_error(row.status().message());
263       std::cout << row->row_key() << " = ";
264       for (auto const& cell : row->cells()) {
265         std::cout << "[" << cell.family_name() << ", "
266                   << cell.column_qualifier() << ", " << cell.value() << "],";
267       }
268       std::cout << "\n";
269     }
270   }
271   //! [END bigtable_filters_limit_value_regex]
272   (std::move(table));
273 }
274 
FilterLimitTimestampRange(google::cloud::bigtable::Table table,std::vector<std::string> const &)275 void FilterLimitTimestampRange(google::cloud::bigtable::Table table,
276                                std::vector<std::string> const&) {
277   //! [START bigtable_filters_limit_timestamp_range]
278   namespace cbt = google::cloud::bigtable;
279   using google::cloud::StatusOr;
280   [](cbt::Table table) {
281     // Create the range of rows to read.
282     auto range = cbt::RowRange::Range("key-000011", "key-000015");
283     cbt::Filter filter =
284         cbt::Filter::TimestampRange(microseconds(1000), milliseconds(2));
285     // Read and print the rows.
286     for (StatusOr<cbt::Row> const& row : table.ReadRows(range, filter)) {
287       if (!row) throw std::runtime_error(row.status().message());
288       std::cout << row->row_key() << " = ";
289       for (auto const& cell : row->cells()) {
290         std::cout << "[" << cell.family_name() << ", "
291                   << cell.column_qualifier() << ", " << cell.value() << "],";
292       }
293       std::cout << "\n";
294     }
295   }
296   //! [END bigtable_filters_limit_timestamp_range]
297   (std::move(table));
298 }
299 
FilterLimitBlockAll(google::cloud::bigtable::Table table,std::vector<std::string> const &)300 void FilterLimitBlockAll(google::cloud::bigtable::Table table,
301                          std::vector<std::string> const&) {
302   //! [START bigtable_filters_limit_block_all]
303   namespace cbt = google::cloud::bigtable;
304   using google::cloud::StatusOr;
305   [](cbt::Table table) {
306     // Create the range of rows to read.
307     auto range = cbt::RowRange::Range("key-000000", "key-000050");
308     cbt::Filter filter = cbt::Filter::BlockAllFilter();
309     // Read and print the rows.
310     for (StatusOr<cbt::Row> const& row : table.ReadRows(range, filter)) {
311       if (!row) throw std::runtime_error(row.status().message());
312       std::cout << row->row_key();
313       std::cout << row->row_key() << " = ";
314       for (auto const& cell : row->cells()) {
315         std::cout << "[" << cell.family_name() << ", "
316                   << cell.column_qualifier() << ", " << cell.value() << "],";
317       }
318       std::cout << "\n";
319     }
320   }
321   //! [END bigtable_filters_limit_block_all]
322   (std::move(table));
323 }
324 
FilterLimitPassAll(google::cloud::bigtable::Table table,std::vector<std::string> const &)325 void FilterLimitPassAll(google::cloud::bigtable::Table table,
326                         std::vector<std::string> const&) {
327   //! [START bigtable_filters_limit_pass_all]
328   namespace cbt = google::cloud::bigtable;
329   using google::cloud::StatusOr;
330   [](cbt::Table table) {
331     // Create the range of rows to read.
332     auto range = cbt::RowRange::Range("key-000011", "key-000015");
333     cbt::Filter filter = cbt::Filter::PassAllFilter();
334     // Read and print the rows.
335     for (StatusOr<cbt::Row> const& row : table.ReadRows(range, filter)) {
336       if (!row) throw std::runtime_error(row.status().message());
337       std::cout << row->row_key() << " = ";
338       for (auto const& cell : row->cells()) {
339         std::cout << "[" << cell.family_name() << ", "
340                   << cell.column_qualifier() << ", " << cell.value() << "],";
341       }
342       std::cout << "\n";
343     }
344   }
345   //! [END bigtable_filters_limit_pass_all]
346   (std::move(table));
347 }
348 
FilterModifyStripValue(google::cloud::bigtable::Table table,std::vector<std::string> const &)349 void FilterModifyStripValue(google::cloud::bigtable::Table table,
350                             std::vector<std::string> const&) {
351   //! [START bigtable_filters_modify_strip_value]
352   namespace cbt = google::cloud::bigtable;
353   using google::cloud::StatusOr;
354   [](cbt::Table table) {
355     // Create the range of rows to read.
356     auto range = cbt::RowRange::Range("key-000011", "key-000015");
357     cbt::Filter filter = cbt::Filter::StripValueTransformer();
358     // Read and print the rows.
359     for (StatusOr<cbt::Row> const& row : table.ReadRows(range, filter)) {
360       if (!row) throw std::runtime_error(row.status().message());
361       std::cout << row->row_key() << " = ";
362       for (auto const& cell : row->cells()) {
363         std::cout << "[" << cell.family_name() << ", "
364                   << cell.column_qualifier() << ", " << cell.value() << "],";
365       }
366       std::cout << "\n";
367     }
368   }
369   //! [END bigtable_filters_modify_strip_value]
370   (std::move(table));
371 }
372 
FilterModifyApplyLabel(google::cloud::bigtable::Table table,std::vector<std::string> const &)373 void FilterModifyApplyLabel(google::cloud::bigtable::Table table,
374                             std::vector<std::string> const&) {
375   //! [START bigtable_filters_modify_apply_label]
376   namespace cbt = google::cloud::bigtable;
377   using google::cloud::StatusOr;
378   [](cbt::Table table) {
379     // Create the range of rows to read.
380     auto range = cbt::RowRange::Range("key-000011", "key-000015");
381     cbt::Filter filter = cbt::Filter::ApplyLabelTransformer("label-value");
382     // Read and print the rows.
383     for (StatusOr<cbt::Row> const& row : table.ReadRows(range, filter)) {
384       if (!row) throw std::runtime_error(row.status().message());
385       std::cout << row->row_key() << " = ";
386       for (auto const& cell : row->cells()) {
387         std::cout << "[" << cell.family_name() << ", "
388                   << cell.column_qualifier() << ", " << cell.value()
389                   << ", label(";
390         for (auto const& label : cell.labels()) {
391           std::cout << label << ",";
392         }
393         std::cout << ")],";
394       }
395       std::cout << "\n";
396     }
397   }
398   //! [END bigtable_filters_modify_apply_label]
399   (std::move(table));
400 }
401 
FilterComposingChain(google::cloud::bigtable::Table table,std::vector<std::string> const &)402 void FilterComposingChain(google::cloud::bigtable::Table table,
403                           std::vector<std::string> const&) {
404   //! [START bigtable_filters_composing_chain]
405   namespace cbt = google::cloud::bigtable;
406   using google::cloud::StatusOr;
407   [](cbt::Table table) {
408     // Create the range of rows to read.
409     auto range = cbt::RowRange::Range("key-000011", "key-000015");
410     cbt::Filter filter = cbt::Filter::Chain(cbt::Filter::Latest(1),
411                                             cbt::Filter::FamilyRegex("fam-0"));
412     // Read and print the rows.
413     for (StatusOr<cbt::Row> const& row : table.ReadRows(range, filter)) {
414       if (!row) throw std::runtime_error(row.status().message());
415       std::cout << row->row_key() << " = ";
416       for (auto const& cell : row->cells()) {
417         std::cout << "[" << cell.family_name() << ", "
418                   << cell.column_qualifier() << ", " << cell.value() << "],";
419       }
420       std::cout << "\n";
421     }
422   }
423   //! [END bigtable_filters_composing_chain]
424   (std::move(table));
425 }
426 
FilterComposingInterleave(google::cloud::bigtable::Table table,std::vector<std::string> const &)427 void FilterComposingInterleave(google::cloud::bigtable::Table table,
428                                std::vector<std::string> const&) {
429   //! [START bigtable_filters_composing_interleave]
430   namespace cbt = google::cloud::bigtable;
431   using google::cloud::StatusOr;
432   [](cbt::Table table) {
433     // Create the range of rows to read.
434     auto range = cbt::RowRange::Range("key-000011", "key-000015");
435     cbt::Filter filter = cbt::Filter::Interleave(
436         cbt::Filter::FamilyRegex("fam-1"), cbt::Filter::ColumnRegex("col-c"));
437     // Read and print the rows.
438     for (StatusOr<cbt::Row> const& row : table.ReadRows(range, filter)) {
439       if (!row) throw std::runtime_error(row.status().message());
440       std::cout << row->row_key() << " = ";
441       for (auto const& cell : row->cells()) {
442         std::cout << "[" << cell.family_name() << ", "
443                   << cell.column_qualifier() << ", " << cell.value() << "],";
444       }
445       std::cout << "\n";
446     }
447   }
448   //! [END bigtable_filters_composing_interleave]
449   (std::move(table));
450 }
451 
FilterComposingCondition(google::cloud::bigtable::Table table,std::vector<std::string> const &)452 void FilterComposingCondition(google::cloud::bigtable::Table table,
453                               std::vector<std::string> const&) {
454   //! [START bigtable_filters_composing_condition]
455   namespace cbt = google::cloud::bigtable;
456   using google::cloud::StatusOr;
457   [](cbt::Table table) {
458     // Create the range of rows to read.
459     auto range = cbt::RowRange::Range("key-000000", "key-000005");
460     cbt::Filter filter = cbt::Filter::Condition(
461         cbt::Filter::Chain(cbt::Filter::FamilyRegex("fam-0"),
462                            cbt::Filter::ColumnRegex("col-a")),
463         cbt::Filter::ApplyLabelTransformer("condition"),
464         cbt::Filter::StripValueTransformer());
465     // Read and print the rows.
466     for (StatusOr<cbt::Row> const& row : table.ReadRows(range, filter)) {
467       if (!row) throw std::runtime_error(row.status().message());
468       std::cout << row->row_key() << " = ";
469       for (auto const& cell : row->cells()) {
470         std::cout << "[" << cell.family_name() << ", "
471                   << cell.column_qualifier() << ", " << cell.value()
472                   << ", label(";
473         for (auto const& label : cell.labels()) {
474           std::cout << label << ",";
475         }
476         std::cout << ")],";
477       }
478       std::cout << "\n";
479     }
480   }
481   //! [END bigtable_filters_composing_condition]
482   (std::move(table));
483 }
484 
485 // This command just generates data suitable for other examples to run. This
486 // code is not extracted into the documentation.
InsertTestData(google::cloud::bigtable::Table table,std::vector<std::string> const &)487 void InsertTestData(google::cloud::bigtable::Table table,
488                     std::vector<std::string> const&) {
489   // Write several rows in a single operation, each row has some trivial data.
490   // This is not a code sample in the normal sense, we do not display this code
491   // in the documentation. We use it to populate data in the table used to run
492   // the actual examples during the CI builds.
493   namespace cbt = google::cloud::bigtable;
494   cbt::BulkMutation bulk;
495   for (int i = 0; i != 50; ++i) {
496     // Note: This example uses sequential numeric IDs for simplicity, but
497     // this can result in poor performance in a production application.
498     // Since rows are stored in sorted order by key, sequential keys can
499     // result in poor distribution of operations across nodes.
500     //
501     // For more information about how to design a Bigtable schema for the
502     // best performance, see the documentation:
503     //
504     //     https://cloud.google.com/bigtable/docs/schema-design
505     char buf[32];
506     snprintf(buf, sizeof(buf), "key-%06d", i);
507     cbt::SingleRowMutation mutation(buf);
508     mutation.emplace_back(cbt::SetCell("fam-0", "col-a", milliseconds(1),
509                                        "value-0-" + std::to_string(i)));
510     mutation.emplace_back(cbt::SetCell("fam-0", "col-a", milliseconds(2),
511                                        "value-1-" + std::to_string(i)));
512     mutation.emplace_back(cbt::SetCell("fam-0", "col-b", milliseconds(1),
513                                        "value-0-" + std::to_string(i)));
514     mutation.emplace_back(cbt::SetCell("fam-0", "col-c", milliseconds(1),
515                                        "value-0-" + std::to_string(i)));
516     mutation.emplace_back(cbt::SetCell("fam-0", "col-c", milliseconds(2),
517                                        "value-1-" + std::to_string(i)));
518     mutation.emplace_back(cbt::SetCell("fam-0", "col-c", milliseconds(3),
519                                        "value-2-" + std::to_string(i)));
520     mutation.emplace_back(cbt::SetCell("fam-1", "col-a", milliseconds(1),
521                                        "value-0-" + std::to_string(i)));
522     bulk.emplace_back(std::move(mutation));
523   }
524   auto failures = table.BulkApply(std::move(bulk));
525   if (failures.empty()) {
526     return;
527   }
528   std::cerr << "The following mutations failed:\n";
529   for (auto const& f : failures) {
530     std::cerr << "index[" << f.original_index() << "]=" << f.status() << "\n";
531   }
532   throw std::runtime_error(failures.front().status().message());
533 }
534 
DefaultTablePrefix()535 std::string DefaultTablePrefix() { return "tbl-data-"; }
536 
RunAll(std::vector<std::string> const & argv)537 void RunAll(std::vector<std::string> const& argv) {
538   namespace examples = ::google::cloud::bigtable::examples;
539   namespace cbt = google::cloud::bigtable;
540 
541   if (!argv.empty()) throw google::cloud::bigtable::examples::Usage{"auto"};
542   examples::CheckEnvironmentVariablesAreSet({
543       "GOOGLE_CLOUD_PROJECT",
544       "GOOGLE_CLOUD_CPP_BIGTABLE_TEST_INSTANCE_ID",
545   });
546   auto const project_id =
547       google::cloud::internal::GetEnv("GOOGLE_CLOUD_PROJECT").value();
548   auto const instance_id = google::cloud::internal::GetEnv(
549                                "GOOGLE_CLOUD_CPP_BIGTABLE_TEST_INSTANCE_ID")
550                                .value();
551 
552   cbt::TableAdmin admin(
553       cbt::CreateDefaultAdminClient(project_id, cbt::ClientOptions{}),
554       instance_id);
555 
556   // If a previous run of these samples crashes before cleaning up there may be
557   // old tables left over. As there are quotas on the total number of tables we
558   // remove stale tables after 48 hours.
559   examples::CleanupOldTables(DefaultTablePrefix(), admin);
560   examples::CleanupOldTables("mobile-time-series-", admin);
561 
562   // Initialize a generator with some amount of entropy.
563   auto generator = google::cloud::internal::DefaultPRNG(std::random_device{}());
564 
565   auto table_id = examples::RandomTableId(DefaultTablePrefix(), generator);
566   auto schema = admin.CreateTable(
567       table_id, cbt::TableConfig({{"fam-0", cbt::GcRule::MaxNumVersions(10)},
568                                   {"fam-1", cbt::GcRule::MaxNumVersions(10)}},
569                                  {}));
570   if (!schema) throw std::runtime_error(schema.status().message());
571 
572   google::cloud::bigtable::Table table(
573       google::cloud::bigtable::CreateDefaultDataClient(
574           admin.project(), admin.instance_id(),
575           google::cloud::bigtable::ClientOptions()),
576       table_id);
577 
578   std::cout << "\nPreparing data for multiple examples" << std::endl;
579   InsertTestData(table, {});
580   std::cout << "Running FilterLimitRowSample() example [1]" << std::endl;
581   FilterLimitRowSample(table, {});
582   std::cout << "Running FilterLimitRowRegex() example [2]" << std::endl;
583   FilterLimitRowRegex(table, {});
584   std::cout << "Running FilterLimitCellsPerColumn() example [3]" << std::endl;
585   FilterLimitCellsPerColumn(table, {});
586   std::cout << "Running FilterLimitCellsPerRow() example [4]" << std::endl;
587   FilterLimitCellsPerRow(table, {});
588   std::cout << "Running FilterLimitCellsPerRowOffset() example [5]"
589             << std::endl;
590   FilterLimitCellsPerRowOfset(table, {});
591   std::cout << "Running FilterLimitColFamilyRegex() example [6]" << std::endl;
592   FilterLimitColFamilyRegex(table, {});
593   std::cout << "Running FilterLimitColQualifierRegex() example [7]"
594             << std::endl;
595   FilterLimitColQualifierRegex(table, {});
596   std::cout << "Running FilterLimitColRange() example [8]" << std::endl;
597   FilterLimitColRange(table, {});
598   std::cout << "Running FilterLimitValueRange() example [9]" << std::endl;
599   FilterLimitValueRange(table, {});
600   std::cout << "Running FilterLimitValueRegex() example [10]" << std::endl;
601   FilterLimitValueRegex(table, {});
602   std::cout << "Running FilterLimitTimestampRange() example [11]" << std::endl;
603   FilterLimitTimestampRange(table, {});
604   std::cout << "Running FilterLimitBlockAll() example [12]" << std::endl;
605   FilterLimitBlockAll(table, {});
606   std::cout << "Running FilterLimitPassAll() example [13]" << std::endl;
607   FilterLimitPassAll(table, {});
608   std::cout << "Running FilterModifyStripValue() example [14]" << std::endl;
609   FilterModifyStripValue(table, {});
610   std::cout << "Running FilterModifyApplyLabel() example [15]" << std::endl;
611   FilterModifyApplyLabel(table, {});
612   std::cout << "Running FilterComposingChain() example [16]" << std::endl;
613   FilterComposingChain(table, {});
614   std::cout << "Running FilterComposingInterleave() example [17]" << std::endl;
615   FilterComposingInterleave(table, {});
616   std::cout << "Running FilterComposingCondition() example [18]" << std::endl;
617   FilterComposingCondition(table, {});
618   admin.DeleteTable(table_id);
619 }
620 
621 }  // anonymous namespace
622 
main(int argc,char * argv[])623 int main(int argc, char* argv[]) {
624   google::cloud::testing_util::InstallCrashHandler(argv[0]);
625 
626   using google::cloud::bigtable::examples::MakeCommandEntry;
627   google::cloud::bigtable::examples::Commands commands = {
628       MakeCommandEntry("insert-test-data", {}, InsertTestData),
629       MakeCommandEntry("filter-limit-row-sample", {}, FilterLimitRowSample),
630       MakeCommandEntry("filter-limit-row-regex", {}, FilterLimitRowRegex),
631       MakeCommandEntry("filter-limit-cells-per-column", {},
632                        FilterLimitCellsPerColumn),
633       MakeCommandEntry("filter-limit-cells-per-row", {},
634                        FilterLimitCellsPerRow),
635       MakeCommandEntry("filter-limit-cells-per-row-offset", {},
636                        FilterLimitCellsPerRowOfset),
637       MakeCommandEntry("filters-limit-col-family-regex", {},
638                        FilterLimitColFamilyRegex),
639       MakeCommandEntry("filters-limit-col-qualifier-regex", {},
640                        FilterLimitColQualifierRegex),
641       MakeCommandEntry("filters-limit-col-range", {}, FilterLimitColRange),
642       MakeCommandEntry("filters-limit-value-range", {}, FilterLimitValueRange),
643       MakeCommandEntry("filters-limit-value-regex", {}, FilterLimitValueRegex),
644       MakeCommandEntry("filters-limit-timestamp-range", {},
645                        FilterLimitTimestampRange),
646       MakeCommandEntry("filters-limit-block-all", {}, FilterLimitBlockAll),
647       MakeCommandEntry("filters-limit-pass-all", {}, FilterLimitPassAll),
648       MakeCommandEntry("filters-modify-strip-value", {},
649                        FilterModifyStripValue),
650       MakeCommandEntry("filters-modify-apply-label", {},
651                        FilterModifyApplyLabel),
652       MakeCommandEntry("filters-composing-chain", {}, FilterComposingChain),
653       MakeCommandEntry("filters-composing-interleave", {},
654                        FilterComposingInterleave),
655       MakeCommandEntry("filters-composing-condition", {},
656                        FilterComposingCondition),
657       {"auto", RunAll},
658   };
659 
660   google::cloud::bigtable::examples::Example example(std::move(commands));
661   return example.Run(argc, argv);
662 }
663