YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/tablet/operations/change_metadata_operation.cc
Line
Count
Source (jump to first uncovered line)
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
//
18
// The following only applies to changes made to this file as part of YugaByte development.
19
//
20
// Portions Copyright (c) YugaByte, Inc.
21
//
22
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
23
// in compliance with the License.  You may obtain a copy of the License at
24
//
25
// http://www.apache.org/licenses/LICENSE-2.0
26
//
27
// Unless required by applicable law or agreed to in writing, software distributed under the License
28
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
29
// or implied.  See the License for the specific language governing permissions and limitations
30
// under the License.
31
//
32
33
#include "yb/tablet/operations/change_metadata_operation.h"
34
35
#include <glog/logging.h>
36
37
#include "yb/common/schema.h"
38
#include "yb/common/wire_protocol.h"
39
40
#include "yb/consensus/consensus_round.h"
41
#include "yb/consensus/log.h"
42
43
#include "yb/tablet/tablet.h"
44
#include "yb/tablet/tablet_metadata.h"
45
#include "yb/tablet/tablet_peer.h"
46
47
#include "yb/tserver/tserver_error.h"
48
49
#include "yb/util/async_util.h"
50
#include "yb/util/logging.h"
51
#include "yb/util/status_format.h"
52
#include "yb/util/trace.h"
53
54
namespace yb {
55
namespace tablet {
56
57
using google::protobuf::RepeatedPtrField;
58
using tserver::TabletServerErrorPB;
59
60
template <>
61
void RequestTraits<ChangeMetadataRequestPB>::SetAllocatedRequest(
62
0
    consensus::ReplicateMsg* replicate, ChangeMetadataRequestPB* request) {
63
0
  replicate->set_allocated_change_metadata_request(request);
64
0
}
65
66
template <>
67
ChangeMetadataRequestPB* RequestTraits<ChangeMetadataRequestPB>::MutableRequest(
68
769k
    consensus::ReplicateMsg* replicate) {
69
769k
  return replicate->mutable_change_metadata_request();
70
769k
}
71
72
ChangeMetadataOperation::ChangeMetadataOperation(
73
    Tablet* tablet, log::Log* log, const ChangeMetadataRequestPB* request)
74
546k
    : ExclusiveSchemaOperation(tablet, request), log_(log) {
75
546k
}
76
77
ChangeMetadataOperation::ChangeMetadataOperation(const ChangeMetadataRequestPB* request)
78
1.64k
    : ChangeMetadataOperation(nullptr, nullptr, request) {
79
1.64k
}
Unexecuted instantiation: _ZN2yb6tablet23ChangeMetadataOperationC2EPKNS0_23ChangeMetadataRequestPBE
_ZN2yb6tablet23ChangeMetadataOperationC1EPKNS0_23ChangeMetadataRequestPBE
Line
Count
Source
78
1.64k
    : ChangeMetadataOperation(nullptr, nullptr, request) {
79
1.64k
}
80
81
547k
ChangeMetadataOperation::~ChangeMetadataOperation() = default;
82
83
545k
void ChangeMetadataOperation::SetIndexes(const RepeatedPtrField<IndexInfoPB>& indexes) {
84
545k
  index_map_.FromPB(indexes);
85
545k
}
86
87
2.59k
string ChangeMetadataOperation::ToString() const {
88
2.59k
  return Format("ChangeMetadataOperation { hybrid_time: $0 schema: $1 request: $2 }",
89
2.59k
                hybrid_time_even_if_unset(), schema_, request());
90
2.59k
}
91
92
545k
Status ChangeMetadataOperation::Prepare() {
93
545k
  TRACE("PREPARE CHANGE-METADATA: Starting");
94
95
  // Decode schema
96
545k
  auto has_schema = request()->has_schema();
97
545k
  if (has_schema) {
98
49.0k
    schema_holder_ = std::make_unique<Schema>();
99
49.0k
    Status s = SchemaFromPB(request()->schema(), schema_holder_.get());
100
49.0k
    if (!s.ok()) {
101
0
      return s.CloneAndAddErrorCode(
102
0
          tserver::TabletServerError(TabletServerErrorPB::INVALID_SCHEMA));
103
0
    }
104
545k
  }
105
106
545k
  Tablet* tablet = this->tablet();
107
545k
  RETURN_NOT_OK(tablet->CreatePreparedChangeMetadata(this, schema_holder_.get()));
108
109
545k
  SetIndexes(request()->indexes());
110
111
545k
  TRACE("PREPARE CHANGE-METADATA: finished");
112
545k
  return Status::OK();
113
545k
}
114
115
545k
Status ChangeMetadataOperation::DoReplicated(int64_t leader_term, Status* complete_status) {
116
545k
  TRACE("APPLY CHANGE-METADATA: Starting");
117
118
545k
  Tablet* tablet = this->tablet();
119
545k
  log::Log* log = mutable_log();
120
545k
  size_t num_operations = 0;
121
122
545k
  if (request()->has_wal_retention_secs()) {
123
    // We don't consider wal retention changes as another operation because this value is always
124
    // sent together with the schema, as long as it has been changed in the master's sys-catalog.
125
2.55k
    auto s = tablet->AlterWalRetentionSecs(this);
126
2.55k
    if (s.ok()) {
127
2.55k
      log->set_wal_retention_secs(request()->wal_retention_secs());
128
18.4E
    } else {
129
18.4E
      LOG(WARNING) << "T " << tablet->tablet_id() << ": Unable to alter wal retention secs";
130
18.4E
    }
131
2.55k
  }
132
133
  // Only perform one operation.
134
545k
  enum MetadataChange {
135
545k
    NONE,
136
545k
    SCHEMA,
137
545k
    ADD_TABLE,
138
545k
    REMOVE_TABLE,
139
545k
    BACKFILL_DONE,
140
545k
  };
141
142
545k
  MetadataChange metadata_change = MetadataChange::NONE;
143
545k
  bool request_has_newer_schema = false;
144
545k
  if (request()->has_schema()) {
145
49.0k
    metadata_change = MetadataChange::SCHEMA;
146
49.0k
    request_has_newer_schema = tablet->metadata()->schema_version() < schema_version();
147
49.0k
    if (request_has_newer_schema) {
148
46.6k
      ++num_operations;
149
46.6k
    }
150
49.0k
  }
151
152
545k
  if (request()->has_add_table()) {
153
489k
    metadata_change = MetadataChange::NONE;
154
489k
    if (++num_operations == 1) {
155
489k
      metadata_change = MetadataChange::ADD_TABLE;
156
489k
    }
157
489k
  }
158
159
545k
  if (request()->has_remove_table_id()) {
160
45
    metadata_change = MetadataChange::NONE;
161
45
    if (++num_operations == 1) {
162
45
      metadata_change = MetadataChange::REMOVE_TABLE;
163
45
    }
164
45
  }
165
166
545k
  if (request()->has_mark_backfill_done()) {
167
7.28k
    metadata_change = MetadataChange::NONE;
168
7.28k
    if (++num_operations == 1) {
169
7.28k
      metadata_change = MetadataChange::BACKFILL_DONE;
170
7.28k
    }
171
7.28k
  }
172
173
545k
  switch (metadata_change) {
174
0
    case MetadataChange::NONE:
175
0
      return STATUS_FORMAT(
176
0
          InvalidArgument, "Wrong number of operations in Change Metadata Operation: $0",
177
0
          num_operations);
178
49.2k
    case MetadataChange::SCHEMA:
179
49.2k
      if (!request_has_newer_schema) {
180
2.59k
        LOG_WITH_PREFIX(INFO)
181
2.59k
            << "Already running schema version " << tablet->metadata()->schema_version()
182
2.59k
            << " got alter request for version " << schema_version();
183
2.59k
        break;
184
2.59k
      }
185
0
      DCHECK_EQ(1, num_operations) << "Invalid number of change metadata operations: "
186
0
                                   << num_operations;
187
46.6k
      RETURN_NOT_OK(tablet->AlterSchema(this));
188
46.6k
      log->SetSchemaForNextLogSegment(*DCHECK_NOTNULL(schema()), schema_version());
189
46.6k
      break;
190
489k
    case MetadataChange::ADD_TABLE:
191
0
      DCHECK_EQ(1, num_operations) << "Invalid number of change metadata operations: "
192
0
                                   << num_operations;
193
489k
      RETURN_NOT_OK(tablet->AddTable(request()->add_table()));
194
489k
      break;
195
45
    case MetadataChange::REMOVE_TABLE:
196
0
      DCHECK_EQ(1, num_operations) << "Invalid number of change metadata operations: "
197
0
                                   << num_operations;
198
45
      RETURN_NOT_OK(tablet->RemoveTable(request()->remove_table_id()));
199
45
      break;
200
7.29k
    case MetadataChange::BACKFILL_DONE:
201
0
      DCHECK_EQ(1, num_operations) << "Invalid number of change metadata operations: "
202
0
                                   << num_operations;
203
7.29k
      RETURN_NOT_OK(tablet->MarkBackfillDone(request()->backfill_done_table_id()));
204
7.29k
      break;
205
545k
  }
206
207
  // Now that all of the changes have been applied and the commit is durable
208
  // make the changes visible to readers.
209
545k
  TRACE("AlterSchemaCommitCallback: making alter schema visible");
210
545k
  return Status::OK();
211
545k
}
212
213
12
Status ChangeMetadataOperation::DoAborted(const Status& status) {
214
12
  TRACE("AlterSchemaCommitCallback: transaction aborted");
215
12
  return status;
216
12
}
217
218
CHECKED_STATUS SyncReplicateChangeMetadataOperation(
219
    const ChangeMetadataRequestPB* req,
220
    TabletPeer* tablet_peer,
221
204k
    int64_t term) {
222
204k
  auto operation = std::make_unique<ChangeMetadataOperation>(
223
204k
      tablet_peer->tablet(), tablet_peer->log(), req);
224
225
204k
  Synchronizer synchronizer;
226
227
204k
  operation->set_completion_callback(synchronizer.AsStdStatusCallback());
228
229
204k
  tablet_peer->Submit(std::move(operation), term);
230
231
204k
  return synchronizer.Wait();
232
204k
}
233
234
}  // namespace tablet
235
}  // namespace yb