Google Cloud Spanner C++ Client  1.33.0
A C++ Client Library for Google Cloud Spanner
database_admin_connection.cc
Go to the documentation of this file.
1 // Copyright 2019 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 // TODO(#7356): Remove this file after the deprecation period expires
16 #include "google/cloud/internal/disable_deprecation_warnings.inc"
17 #include "google/cloud/spanner/database_admin_connection.h"
18 #include "google/cloud/spanner/internal/defaults.h"
19 #include "google/cloud/spanner/options.h"
20 #include "google/cloud/spanner/timestamp.h"
21 #include "google/cloud/common_options.h"
22 #include "google/cloud/grpc_options.h"
23 #include "google/cloud/internal/async_long_running_operation.h"
24 #include "google/cloud/internal/retry_loop.h"
25 #include "google/cloud/options.h"
26 #include <grpcpp/grpcpp.h>
27 #include <chrono>
28 
29 namespace google {
30 namespace cloud {
31 namespace spanner {
33 
34 namespace gcsa = ::google::spanner::admin::database::v1;
35 
36 using ::google::cloud::internal::Idempotency;
37 using ::google::cloud::internal::RetryLoop;
38 
39 future<StatusOr<google::spanner::admin::database::v1::Backup>>
40 // NOLINTNEXTLINE(performance-unnecessary-value-param)
42  return google::cloud::make_ready_future(StatusOr<gcsa::Backup>(
43  Status(StatusCode::kUnimplemented, "not implemented")));
44 }
45 
46 future<StatusOr<google::spanner::admin::database::v1::Database>>
47 // NOLINTNEXTLINE(performance-unnecessary-value-param)
49  return google::cloud::make_ready_future(StatusOr<gcsa::Database>(
50  Status(StatusCode::kUnimplemented, "not implemented")));
51 }
52 
53 StatusOr<google::spanner::admin::database::v1::Backup>
54 // NOLINTNEXTLINE(performance-unnecessary-value-param)
56  return Status(StatusCode::kUnimplemented, "not implemented");
57 }
58 
59 // NOLINTNEXTLINE(performance-unnecessary-value-param)
61  return Status(StatusCode::kUnimplemented, "not implemented");
62 }
63 
64 // NOLINTNEXTLINE(performance-unnecessary-value-param)
66  return google::cloud::internal::MakePaginationRange<ListBackupsRange>(
67  gcsa::ListBackupsRequest{},
68  [](gcsa::ListBackupsRequest const&) {
69  return StatusOr<gcsa::ListBackupsResponse>(
70  Status(StatusCode::kUnimplemented, "not implemented"));
71  },
72  [](gcsa::ListBackupsResponse const&) {
73  return std::vector<gcsa::Backup>{};
74  });
75 }
76 
77 StatusOr<google::spanner::admin::database::v1::Backup>
78 // NOLINTNEXTLINE(performance-unnecessary-value-param)
80  return Status(StatusCode::kUnimplemented, "not implemented");
81 }
82 
83 ListBackupOperationsRange DatabaseAdminConnection::ListBackupOperations(
84  // NOLINTNEXTLINE(performance-unnecessary-value-param)
86  return google::cloud::internal::MakePaginationRange<
87  ListBackupOperationsRange>(
88  gcsa::ListBackupOperationsRequest{},
89  [](gcsa::ListBackupOperationsRequest const&) {
90  return StatusOr<gcsa::ListBackupOperationsResponse>(
91  Status(StatusCode::kUnimplemented, "not implemented"));
92  },
93  [](gcsa::ListBackupOperationsResponse const&) {
94  return std::vector<google::longrunning::Operation>{};
95  });
96 }
97 
98 ListDatabaseOperationsRange DatabaseAdminConnection::ListDatabaseOperations(
99  // NOLINTNEXTLINE(performance-unnecessary-value-param)
101  return google::cloud::internal::MakePaginationRange<
102  ListDatabaseOperationsRange>(
103  gcsa::ListDatabaseOperationsRequest{},
104  [](gcsa::ListDatabaseOperationsRequest const&) {
105  return StatusOr<gcsa::ListDatabaseOperationsResponse>(
106  Status(StatusCode::kUnimplemented, "not implemented"));
107  },
108  [](gcsa::ListDatabaseOperationsResponse const&) {
109  return std::vector<google::longrunning::Operation>{};
110  });
111 }
112 
113 namespace {
114 
115 class DatabaseAdminConnectionImpl : public DatabaseAdminConnection {
116  public:
117  // Note all the policies will be set to their default non-null values in the
118  // `MakeDatabaseAdminConnection()` function below.
119  explicit DatabaseAdminConnectionImpl(
120  std::shared_ptr<spanner_internal::DatabaseAdminStub> stub,
121  Options const& opts)
122  : stub_(std::move(stub)),
123  retry_policy_prototype_(opts.get<SpannerRetryPolicyOption>()->clone()),
124  backoff_policy_prototype_(
126  polling_policy_prototype_(
128  background_threads_(internal::MakeBackgroundThreadsFactory(opts)()) {}
129 
130  ~DatabaseAdminConnectionImpl() override = default;
131 
132  future<StatusOr<google::spanner::admin::database::v1::Database>>
133  CreateDatabase(CreateDatabaseParams p) override {
134  gcsa::CreateDatabaseRequest request;
135  request.set_parent(p.database.instance().FullName());
136  request.set_create_statement("CREATE DATABASE `" +
137  p.database.database_id() + "`");
138  struct EncryptionVisitor {
139  explicit EncryptionVisitor(gcsa::CreateDatabaseRequest& request)
140  : request_(request) {}
141  void operator()(DefaultEncryption const&) const {
142  // No encryption_config => GOOGLE_DEFAULT_ENCRYPTION.
143  }
144  void operator()(GoogleEncryption const&) const {
145  // No encryption_config => GOOGLE_DEFAULT_ENCRYPTION.
146  }
147  void operator()(CustomerManagedEncryption const& cme) const {
148  auto* config = request_.mutable_encryption_config();
149  config->set_kms_key_name(cme.encryption_key().FullName());
150  }
151  gcsa::CreateDatabaseRequest& request_;
152  };
153  absl::visit(EncryptionVisitor(request), p.encryption_config);
154  for (auto& s : p.extra_statements) {
155  *request.add_extra_statements() = std::move(s);
156  }
157  auto stub = stub_;
158  return google::cloud::internal::AsyncLongRunningOperation<gcsa::Database>(
159  background_threads_->cq(), std::move(request),
160  [stub](google::cloud::CompletionQueue& cq,
161  std::unique_ptr<grpc::ClientContext> context,
162  gcsa::CreateDatabaseRequest const& request) {
163  return stub->AsyncCreateDatabase(cq, std::move(context), request);
164  },
165  [stub](google::cloud::CompletionQueue& cq,
166  std::unique_ptr<grpc::ClientContext> context,
167  google::longrunning::GetOperationRequest const& request) {
168  return stub->AsyncGetOperation(cq, std::move(context), request);
169  },
170  [stub](google::cloud::CompletionQueue& cq,
171  std::unique_ptr<grpc::ClientContext> context,
172  google::longrunning::CancelOperationRequest const& request) {
173  return stub->AsyncCancelOperation(cq, std::move(context), request);
174  },
175  &google::cloud::internal::ExtractLongRunningResultResponse<
176  gcsa::Database>,
177  retry_policy_prototype_->clone(), backoff_policy_prototype_->clone(),
178  Idempotency::kNonIdempotent, polling_policy_prototype_->clone(),
179  __func__);
180  }
181 
182  StatusOr<google::spanner::admin::database::v1::Database> GetDatabase(
183  GetDatabaseParams p) override {
184  gcsa::GetDatabaseRequest request;
185  request.set_name(p.database.FullName());
186  return RetryLoop(
187  retry_policy_prototype_->clone(), backoff_policy_prototype_->clone(),
188  Idempotency::kIdempotent,
189  [this](grpc::ClientContext& context,
190  gcsa::GetDatabaseRequest const& request) {
191  return stub_->GetDatabase(context, request);
192  },
193  request, __func__);
194  }
195 
196  StatusOr<google::spanner::admin::database::v1::GetDatabaseDdlResponse>
197  GetDatabaseDdl(GetDatabaseDdlParams p) override {
198  gcsa::GetDatabaseDdlRequest request;
199  request.set_database(p.database.FullName());
200  return RetryLoop(
201  retry_policy_prototype_->clone(), backoff_policy_prototype_->clone(),
202  Idempotency::kIdempotent,
203  [this](grpc::ClientContext& context,
204  gcsa::GetDatabaseDdlRequest const& request) {
205  return stub_->GetDatabaseDdl(context, request);
206  },
207  request, __func__);
208  }
209 
210  future<
211  StatusOr<google::spanner::admin::database::v1::UpdateDatabaseDdlMetadata>>
212  UpdateDatabase(UpdateDatabaseParams p) override {
213  gcsa::UpdateDatabaseDdlRequest request;
214  request.set_database(p.database.FullName());
215  for (auto& s : p.statements) {
216  *request.add_statements() = std::move(s);
217  }
218  auto stub = stub_;
219  return google::cloud::internal::AsyncLongRunningOperation<
220  gcsa::UpdateDatabaseDdlMetadata>(
221  background_threads_->cq(), std::move(request),
222  [stub](google::cloud::CompletionQueue& cq,
223  std::unique_ptr<grpc::ClientContext> context,
224  gcsa::UpdateDatabaseDdlRequest const& request) {
225  return stub->AsyncUpdateDatabaseDdl(cq, std::move(context), request);
226  },
227  [stub](google::cloud::CompletionQueue& cq,
228  std::unique_ptr<grpc::ClientContext> context,
229  google::longrunning::GetOperationRequest const& request) {
230  return stub->AsyncGetOperation(cq, std::move(context), request);
231  },
232  [stub](google::cloud::CompletionQueue& cq,
233  std::unique_ptr<grpc::ClientContext> context,
234  google::longrunning::CancelOperationRequest const& request) {
235  return stub->AsyncCancelOperation(cq, std::move(context), request);
236  },
237  &google::cloud::internal::ExtractLongRunningResultMetadata<
238  gcsa::UpdateDatabaseDdlMetadata>,
239  retry_policy_prototype_->clone(), backoff_policy_prototype_->clone(),
240  Idempotency::kNonIdempotent, polling_policy_prototype_->clone(),
241  __func__);
242  }
243 
244  Status DropDatabase(DropDatabaseParams p) override {
245  google::spanner::admin::database::v1::DropDatabaseRequest request;
246  request.set_database(p.database.FullName());
247  return RetryLoop(
248  retry_policy_prototype_->clone(), backoff_policy_prototype_->clone(),
249  Idempotency::kIdempotent,
250  [this](grpc::ClientContext& context,
251  gcsa::DropDatabaseRequest const& request) {
252  return stub_->DropDatabase(context, request);
253  },
254  request, __func__);
255  }
256 
257  ListDatabaseRange ListDatabases(ListDatabasesParams p) override {
258  gcsa::ListDatabasesRequest request;
259  request.set_parent(p.instance.FullName());
260  request.clear_page_token();
261  auto stub = stub_;
262  // Because we do not have C++14 generalized lambda captures we cannot just
263  // use the unique_ptr<> here, so convert to shared_ptr<> instead.
264  auto retry =
265  std::shared_ptr<RetryPolicy const>(retry_policy_prototype_->clone());
266  auto backoff = std::shared_ptr<BackoffPolicy const>(
267  backoff_policy_prototype_->clone());
268 
269  char const* function_name = __func__;
270  return google::cloud::internal::MakePaginationRange<ListDatabaseRange>(
271  std::move(request),
272  [stub, retry, backoff,
273  function_name](gcsa::ListDatabasesRequest const& r) {
274  return RetryLoop(
275  retry->clone(), backoff->clone(), Idempotency::kIdempotent,
276  [stub](grpc::ClientContext& context,
277  gcsa::ListDatabasesRequest const& request) {
278  return stub->ListDatabases(context, request);
279  },
280  r, function_name);
281  },
282  [](gcsa::ListDatabasesResponse r) {
283  std::vector<gcsa::Database> result(r.databases().size());
284  auto& dbs = *r.mutable_databases();
285  std::move(dbs.begin(), dbs.end(), result.begin());
286  return result;
287  });
288  }
289 
290  future<StatusOr<google::spanner::admin::database::v1::Database>>
291  RestoreDatabase(RestoreDatabaseParams p) override {
292  gcsa::RestoreDatabaseRequest request;
293  request.set_parent(p.database.instance().FullName());
294  request.set_database_id(p.database.database_id());
295  request.set_backup(std::move(p.backup_full_name));
296  struct EncryptionVisitor {
297  explicit EncryptionVisitor(gcsa::RestoreDatabaseRequest& request)
298  : request_(request) {}
299  void operator()(DefaultEncryption const&) const {
300  // No encryption_config => USE_CONFIG_DEFAULT_OR_BACKUP_ENCRYPTION.
301  // That is, use the same encryption configuration as the backup.
302  }
303  void operator()(GoogleEncryption const&) const {
304  auto* config = request_.mutable_encryption_config();
305  config->set_encryption_type(
306  gcsa::RestoreDatabaseEncryptionConfig::GOOGLE_DEFAULT_ENCRYPTION);
307  }
308  void operator()(CustomerManagedEncryption const& cme) const {
309  auto* config = request_.mutable_encryption_config();
310  config->set_encryption_type(
311  gcsa::RestoreDatabaseEncryptionConfig::CUSTOMER_MANAGED_ENCRYPTION);
312  config->set_kms_key_name(cme.encryption_key().FullName());
313  }
314  gcsa::RestoreDatabaseRequest& request_;
315  };
316  absl::visit(EncryptionVisitor(request), p.encryption_config);
317  auto stub = stub_;
318  return google::cloud::internal::AsyncLongRunningOperation<gcsa::Database>(
319  background_threads_->cq(), std::move(request),
320  [stub](google::cloud::CompletionQueue& cq,
321  std::unique_ptr<grpc::ClientContext> context,
322  gcsa::RestoreDatabaseRequest const& request) {
323  return stub->AsyncRestoreDatabase(cq, std::move(context), request);
324  },
325  [stub](google::cloud::CompletionQueue& cq,
326  std::unique_ptr<grpc::ClientContext> context,
327  google::longrunning::GetOperationRequest const& request) {
328  return stub->AsyncGetOperation(cq, std::move(context), request);
329  },
330  [stub](google::cloud::CompletionQueue& cq,
331  std::unique_ptr<grpc::ClientContext> context,
332  google::longrunning::CancelOperationRequest const& request) {
333  return stub->AsyncCancelOperation(cq, std::move(context), request);
334  },
335  &google::cloud::internal::ExtractLongRunningResultResponse<
336  gcsa::Database>,
337  retry_policy_prototype_->clone(), backoff_policy_prototype_->clone(),
338  Idempotency::kNonIdempotent, polling_policy_prototype_->clone(),
339  __func__);
340  }
341 
342  StatusOr<google::iam::v1::Policy> GetIamPolicy(
343  GetIamPolicyParams p) override {
344  google::iam::v1::GetIamPolicyRequest request;
345  request.set_resource(p.database.FullName());
346  return RetryLoop(
347  retry_policy_prototype_->clone(), backoff_policy_prototype_->clone(),
348  Idempotency::kIdempotent,
349  [this](grpc::ClientContext& context,
350  google::iam::v1::GetIamPolicyRequest const& request) {
351  return stub_->GetIamPolicy(context, request);
352  },
353  request, __func__);
354  }
355 
356  StatusOr<google::iam::v1::Policy> SetIamPolicy(
357  SetIamPolicyParams p) override {
358  google::iam::v1::SetIamPolicyRequest request;
359  request.set_resource(p.database.FullName());
360  *request.mutable_policy() = std::move(p.policy);
361  auto const idempotency = request.policy().etag().empty()
362  ? Idempotency::kNonIdempotent
363  : Idempotency::kIdempotent;
364  return RetryLoop(
365  retry_policy_prototype_->clone(), backoff_policy_prototype_->clone(),
366  idempotency,
367  [this](grpc::ClientContext& context,
368  google::iam::v1::SetIamPolicyRequest const& request) {
369  return stub_->SetIamPolicy(context, request);
370  },
371  request, __func__);
372  }
373 
374  StatusOr<google::iam::v1::TestIamPermissionsResponse> TestIamPermissions(
375  TestIamPermissionsParams p) override {
376  google::iam::v1::TestIamPermissionsRequest request;
377  request.set_resource(p.database.FullName());
378  for (auto& permission : p.permissions) {
379  request.add_permissions(std::move(permission));
380  }
381  return RetryLoop(
382  retry_policy_prototype_->clone(), backoff_policy_prototype_->clone(),
383  Idempotency::kIdempotent,
384  [this](grpc::ClientContext& context,
385  google::iam::v1::TestIamPermissionsRequest const& request) {
386  return stub_->TestIamPermissions(context, request);
387  },
388  request, __func__);
389  }
390 
391  future<StatusOr<gcsa::Backup>> CreateBackup(CreateBackupParams p) override {
392  gcsa::CreateBackupRequest request;
393  request.set_parent(p.database.instance().FullName());
394  request.set_backup_id(p.backup_id);
395  auto& backup = *request.mutable_backup();
396  backup.set_database(p.database.FullName());
397  // `p.expire_time` is deprecated and ignored here.
398  *backup.mutable_expire_time() =
399  p.expire_timestamp.get<protobuf::Timestamp>().value();
400  if (p.version_time) {
401  *backup.mutable_version_time() =
402  p.version_time->get<protobuf::Timestamp>().value();
403  }
404  struct EncryptionVisitor {
405  explicit EncryptionVisitor(gcsa::CreateBackupRequest& request)
406  : request_(request) {}
407  void operator()(DefaultEncryption const&) const {
408  // No encryption_config => USE_DATABASE_ENCRYPTION.
409  // That is, use the same encryption configuration as the database.
410  }
411  void operator()(GoogleEncryption const&) const {
412  auto* config = request_.mutable_encryption_config();
413  config->set_encryption_type(
414  gcsa::CreateBackupEncryptionConfig::GOOGLE_DEFAULT_ENCRYPTION);
415  }
416  void operator()(CustomerManagedEncryption const& cme) const {
417  auto* config = request_.mutable_encryption_config();
418  config->set_encryption_type(
419  gcsa::CreateBackupEncryptionConfig::CUSTOMER_MANAGED_ENCRYPTION);
420  config->set_kms_key_name(cme.encryption_key().FullName());
421  }
422  gcsa::CreateBackupRequest& request_;
423  };
424  absl::visit(EncryptionVisitor(request), p.encryption_config);
425  auto stub = stub_;
426  return google::cloud::internal::AsyncLongRunningOperation<gcsa::Backup>(
427  background_threads_->cq(), std::move(request),
428  [stub](google::cloud::CompletionQueue& cq,
429  std::unique_ptr<grpc::ClientContext> context,
430  gcsa::CreateBackupRequest const& request) {
431  return stub->AsyncCreateBackup(cq, std::move(context), request);
432  },
433  [stub](google::cloud::CompletionQueue& cq,
434  std::unique_ptr<grpc::ClientContext> context,
435  google::longrunning::GetOperationRequest const& request) {
436  return stub->AsyncGetOperation(cq, std::move(context), request);
437  },
438  [stub](google::cloud::CompletionQueue& cq,
439  std::unique_ptr<grpc::ClientContext> context,
440  google::longrunning::CancelOperationRequest const& request) {
441  return stub->AsyncCancelOperation(cq, std::move(context), request);
442  },
443  &google::cloud::internal::ExtractLongRunningResultResponse<
444  gcsa::Backup>,
445  retry_policy_prototype_->clone(), backoff_policy_prototype_->clone(),
446  Idempotency::kNonIdempotent, polling_policy_prototype_->clone(),
447  __func__);
448  }
449 
450  StatusOr<google::spanner::admin::database::v1::Backup> GetBackup(
451  GetBackupParams p) override {
452  gcsa::GetBackupRequest request;
453  request.set_name(p.backup_full_name);
454  return RetryLoop(
455  retry_policy_prototype_->clone(), backoff_policy_prototype_->clone(),
456  Idempotency::kIdempotent,
457  [this](grpc::ClientContext& context,
458  gcsa::GetBackupRequest const& request) {
459  return stub_->GetBackup(context, request);
460  },
461  request, __func__);
462  }
463 
464  Status DeleteBackup(DeleteBackupParams p) override {
465  google::spanner::admin::database::v1::DeleteBackupRequest request;
466  request.set_name(p.backup_full_name);
467  return RetryLoop(
468  retry_policy_prototype_->clone(), backoff_policy_prototype_->clone(),
469  Idempotency::kIdempotent,
470  [this](grpc::ClientContext& context,
471  gcsa::DeleteBackupRequest const& request) {
472  return stub_->DeleteBackup(context, request);
473  },
474  request, __func__);
475  }
476 
477  ListBackupsRange ListBackups(ListBackupsParams p) override {
478  gcsa::ListBackupsRequest request;
479  request.set_parent(p.instance.FullName());
480  request.set_filter(std::move(p.filter));
481  auto stub = stub_;
482  // Because we do not have C++14 generalized lambda captures we cannot just
483  // use the unique_ptr<> here, so convert to shared_ptr<> instead.
484  auto retry =
485  std::shared_ptr<RetryPolicy const>(retry_policy_prototype_->clone());
486  auto backoff = std::shared_ptr<BackoffPolicy const>(
487  backoff_policy_prototype_->clone());
488 
489  char const* function_name = __func__;
490  return google::cloud::internal::MakePaginationRange<ListBackupsRange>(
491  std::move(request),
492  [stub, retry, backoff,
493  function_name](gcsa::ListBackupsRequest const& r) {
494  return RetryLoop(
495  retry->clone(), backoff->clone(), Idempotency::kIdempotent,
496  [stub](grpc::ClientContext& context,
497  gcsa::ListBackupsRequest const& request) {
498  return stub->ListBackups(context, request);
499  },
500  r, function_name);
501  },
502  [](gcsa::ListBackupsResponse r) {
503  std::vector<gcsa::Backup> result(r.backups().size());
504  auto& backups = *r.mutable_backups();
505  std::move(backups.begin(), backups.end(), result.begin());
506  return result;
507  });
508  }
509 
510  StatusOr<google::spanner::admin::database::v1::Backup> UpdateBackup(
511  UpdateBackupParams p) override {
512  return RetryLoop(
513  retry_policy_prototype_->clone(), backoff_policy_prototype_->clone(),
514  Idempotency::kIdempotent,
515  [this](grpc::ClientContext& context,
516  gcsa::UpdateBackupRequest const& request) {
517  return stub_->UpdateBackup(context, request);
518  },
519  p.request, __func__);
520  }
521 
522  ListBackupOperationsRange ListBackupOperations(
523  ListBackupOperationsParams p) override {
524  gcsa::ListBackupOperationsRequest request;
525  request.set_parent(p.instance.FullName());
526  request.set_filter(std::move(p.filter));
527  auto stub = stub_;
528  // Because we do not have C++14 generalized lambda captures we cannot just
529  // use the unique_ptr<> here, so convert to shared_ptr<> instead.
530  auto retry =
531  std::shared_ptr<RetryPolicy const>(retry_policy_prototype_->clone());
532  auto backoff = std::shared_ptr<BackoffPolicy const>(
533  backoff_policy_prototype_->clone());
534 
535  char const* function_name = __func__;
536  return google::cloud::internal::MakePaginationRange<
537  ListBackupOperationsRange>(
538  std::move(request),
539  [stub, retry, backoff,
540  function_name](gcsa::ListBackupOperationsRequest const& r) {
541  return RetryLoop(
542  retry->clone(), backoff->clone(), Idempotency::kIdempotent,
543  [stub](grpc::ClientContext& context,
544  gcsa::ListBackupOperationsRequest const& request) {
545  return stub->ListBackupOperations(context, request);
546  },
547  r, function_name);
548  },
549  [](gcsa::ListBackupOperationsResponse r) {
550  std::vector<google::longrunning::Operation> result(
551  r.operations().size());
552  auto& operations = *r.mutable_operations();
553  std::move(operations.begin(), operations.end(), result.begin());
554  return result;
555  });
556  }
557 
558  ListDatabaseOperationsRange ListDatabaseOperations(
559  ListDatabaseOperationsParams p) override {
560  gcsa::ListDatabaseOperationsRequest request;
561  request.set_parent(p.instance.FullName());
562  request.set_filter(std::move(p.filter));
563  auto stub = stub_;
564  // Because we do not have C++14 generalized lambda captures we cannot just
565  // use the unique_ptr<> here, so convert to shared_ptr<> instead.
566  auto retry =
567  std::shared_ptr<RetryPolicy const>(retry_policy_prototype_->clone());
568  auto backoff = std::shared_ptr<BackoffPolicy const>(
569  backoff_policy_prototype_->clone());
570 
571  char const* function_name = __func__;
572  return google::cloud::internal::MakePaginationRange<
573  ListDatabaseOperationsRange>(
574  std::move(request),
575  [stub, retry, backoff,
576  function_name](gcsa::ListDatabaseOperationsRequest const& r) {
577  return RetryLoop(
578  retry->clone(), backoff->clone(), Idempotency::kIdempotent,
579  [stub](grpc::ClientContext& context,
580  gcsa::ListDatabaseOperationsRequest const& request) {
581  return stub->ListDatabaseOperations(context, request);
582  },
583  r, function_name);
584  },
585  [](gcsa::ListDatabaseOperationsResponse r) {
586  std::vector<google::longrunning::Operation> result(
587  r.operations().size());
588  auto& operations = *r.mutable_operations();
589  std::move(operations.begin(), operations.end(), result.begin());
590  return result;
591  });
592  }
593 
594  private:
595  std::shared_ptr<spanner_internal::DatabaseAdminStub> stub_;
596  std::unique_ptr<RetryPolicy const> retry_policy_prototype_;
597  std::unique_ptr<BackoffPolicy const> backoff_policy_prototype_;
598  std::unique_ptr<PollingPolicy const> polling_policy_prototype_;
599 
600  // Implementations of `BackgroundThreads` typically create a pool of
601  // threads that are joined during destruction, so, to avoid ownership
602  // cycles, those threads should never assume ownership of this object
603  // (e.g., via a `std::shared_ptr<>`).
604  std::unique_ptr<BackgroundThreads> background_threads_;
605 };
606 
607 } // namespace
608 
610 
612  Options opts) {
613  internal::CheckExpectedOptions<CommonOptionList, GrpcOptionList,
614  SpannerPolicyOptionList>(opts, __func__);
615  opts = spanner_internal::DefaultAdminOptions(std::move(opts));
616  auto stub = spanner_internal::CreateDefaultDatabaseAdminStub(opts);
617  return std::make_shared<spanner::DatabaseAdminConnectionImpl>(
618  std::move(stub), std::move(opts));
619 }
620 
622  ConnectionOptions const& options) {
623  return MakeDatabaseAdminConnection(internal::MakeOptions(options));
624 }
625 
627  ConnectionOptions const& options, std::unique_ptr<RetryPolicy> retry_policy,
628  std::unique_ptr<BackoffPolicy> backoff_policy,
629  std::unique_ptr<PollingPolicy> polling_policy) {
630  auto opts = internal::MakeOptions(options);
631  opts.set<SpannerRetryPolicyOption>(std::move(retry_policy));
632  opts.set<SpannerBackoffPolicyOption>(std::move(backoff_policy));
633  opts.set<SpannerPollingPolicyOption>(std::move(polling_policy));
634  return MakeDatabaseAdminConnection(std::move(opts));
635 }
636 
638 } // namespace spanner
639 
640 namespace spanner_internal {
642 
643 std::shared_ptr<spanner::DatabaseAdminConnection>
644 MakeDatabaseAdminConnectionForTesting(std::shared_ptr<DatabaseAdminStub> stub,
645  Options opts) {
646  opts = spanner_internal::DefaultAdminOptions(std::move(opts));
647  return std::make_shared<spanner::DatabaseAdminConnectionImpl>(
648  std::move(stub), std::move(opts));
649 }
650 
652 } // namespace spanner_internal
653 } // namespace cloud
654 } // namespace google