YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/ent/src/yb/master/async_snapshot_tasks.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
#include "yb/master/async_snapshot_tasks.h"
14
15
#include "yb/consensus/consensus_error.h"
16
17
#include "yb/common/transaction_error.h"
18
#include "yb/common/wire_protocol.h"
19
20
#include "yb/master/catalog_entity_info.h"
21
#include "yb/master/catalog_manager_if.h"
22
#include "yb/master/master.h"
23
#include "yb/master/ts_descriptor.h"
24
25
#include "yb/rpc/messenger.h"
26
27
#include "yb/tserver/backup.proxy.h"
28
29
#include "yb/util/flag_tags.h"
30
#include "yb/util/format.h"
31
#include "yb/util/logging.h"
32
33
namespace yb {
34
namespace master {
35
36
using std::string;
37
using tserver::TabletServerErrorPB;
38
39
////////////////////////////////////////////////////////////
40
// AsyncTabletSnapshotOp
41
////////////////////////////////////////////////////////////
42
43
namespace {
44
45
0
std::string SnapshotIdToString(const std::string& snapshot_id) {
46
0
  auto uuid = TryFullyDecodeTxnSnapshotId(snapshot_id);
47
0
  return uuid.IsNil() ? snapshot_id : uuid.ToString();
48
0
}
49
50
}
51
52
AsyncTabletSnapshotOp::AsyncTabletSnapshotOp(Master *master,
53
                                             ThreadPool* callback_pool,
54
                                             const scoped_refptr<TabletInfo>& tablet,
55
                                             const string& snapshot_id,
56
                                             tserver::TabletSnapshotOpRequestPB::Operation op)
57
  : RetryingTSRpcTask(
58
        master, callback_pool, std::make_unique<PickLeaderReplica>(tablet), tablet->table().get()),
59
    tablet_(tablet),
60
    snapshot_id_(snapshot_id),
61
0
    operation_(op) {
62
0
}
63
64
0
string AsyncTabletSnapshotOp::description() const {
65
0
  return Format("$0 Tablet Snapshot Operation $1 RPC $2",
66
0
                *tablet_, tserver::TabletSnapshotOpRequestPB::Operation_Name(operation_),
67
0
                SnapshotIdToString(snapshot_id_));
68
0
}
69
70
0
TabletId AsyncTabletSnapshotOp::tablet_id() const {
71
0
  return tablet_->tablet_id();
72
0
}
73
74
0
TabletServerId AsyncTabletSnapshotOp::permanent_uuid() const {
75
0
  return target_ts_desc_ != nullptr ? target_ts_desc_->permanent_uuid() : "";
76
0
}
77
78
0
bool AsyncTabletSnapshotOp::RetryAllowed(TabletServerErrorPB::Code code, const Status& status) {
79
0
  switch (code) {
80
0
    case TabletServerErrorPB::TABLET_NOT_FOUND:
81
0
      return false;
82
0
    case TabletServerErrorPB::INVALID_SNAPSHOT:
83
0
      return operation_ != tserver::TabletSnapshotOpRequestPB::RESTORE_ON_TABLET;
84
0
    default:
85
0
      return TransactionError(status) != TransactionErrorCode::kSnapshotTooOld &&
86
0
             consensus::ConsensusError(status) != consensus::ConsensusErrorPB::TABLET_SPLIT;
87
0
  }
88
0
}
89
90
0
void AsyncTabletSnapshotOp::HandleResponse(int attempt) {
91
0
  server::UpdateClock(resp_, master_->clock());
92
93
0
  if (resp_.has_error()) {
94
0
    Status status = StatusFromPB(resp_.error().status());
95
96
0
    if (!RetryAllowed(resp_.error().code(), status)) {
97
0
      LOG_WITH_PREFIX(WARNING) << "Failed, NO retry: " << status;
98
0
      TransitionToCompleteState();
99
0
    } else {
100
0
      LOG_WITH_PREFIX(WARNING) << "Failed, will be retried: " << status;
101
0
    }
102
0
  } else {
103
0
    TransitionToCompleteState();
104
0
    VLOG_WITH_PREFIX(1) << "Complete";
105
0
  }
106
107
0
  if (state() != server::MonitoredTaskState::kComplete) {
108
0
    VLOG_WITH_PREFIX(1) << "TabletSnapshotOp task is not completed";
109
0
    return;
110
0
  }
111
112
0
  switch (operation_) {
113
0
    case tserver::TabletSnapshotOpRequestPB::CREATE_ON_TABLET: {
114
      // TODO: this class should not know CatalogManager API,
115
      //       remove circular dependency between classes.
116
0
      master_->catalog_manager()->HandleCreateTabletSnapshotResponse(
117
0
          tablet_.get(), resp_.has_error());
118
0
      return;
119
0
    }
120
0
    case tserver::TabletSnapshotOpRequestPB::RESTORE_ON_TABLET: {
121
      // TODO: this class should not know CatalogManager API,
122
      //       remove circular dependency between classes.
123
0
      master_->catalog_manager()->HandleRestoreTabletSnapshotResponse(
124
0
          tablet_.get(), resp_.has_error());
125
0
      return;
126
0
    }
127
0
    case tserver::TabletSnapshotOpRequestPB::DELETE_ON_TABLET: {
128
      // TODO: this class should not know CatalogManager API,
129
      //       remove circular dependency between classes.
130
      // HandleDeleteTabletSnapshotResponse handles only non transaction aware snapshots.
131
      // So prevent log flooding for transaction aware snapshots.
132
0
      if (!TryFullyDecodeTxnSnapshotId(snapshot_id_)) {
133
0
        master_->catalog_manager()->HandleDeleteTabletSnapshotResponse(
134
0
            snapshot_id_, tablet_.get(), resp_.has_error());
135
0
      }
136
0
      return;
137
0
    }
138
0
    case tserver::TabletSnapshotOpRequestPB::RESTORE_FINISHED:
139
0
      return;
140
0
    case tserver::TabletSnapshotOpRequestPB::CREATE_ON_MASTER: FALLTHROUGH_INTENDED;
141
0
    case tserver::TabletSnapshotOpRequestPB::DELETE_ON_MASTER: FALLTHROUGH_INTENDED;
142
0
    case tserver::TabletSnapshotOpRequestPB::RESTORE_SYS_CATALOG: FALLTHROUGH_INTENDED;
143
0
    case google::protobuf::kint32min: FALLTHROUGH_INTENDED;
144
0
    case google::protobuf::kint32max: FALLTHROUGH_INTENDED;
145
0
    case tserver::TabletSnapshotOpRequestPB::UNKNOWN: break; // Not handled.
146
0
  }
147
148
0
  FATAL_INVALID_ENUM_VALUE(tserver::TabletSnapshotOpRequestPB::Operation, operation_);
149
0
}
150
151
0
bool AsyncTabletSnapshotOp::SendRequest(int attempt) {
152
0
  tserver::TabletSnapshotOpRequestPB req;
153
0
  req.set_dest_uuid(permanent_uuid());
154
0
  req.add_tablet_id(tablet_->tablet_id());
155
0
  req.set_snapshot_id(snapshot_id_);
156
0
  req.set_operation(operation_);
157
0
  if (snapshot_schedule_id_) {
158
0
    req.set_schedule_id(snapshot_schedule_id_.data(), snapshot_schedule_id_.size());
159
0
  }
160
0
  if (restoration_id_) {
161
0
    req.set_restoration_id(restoration_id_.data(), restoration_id_.size());
162
0
  }
163
0
  if (snapshot_hybrid_time_) {
164
0
    req.set_snapshot_hybrid_time(snapshot_hybrid_time_.ToUint64());
165
0
  }
166
0
  if (restoration_hybrid_time_) {
167
0
    req.set_restoration_hybrid_time(restoration_hybrid_time_.ToUint64());
168
0
  }
169
0
  if (has_metadata_) {
170
0
    req.set_schema_version(schema_version_);
171
0
    *req.mutable_schema() = schema_;
172
0
    *req.mutable_indexes() = indexes_;
173
0
    req.set_hide(hide_);
174
0
  }
175
0
  req.set_propagated_hybrid_time(master_->clock()->Now().ToUint64());
176
177
0
  ts_backup_proxy_->TabletSnapshotOpAsync(req, &resp_, &rpc_, BindRpcCallback());
178
0
  VLOG_WITH_PREFIX(1) << "Sent to " << permanent_uuid() << " (attempt " << attempt << "): "
179
0
                      << (VLOG_IS_ON(4) ? req.ShortDebugString() : "");
180
0
  return true;
181
0
}
182
183
0
void AsyncTabletSnapshotOp::Finished(const Status& status) {
184
0
  if (!callback_) {
185
0
    return;
186
0
  }
187
0
  if (!status.ok()) {
188
0
    callback_(status);
189
0
    return;
190
0
  }
191
0
  if (resp_.has_error()) {
192
0
    auto status = tablet_->CheckRunning();
193
0
    if (status.ok()) {
194
0
      status = StatusFromPB(resp_.error().status());
195
0
    }
196
0
    callback_(status);
197
0
  } else {
198
0
    callback_(&resp_);
199
0
  }
200
0
}
201
202
0
void AsyncTabletSnapshotOp::SetMetadata(const SysTablesEntryPB& pb) {
203
0
  has_metadata_ = true;
204
0
  schema_version_ = pb.version();
205
0
  schema_ = pb.schema();
206
0
  indexes_ = pb.indexes();
207
0
}
208
209
} // namespace master
210
} // namespace yb