Introduce examples directory This introduces the top-level examples directory, which will be for examples of how to use the Kudu clients and integrations.
As a first step, I moved the client examples from src/kudu/client/examples to examples/cpp. I also renamed "sample" -> "example" generally. I also manually verified that the instructions in the README for building the example application still work. Change-Id: Iceca48771541f95e4f0caf8c098bc85d34aa558e Reviewed-on: http://gerrit.cloudera.org:8080/9837 Reviewed-by: Adar Dembo <[email protected]> Tested-by: Kudu Jenkins Reviewed-by: Andrew Wong <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/kudu/repo Commit: http://git-wip-us.apache.org/repos/asf/kudu/commit/9bf32a42 Tree: http://git-wip-us.apache.org/repos/asf/kudu/tree/9bf32a42 Diff: http://git-wip-us.apache.org/repos/asf/kudu/diff/9bf32a42 Branch: refs/heads/master Commit: 9bf32a42486bdb4f97834737283c30129ffe71a6 Parents: f7ab95e Author: Will Berkeley <[email protected]> Authored: Tue Mar 27 21:52:37 2018 -0700 Committer: Will Berkeley <[email protected]> Committed: Wed Mar 28 21:42:38 2018 +0000 ---------------------------------------------------------------------- examples/cpp/CMakeLists.txt | 26 +++ examples/cpp/README.adoc | 183 +++++++++++++++ examples/cpp/example.cc | 320 +++++++++++++++++++++++++++ src/kudu/client/CMakeLists.txt | 12 +- src/kudu/client/client_examples-test.sh | 218 ++++++++++++++++++ src/kudu/client/client_samples-test.sh | 218 ------------------ src/kudu/client/samples/CMakeLists.txt | 26 --- src/kudu/client/samples/README.adoc | 183 --------------- src/kudu/client/samples/sample.cc | 320 --------------------------- 9 files changed, 753 insertions(+), 753 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/kudu/blob/9bf32a42/examples/cpp/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/examples/cpp/CMakeLists.txt b/examples/cpp/CMakeLists.txt new file mode 100644 index 0000000..62bc177 --- /dev/null +++ b/examples/cpp/CMakeLists.txt @@ -0,0 +1,26 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +# Client API example executables + +cmake_minimum_required(VERSION 2.8) + +find_package(kuduClient REQUIRED) +include_directories(${KUDU_CLIENT_INCLUDE_DIR}) + +add_executable(example example.cc) +target_link_libraries(example kudu_client) http://git-wip-us.apache.org/repos/asf/kudu/blob/9bf32a42/examples/cpp/README.adoc ---------------------------------------------------------------------- diff --git a/examples/cpp/README.adoc b/examples/cpp/README.adoc new file mode 100644 index 0000000..6bad943 --- /dev/null +++ b/examples/cpp/README.adoc @@ -0,0 +1,183 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. += Kudu {cpp} client example README +:author: Kudu Team +:homepage: https://kudu.apache.org/ + +== Summary +The Kudu {cpp} client library distribution contains {cpp} example application +that demonstrates how to use the Kudu {cpp} client API. The example +can be used as a starting point for a custom Kudu {cpp} client application. +This note contains information on how to build the Kudu {cpp} client example. + +== How to build the example if installing Kudu from packages +This section describes how to build the example if installing Kudu +using pre-built packages. + +. Install the required packages as described in the +https://kudu.apache.org/docs/installation.html#install_packages[documentation on the Kudu Web site]. +The `kudu-client0` package (`libkuduclient0` on Debian/Ubuntu Linux +distributions) contains the Kudu {cpp} client library, and the `kudu-client-dev` +package (`libkuduclient-dev` on Debian/Ubuntu Linux distributions) contains +the Kudu {cpp} client header files and {cpp} code example (`example.cc`) +along with other auxiliary content. + +. Make sure `cmake` of version at least 2.8 is installed on the system. + +. Copy the example into a custom location where you would like to work +with the code. Working in the `/usr/share/doc/kuduClient/examples` +directory is possible but is not recommended since it requires +super-user access and pollutes the `example` directory with +intermediate files. +For example, to copy the `/usr/share/doc/kuduClient/examples` directory +recursively into `/tmp/kuduClient`: +[source,shell] +cp -r /usr/share/doc/kuduClient/examples /tmp/kuduClient + +. Navigate into the directory where the `example.cc.gz` file was copied and +unpack the example source file. For example: +[source,shell] +cd /tmp/kuduClient/examples +gunzip example.cc.gz + +. Run `cmake` to generate appropriate makefiles. For example, if targeting +for a debug build +(for a release build, use `release` for `CMAKE_BUILD_TYPE` correspondingly): +[source,shell] +cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=debug + +. Run `make` to build the example: +[source,shell] +make + +. After the example is built, it is ready to run against your Kudu master server. +The example application assumes the target Kudu cluster has at least 3 +tablet servers up and running (because it creates a table with replication +factor 3). If it's not the case, you can modify the `example.cc` accordingly +and re-compile it. Below is the example output with log messages in the middle +removed: the `example` binary runs against Kudu master server running +with the default parameters at the same machine. Port 7051 is the default +one and could be omitted along with the preceding colomn because the master +server is running with the default parameters (it's left only to illustrate how +to specify port number). +[source,shell] +$ ./example 127.0.0.1:7051 +Running with Kudu client version: kudu 1.1.0-SNAPSHOT (rev 91a1ed09c4c572a22bab15360ddaf481d5632927) +Long version info: kudu 1.1.0-SNAPSHOT +revision 91a1ed09c4c572a22bab15360ddaf481d5632927 +build type DEBUG +built by aserbin at 06 Oct 2016 14:15:10 PST on ve0518.halxg.cloudera.com +Received log message from Kudu client library + Severity: 0 + Filename: /home/aserbin/Projects/kudu/src/kudu/util/thread.cc + Line number: 546 + Time: Thu Oct 06 14:50:47 2016 + Message: Started thread 11197 - kernel-watchdog:kernel-watcher +... +Received log message from Kudu client library + Severity: 0 + Filename: /home/aserbin/Projects/kudu/src/kudu/client/client-internal.cc + Line number: 534 + Time: Thu Oct 06 14:50:47 2016 + Message: Considering host 10.17.240.17 local +Created a client connection +Created a schema +Created a table +Altered a table +Inserted some rows into a table +Scanned some rows out of a table +Deleted a table +Done + +== How to build the example if building Kudu from source +This section describes how to build the example if building Kudu from source. +To install the `example.cc` and other files, an alternate destination root +is used. + +Specifying an alternate destination root allows you to install the +Kudu {cpp} client library, the example file and other content +under the specified destination prefix. + +. Follow the https://kudu.apache.org/docs/installation.html#_build_from_source[instructions on the Kudu Web site] +to build the project from source. + +. Once the project is built, change into the `<build_dir>/src/kudu/client` +sub-directory. + +. Run `make install` with an alternate destination root. For example, if +installing into `/tmp/client_alt_root` +[source,shell] +make install DESTDIR=/tmp/client_alt_root + +. Change the current working directory into the +`usr/local/share/doc/kuduClient/examples` subdirectory of the alternate +destination root. For example, if installing into `/tmp/client_alt_root` +[source,shell] +cd /tmp/client_alt_root/usr/local/share/doc/kuduClient/examples + +. Run `cmake` to generate appropriate makefiles. For example, if installing +into `/tmp/client_alt_root` and targeting for a debug build +(for a release build, use `release` for `CMAKE_BUILD_TYPE` correspondingly): +[source,shell] +cmake -G "Unix Makefiles" -DkuduClient_DIR=/tmp/client_alt_root/usr/local/share/kuduClient/cmake -DCMAKE_BUILD_TYPE=debug + +. Run `make` to build the example: +[source,shell] +make + +. After the example is built, it is ready to run against your Kudu master server. +The example application assumes the target Kudu cluster has at least 3 +tablet servers up and running (because it creates a table with replication +factor 3). If it's not the case, you can modify the `example.cc` accordingly +and re-compile it. Below is the example output with log messages in the middle +removed: the `example` binary runs against Kudu master server running +with the default parameters at the same machine. Port 7051 is the default +one and could be omitted along with the preceding colomn because the master +server is running with the default parameters (it's left only to illustrate how +to specify port number). +[source,shell] +$ ./example 127.0.0.1:7051 +Running with Kudu client version: kudu 1.1.0-SNAPSHOT (rev 91a1ed09c4c572a22bab15360ddaf481d5632927) +Long version info: kudu 1.1.0-SNAPSHOT +revision 91a1ed09c4c572a22bab15360ddaf481d5632927 +build type DEBUG +built by aserbin at 06 Oct 2016 14:15:10 PST on ve0518.halxg.cloudera.com +Received log message from Kudu client library + Severity: 0 + Filename: /home/aserbin/Projects/kudu/src/kudu/util/thread.cc + Line number: 546 + Time: Thu Oct 06 14:50:47 2016 + Message: Started thread 11197 - kernel-watchdog:kernel-watcher +... +Received log message from Kudu client library + Severity: 0 + Filename: /home/aserbin/Projects/kudu/src/kudu/client/client-internal.cc + Line number: 534 + Time: Thu Oct 06 14:50:47 2016 + Message: Considering host 10.17.240.17 local +Created a client connection +Created a schema +Created a table +Altered a table +Inserted some rows into a table +Scanned some rows out of a table +Deleted a table +Done + +== References +. https://kudu.apache.org/[The Kudu Project Web Site] +. https://kudu.apache.org/cpp-client-api/[Kudu {cpp} client API documentation] http://git-wip-us.apache.org/repos/asf/kudu/blob/9bf32a42/examples/cpp/example.cc ---------------------------------------------------------------------- diff --git a/examples/cpp/example.cc b/examples/cpp/example.cc new file mode 100644 index 0000000..9b5d65e --- /dev/null +++ b/examples/cpp/example.cc @@ -0,0 +1,320 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#include <ctime> +#include <iostream> +#include <sstream> + +#include "kudu/client/callbacks.h" +#include "kudu/client/client.h" +#include "kudu/client/row_result.h" +#include "kudu/client/stubs.h" +#include "kudu/client/value.h" +#include "kudu/client/write_op.h" +#include "kudu/common/partial_row.h" +#include "kudu/util/monotime.h" + +using kudu::client::KuduClient; +using kudu::client::KuduClientBuilder; +using kudu::client::KuduColumnSchema; +using kudu::client::KuduError; +using kudu::client::KuduInsert; +using kudu::client::KuduPredicate; +using kudu::client::KuduRowResult; +using kudu::client::KuduScanner; +using kudu::client::KuduSchema; +using kudu::client::KuduSchemaBuilder; +using kudu::client::KuduSession; +using kudu::client::KuduStatusFunctionCallback; +using kudu::client::KuduTable; +using kudu::client::KuduTableAlterer; +using kudu::client::KuduTableCreator; +using kudu::client::KuduValue; +using kudu::client::sp::shared_ptr; +using kudu::KuduPartialRow; +using kudu::MonoDelta; +using kudu::Status; + +using std::ostringstream; +using std::string; +using std::vector; + +static Status CreateClient(const string& addr, + shared_ptr<KuduClient>* client) { + return KuduClientBuilder() + .add_master_server_addr(addr) + .default_admin_operation_timeout(MonoDelta::FromSeconds(20)) + .Build(client); +} + +static KuduSchema CreateSchema() { + KuduSchema schema; + KuduSchemaBuilder b; + b.AddColumn("key")->Type(KuduColumnSchema::INT32)->NotNull()->PrimaryKey(); + b.AddColumn("int_val")->Type(KuduColumnSchema::INT32)->NotNull(); + b.AddColumn("string_val")->Type(KuduColumnSchema::STRING)->NotNull(); + b.AddColumn("non_null_with_default")->Type(KuduColumnSchema::INT32)->NotNull() + ->Default(KuduValue::FromInt(12345)); + KUDU_CHECK_OK(b.Build(&schema)); + return schema; +} + +static Status DoesTableExist(const shared_ptr<KuduClient>& client, + const string& table_name, + bool *exists) { + shared_ptr<KuduTable> table; + Status s = client->OpenTable(table_name, &table); + if (s.ok()) { + *exists = true; + } else if (s.IsNotFound()) { + *exists = false; + s = Status::OK(); + } + return s; +} + +static Status CreateTable(const shared_ptr<KuduClient>& client, + const string& table_name, + const KuduSchema& schema, + int num_tablets) { + // Generate the split keys for the table. + vector<const KuduPartialRow*> splits; + int32_t increment = 1000 / num_tablets; + for (int32_t i = 1; i < num_tablets; i++) { + KuduPartialRow* row = schema.NewRow(); + KUDU_CHECK_OK(row->SetInt32(0, i * increment)); + splits.push_back(row); + } + + vector<string> column_names; + column_names.push_back("key"); + + // Create the table. + KuduTableCreator* table_creator = client->NewTableCreator(); + Status s = table_creator->table_name(table_name) + .schema(&schema) + .set_range_partition_columns(column_names) + .split_rows(splits) + .Create(); + delete table_creator; + return s; +} + +static Status AlterTable(const shared_ptr<KuduClient>& client, + const string& table_name) { + KuduTableAlterer* table_alterer = client->NewTableAlterer(table_name); + table_alterer->AlterColumn("int_val")->RenameTo("integer_val"); + table_alterer->AddColumn("another_val")->Type(KuduColumnSchema::BOOL); + table_alterer->DropColumn("string_val"); + Status s = table_alterer->Alter(); + delete table_alterer; + return s; +} + +static void StatusCB(void* unused, const Status& status) { + KUDU_LOG(INFO) << "Asynchronous flush finished with status: " + << status.ToString(); +} + +static Status InsertRows(const shared_ptr<KuduTable>& table, int num_rows) { + shared_ptr<KuduSession> session = table->client()->NewSession(); + KUDU_RETURN_NOT_OK(session->SetFlushMode(KuduSession::MANUAL_FLUSH)); + session->SetTimeoutMillis(5000); + + for (int i = 0; i < num_rows; i++) { + KuduInsert* insert = table->NewInsert(); + KuduPartialRow* row = insert->mutable_row(); + KUDU_CHECK_OK(row->SetInt32("key", i)); + KUDU_CHECK_OK(row->SetInt32("integer_val", i * 2)); + KUDU_CHECK_OK(row->SetInt32("non_null_with_default", i * 5)); + KUDU_CHECK_OK(session->Apply(insert)); + } + Status s = session->Flush(); + if (s.ok()) { + return s; + } + + // Test asynchronous flush. + KuduStatusFunctionCallback<void*> status_cb(&StatusCB, NULL); + session->FlushAsync(&status_cb); + + // Look at the session's errors. + vector<KuduError*> errors; + bool overflow; + session->GetPendingErrors(&errors, &overflow); + if (!errors.empty()) { + s = overflow ? Status::IOError("Overflowed pending errors in session") : + errors.front()->status(); + while (!errors.empty()) { + delete errors.back(); + errors.pop_back(); + } + } + KUDU_RETURN_NOT_OK(s); + + // Close the session. + return session->Close(); +} + +static Status ScanRows(const shared_ptr<KuduTable>& table) { + const int kLowerBound = 5; + const int kUpperBound = 600; + + KuduScanner scanner(table.get()); + + // Add a predicate: WHERE key >= 5 + KuduPredicate* p = table->NewComparisonPredicate( + "key", KuduPredicate::GREATER_EQUAL, KuduValue::FromInt(kLowerBound)); + KUDU_RETURN_NOT_OK(scanner.AddConjunctPredicate(p)); + + // Add a predicate: WHERE key <= 600 + p = table->NewComparisonPredicate( + "key", KuduPredicate::LESS_EQUAL, KuduValue::FromInt(kUpperBound)); + KUDU_RETURN_NOT_OK(scanner.AddConjunctPredicate(p)); + + KUDU_RETURN_NOT_OK(scanner.Open()); + vector<KuduRowResult> results; + + int next_row = kLowerBound; + while (scanner.HasMoreRows()) { + KUDU_RETURN_NOT_OK(scanner.NextBatch(&results)); + for (vector<KuduRowResult>::iterator iter = results.begin(); + iter != results.end(); + iter++, next_row++) { + const KuduRowResult& result = *iter; + int32_t val; + KUDU_RETURN_NOT_OK(result.GetInt32("key", &val)); + if (val != next_row) { + ostringstream out; + out << "Scan returned the wrong results. Expected key " + << next_row << " but got " << val; + return Status::IOError(out.str()); + } + } + results.clear(); + } + + // next_row is now one past the last row we read. + int last_row_seen = next_row - 1; + + if (last_row_seen != kUpperBound) { + ostringstream out; + out << "Scan returned the wrong results. Expected last row to be " + << kUpperBound << " rows but got " << last_row_seen; + return Status::IOError(out.str()); + } + return Status::OK(); +} + +// A helper class providing custom logging callback. It also manages +// automatic callback installation and removal. +class LogCallbackHelper { + public: + LogCallbackHelper() : log_cb_(&LogCallbackHelper::LogCb, NULL) { + kudu::client::InstallLoggingCallback(&log_cb_); + } + + ~LogCallbackHelper() { + kudu::client::UninstallLoggingCallback(); + } + + static void LogCb(void* unused, + kudu::client::KuduLogSeverity severity, + const char* filename, + int line_number, + const struct ::tm* time, + const char* message, + size_t message_len) { + KUDU_LOG(INFO) << "Received log message from Kudu client library"; + KUDU_LOG(INFO) << " Severity: " << severity; + KUDU_LOG(INFO) << " Filename: " << filename; + KUDU_LOG(INFO) << " Line number: " << line_number; + char time_buf[32]; + // Example: Tue Mar 24 11:46:43 2015. + KUDU_CHECK(strftime(time_buf, sizeof(time_buf), "%a %b %d %T %Y", time)); + KUDU_LOG(INFO) << " Time: " << time_buf; + KUDU_LOG(INFO) << " Message: " << string(message, message_len); + } + + private: + kudu::client::KuduLoggingFunctionCallback<void*> log_cb_; +}; + +int main(int argc, char* argv[]) { + KUDU_LOG(INFO) << "Running with Kudu client version: " << + kudu::client::GetShortVersionString(); + KUDU_LOG(INFO) << "Long version info: " << + kudu::client::GetAllVersionInfo(); + + // This is to install and automatically un-install custom logging callback. + LogCallbackHelper log_cb_helper; + + if (argc != 2) { + KUDU_LOG(FATAL) << "usage: " << argv[0] << " <master host>"; + } + const string master_host = argv[1]; + + const string kTableName = "test_table"; + + // Enable verbose debugging for the client library. + kudu::client::SetVerboseLogLevel(2); + + // Create and connect a client. + shared_ptr<KuduClient> client; + KUDU_CHECK_OK(CreateClient(master_host, &client)); + KUDU_LOG(INFO) << "Created a client connection"; + + // Disable the verbose logging. + kudu::client::SetVerboseLogLevel(0); + + // Create a schema. + KuduSchema schema(CreateSchema()); + KUDU_LOG(INFO) << "Created a schema"; + + // Create a table with that schema. + bool exists; + KUDU_CHECK_OK(DoesTableExist(client, kTableName, &exists)); + if (exists) { + client->DeleteTable(kTableName); + KUDU_LOG(INFO) << "Deleting old table before creating new one"; + } + KUDU_CHECK_OK(CreateTable(client, kTableName, schema, 10)); + KUDU_LOG(INFO) << "Created a table"; + + // Alter the table. + KUDU_CHECK_OK(AlterTable(client, kTableName)); + KUDU_LOG(INFO) << "Altered a table"; + + // Insert some rows into the table. + shared_ptr<KuduTable> table; + KUDU_CHECK_OK(client->OpenTable(kTableName, &table)); + KUDU_CHECK_OK(InsertRows(table, 1000)); + KUDU_LOG(INFO) << "Inserted some rows into a table"; + + // Scan some rows. + KUDU_CHECK_OK(ScanRows(table)); + KUDU_LOG(INFO) << "Scanned some rows out of a table"; + + // Delete the table. + KUDU_CHECK_OK(client->DeleteTable(kTableName)); + KUDU_LOG(INFO) << "Deleted a table"; + + // Done! + KUDU_LOG(INFO) << "Done"; + + return 0; +} http://git-wip-us.apache.org/repos/asf/kudu/blob/9bf32a42/src/kudu/client/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/src/kudu/client/CMakeLists.txt b/src/kudu/client/CMakeLists.txt index 776acdb..2e6ab1c 100644 --- a/src/kudu/client/CMakeLists.txt +++ b/src/kudu/client/CMakeLists.txt @@ -199,13 +199,13 @@ install(FILES ../util/status.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/kudu/util) -# Client sample code. +# Client example code. # # Can't use CMAKE_INSTALL_DOCDIR because we don't ever call project(). install(FILES - samples/CMakeLists.txt - samples/sample.cc - DESTINATION ${CMAKE_INSTALL_DATADIR}/doc/kuduClient/samples) + ../../../examples/cpp/CMakeLists.txt + ../../../examples/cpp/example.cc + DESTINATION ${CMAKE_INSTALL_DATADIR}/doc/kuduClient/examples) # Exported cmake file for just the library's targets. # @@ -252,9 +252,9 @@ if (NOT APPLE AND NOT "${KUDU_GENERATE_COVERAGE}") ADD_KUDU_TEST(client_symbol-test.sh LABELS no_dist_test) endif() -# The samples are never built with ASAN/TSAN. +# The examples are never built with ASAN/TSAN. if(NOT "${KUDU_USE_ASAN}" AND NOT "${KUDU_USE_TSAN}") - ADD_KUDU_TEST(client_samples-test.sh RUN_SERIAL true LABELS no_dist_test) + ADD_KUDU_TEST(client_examples-test.sh RUN_SERIAL true LABELS no_dist_test) endif() set(KUDU_TEST_LINK_LIBS itest_util http://git-wip-us.apache.org/repos/asf/kudu/blob/9bf32a42/src/kudu/client/client_examples-test.sh ---------------------------------------------------------------------- diff --git a/src/kudu/client/client_examples-test.sh b/src/kudu/client/client_examples-test.sh new file mode 100755 index 0000000..ad0e86c --- /dev/null +++ b/src/kudu/client/client_examples-test.sh @@ -0,0 +1,218 @@ +#!/bin/bash +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +# This script verifies that the Kudu client library can be installed outside +# the build tree, that the installed headers are sane, and that the example code +# can be built and runs correctly. + +# Clean up after the test. Must be idempotent. +cleanup() { + if [ -n "$TS_PID" ]; then + kill -9 "$TS_PID" || : + wait $TS_PID || : + fi + if [ -n "$MASTER_PID" ]; then + kill -9 "$MASTER_PID" || : + wait $MASTER_PID || : + fi + if [ -n "$BASE_DIR" -a -d "$BASE_DIR" ]; then + rm -rf "$BASE_DIR" + fi + if [ -n "$LIBRARY_DIR" -a -d "$LIBRARY_DIR" ]; then + rm -rf "$LIBRARY_DIR" + fi +} +trap cleanup EXIT + +set -e +set -o pipefail +set -x + +wait_for_listen_port() { + local pid=$1 + local expected_port=$2 + local num_attempts=$3 + + local attempt=0 + while [ true ]; do + # The lsof utility does not allow to distinguish between an existing + # process not listening to the specified port and a non-existing process + # by its return code. For the fast check let's verify that the process + # is still running. + if ! kill -0 $pid; then + return 1 + fi + local ports=$(lsof -wbnP -Fn -p $pid -a -i 4TCP -a -s TCP:LISTEN | \ + sed '1d;s/^[^:].*://') + for i in $ports; do + if [ $i -eq $expected_port ]; then + return 0 + fi + done + + attempt=$((attempt+1)) + if [ $attempt -ge $num_attempts ]; then + break + fi + sleep 1 + done + + return 1 +} + +exit_error() { + local err_msg="$1" + + set +x + echo ---------------------------------------------------------------------- + echo ERROR: $err_msg + echo ---------------------------------------------------------------------- + exit 1 +} + +OUTPUT_DIR=$(cd $(dirname "$BASH_SOURCE"); pwd) + +# Install the client library to a temporary directory. +# Try to detect whether we're building using Ninja or Make. +LIBRARY_DIR=$(mktemp -d -t kudu-examples-test.XXXXXXXXXXXXX) +PREFIX_DIR=$LIBRARY_DIR/usr/local +EXAMPLES_DIR=$PREFIX_DIR/share/doc/kuduClient/examples +pushd $OUTPUT_DIR/.. +NINJA=$(which ninja 2>/dev/null) || NINJA="" +if [ -r build.ninja -a -n "$NINJA" ]; then + DESTDIR=$LIBRARY_DIR ninja install +else + make -j$(getconf _NPROCESSORS_ONLN) DESTDIR=$LIBRARY_DIR install +fi +popd + +# Test that all of the installed headers can be compiled on their own. +# This catches bugs where we've made a mistake in 'include-what-you-use' +# within the library. +for include_file in $(find $LIBRARY_DIR -name \*.h) ; do + echo Checking standalone compilation of $include_file... + if ! ${CXX:-g++} \ + -o /dev/null \ + -I$LIBRARY_DIR/usr/local/include \ + $include_file ; then + set +x + echo + echo ----------------------------------------- + echo $include_file fails to build on its own. + echo See log above for details. + echo ----------------------------------------- + exit 1 + fi +done + +# Prefer the cmake on the system path, since we expect our client library +# to be usable with older versions of cmake. But if it isn't there, +# use the one from thirdparty. +CMAKE=$(which cmake || :) +if [ -z "$CMAKE" ]; then + # TODO: temporary hack which assumes this script is in src/build/<type>/bin + CMAKE=$OUTPUT_DIR/../../../thirdparty/installed/common/bin/cmake +fi + +# Build the client examples using the client library. +# We can just always use Make here, since we're calling cmake ourselves. +pushd $EXAMPLES_DIR +CMAKE_PREFIX_PATH=$PREFIX_DIR $CMAKE . +make -j$(getconf _NPROCESSORS_ONLN) +popd + +LOCALHOST_IP=127.0.0.1 +if [ "$(uname)" == "Linux" ]; then + # Pick a unique localhost IP address so this can run in parallel with other + # tests. This only works on Linux. + LOCALHOST_IP=127.$[($$ >> 8) & 0xff].$[$$ & 0xff].1 +fi +echo Using localhost IP $LOCALHOST_IP + + +# Start master+ts +export TMPDIR=${TMPDIR:-/tmp} +export TEST_TMPDIR=${TEST_TMPDIR:-$TMPDIR/kudutest-$UID} +mkdir -p $TEST_TMPDIR +BASE_DIR=$(mktemp -d $TEST_TMPDIR/client_examples-test.XXXXXXXX) +MASTER_RPC_PORT=7051 +mkdir -p "$BASE_DIR/master/logs" +$OUTPUT_DIR/kudu-master \ + --unlock_experimental_flags \ + --default_num_replicas=1 \ + --log_dir=$BASE_DIR/master/logs \ + --fs_wal_dir=$BASE_DIR/master/wals \ + --fs_data_dirs=$BASE_DIR/master/data \ + --webserver_interface=$LOCALHOST_IP \ + --webserver_port=0 \ + --rpc_bind_addresses=$LOCALHOST_IP:$MASTER_RPC_PORT & +MASTER_PID=$! + +TSERVER_RPC_PORT=7050 +mkdir -p "$BASE_DIR/ts/logs" +$OUTPUT_DIR/kudu-tserver \ + --unlock_experimental_flags \ + --heartbeat_interval_ms=200 \ + --heartbeat_rpc_timeout_ms=1000 \ + --log_dir=$BASE_DIR/ts/logs \ + --fs_wal_dir=$BASE_DIR/ts/wals \ + --fs_data_dirs=$BASE_DIR/ts/data \ + --rpc_bind_addresses=$LOCALHOST_IP:$TSERVER_RPC_PORT \ + --local_ip_for_outbound_sockets=$LOCALHOST_IP \ + --webserver_interface=$LOCALHOST_IP \ + --webserver_port=0 \ + --tserver_master_addrs=$LOCALHOST_IP:$MASTER_RPC_PORT & +TS_PID=$! + +# Make sure that at least it's possible to establish a TCP connection to the +# master's and the tablet server's RPC ports before running the client example +# application. +if ! wait_for_listen_port $MASTER_PID $MASTER_RPC_PORT 30; then + exit_error "master is not accepting connections" +fi +if ! wait_for_listen_port $TS_PID $TSERVER_RPC_PORT 30; then + exit_error "tserver is not accepting connections" +fi + +# Allow for the tablet server registering with the master: wait for ~10s max. +max_attempts=10 +attempt=0 +num_tservers=0 +while [ true ]; do + if ! num_tservers=$($OUTPUT_DIR/kudu tserver list \ + $LOCALHOST_IP:$MASTER_RPC_PORT -format=space | wc -l); then + exit_error "failed to determine number of registered tservers" + fi + if [ $num_tservers -ge 1 ]; then + break + fi + attempt=$((attempt+1)) + if [ $attempt -ge $max_attempts ]; then + break + fi + sleep 1 +done + +if [ $num_tservers -lt 1 ]; then + exit_error "tserver has not registered with the master" +fi + +# Run the examples. +$EXAMPLES_DIR/example $LOCALHOST_IP http://git-wip-us.apache.org/repos/asf/kudu/blob/9bf32a42/src/kudu/client/client_samples-test.sh ---------------------------------------------------------------------- diff --git a/src/kudu/client/client_samples-test.sh b/src/kudu/client/client_samples-test.sh deleted file mode 100755 index c2160c6..0000000 --- a/src/kudu/client/client_samples-test.sh +++ /dev/null @@ -1,218 +0,0 @@ -#!/bin/bash -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# This script verifies that the Kudu client library can be installed outside -# the build tree, that the installed headers are sane, and that the sample code -# can be built and runs correctly. - -# Clean up after the test. Must be idempotent. -cleanup() { - if [ -n "$TS_PID" ]; then - kill -9 "$TS_PID" || : - wait $TS_PID || : - fi - if [ -n "$MASTER_PID" ]; then - kill -9 "$MASTER_PID" || : - wait $MASTER_PID || : - fi - if [ -n "$BASE_DIR" -a -d "$BASE_DIR" ]; then - rm -rf "$BASE_DIR" - fi - if [ -n "$LIBRARY_DIR" -a -d "$LIBRARY_DIR" ]; then - rm -rf "$LIBRARY_DIR" - fi -} -trap cleanup EXIT - -set -e -set -o pipefail -set -x - -wait_for_listen_port() { - local pid=$1 - local expected_port=$2 - local num_attempts=$3 - - local attempt=0 - while [ true ]; do - # The lsof utility does not allow to distinguish between an existing - # process not listening to the specified port and a non-existing process - # by its return code. For the fast check let's verify that the process - # is still running. - if ! kill -0 $pid; then - return 1 - fi - local ports=$(lsof -wbnP -Fn -p $pid -a -i 4TCP -a -s TCP:LISTEN | \ - sed '1d;s/^[^:].*://') - for i in $ports; do - if [ $i -eq $expected_port ]; then - return 0 - fi - done - - attempt=$((attempt+1)) - if [ $attempt -ge $num_attempts ]; then - break - fi - sleep 1 - done - - return 1 -} - -exit_error() { - local err_msg="$1" - - set +x - echo ---------------------------------------------------------------------- - echo ERROR: $err_msg - echo ---------------------------------------------------------------------- - exit 1 -} - -OUTPUT_DIR=$(cd $(dirname "$BASH_SOURCE"); pwd) - -# Install the client library to a temporary directory. -# Try to detect whether we're building using Ninja or Make. -LIBRARY_DIR=$(mktemp -d -t kudu-samples-test.XXXXXXXXXXXXX) -PREFIX_DIR=$LIBRARY_DIR/usr/local -SAMPLES_DIR=$PREFIX_DIR/share/doc/kuduClient/samples -pushd $OUTPUT_DIR/.. -NINJA=$(which ninja 2>/dev/null) || NINJA="" -if [ -r build.ninja -a -n "$NINJA" ]; then - DESTDIR=$LIBRARY_DIR ninja install -else - make -j$(getconf _NPROCESSORS_ONLN) DESTDIR=$LIBRARY_DIR install -fi -popd - -# Test that all of the installed headers can be compiled on their own. -# This catches bugs where we've made a mistake in 'include-what-you-use' -# within the library. -for include_file in $(find $LIBRARY_DIR -name \*.h) ; do - echo Checking standalone compilation of $include_file... - if ! ${CXX:-g++} \ - -o /dev/null \ - -I$LIBRARY_DIR/usr/local/include \ - $include_file ; then - set +x - echo - echo ----------------------------------------- - echo $include_file fails to build on its own. - echo See log above for details. - echo ----------------------------------------- - exit 1 - fi -done - -# Prefer the cmake on the system path, since we expect our client library -# to be usable with older versions of cmake. But if it isn't there, -# use the one from thirdparty. -CMAKE=$(which cmake || :) -if [ -z "$CMAKE" ]; then - # TODO: temporary hack which assumes this script is in src/build/<type>/bin - CMAKE=$OUTPUT_DIR/../../../thirdparty/installed/common/bin/cmake -fi - -# Build the client samples using the client library. -# We can just always use Make here, since we're calling cmake ourselves. -pushd $SAMPLES_DIR -CMAKE_PREFIX_PATH=$PREFIX_DIR $CMAKE . -make -j$(getconf _NPROCESSORS_ONLN) -popd - -LOCALHOST_IP=127.0.0.1 -if [ "$(uname)" == "Linux" ]; then - # Pick a unique localhost IP address so this can run in parallel with other - # tests. This only works on Linux. - LOCALHOST_IP=127.$[($$ >> 8) & 0xff].$[$$ & 0xff].1 -fi -echo Using localhost IP $LOCALHOST_IP - - -# Start master+ts -export TMPDIR=${TMPDIR:-/tmp} -export TEST_TMPDIR=${TEST_TMPDIR:-$TMPDIR/kudutest-$UID} -mkdir -p $TEST_TMPDIR -BASE_DIR=$(mktemp -d $TEST_TMPDIR/client_samples-test.XXXXXXXX) -MASTER_RPC_PORT=7051 -mkdir -p "$BASE_DIR/master/logs" -$OUTPUT_DIR/kudu-master \ - --unlock_experimental_flags \ - --default_num_replicas=1 \ - --log_dir=$BASE_DIR/master/logs \ - --fs_wal_dir=$BASE_DIR/master/wals \ - --fs_data_dirs=$BASE_DIR/master/data \ - --webserver_interface=$LOCALHOST_IP \ - --webserver_port=0 \ - --rpc_bind_addresses=$LOCALHOST_IP:$MASTER_RPC_PORT & -MASTER_PID=$! - -TSERVER_RPC_PORT=7050 -mkdir -p "$BASE_DIR/ts/logs" -$OUTPUT_DIR/kudu-tserver \ - --unlock_experimental_flags \ - --heartbeat_interval_ms=200 \ - --heartbeat_rpc_timeout_ms=1000 \ - --log_dir=$BASE_DIR/ts/logs \ - --fs_wal_dir=$BASE_DIR/ts/wals \ - --fs_data_dirs=$BASE_DIR/ts/data \ - --rpc_bind_addresses=$LOCALHOST_IP:$TSERVER_RPC_PORT \ - --local_ip_for_outbound_sockets=$LOCALHOST_IP \ - --webserver_interface=$LOCALHOST_IP \ - --webserver_port=0 \ - --tserver_master_addrs=$LOCALHOST_IP:$MASTER_RPC_PORT & -TS_PID=$! - -# Make sure that at least it's possible to establish a TCP connection to the -# master's and the tablet server's RPC ports before running the client sample -# application. -if ! wait_for_listen_port $MASTER_PID $MASTER_RPC_PORT 30; then - exit_error "master is not accepting connections" -fi -if ! wait_for_listen_port $TS_PID $TSERVER_RPC_PORT 30; then - exit_error "tserver is not accepting connections" -fi - -# Allow for the tablet server registering with the master: wait for ~10s max. -max_attempts=10 -attempt=0 -num_tservers=0 -while [ true ]; do - if ! num_tservers=$($OUTPUT_DIR/kudu tserver list \ - $LOCALHOST_IP:$MASTER_RPC_PORT -format=space | wc -l); then - exit_error "failed to determine number of registered tservers" - fi - if [ $num_tservers -ge 1 ]; then - break - fi - attempt=$((attempt+1)) - if [ $attempt -ge $max_attempts ]; then - break - fi - sleep 1 -done - -if [ $num_tservers -lt 1 ]; then - exit_error "tserver has not registered with the master" -fi - -# Run the samples. -$SAMPLES_DIR/sample $LOCALHOST_IP http://git-wip-us.apache.org/repos/asf/kudu/blob/9bf32a42/src/kudu/client/samples/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/src/kudu/client/samples/CMakeLists.txt b/src/kudu/client/samples/CMakeLists.txt deleted file mode 100644 index 85ff85b..0000000 --- a/src/kudu/client/samples/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# -# Client API sample executables - -cmake_minimum_required(VERSION 2.8) - -find_package(kuduClient REQUIRED) -include_directories(${KUDU_CLIENT_INCLUDE_DIR}) - -add_executable(sample sample.cc) -target_link_libraries(sample kudu_client) http://git-wip-us.apache.org/repos/asf/kudu/blob/9bf32a42/src/kudu/client/samples/README.adoc ---------------------------------------------------------------------- diff --git a/src/kudu/client/samples/README.adoc b/src/kudu/client/samples/README.adoc deleted file mode 100644 index f65723c..0000000 --- a/src/kudu/client/samples/README.adoc +++ /dev/null @@ -1,183 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -= Kudu {cpp} client sample README -:author: Kudu Team -:homepage: https://kudu.apache.org/ - -== Summary -The Kudu {cpp} client library distribution contains {cpp} example application -that demonstrates how to use the Kudu {cpp} client API. The sample -can be used as a starting point for a custom Kudu {cpp} client application. -This note contains information on how to build the Kudu {cpp} client sample. - -== How to build the example if installing Kudu from packages -This section describes how to build the example if installing Kudu -using pre-built packages. - -. Install the required packages as described in the -https://kudu.apache.org/docs/installation.html#install_packages[documentation on the Kudu Web site]. -The `kudu-client0` package (`libkuduclient0` on Debian/Ubuntu Linux -distributions) contains the Kudu {cpp} client library, and the `kudu-client-dev` -package (`libkuduclient-dev` on Debian/Ubuntu Linux distributions) contains -the Kudu {cpp} client header files and {cpp} code sample (`sample.cc`) -along with other auxiliary content. - -. Make sure `cmake` of version at least 2.8 is installed on the system. - -. Copy the sample into a custom location where you would like to work -with the code. Working in the `/usr/share/doc/kuduClient/samples` -directory is possible but is not recommended since it requires -super-user access and pollutes the `sample` directory with -intermediate files. -For example, to copy the `/usr/share/doc/kuduClient/samples` directory -recursively into `/tmp/kuduClient`: -[source,shell] -cp -r /usr/share/doc/kuduClient/samples /tmp/kuduClient - -. Navigate into the directory where the `sample.cc.gz` file was copied and -unpack the sample source file. For example: -[source,shell] -cd /tmp/kuduClient/samples -gunzip sample.cc.gz - -. Run `cmake` to generate appropriate makefiles. For example, if targeting -for a debug build -(for a release build, use `release` for `CMAKE_BUILD_TYPE` correspondingly): -[source,shell] -cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=debug - -. Run `make` to build the sample: -[source,shell] -make - -. After the sample is built, it is ready to run against your Kudu master server. -The sample application assumes the target Kudu cluster has at least 3 -tablet servers up and running (because it creates a table with replication -factor 3). If it's not the case, you can modify the `sample.cc` accordingly -and re-compile it. Below is the sample output with log messages in the middle -removed: the `sample` binary runs against Kudu master server running -with the default parameters at the same machine. Port 7051 is the default -one and could be omitted along with the preceding colomn because the master -server is running with the default parameters (it's left only to illustrate how -to specify port number). -[source,shell] -$ ./sample 127.0.0.1:7051 -Running with Kudu client version: kudu 1.1.0-SNAPSHOT (rev 91a1ed09c4c572a22bab15360ddaf481d5632927) -Long version info: kudu 1.1.0-SNAPSHOT -revision 91a1ed09c4c572a22bab15360ddaf481d5632927 -build type DEBUG -built by aserbin at 06 Oct 2016 14:15:10 PST on ve0518.halxg.cloudera.com -Received log message from Kudu client library - Severity: 0 - Filename: /home/aserbin/Projects/kudu/src/kudu/util/thread.cc - Line number: 546 - Time: Thu Oct 06 14:50:47 2016 - Message: Started thread 11197 - kernel-watchdog:kernel-watcher -... -Received log message from Kudu client library - Severity: 0 - Filename: /home/aserbin/Projects/kudu/src/kudu/client/client-internal.cc - Line number: 534 - Time: Thu Oct 06 14:50:47 2016 - Message: Considering host 10.17.240.17 local -Created a client connection -Created a schema -Created a table -Altered a table -Inserted some rows into a table -Scanned some rows out of a table -Deleted a table -Done - -== How to build the example if building Kudu from source -This section describes how to build the example if building Kudu from source. -To install the `sample.cc` and other files, an alternate destination root -is used. - -Specifying an alternate destination root allows you to install the -Kudu {cpp} client library, the sample file and other content -under the specified destination prefix. - -. Follow the https://kudu.apache.org/docs/installation.html#_build_from_source[instructions on the Kudu Web site] -to build the project from source. - -. Once the project is built, change into the `<build_dir>/src/kudu/client` -sub-directory. - -. Run `make install` with an alternate destination root. For example, if -installing into `/tmp/client_alt_root` -[source,shell] -make install DESTDIR=/tmp/client_alt_root - -. Change the current working directory into the -`usr/local/share/doc/kuduClient/samples` subdirectory of the alternate -destination root. For example, if installing into `/tmp/client_alt_root` -[source,shell] -cd /tmp/client_alt_root/usr/local/share/doc/kuduClient/samples - -. Run `cmake` to generate appropriate makefiles. For example, if installing -into `/tmp/client_alt_root` and targeting for a debug build -(for a release build, use `release` for `CMAKE_BUILD_TYPE` correspondingly): -[source,shell] -cmake -G "Unix Makefiles" -DkuduClient_DIR=/tmp/client_alt_root/usr/local/share/kuduClient/cmake -DCMAKE_BUILD_TYPE=debug - -. Run `make` to build the sample: -[source,shell] -make - -. After the sample is built, it is ready to run against your Kudu master server. -The sample application assumes the target Kudu cluster has at least 3 -tablet servers up and running (because it creates a table with replication -factor 3). If it's not the case, you can modify the `sample.cc` accordingly -and re-compile it. Below is the sample output with log messages in the middle -removed: the `sample` binary runs against Kudu master server running -with the default parameters at the same machine. Port 7051 is the default -one and could be omitted along with the preceding colomn because the master -server is running with the default parameters (it's left only to illustrate how -to specify port number). -[source,shell] -$ ./sample 127.0.0.1:7051 -Running with Kudu client version: kudu 1.1.0-SNAPSHOT (rev 91a1ed09c4c572a22bab15360ddaf481d5632927) -Long version info: kudu 1.1.0-SNAPSHOT -revision 91a1ed09c4c572a22bab15360ddaf481d5632927 -build type DEBUG -built by aserbin at 06 Oct 2016 14:15:10 PST on ve0518.halxg.cloudera.com -Received log message from Kudu client library - Severity: 0 - Filename: /home/aserbin/Projects/kudu/src/kudu/util/thread.cc - Line number: 546 - Time: Thu Oct 06 14:50:47 2016 - Message: Started thread 11197 - kernel-watchdog:kernel-watcher -... -Received log message from Kudu client library - Severity: 0 - Filename: /home/aserbin/Projects/kudu/src/kudu/client/client-internal.cc - Line number: 534 - Time: Thu Oct 06 14:50:47 2016 - Message: Considering host 10.17.240.17 local -Created a client connection -Created a schema -Created a table -Altered a table -Inserted some rows into a table -Scanned some rows out of a table -Deleted a table -Done - -== References -. https://kudu.apache.org/[The Kudu Project Web Site] -. https://kudu.apache.org/cpp-client-api/[Kudu {cpp} client API documentation] http://git-wip-us.apache.org/repos/asf/kudu/blob/9bf32a42/src/kudu/client/samples/sample.cc ---------------------------------------------------------------------- diff --git a/src/kudu/client/samples/sample.cc b/src/kudu/client/samples/sample.cc deleted file mode 100644 index 9b5d65e..0000000 --- a/src/kudu/client/samples/sample.cc +++ /dev/null @@ -1,320 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -#include <ctime> -#include <iostream> -#include <sstream> - -#include "kudu/client/callbacks.h" -#include "kudu/client/client.h" -#include "kudu/client/row_result.h" -#include "kudu/client/stubs.h" -#include "kudu/client/value.h" -#include "kudu/client/write_op.h" -#include "kudu/common/partial_row.h" -#include "kudu/util/monotime.h" - -using kudu::client::KuduClient; -using kudu::client::KuduClientBuilder; -using kudu::client::KuduColumnSchema; -using kudu::client::KuduError; -using kudu::client::KuduInsert; -using kudu::client::KuduPredicate; -using kudu::client::KuduRowResult; -using kudu::client::KuduScanner; -using kudu::client::KuduSchema; -using kudu::client::KuduSchemaBuilder; -using kudu::client::KuduSession; -using kudu::client::KuduStatusFunctionCallback; -using kudu::client::KuduTable; -using kudu::client::KuduTableAlterer; -using kudu::client::KuduTableCreator; -using kudu::client::KuduValue; -using kudu::client::sp::shared_ptr; -using kudu::KuduPartialRow; -using kudu::MonoDelta; -using kudu::Status; - -using std::ostringstream; -using std::string; -using std::vector; - -static Status CreateClient(const string& addr, - shared_ptr<KuduClient>* client) { - return KuduClientBuilder() - .add_master_server_addr(addr) - .default_admin_operation_timeout(MonoDelta::FromSeconds(20)) - .Build(client); -} - -static KuduSchema CreateSchema() { - KuduSchema schema; - KuduSchemaBuilder b; - b.AddColumn("key")->Type(KuduColumnSchema::INT32)->NotNull()->PrimaryKey(); - b.AddColumn("int_val")->Type(KuduColumnSchema::INT32)->NotNull(); - b.AddColumn("string_val")->Type(KuduColumnSchema::STRING)->NotNull(); - b.AddColumn("non_null_with_default")->Type(KuduColumnSchema::INT32)->NotNull() - ->Default(KuduValue::FromInt(12345)); - KUDU_CHECK_OK(b.Build(&schema)); - return schema; -} - -static Status DoesTableExist(const shared_ptr<KuduClient>& client, - const string& table_name, - bool *exists) { - shared_ptr<KuduTable> table; - Status s = client->OpenTable(table_name, &table); - if (s.ok()) { - *exists = true; - } else if (s.IsNotFound()) { - *exists = false; - s = Status::OK(); - } - return s; -} - -static Status CreateTable(const shared_ptr<KuduClient>& client, - const string& table_name, - const KuduSchema& schema, - int num_tablets) { - // Generate the split keys for the table. - vector<const KuduPartialRow*> splits; - int32_t increment = 1000 / num_tablets; - for (int32_t i = 1; i < num_tablets; i++) { - KuduPartialRow* row = schema.NewRow(); - KUDU_CHECK_OK(row->SetInt32(0, i * increment)); - splits.push_back(row); - } - - vector<string> column_names; - column_names.push_back("key"); - - // Create the table. - KuduTableCreator* table_creator = client->NewTableCreator(); - Status s = table_creator->table_name(table_name) - .schema(&schema) - .set_range_partition_columns(column_names) - .split_rows(splits) - .Create(); - delete table_creator; - return s; -} - -static Status AlterTable(const shared_ptr<KuduClient>& client, - const string& table_name) { - KuduTableAlterer* table_alterer = client->NewTableAlterer(table_name); - table_alterer->AlterColumn("int_val")->RenameTo("integer_val"); - table_alterer->AddColumn("another_val")->Type(KuduColumnSchema::BOOL); - table_alterer->DropColumn("string_val"); - Status s = table_alterer->Alter(); - delete table_alterer; - return s; -} - -static void StatusCB(void* unused, const Status& status) { - KUDU_LOG(INFO) << "Asynchronous flush finished with status: " - << status.ToString(); -} - -static Status InsertRows(const shared_ptr<KuduTable>& table, int num_rows) { - shared_ptr<KuduSession> session = table->client()->NewSession(); - KUDU_RETURN_NOT_OK(session->SetFlushMode(KuduSession::MANUAL_FLUSH)); - session->SetTimeoutMillis(5000); - - for (int i = 0; i < num_rows; i++) { - KuduInsert* insert = table->NewInsert(); - KuduPartialRow* row = insert->mutable_row(); - KUDU_CHECK_OK(row->SetInt32("key", i)); - KUDU_CHECK_OK(row->SetInt32("integer_val", i * 2)); - KUDU_CHECK_OK(row->SetInt32("non_null_with_default", i * 5)); - KUDU_CHECK_OK(session->Apply(insert)); - } - Status s = session->Flush(); - if (s.ok()) { - return s; - } - - // Test asynchronous flush. - KuduStatusFunctionCallback<void*> status_cb(&StatusCB, NULL); - session->FlushAsync(&status_cb); - - // Look at the session's errors. - vector<KuduError*> errors; - bool overflow; - session->GetPendingErrors(&errors, &overflow); - if (!errors.empty()) { - s = overflow ? Status::IOError("Overflowed pending errors in session") : - errors.front()->status(); - while (!errors.empty()) { - delete errors.back(); - errors.pop_back(); - } - } - KUDU_RETURN_NOT_OK(s); - - // Close the session. - return session->Close(); -} - -static Status ScanRows(const shared_ptr<KuduTable>& table) { - const int kLowerBound = 5; - const int kUpperBound = 600; - - KuduScanner scanner(table.get()); - - // Add a predicate: WHERE key >= 5 - KuduPredicate* p = table->NewComparisonPredicate( - "key", KuduPredicate::GREATER_EQUAL, KuduValue::FromInt(kLowerBound)); - KUDU_RETURN_NOT_OK(scanner.AddConjunctPredicate(p)); - - // Add a predicate: WHERE key <= 600 - p = table->NewComparisonPredicate( - "key", KuduPredicate::LESS_EQUAL, KuduValue::FromInt(kUpperBound)); - KUDU_RETURN_NOT_OK(scanner.AddConjunctPredicate(p)); - - KUDU_RETURN_NOT_OK(scanner.Open()); - vector<KuduRowResult> results; - - int next_row = kLowerBound; - while (scanner.HasMoreRows()) { - KUDU_RETURN_NOT_OK(scanner.NextBatch(&results)); - for (vector<KuduRowResult>::iterator iter = results.begin(); - iter != results.end(); - iter++, next_row++) { - const KuduRowResult& result = *iter; - int32_t val; - KUDU_RETURN_NOT_OK(result.GetInt32("key", &val)); - if (val != next_row) { - ostringstream out; - out << "Scan returned the wrong results. Expected key " - << next_row << " but got " << val; - return Status::IOError(out.str()); - } - } - results.clear(); - } - - // next_row is now one past the last row we read. - int last_row_seen = next_row - 1; - - if (last_row_seen != kUpperBound) { - ostringstream out; - out << "Scan returned the wrong results. Expected last row to be " - << kUpperBound << " rows but got " << last_row_seen; - return Status::IOError(out.str()); - } - return Status::OK(); -} - -// A helper class providing custom logging callback. It also manages -// automatic callback installation and removal. -class LogCallbackHelper { - public: - LogCallbackHelper() : log_cb_(&LogCallbackHelper::LogCb, NULL) { - kudu::client::InstallLoggingCallback(&log_cb_); - } - - ~LogCallbackHelper() { - kudu::client::UninstallLoggingCallback(); - } - - static void LogCb(void* unused, - kudu::client::KuduLogSeverity severity, - const char* filename, - int line_number, - const struct ::tm* time, - const char* message, - size_t message_len) { - KUDU_LOG(INFO) << "Received log message from Kudu client library"; - KUDU_LOG(INFO) << " Severity: " << severity; - KUDU_LOG(INFO) << " Filename: " << filename; - KUDU_LOG(INFO) << " Line number: " << line_number; - char time_buf[32]; - // Example: Tue Mar 24 11:46:43 2015. - KUDU_CHECK(strftime(time_buf, sizeof(time_buf), "%a %b %d %T %Y", time)); - KUDU_LOG(INFO) << " Time: " << time_buf; - KUDU_LOG(INFO) << " Message: " << string(message, message_len); - } - - private: - kudu::client::KuduLoggingFunctionCallback<void*> log_cb_; -}; - -int main(int argc, char* argv[]) { - KUDU_LOG(INFO) << "Running with Kudu client version: " << - kudu::client::GetShortVersionString(); - KUDU_LOG(INFO) << "Long version info: " << - kudu::client::GetAllVersionInfo(); - - // This is to install and automatically un-install custom logging callback. - LogCallbackHelper log_cb_helper; - - if (argc != 2) { - KUDU_LOG(FATAL) << "usage: " << argv[0] << " <master host>"; - } - const string master_host = argv[1]; - - const string kTableName = "test_table"; - - // Enable verbose debugging for the client library. - kudu::client::SetVerboseLogLevel(2); - - // Create and connect a client. - shared_ptr<KuduClient> client; - KUDU_CHECK_OK(CreateClient(master_host, &client)); - KUDU_LOG(INFO) << "Created a client connection"; - - // Disable the verbose logging. - kudu::client::SetVerboseLogLevel(0); - - // Create a schema. - KuduSchema schema(CreateSchema()); - KUDU_LOG(INFO) << "Created a schema"; - - // Create a table with that schema. - bool exists; - KUDU_CHECK_OK(DoesTableExist(client, kTableName, &exists)); - if (exists) { - client->DeleteTable(kTableName); - KUDU_LOG(INFO) << "Deleting old table before creating new one"; - } - KUDU_CHECK_OK(CreateTable(client, kTableName, schema, 10)); - KUDU_LOG(INFO) << "Created a table"; - - // Alter the table. - KUDU_CHECK_OK(AlterTable(client, kTableName)); - KUDU_LOG(INFO) << "Altered a table"; - - // Insert some rows into the table. - shared_ptr<KuduTable> table; - KUDU_CHECK_OK(client->OpenTable(kTableName, &table)); - KUDU_CHECK_OK(InsertRows(table, 1000)); - KUDU_LOG(INFO) << "Inserted some rows into a table"; - - // Scan some rows. - KUDU_CHECK_OK(ScanRows(table)); - KUDU_LOG(INFO) << "Scanned some rows out of a table"; - - // Delete the table. - KUDU_CHECK_OK(client->DeleteTable(kTableName)); - KUDU_LOG(INFO) << "Deleted a table"; - - // Done! - KUDU_LOG(INFO) << "Done"; - - return 0; -}
