YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/client/transaction_cleanup.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) YugaByte, Inc.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
4
// in compliance with the License.  You may obtain a copy of the License at
5
//
6
// http://www.apache.org/licenses/LICENSE-2.0
7
//
8
// Unless required by applicable law or agreed to in writing, software distributed under the License
9
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
10
// or implied.  See the License for the specific language governing permissions and limitations
11
// under the License.
12
//
13
14
#include "yb/client/transaction_cleanup.h"
15
16
#include "yb/client/client.h"
17
#include "yb/client/meta_cache.h"
18
19
#include "yb/rpc/rpc_controller.h"
20
21
#include "yb/tserver/tserver_service.proxy.h"
22
23
#include "yb/util/logging.h"
24
#include "yb/util/result.h"
25
26
DEFINE_CAPABILITY(GracefulCleanup, 0x5512d2a9);
27
28
using namespace std::literals;
29
using namespace std::placeholders;
30
31
namespace yb {
32
namespace client {
33
34
namespace {
35
36
class TransactionCleanup : public std::enable_shared_from_this<TransactionCleanup> {
37
 public:
38
  TransactionCleanup(
39
      YBClient* client, const scoped_refptr<ClockBase>& clock, const TransactionId& transaction_id,
40
      Sealed sealed, CleanupType type)
41
      : client_(client), clock_(clock), transaction_id_(transaction_id), sealed_(sealed),
42
135k
        type_(type) {
43
135k
  }
44
45
135k
  void Perform(const std::vector<TabletId>& tablet_ids) {
46
135k
    auto self = shared_from_this();
47
182k
    for (const auto& tablet_id : tablet_ids) {
48
      // TODO(tsplit): pass table if needed as a part of
49
      // https://github.com/yugabyte/yugabyte-db/issues/4942.
50
182k
      client_->LookupTabletById(
51
182k
          tablet_id,
52
182k
          /* table =*/ nullptr,
53
182k
          master::IncludeInactive::kFalse,
54
182k
          TransactionRpcDeadline(),
55
182k
          std::bind(&TransactionCleanup::LookupTabletDone, this, _1, self),
56
182k
          client::UseCache::kTrue);
57
182k
    }
58
135k
  }
59
60
 private:
61
  void LookupTabletDone(const Result<internal::RemoteTabletPtr>& remote_tablet,
62
182k
                        const std::shared_ptr<TransactionCleanup>& self) {
63
182k
    if (!remote_tablet.ok()) {
64
      // Intents will be cleaned up later in this case.
65
30
      LOG_WITH_PREFIX(WARNING) << "Tablet lookup failed: " << remote_tablet.status();
66
30
      return;
67
30
    }
68
182k
    VLOG_WITH_PREFIX(1) << "Lookup tablet for cleanup done: " << yb::ToString(*remote_tablet);
69
182k
    auto remote_tablet_servers = (**remote_tablet).GetRemoteTabletServers(
70
182k
        internal::IncludeFailedReplicas::kTrue);
71
72
182k
    constexpr auto kCallTimeout = 15s;
73
182k
    auto now = clock_->Now().ToUint64();
74
75
182k
    const auto& tablet_id = (**remote_tablet).tablet_id();
76
77
182k
    std::lock_guard<std::mutex> lock(mutex_);
78
182k
    calls_.reserve(calls_.size() + remote_tablet_servers.size());
79
548k
    for (auto* server : remote_tablet_servers) {
80
548k
      if (type_ == CleanupType::kGraceful && !server->HasCapability(CAPABILITY_GracefulCleanup)) {
81
0
        VLOG_WITH_PREFIX(1)
82
0
            << "Skipping graceful cleanup at T " << (**remote_tablet).tablet_id() << " P "
83
0
            << server->permanent_uuid() << " because server does support it";
84
0
        continue;
85
0
      }
86
548k
      VLOG_WITH_PREFIX(2) << "Sending cleanup to T " << (**remote_tablet).tablet_id() << " P "
87
23
                          << server->permanent_uuid();
88
548k
      auto status = server->InitProxy(client_);
89
548k
      if (!status.ok()) {
90
0
        LOG_WITH_PREFIX(WARNING) << "Failed to init proxy to " << server->ToString() << ": "
91
0
                                 << status;
92
0
        continue;
93
0
      }
94
548k
      calls_.emplace_back();
95
548k
      auto& call = calls_.back();
96
97
548k
      auto& request = call.request;
98
548k
      request.set_tablet_id(tablet_id);
99
548k
      request.set_propagated_hybrid_time(now);
100
548k
      auto& state = *request.mutable_state();
101
548k
      state.set_transaction_id(transaction_id_.data(), transaction_id_.size());
102
367k
      state.set_status(type_ == CleanupType::kImmediate ? TransactionStatus::IMMEDIATE_CLEANUP
103
181k
                                                        : TransactionStatus::GRACEFUL_CLEANUP);
104
548k
      state.set_sealed(sealed_);
105
106
548k
      call.controller.set_timeout(kCallTimeout);
107
108
548k
      server->proxy()->UpdateTransactionAsync(
109
548k
          request, &call.response, &call.controller,
110
548k
          [this, self, remote_tablet = *remote_tablet, server] {
111
17
            VLOG_WITH_PREFIX(3) << "Cleaned intents at T " << remote_tablet->tablet_id() << " P "
112
17
                                << server->permanent_uuid();
113
548k
          });
114
548k
    }
115
182k
  }
116
117
30
  std::string LogPrefix() const {
118
30
    return Format("ID $0: ", transaction_id_);
119
30
  }
120
121
  struct Call {
122
    tserver::UpdateTransactionRequestPB request;
123
    tserver::UpdateTransactionResponsePB response;
124
    rpc::RpcController controller;
125
  };
126
127
  YBClient* const client_;
128
  const scoped_refptr<ClockBase> clock_;
129
  const TransactionId transaction_id_;
130
  const Sealed sealed_;
131
  const CleanupType type_;
132
133
  std::mutex mutex_;
134
  boost::container::stable_vector<Call> calls_ GUARDED_BY(mutex_);
135
};
136
137
} // namespace
138
139
void CleanupTransaction(
140
    YBClient* client, const scoped_refptr<ClockBase>& clock, const TransactionId& transaction_id,
141
135k
    Sealed sealed, CleanupType type, const std::vector<TabletId>& tablets) {
142
135k
  auto cleanup = std::make_shared<TransactionCleanup>(
143
135k
      client, clock, transaction_id, sealed, type);
144
135k
  cleanup->Perform(tablets);
145
135k
}
146
147
} // namespace client
148
} // namespace yb