YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/ent/src/yb/tserver/backup_service.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/tserver/backup_service.h"
14
15
#include "yb/util/debug/trace_event.h"
16
#include "yb/common/wire_protocol.h"
17
18
#include "yb/tablet/tablet.h"
19
#include "yb/tablet/tablet_retention_policy.h"
20
#include "yb/tablet/transaction_participant.h"
21
#include "yb/tablet/operations/snapshot_operation.h"
22
23
#include "yb/tserver/service_util.h"
24
#include "yb/tserver/tablet_server.h"
25
#include "yb/tserver/ts_tablet_manager.h"
26
27
#include "yb/util/flag_tags.h"
28
#include "yb/util/format.h"
29
#include "yb/util/random_util.h"
30
#include "yb/util/status_format.h"
31
32
using namespace std::literals;
33
34
DEFINE_test_flag(int32, tablet_delay_restore_ms, 0, "Delay restore on tablet");
35
36
namespace yb {
37
namespace tserver {
38
39
using rpc::RpcContext;
40
using tablet::SnapshotOperation;
41
using tablet::OperationCompletionCallback;
42
using tablet::Tablet;
43
44
TabletServiceBackupImpl::TabletServiceBackupImpl(TSTabletManager* tablet_manager,
45
                                                 const scoped_refptr<MetricEntity>& metric_entity)
46
    : TabletServerBackupServiceIf(metric_entity),
47
5.81k
      tablet_manager_(tablet_manager) {
48
5.81k
}
49
50
void TabletServiceBackupImpl::TabletSnapshotOp(const TabletSnapshotOpRequestPB* req,
51
                                               TabletSnapshotOpResponsePB* resp,
52
4
                                               RpcContext context) {
53
4
  if (!CheckUuidMatchOrRespond(tablet_manager_, "TabletSnapshotOp", req, resp, &context)) {
54
0
    return;
55
0
  }
56
57
4
  if (req->tablet_id_size() != 1) {
58
1
    auto status = STATUS_FORMAT(
59
1
        InvalidArgument, "Wrong number of tablets: expected one, but found $0",
60
1
        req->tablet_id_size());
61
1
    SetupErrorAndRespond(resp->mutable_error(), status, &context);
62
1
    return;
63
1
  }
64
65
3
  server::UpdateClock(*req, tablet_manager_->server()->Clock());
66
67
3
  const auto& tablet_id = req->tablet_id(0);
68
69
3
  TRACE_EVENT1("tserver", "TabletSnapshotOp", "tablet_id: ", tablet_id);
70
71
3
  LOG(INFO) << "Processing TabletSnapshotOp for tablet " << tablet_id << " from "
72
3
            << context.requestor_string() << ": "
73
3
            << TabletSnapshotOpRequestPB::Operation_Name(req->operation());
74
0
  VLOG(1) << "Full request: " << req->DebugString();
75
76
3
  auto tablet = LookupLeaderTabletOrRespond(tablet_manager_, tablet_id, resp, &context);
77
3
  if (!tablet) {
78
0
    return;
79
0
  }
80
81
3
  auto snapshot_hybrid_time = HybridTime::FromPB(req->snapshot_hybrid_time());
82
3
  tablet::ScopedReadOperation read_operation;
83
  // Transaction aware snapshot
84
3
  if (snapshot_hybrid_time && req->operation() == TabletSnapshotOpRequestPB::CREATE_ON_TABLET) {
85
    // We need to ensure that the state of the tablet's data at the snapshot hybrid time is not
86
    // garbage-collected away only while performing submit.
87
    // Since history cutoff is propagated using Raft, it will use the same queue as the
88
    // "create snapshot" operation.
89
    // So history cutoff could be updated only after the "create snapshot" operation is applied.
90
0
    auto temp_read_operation_result = tablet::ScopedReadOperation::Create(
91
0
        tablet.peer->tablet(), tablet::RequireLease::kTrue,
92
0
        ReadHybridTime::SingleTime(snapshot_hybrid_time));
93
0
    Status status;
94
0
    if (temp_read_operation_result.ok()) {
95
0
      read_operation = std::move(*temp_read_operation_result);
96
0
      if (tablet.peer->tablet()->transaction_participant()) {
97
0
        status = tablet.peer->tablet()->transaction_participant()->ResolveIntents(
98
0
            snapshot_hybrid_time, context.GetClientDeadline());
99
0
      }
100
0
    } else {
101
0
      status = temp_read_operation_result.status();
102
0
    }
103
0
    if (!status.ok()) {
104
0
      return SetupErrorAndRespond(resp->mutable_error(), status, &context);
105
0
    }
106
3
  }
107
108
3
  auto operation = std::make_unique<SnapshotOperation>(tablet.peer->tablet(), req);
109
110
3
  auto clock = tablet_manager_->server()->Clock();
111
3
  operation->set_completion_callback(
112
3
      MakeRpcOperationCompletionCallback(std::move(context), resp, clock));
113
114
3
  if (operation->request()->operation() == TabletSnapshotOpRequestPB::RESTORE_ON_TABLET) {
115
1
    AtomicFlagRandomSleepMs(&FLAGS_TEST_tablet_delay_restore_ms);
116
1
  }
117
118
3
  if (!operation->CheckOperationRequirements()) {
119
0
    return;
120
0
  }
121
122
  // TODO(txn_snapshot) Avoid duplicate snapshots.
123
  // Submit the create snapshot op. The RPC will be responded to asynchronously.
124
3
  tablet.peer->Submit(std::move(operation), tablet.leader_term);
125
3
}
126
127
}  // namespace tserver
128
}  // namespace yb