Группа :: Сети/WWW
Пакет: chromium-gost
Главная Изменения Спек Патчи Sources Загрузить Gear Bugs and FR Repocop
Патч: 0013-sql-make-VirtualCursor-standard-layout-type.patch
Скачать
Скачать
From 80da859541cecc0e75e1e8260f547bf2447482a1 Mon Sep 17 00:00:00 2001
From: Stephan Hartmann <stha09@googlemail.com>
Date: Tue, 4 May 2021 15:00:19 +0000
Subject: [PATCH] sql: make VirtualCursor standard layout type
sql::recover::VirtualCursor needs to be a standard layout type, but
has members of type std::unique_ptr. However, std::unique_ptr is not
guaranteed to be standard layout. Compiling with clang combined with
gcc-11 libstdc++ fails because of this. Replace std::unique_ptr with
raw pointers.
Bug: 1189788
Change-Id: Ia6dc388cc5ef1c0f2afc75f8ca45b9f12687ca9c
---
sql/recover_module/btree.cc | 21 +++++++++++++++------
sql/recover_module/btree.h | 17 +++++++++++++----
sql/recover_module/cursor.cc | 24 ++++++++++++------------
sql/recover_module/cursor.h | 2 +-
sql/recover_module/pager.cc | 7 +++----
sql/recover_module/pager.h | 5 +++--
6 files changed, 47 insertions(+), 29 deletions(-)
diff --git a/sql/recover_module/btree.cc b/sql/recover_module/btree.cc
index cc9420e5c05..62fcaaf79ed 100644
--- a/sql/recover_module/btree.cc
+++ b/sql/recover_module/btree.cc
@@ -129,30 +129,39 @@ int InnerPageDecoder::ComputeCellCount(DatabasePageReader* db_reader) {
return std::min(header_count, upper_bound);
}
#if !DCHECK_IS_ON()
// In DCHECKed builds, the decoder contains a sequence checker, which has a
// non-trivial destructor.
static_assert(std::is_trivially_destructible<LeafPageDecoder>::value,
"Move the destructor to the .cc file if it's non-trival");
#endif // !DCHECK_IS_ON()
-LeafPageDecoder::LeafPageDecoder(DatabasePageReader* db_reader) noexcept
- : page_id_(db_reader->page_id()),
- db_reader_(db_reader),
- cell_count_(ComputeCellCount(db_reader)),
- next_read_index_(0),
- last_record_size_(0) {
+void LeafPageDecoder::Initialize(DatabasePageReader* db_reader) {
+ DCHECK(db_reader);
DCHECK(IsOnValidPage(db_reader));
+ page_id_ = db_reader->page_id();
+ db_reader_ = db_reader;
+ cell_count_ = ComputeCellCount(db_reader);
+ next_read_index_ = 0;
+ last_record_size_ = 0;
DCHECK(DatabasePageReader::IsValidPageId(page_id_));
}
+void LeafPageDecoder::Reset() {
+ db_reader_ = nullptr;
+ page_id_ = 0;
+ cell_count_ = 0;
+ next_read_index_ = 0;
+ last_record_size_ = 0;
+}
+
bool LeafPageDecoder::TryAdvance() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(CanAdvance());
#if DCHECK_IS_ON()
// DCHECKs use last_record_size == 0 to check for incorrect access to the
// decoder's state.
last_record_size_ = 0;
#endif // DCHECK_IS_ON()
diff --git a/sql/recover_module/btree.h b/sql/recover_module/btree.h
index eaa087a5c52..78ce00e057c 100644
--- a/sql/recover_module/btree.h
+++ b/sql/recover_module/btree.h
@@ -96,21 +96,21 @@ class InnerPageDecoder {
// via last_record_{rowid, size, offset}() methods.
//
// An instance can only be used to decode a single page. Instances are not
// thread-safe.
class LeafPageDecoder {
public:
// Creates a decoder for a DatabasePageReader's last read page.
//
// |db_reader| must have been used to read an inner page of a table B-tree.
// |db_reader| must outlive this instance.
- explicit LeafPageDecoder(DatabasePageReader* db_reader) noexcept;
+ explicit LeafPageDecoder() noexcept = default;
~LeafPageDecoder() noexcept = default;
LeafPageDecoder(const LeafPageDecoder&) = delete;
LeafPageDecoder& operator=(const LeafPageDecoder&) = delete;
// The rowid of the most recent record read by TryAdvance().
//
// Must only be called after a successful call to TryAdvance().
int64_t last_record_rowid() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -144,41 +144,50 @@ class LeafPageDecoder {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return next_read_index_ < cell_count_;
}
// Advances the reader and returns the last read value.
//
// Returns false if the read fails. The caller should continue attempting to
// read as long as CanAdvance() returns true.
bool TryAdvance();
+ // Initialize with DatabasePageReader
+ void Initialize(DatabasePageReader* db_reader);
+
+ // Reset internal DatabasePageReader
+ void Reset();
+
+ // True if DatabasePageReader is valid
+ bool IsValid() { return (db_reader_ != nullptr); }
+
// True if the given reader may point to an inner page in a table B-tree.
//
// The last ReadPage() call on |db_reader| must have succeeded.
static bool IsOnValidPage(DatabasePageReader* db_reader);
private:
// Returns the number of cells in the B-tree page.
//
// Checks for database corruption. The caller can assume that the cell pointer
// array with the returned size will not extend past the page buffer.
static int ComputeCellCount(DatabasePageReader* db_reader);
// The number of the B-tree page this reader is reading.
- const int64_t page_id_;
+ int64_t page_id_;
// Used to read the tree page.
//
// Raw pointer usage is acceptable because this instance's owner is expected
// to ensure that the DatabasePageReader outlives this.
- DatabasePageReader* const db_reader_;
+ DatabasePageReader* db_reader_;
// Caches the ComputeCellCount() value for this reader's page.
- const int cell_count_ = ComputeCellCount(db_reader_);
+ int cell_count_;
// The reader's cursor state.
//
// Each B-tree cell contains a value. So, this member takes values in
// [0, cell_count_).
int next_read_index_ = 0;
int64_t last_record_size_ = 0;
int64_t last_record_rowid_ = 0;
int last_record_offset_ = 0;
diff --git a/sql/recover_module/cursor.cc b/sql/recover_module/cursor.cc
index 4f827edf1b4..240de4999fe 100644
--- a/sql/recover_module/cursor.cc
+++ b/sql/recover_module/cursor.cc
@@ -21,42 +21,42 @@ VirtualCursor::VirtualCursor(VirtualTable* table)
}
VirtualCursor::~VirtualCursor() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
table_->WillDeleteCursor(this);
}
int VirtualCursor::First() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
inner_decoders_.clear();
- leaf_decoder_ = nullptr;
+ leaf_decoder_.Reset();
AppendPageDecoder(table_->root_page_id());
return Next();
}
int VirtualCursor::Next() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
record_reader_.Reset();
- while (!inner_decoders_.empty() || leaf_decoder_.get()) {
- if (leaf_decoder_.get()) {
- if (!leaf_decoder_->CanAdvance()) {
+ while (!inner_decoders_.empty() || leaf_decoder_.IsValid()) {
+ if (leaf_decoder_.IsValid()) {
+ if (!leaf_decoder_.CanAdvance()) {
// The leaf has been exhausted. Remove it from the DFS stack.
- leaf_decoder_ = nullptr;
+ leaf_decoder_.Reset();
continue;
}
- if (!leaf_decoder_->TryAdvance())
+ if (!leaf_decoder_.TryAdvance())
continue;
- if (!payload_reader_.Initialize(leaf_decoder_->last_record_size(),
- leaf_decoder_->last_record_offset())) {
+ if (!payload_reader_.Initialize(leaf_decoder_.last_record_size(),
+ leaf_decoder_.last_record_offset())) {
continue;
}
if (!record_reader_.Initialize())
continue;
// Found a healthy record.
if (!IsAcceptableRecord()) {
record_reader_.Reset();
continue;
}
@@ -94,35 +94,35 @@ int VirtualCursor::ReadColumn(int column_index,
}
if (record_reader_.ReadValue(column_index, result_context))
return SQLITE_OK;
return SQLITE_ERROR;
}
int64_t VirtualCursor::RowId() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(record_reader_.IsInitialized());
- DCHECK(leaf_decoder_.get());
- return leaf_decoder_->last_record_rowid();
+ DCHECK(leaf_decoder_.IsValid());
+ return leaf_decoder_.last_record_rowid();
}
void VirtualCursor::AppendPageDecoder(int page_id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(leaf_decoder_.get() == nullptr)
+ DCHECK(!leaf_decoder_.IsValid())
<< __func__
<< " must only be called when the current path has no leaf decoder";
if (db_reader_.ReadPage(page_id) != SQLITE_OK)
return;
if (LeafPageDecoder::IsOnValidPage(&db_reader_)) {
- leaf_decoder_ = std::make_unique<LeafPageDecoder>(&db_reader_);
+ leaf_decoder_.Initialize(&db_reader_);
return;
}
if (InnerPageDecoder::IsOnValidPage(&db_reader_)) {
// Detect cycles.
for (const auto& decoder : inner_decoders_) {
if (decoder->page_id() == page_id)
return;
}
diff --git a/sql/recover_module/cursor.h b/sql/recover_module/cursor.h
index 845b7852648..cc4e85f83f9 100644
--- a/sql/recover_module/cursor.h
+++ b/sql/recover_module/cursor.h
@@ -123,19 +123,19 @@ class VirtualCursor {
// Reads record rows for this cursor.
RecordReader record_reader_;
// Decoders for the current chain of inner pages.
//
// The current chain of pages consists of the inner page decoders here and the
// decoder in |leaf_decoder_|.
std::vector<std::unique_ptr<InnerPageDecoder>> inner_decoders_;
// Decodes the leaf page containing records.
- std::unique_ptr<LeafPageDecoder> leaf_decoder_;
+ LeafPageDecoder leaf_decoder_;
SEQUENCE_CHECKER(sequence_checker_);
};
} // namespace recover
} // namespace sql
#endif // SQL_RECOVER_MODULE_CURSOR_H_
diff --git a/sql/recover_module/pager.cc b/sql/recover_module/pager.cc
index 58e75de2704..5fe96204e56 100644
--- a/sql/recover_module/pager.cc
+++ b/sql/recover_module/pager.cc
@@ -16,22 +16,21 @@ constexpr int DatabasePageReader::kInvalidPageId;
constexpr int DatabasePageReader::kMinPageSize;
constexpr int DatabasePageReader::kMaxPageSize;
constexpr int DatabasePageReader::kDatabaseHeaderSize;
constexpr int DatabasePageReader::kMinUsablePageSize;
constexpr int DatabasePageReader::kMaxPageId;
static_assert(DatabasePageReader::kMaxPageId <= std::numeric_limits<int>::max(),
"ints are not appropriate for representing page IDs");
DatabasePageReader::DatabasePageReader(VirtualTable* table)
- : page_data_(std::make_unique<uint8_t[]>(table->page_size())),
- table_(table) {
+ : page_data_(), table_(table) {
DCHECK(table != nullptr);
DCHECK(IsValidPageSize(table->page_size()));
}
DatabasePageReader::~DatabasePageReader() = default;
int DatabasePageReader::ReadPage(int page_id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_GT(page_id, kInvalidPageId);
DCHECK_LE(page_id, kMaxPageId);
@@ -50,22 +49,22 @@ int DatabasePageReader::ReadPage(int page_id) {
DCHECK_GE(page_size_, kMinUsablePageSize);
DCHECK_LE(page_size_, kMaxPageSize);
const int64_t read_offset =
static_cast<int64_t>(page_id - 1) * page_size + page_offset;
static_assert(static_cast<int64_t>(kMaxPageId - 1) * kMaxPageSize +
kDatabaseHeaderSize <=
std::numeric_limits<int64_t>::max(),
"The |read_offset| computation above may overflow");
- int sqlite_status =
- RawRead(sqlite_file, read_size, read_offset, page_data_.get());
+ int sqlite_status = RawRead(sqlite_file, read_size, read_offset,
+ const_cast<uint8_t*>(page_data_.data()));
// |page_id_| needs to be set to kInvalidPageId if the read failed.
// Otherwise, future ReadPage() calls with the previous |page_id_| value
// would return SQLITE_OK, but the page data buffer might be trashed.
page_id_ = (sqlite_status == SQLITE_OK) ? page_id : kInvalidPageId;
return sqlite_status;
}
// static
int DatabasePageReader::RawRead(sqlite3_file* sqlite_file,
diff --git a/sql/recover_module/pager.h b/sql/recover_module/pager.h
index 07cac3cb989..646e0223fd7 100644
--- a/sql/recover_module/pager.h
+++ b/sql/recover_module/pager.h
@@ -1,17 +1,18 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SQL_RECOVER_MODULE_PAGER_H_
#define SQL_RECOVER_MODULE_PAGER_H_
+#include <array>
#include <cstdint>
#include <memory>
#include <ostream>
#include "base/check_op.h"
#include "base/memory/raw_ptr.h"
#include "base/sequence_checker.h"
struct sqlite3_file;
@@ -65,21 +66,21 @@ class DatabasePageReader {
DatabasePageReader& operator=(const DatabasePageReader&) = delete;
// The page data read by the last ReadPage() call.
//
// The page data is undefined if the last ReadPage() call failed, or if
// ReadPage() was never called.
const uint8_t* page_data() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_NE(page_id_, kInvalidPageId)
<< "Successful ReadPage() required before accessing pager state";
- return page_data_.get();
+ return page_data_.data();
}
// The number of bytes in the page read by the last ReadPage() call.
//
// The result is guaranteed to be in [kMinUsablePageSize, kMaxPageSize].
//
// In general, pages have the same size. However, the first page in each
// database is smaller, because it starts after the database header.
//
// The result is undefined if the last ReadPage() call failed, or if
@@ -132,21 +133,21 @@ class DatabasePageReader {
int read_size,
int64_t read_offset,
uint8_t* buffer);
private:
// Points to the last page successfully read by ReadPage().
// Set to kInvalidPageId if the last read was unsuccessful.
int page_id_ = kInvalidPageId;
// Stores the bytes of the last page successfully read by ReadPage().
// The content is undefined if the last call to ReadPage() did not succeed.
- const std::unique_ptr<uint8_t[]> page_data_;
+ const std::array<uint8_t, kMaxPageSize> page_data_;
// Raw pointer usage is acceptable because this instance's owner is expected
// to ensure that the VirtualTable outlives this.
const raw_ptr<VirtualTable> table_;
int page_size_ = 0;
SEQUENCE_CHECKER(sequence_checker_);
};
} // namespace recover
} // namespace sql
--
2.25.4