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] [START bigtable_hw_imports]
18 #include "google/cloud/bigtable/table.h"
19 #include "google/cloud/bigtable/table_admin.h"
20 //! [bigtable includes] [END bigtable_hw_imports]
21 #include "google/cloud/bigtable/examples/bigtable_examples_common.h"
22 #include "google/cloud/internal/getenv.h"
23 #include "google/cloud/internal/random.h"
24 #include "google/cloud/testing_util/crash_handler.h"
25 #include <iostream>
26 
27 namespace {
28 
29 using google::cloud::bigtable::examples::Usage;
30 
BigtableHelloWorld(std::vector<std::string> const & argv)31 void BigtableHelloWorld(std::vector<std::string> const& argv) {
32   if (argv.size() != 3) {
33     throw Usage{"hello-world <project-id> <instance-id> <table-id>"};
34   }
35   std::string const project_id = argv[0];
36   std::string const instance_id = argv[1];
37   std::string const table_id = argv[2];
38 
39   // Create a namespace alias to make the code easier to read.
40   //! [aliases]
41   namespace cbt = google::cloud::bigtable;
42   using google::cloud::StatusOr;
43   //! [aliases]
44 
45   // Connect to the Cloud Bigtable Admin API.
46   //! [connect admin] [START bigtable_hw_connect]
47   cbt::TableAdmin table_admin(
48       cbt::CreateDefaultAdminClient(project_id, cbt::ClientOptions()),
49       instance_id);
50   //! [connect admin] [END bigtable_hw_connect]
51 
52   //! [create table] [START bigtable_hw_create_table]
53   // Define the desired schema for the Table.
54   cbt::GcRule gc_rule = cbt::GcRule::MaxNumVersions(1);
55   cbt::TableConfig schema({{"family", gc_rule}}, {});
56 
57   // Create a table.
58   StatusOr<google::bigtable::admin::v2::Table> returned_schema =
59       table_admin.CreateTable(table_id, schema);
60   //! [create table]
61 
62   // Create an object to access the Cloud Bigtable Data API.
63   //! [connect data]
64   cbt::Table table(cbt::CreateDefaultDataClient(project_id, instance_id,
65                                                 cbt::ClientOptions()),
66                    table_id);
67   //! [connect data] [END bigtable_hw_create_table]
68 
69   // Modify (and create if necessary) a row.
70   //! [write rows] [START bigtable_hw_write_rows]
71   std::vector<std::string> greetings{"Hello World!", "Hello Cloud Bigtable!",
72                                      "Hello C++!"};
73   int i = 0;
74   for (auto const& greeting : greetings) {
75     // Each row has a unique row key.
76     //
77     // Note: This example uses sequential numeric IDs for simplicity, but
78     // this can result in poor performance in a production application.
79     // Since rows are stored in sorted order by key, sequential keys can
80     // result in poor distribution of operations across nodes.
81     //
82     // For more information about how to design a Bigtable schema for the
83     // best performance, see the documentation:
84     //
85     //     https://cloud.google.com/bigtable/docs/schema-design
86     std::string row_key = "key-" + std::to_string(i);
87     google::cloud::Status status = table.Apply(cbt::SingleRowMutation(
88         std::move(row_key), cbt::SetCell("family", "c0", greeting)));
89 
90     if (!status.ok()) throw std::runtime_error(status.message());
91     ++i;
92   }
93   //! [write rows] [END bigtable_hw_write_rows]
94 
95   //! [create filter] [START bigtable_hw_create_filter]
96   cbt::Filter filter = cbt::Filter::ColumnRangeClosed("family", "c0", "c0");
97   //! [create filter] [END bigtable_hw_create_filter]
98 
99   // Read a single row.
100   //! [read row] [START bigtable_hw_get_with_filter]
101   StatusOr<std::pair<bool, cbt::Row>> result = table.ReadRow("key-0", filter);
102   if (!result) throw std::runtime_error(result.status().message());
103   if (!result->first) {
104     std::cout << "Cannot find row 'key-0' in the table: " << table.table_name()
105               << "\n";
106     return;
107   }
108   cbt::Cell const& cell = result->second.cells().front();
109   std::cout << cell.family_name() << ":" << cell.column_qualifier() << "    @ "
110             << cell.timestamp().count() << "us\n"
111             << '"' << cell.value() << '"' << "\n";
112   //! [read row] [END bigtable_hw_get_with_filter]
113 
114   // Read all rows.
115   //! [scan all] [START bigtable_hw_scan_with_filter]
116   for (StatusOr<cbt::Row> const& row : table.ReadRows(
117            cbt::RowRange::InfiniteRange(), cbt::Filter::PassAllFilter())) {
118     if (!row) throw std::runtime_error(row.status().message());
119     std::cout << row->row_key() << ":\n";
120     for (cbt::Cell const& c : row->cells()) {
121       std::cout << "\t" << c.family_name() << ":" << c.column_qualifier()
122                 << "    @ " << c.timestamp().count() << "us\n"
123                 << "\t\"" << c.value() << '"' << "\n";
124     }
125   }
126   //! [scan all] [END bigtable_hw_scan_with_filter]
127 
128   // Delete the table
129   //! [delete table] [START bigtable_hw_delete_table]
130   google::cloud::Status status = table_admin.DeleteTable(table_id);
131   if (!status.ok()) throw std::runtime_error(status.message());
132   //! [delete table] [END bigtable_hw_delete_table]
133 }
134 
RunAll(std::vector<std::string> const & argv)135 void RunAll(std::vector<std::string> const& argv) {
136   namespace examples = ::google::cloud::bigtable::examples;
137   namespace cbt = google::cloud::bigtable;
138 
139   if (!argv.empty()) throw Usage{"auto"};
140   if (!examples::RunAdminIntegrationTests()) return;
141   examples::CheckEnvironmentVariablesAreSet({
142       "GOOGLE_CLOUD_PROJECT",
143       "GOOGLE_CLOUD_CPP_BIGTABLE_TEST_INSTANCE_ID",
144   });
145   auto const project_id =
146       google::cloud::internal::GetEnv("GOOGLE_CLOUD_PROJECT").value();
147   auto const instance_id = google::cloud::internal::GetEnv(
148                                "GOOGLE_CLOUD_CPP_BIGTABLE_TEST_INSTANCE_ID")
149                                .value();
150 
151   cbt::TableAdmin admin(
152       cbt::CreateDefaultAdminClient(project_id, cbt::ClientOptions{}),
153       instance_id);
154 
155   examples::CleanupOldTables("hw-tbl-", admin);
156 
157   auto generator = google::cloud::internal::DefaultPRNG(std::random_device{}());
158   auto table_id = examples::RandomTableId("hw-tbl-", generator);
159 
160   std::cout << "\nRunning the BigtableHelloWorld() example" << std::endl;
161   BigtableHelloWorld({project_id, instance_id, table_id});
162 }
163 
164 }  // namespace
165 
main(int argc,char * argv[])166 int main(int argc, char* argv[]) {
167   google::cloud::testing_util::InstallCrashHandler(argv[0]);
168 
169   google::cloud::bigtable::examples::Example example({
170       {"auto", RunAll},
171       {"hello-world", BigtableHelloWorld},
172   });
173   return example.Run(argc, argv);
174 }
175 //! [all code]
176