diff --git a/google/cloud/spanner/CMakeLists.txt b/google/cloud/spanner/CMakeLists.txt index 719f04cd1a9b7..c765d79cb89e5 100644 --- a/google/cloud/spanner/CMakeLists.txt +++ b/google/cloud/spanner/CMakeLists.txt @@ -160,7 +160,6 @@ add_library( internal/partial_result_set_source.cc internal/partial_result_set_source.h internal/polling_loop.h - internal/range_from_pagination.h internal/retry_loop.cc internal/retry_loop.h internal/session.cc diff --git a/google/cloud/spanner/database_admin_connection.h b/google/cloud/spanner/database_admin_connection.h index 75ac7b562b500..9919f48fe09b4 100644 --- a/google/cloud/spanner/database_admin_connection.h +++ b/google/cloud/spanner/database_admin_connection.h @@ -19,9 +19,9 @@ #include "google/cloud/spanner/database.h" #include "google/cloud/spanner/instance.h" #include "google/cloud/spanner/internal/database_admin_stub.h" -#include "google/cloud/spanner/internal/range_from_pagination.h" #include "google/cloud/spanner/polling_policy.h" #include "google/cloud/spanner/retry_policy.h" +#include "google/cloud/internal/pagination_range.h" #include #include #include @@ -40,7 +40,7 @@ inline namespace SPANNER_CLIENT_NS { * * [cppref-input-range]: https://en.cppreference.com/w/cpp/ranges/input_range */ -using ListDatabaseRange = internal::PaginationRange< +using ListDatabaseRange = google::cloud::internal::PaginationRange< google::spanner::admin::database::v1::Database, google::spanner::admin::database::v1::ListDatabasesRequest, google::spanner::admin::database::v1::ListDatabasesResponse>; diff --git a/google/cloud/spanner/instance_admin_connection.h b/google/cloud/spanner/instance_admin_connection.h index 8e88f52bfd3dc..c8fabc472bc0a 100644 --- a/google/cloud/spanner/instance_admin_connection.h +++ b/google/cloud/spanner/instance_admin_connection.h @@ -17,9 +17,9 @@ #include "google/cloud/spanner/backoff_policy.h" #include "google/cloud/spanner/internal/instance_admin_stub.h" -#include "google/cloud/spanner/internal/range_from_pagination.h" #include "google/cloud/spanner/polling_policy.h" #include "google/cloud/spanner/retry_policy.h" +#include "google/cloud/internal/pagination_range.h" #include #include @@ -37,7 +37,7 @@ inline namespace SPANNER_CLIENT_NS { * * [cppref-input-range]: https://en.cppreference.com/w/cpp/ranges/input_range */ -using ListInstancesRange = internal::PaginationRange< +using ListInstancesRange = google::cloud::internal::PaginationRange< google::spanner::admin::instance::v1::Instance, google::spanner::admin::instance::v1::ListInstancesRequest, google::spanner::admin::instance::v1::ListInstancesResponse>; @@ -51,7 +51,7 @@ using ListInstancesRange = internal::PaginationRange< * * [cppref-input-range]: https://en.cppreference.com/w/cpp/ranges/input_range */ -using ListInstanceConfigsRange = internal::PaginationRange< +using ListInstanceConfigsRange = google::cloud::internal::PaginationRange< google::spanner::admin::instance::v1::InstanceConfig, google::spanner::admin::instance::v1::ListInstanceConfigsRequest, google::spanner::admin::instance::v1::ListInstanceConfigsResponse>; diff --git a/google/cloud/spanner/internal/range_from_pagination.h b/google/cloud/spanner/internal/range_from_pagination.h deleted file mode 100644 index 2385d3dec9dfa..0000000000000 --- a/google/cloud/spanner/internal/range_from_pagination.h +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright 2019 Google LLC -// -// Licensed 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. - -#ifndef GOOGLE_CLOUD_CPP_SPANNER_GOOGLE_CLOUD_SPANNER_INTERNAL_RANGE_FROM_PAGINATION_H -#define GOOGLE_CLOUD_CPP_SPANNER_GOOGLE_CLOUD_SPANNER_INTERNAL_RANGE_FROM_PAGINATION_H - -#include "google/cloud/spanner/version.h" -#include "google/cloud/status_or.h" -#include -#include -#include -#include -#include -#include - -namespace google { -namespace cloud { -namespace spanner { -inline namespace SPANNER_CLIENT_NS { -namespace internal { - -/** - * An input iterator for a class with the same interface as `PaginationRange`. - */ -template -class PaginationIterator { - public: - //@{ - /// @name Iterator traits - using iterator_category = std::input_iterator_tag; - using value_type = StatusOr; - using difference_type = std::ptrdiff_t; - using pointer = value_type*; - using reference = value_type&; - //@} - - PaginationIterator() : owner_(nullptr) {} - - PaginationIterator& operator++() { - *this = owner_->GetNext(); - return *this; - } - - PaginationIterator operator++(int) { - PaginationIterator tmp(*this); - operator++(); - return tmp; - } - - value_type const* operator->() const { return &value_; } - value_type* operator->() { return &value_; } - - value_type const& operator*() const& { return value_; } - value_type& operator*() & { return value_; } -#if GOOGLE_CLOUD_CPP_HAVE_CONST_REF_REF - value_type const&& operator*() const&& { return std::move(value_); } -#endif // GOOGLE_CLOUD_CPP_HAVE_CONST_REF_REF - value_type&& operator*() && { return std::move(value_); } - - private: - friend Range; - - friend bool operator==(PaginationIterator const& lhs, - PaginationIterator const& rhs) { - // Iterators on different streams are always different. - if (lhs.owner_ != rhs.owner_) { - return false; - } - // All end iterators are equal. - if (lhs.owner_ == nullptr) { - return true; - } - // Iterators on the same stream are equal if they point to the same object. - if (lhs.value_.ok() && rhs.value_.ok()) { - return google::protobuf::util::MessageDifferencer::Equals(*lhs.value_, - *rhs.value_); - } - // If one is an error and the other is not then they must be different, - // because only one iterator per range can have an error status. For the - // same reason, if both have an error they both are pointing to the same - // element. - return lhs.value_.ok() == rhs.value_.ok(); - } - - friend bool operator!=(PaginationIterator const& lhs, - PaginationIterator const& rhs) { - return std::rel_ops::operator!=(lhs, rhs); - } - - PaginationIterator(Range* owner, value_type value) - : owner_(owner), value_(std::move(value)) {} - - Range* owner_; - value_type value_; -}; - -template -class PaginationRange { - public: - PaginationRange(Request request, - std::function(Request const& r)> loader, - std::function(Response r)> get_items) - : request_(std::move(request)), - next_page_loader_(std::move(loader)), - get_items_(std::move(get_items)), - on_last_page_(false) { - current_ = current_page_.begin(); - } - - /// The iterator type for this Range. - using iterator = PaginationIterator; - - /** - * Return an iterator over the range of `T` objects. - * - * The returned iterator is a single-pass input iterator that reads new `T` - * objects from the underlying `PaginationRange` when incremented. - * - * Creating, and particularly incrementing, multiple iterators on the same - * PaginationRange<> is unsupported and can produce incorrect results. - */ - iterator begin() { return GetNext(); } - - /// Return an iterator pointing to the end of the stream. - iterator end() { return PaginationIterator{}; } - - protected: - friend class PaginationIterator; - - /** - * Fetches (or returns if already fetched) the next object from the stream. - * - * @return An iterator pointing to the next element in the stream. On error, - * it returns an iterator that is different from `.end()`, but has an error - * status. If the stream is exhausted, it returns the `.end()` iterator. - */ - iterator GetNext() { - static Status const kPastTheEndError( - StatusCode::kFailedPrecondition, - "Cannot iterating past the end of ListObjectReader"); - if (current_page_.end() == current_) { - if (on_last_page_) { - return iterator(nullptr, kPastTheEndError); - } - request_.set_page_token(std::move(next_page_token_)); - auto response = next_page_loader_(request_); - if (!response.ok()) { - next_page_token_.clear(); - current_page_.clear(); - on_last_page_ = true; - current_ = current_page_.begin(); - return iterator(this, std::move(response).status()); - } - next_page_token_ = std::move(*response->mutable_next_page_token()); - current_page_ = get_items_(*std::move(response)); - current_ = current_page_.begin(); - if (next_page_token_.empty()) { - on_last_page_ = true; - } - if (current_page_.end() == current_) { - return iterator(nullptr, kPastTheEndError); - } - } - return iterator(this, std::move(*current_++)); - } - - private: - Request request_; - std::function(Request const& r)> next_page_loader_; - std::function(Response r)> get_items_; - std::vector current_page_; - typename std::vector::iterator current_; - std::string next_page_token_; - bool on_last_page_; -}; - -} // namespace internal -} // namespace SPANNER_CLIENT_NS -} // namespace spanner -} // namespace cloud -} // namespace google - -#endif // GOOGLE_CLOUD_CPP_SPANNER_GOOGLE_CLOUD_SPANNER_INTERNAL_RANGE_FROM_PAGINATION_H diff --git a/google/cloud/spanner/spanner_client.bzl b/google/cloud/spanner/spanner_client.bzl index 91aa7fb8a52e3..84ada219469bd 100644 --- a/google/cloud/spanner/spanner_client.bzl +++ b/google/cloud/spanner/spanner_client.bzl @@ -53,7 +53,6 @@ spanner_client_hdrs = [ "internal/partial_result_set_resume.h", "internal/partial_result_set_source.h", "internal/polling_loop.h", - "internal/range_from_pagination.h", "internal/retry_loop.h", "internal/session.h", "internal/session_pool.h",