323 lines
8.5 KiB
C++
323 lines
8.5 KiB
C++
/*****************************************************************************
|
|
|
|
Copyright (c) 2016, 2017, Oracle and/or its affiliates. All Rights Reserved.
|
|
|
|
This program is free software; you can redistribute it and/or modify it under
|
|
the terms of the GNU General Public License, version 2.0, as published by the
|
|
Free Software Foundation.
|
|
|
|
This program is also distributed with certain software (including but not
|
|
limited to OpenSSL) that is licensed under separate terms, as designated in a
|
|
particular file or component or in included license documentation. The authors
|
|
of MySQL hereby grant you an additional permission to link the program and
|
|
your derivative works with the separately licensed software that they have
|
|
included with MySQL.
|
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
|
|
for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along with
|
|
this program; if not, write to the Free Software Foundation, Inc.,
|
|
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*****************************************************************************/
|
|
#ifndef _lot0plist_h_
|
|
#define _lot0plist_h_
|
|
|
|
/** The Page List */
|
|
|
|
#include "lot0types.h"
|
|
#include "mach0data.h"
|
|
#include "mtr0log.h"
|
|
#include "mtr0types.h"
|
|
|
|
using paddr_t = ulint;
|
|
|
|
/** The node of page list. */
|
|
struct plist_node_t {
|
|
static const ulint OFFSET_PREV = 0; /* 2 bytes */
|
|
static const ulint OFFSET_NEXT = 2; /* 2 bytes */
|
|
static const ulint SIZE = 4;
|
|
|
|
plist_node_t() : m_frame(nullptr), m_node(nullptr) {}
|
|
plist_node_t(byte *frame, byte *node) : m_frame(frame), m_node(node) {}
|
|
|
|
bool is_before(const plist_node_t &node) const {
|
|
ut_ad(!is_null());
|
|
ut_ad(!node.is_null());
|
|
return (addr() < node.addr());
|
|
}
|
|
|
|
void init() {
|
|
ut_ad(m_node != nullptr);
|
|
mlog_write_ulint(m_node + OFFSET_PREV, 0, MLOG_2BYTES);
|
|
mlog_write_ulint(m_node + OFFSET_NEXT, 0, MLOG_2BYTES);
|
|
}
|
|
|
|
void set_prev(paddr_t addr) {
|
|
ut_ad(addr < UNIV_PAGE_SIZE);
|
|
mlog_write_ulint(m_node + OFFSET_PREV, addr, MLOG_2BYTES);
|
|
}
|
|
|
|
void set_prev_node(plist_node_t &prev) { set_prev(prev.addr()); }
|
|
|
|
void set_next(paddr_t addr) {
|
|
ut_ad(!is_null());
|
|
ut_ad(addr < UNIV_PAGE_SIZE);
|
|
mlog_write_ulint(m_node + OFFSET_NEXT, addr, MLOG_2BYTES);
|
|
}
|
|
|
|
void set_next_node(const plist_node_t &next) { set_next(next.addr()); }
|
|
|
|
paddr_t get_prev() const { return (mach_read_from_2(m_node + OFFSET_PREV)); }
|
|
|
|
paddr_t get_next() const { return (mach_read_from_2(m_node + OFFSET_NEXT)); }
|
|
|
|
plist_node_t get_next_node() const {
|
|
paddr_t addr = get_next();
|
|
byte *node = nullptr;
|
|
if (addr != 0) {
|
|
node = m_frame + addr;
|
|
}
|
|
return (plist_node_t(m_frame, node));
|
|
}
|
|
|
|
plist_node_t get_prev_node() const {
|
|
paddr_t addr = get_prev();
|
|
byte *node = nullptr;
|
|
if (addr != 0) {
|
|
node = m_frame + addr;
|
|
}
|
|
return (plist_node_t(m_frame, node));
|
|
}
|
|
|
|
paddr_t addr() const { return (m_node == nullptr) ? 0 : (m_node - m_frame); }
|
|
|
|
byte *ptr() const { return (m_node); }
|
|
|
|
bool is_null() const { return (m_node == nullptr); }
|
|
|
|
std::ostream &print(std::ostream &out) const {
|
|
out << "[plist_node_t: next=" << get_next() << ", prev=" << get_prev()
|
|
<< ", this=" << addr() << "]";
|
|
return (out);
|
|
}
|
|
|
|
void set_frame(byte *frame) { m_frame = frame; }
|
|
void set_node(byte *node) { m_node = node; }
|
|
|
|
byte *m_frame;
|
|
byte *m_node;
|
|
};
|
|
|
|
inline std::ostream &operator<<(std::ostream &out, const plist_node_t &obj) {
|
|
return (obj.print(out));
|
|
}
|
|
|
|
/** The base node of page list. */
|
|
struct plist_base_node_t {
|
|
static const ulint OFFSET_LEN = 0; /* 4 bytes */
|
|
static const ulint OFFSET_FIRST = 4; /* 2 bytes */
|
|
static const ulint OFFSET_LAST = 6; /* 2 bytes */
|
|
|
|
/** The total size (in bytes) of a page list base node. */
|
|
static const ulint SIZE = 8;
|
|
|
|
plist_base_node_t(byte *frame, byte *base) : m_frame(frame), m_base(base) {}
|
|
|
|
void init() {
|
|
mlog_write_ulint(m_base + OFFSET_LEN, 0, MLOG_4BYTES);
|
|
mlog_write_ulint(m_base + OFFSET_FIRST, 0, MLOG_2BYTES);
|
|
mlog_write_ulint(m_base + OFFSET_LAST, 0, MLOG_2BYTES);
|
|
}
|
|
|
|
void remove(plist_node_t &node) {
|
|
plist_node_t prev = node.get_prev_node();
|
|
plist_node_t next = node.get_next_node();
|
|
|
|
if (prev.is_null()) {
|
|
set_first(next.addr());
|
|
} else {
|
|
prev.set_next(next.addr());
|
|
}
|
|
|
|
if (next.is_null()) {
|
|
set_last(prev.addr());
|
|
} else {
|
|
next.set_prev(prev.addr());
|
|
}
|
|
|
|
node.set_next(0);
|
|
node.set_prev(0);
|
|
|
|
decr_len();
|
|
}
|
|
|
|
void push_front(plist_node_t &node) {
|
|
if (get_len() == 0) {
|
|
add_to_empty(node);
|
|
} else {
|
|
paddr_t cur_addr = node.addr();
|
|
paddr_t first_addr = get_first();
|
|
plist_node_t first_node = get_node(first_addr);
|
|
node.set_next(first_addr);
|
|
node.set_prev(0);
|
|
first_node.set_prev(cur_addr);
|
|
set_first(cur_addr);
|
|
incr_len();
|
|
}
|
|
}
|
|
|
|
/** Insert node2 after node1. */
|
|
void insert_after(plist_node_t &node1, plist_node_t &node2) {
|
|
if (node1.is_null()) {
|
|
push_back(node2);
|
|
} else {
|
|
plist_node_t node3 = node1.get_next_node();
|
|
node1.set_next_node(node2);
|
|
node2.set_next_node(node3);
|
|
|
|
if (node3.is_null()) {
|
|
set_last(node2.addr());
|
|
} else {
|
|
node3.set_prev_node(node2);
|
|
}
|
|
|
|
node2.set_prev_node(node1);
|
|
|
|
incr_len();
|
|
}
|
|
}
|
|
|
|
/** Insert node2 before node3. */
|
|
void insert_before(plist_node_t &node3, plist_node_t &node2) {
|
|
if (node3.is_null()) {
|
|
push_back(node2);
|
|
} else {
|
|
plist_node_t node1 = node3.get_prev_node();
|
|
|
|
if (node1.is_null()) {
|
|
set_first(node2.addr());
|
|
} else {
|
|
node1.set_next_node(node2);
|
|
}
|
|
|
|
node2.set_next_node(node3);
|
|
node3.set_prev_node(node2);
|
|
node2.set_prev_node(node1);
|
|
|
|
incr_len();
|
|
}
|
|
}
|
|
|
|
void add_to_empty(plist_node_t &node) {
|
|
ut_ad(get_len() == 0);
|
|
|
|
set_first(node.addr());
|
|
set_last(node.addr());
|
|
incr_len();
|
|
}
|
|
|
|
void push_back(plist_node_t &node) {
|
|
if (get_len() == 0) {
|
|
add_to_empty(node);
|
|
} else {
|
|
paddr_t cur_addr = node.addr();
|
|
paddr_t last_addr = get_last();
|
|
plist_node_t last_node = get_node(last_addr);
|
|
node.set_next(0);
|
|
node.set_prev_node(last_node);
|
|
last_node.set_next(cur_addr);
|
|
set_last(cur_addr);
|
|
incr_len();
|
|
}
|
|
}
|
|
|
|
bool empty() const { return (get_len() == 0); }
|
|
|
|
ulint get_len() const { return (mach_read_from_4(m_base + OFFSET_LEN)); }
|
|
|
|
paddr_t get_first() const {
|
|
return (mach_read_from_2(m_base + OFFSET_FIRST));
|
|
}
|
|
|
|
plist_node_t get_first_node() const {
|
|
plist_node_t result;
|
|
result.set_frame(m_frame);
|
|
|
|
if (!empty()) {
|
|
byte *node = m_frame + get_first();
|
|
result.set_node(node);
|
|
}
|
|
return (result);
|
|
}
|
|
|
|
paddr_t get_last() const { return (mach_read_from_2(m_base + OFFSET_LAST)); }
|
|
|
|
plist_node_t get_last_node() const {
|
|
plist_node_t result;
|
|
result.set_frame(m_frame);
|
|
if (!empty()) {
|
|
result.set_node(m_frame + get_last());
|
|
}
|
|
return (result);
|
|
}
|
|
|
|
void set_len(ulint len) {
|
|
mlog_write_ulint(m_base + OFFSET_LEN, len, MLOG_4BYTES);
|
|
}
|
|
|
|
void incr_len() {
|
|
ulint len = mach_read_from_4(m_base + OFFSET_LEN);
|
|
mlog_write_ulint(m_base + OFFSET_LEN, len + 1, MLOG_4BYTES);
|
|
}
|
|
|
|
void decr_len() {
|
|
ulint len = mach_read_from_4(m_base + OFFSET_LEN);
|
|
mlog_write_ulint(m_base + OFFSET_LEN, len - 1, MLOG_4BYTES);
|
|
}
|
|
|
|
void set_first(paddr_t addr) {
|
|
mlog_write_ulint(m_base + OFFSET_FIRST, addr, MLOG_2BYTES);
|
|
}
|
|
|
|
void set_last(paddr_t addr) {
|
|
mlog_write_ulint(m_base + OFFSET_LAST, addr, MLOG_2BYTES);
|
|
}
|
|
|
|
plist_node_t get_node(paddr_t addr) {
|
|
byte *node = m_frame + addr;
|
|
return (plist_node_t(m_frame, node));
|
|
}
|
|
|
|
paddr_t addr() const { return (m_base - m_frame); }
|
|
|
|
std::ostream &print(std::ostream &out) const {
|
|
out << "[plist_base_node_t: len=" << get_len() << ", first=" << get_first()
|
|
<< ", last=" << get_last() << ", this=" << addr() << "]";
|
|
return (out);
|
|
}
|
|
|
|
std::ostream &print_list(std::ostream &out) const {
|
|
print(out);
|
|
out << std::endl;
|
|
for (plist_node_t cur = get_first_node(); !cur.is_null();
|
|
cur = cur.get_next_node()) {
|
|
out << cur << std::endl;
|
|
}
|
|
return (out);
|
|
}
|
|
|
|
byte *m_frame;
|
|
byte *m_base;
|
|
};
|
|
|
|
inline std::ostream &operator<<(std::ostream &out,
|
|
const plist_base_node_t &obj) {
|
|
return (obj.print(out));
|
|
}
|
|
|
|
#endif // _lot0plist_h_
|