payload.h 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef SQL_RECOVER_MODULE_PAYLOAD_H_
  5. #define SQL_RECOVER_MODULE_PAYLOAD_H_
  6. #include <cstdint>
  7. #include <ostream>
  8. #include <vector>
  9. #include "base/check_op.h"
  10. #include "base/memory/raw_ptr.h"
  11. #include "base/sequence_checker.h"
  12. #include "sql/recover_module/pager.h"
  13. namespace sql {
  14. namespace recover {
  15. class DatabasePageReader;
  16. // Reads payloads (records) across B-tree pages and overflow pages.
  17. //
  18. // Instances are designed to be reused for reading multiple payloads. Instances
  19. // are not thread-safe.
  20. //
  21. // Reading a payload is started by calling Initialize() with the information
  22. // from LeafPageDecoder. If the call succeeds, ReadPayload() can be called
  23. // repeatedly.
  24. class LeafPayloadReader {
  25. public:
  26. // Number of payload bytes guaranteed to be on the B-tree page.
  27. //
  28. // The value is derived from the minimum SQLite usable page size, which is
  29. // 380 bytes, and the formula for the minimum payload size given a usable page
  30. // size.
  31. static constexpr int kMinInlineSize = ((380 - 12) * 32) / 255 - 23;
  32. explicit LeafPayloadReader(DatabasePageReader* db_reader);
  33. ~LeafPayloadReader();
  34. LeafPayloadReader(const LeafPayloadReader&) = delete;
  35. LeafPayloadReader& operator=(const LeafPayloadReader&) = delete;
  36. // Sets up the reader for a new payload.
  37. //
  38. // The DatabasePageReader passed to the constructor must be focused on the
  39. // page containing the payload.
  40. //
  41. // This method must complete successfully before any other method on this
  42. // class can be called.
  43. bool Initialize(int64_t payload_size, int payload_offset);
  44. // The number of payload bytes that are stored on the B-tree page.
  45. //
  46. // The return value is guaranteed to be non-negative and at most
  47. // payload_size().
  48. int inline_payload_size() const {
  49. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  50. DCHECK(page_id_ != DatabasePageReader::kInvalidPageId)
  51. << "Initialize() not called, or last call did not succeed";
  52. DCHECK_LE(inline_payload_size_, payload_size_);
  53. return inline_payload_size_;
  54. }
  55. // Total payload size, in bytes.
  56. //
  57. // This includes the bytes stored in the B-tree page, as well as any bytes
  58. // stored in overflow pages.
  59. //
  60. // The return value is guaranteed to be at least inline_payload_size().
  61. int payload_size() const {
  62. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  63. DCHECK(page_id_ != DatabasePageReader::kInvalidPageId)
  64. << "Initialize() not called, or last call did not succeed";
  65. DCHECK_LE(inline_payload_size_, payload_size_);
  66. return payload_size_;
  67. }
  68. // Copies a subset of the payload into a given buffer.
  69. //
  70. // Returns true if the read succeeds.
  71. //
  72. // May only be called after a previous call to Initialize() that returns true.
  73. bool ReadPayload(int64_t offset, int64_t size, uint8_t* buffer);
  74. // Pulls the B-tree containing the payload into the database reader's cache.
  75. //
  76. // Returns a pointer to the beginning of the payload bytes. The pointer is
  77. // inside the database reader's buffer, and may get invalidated if the
  78. // database reader is used.
  79. //
  80. // Returns null if the read operation fails.
  81. //
  82. // May only be called after a previous call to Initialize() that returns true.
  83. const uint8_t* ReadInlinePayload();
  84. private:
  85. // Extends the cached list of overflow page IDs by one page.
  86. //
  87. // Returns false if the operation failed. Failures are due to read errors or
  88. // database corruption.
  89. bool PopulateNextOverflowPageId();
  90. // Used to read the pages containing the payload.
  91. //
  92. // Raw pointer usage is acceptable because this instance's owner is expected
  93. // to ensure that the DatabasePageReader outlives this.
  94. const raw_ptr<DatabasePageReader> db_reader_;
  95. // Total size of the current payload.
  96. int64_t payload_size_;
  97. // The ID of the B-tree page containing the current payload's inline bytes.
  98. //
  99. // Set to kInvalidPageId if the reader wasn't successfully initialized.
  100. int page_id_;
  101. // The start of the current payload's inline bytes on the B-tree page.
  102. //
  103. // Large payloads extend past the B-tree page containing the payload, via
  104. // overflow pages.
  105. int inline_payload_offset_;
  106. // Number of bytes in the current payload stored in its B-tree page.
  107. //
  108. // The rest of the payload is stored on overflow pages.
  109. int inline_payload_size_;
  110. // Number of overflow pages used by the payload.
  111. int overflow_page_count_;
  112. // Number of bytes in each overflow page that stores the payload.
  113. int max_overflow_payload_size_;
  114. // Page IDs for all the payload's overflow pages, in order.
  115. //
  116. // This list is populated on-demand.
  117. std::vector<int> overflow_page_ids_;
  118. SEQUENCE_CHECKER(sequence_checker_);
  119. };
  120. } // namespace recover
  121. } // namespace sql
  122. #endif // SQL_RECOVER_MODULE_PAYLOAD_H_