187 lines
6.2 KiB
C++
187 lines
6.2 KiB
C++
/*****************************************************************************
|
|
|
|
Copyright (c) 2016, 2018, 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 lob0ins_h
|
|
#define lob0ins_h
|
|
|
|
#include "lob0lob.h"
|
|
|
|
namespace lob {
|
|
|
|
/** This struct can hold BLOB routines/functions, and state variables,
|
|
that are common for compressed and uncompressed BLOB. */
|
|
struct BaseInserter {
|
|
/** Constructor.
|
|
@param[in] ctx blob operation context. */
|
|
BaseInserter(InsertContext *ctx)
|
|
: m_ctx(ctx),
|
|
m_err(DB_SUCCESS),
|
|
m_prev_page_no(ctx->get_page_no()),
|
|
m_cur_blob_block(NULL),
|
|
m_cur_blob_page_no(FIL_NULL) {}
|
|
|
|
/** Start the BLOB mtr.
|
|
@return pointer to the BLOB mtr. */
|
|
mtr_t *start_blob_mtr() {
|
|
mtr_start(&m_blob_mtr);
|
|
m_blob_mtr.set_log_mode(m_ctx->get_log_mode());
|
|
m_blob_mtr.set_flush_observer(m_ctx->get_flush_observer());
|
|
return (&m_blob_mtr);
|
|
}
|
|
|
|
/** Allocate one BLOB page.
|
|
@return the allocated block of the BLOB page. */
|
|
buf_block_t *alloc_blob_page();
|
|
|
|
/** Get the previous BLOB page frame. This will return a BLOB page.
|
|
It should not be called for the first BLOB page, because it will not
|
|
have a previous BLOB page.
|
|
@return the previous BLOB page frame. */
|
|
page_t *get_previous_blob_page();
|
|
|
|
/** Get the previous BLOB page block. This will return a BLOB block.
|
|
It should not be called for the first BLOB page, because it will not
|
|
have a previous BLOB page.
|
|
@return the previous BLOB block. */
|
|
buf_block_t *get_previous_blob_block();
|
|
|
|
/** Check if the index is SDI index
|
|
@return true if index is SDI index else false */
|
|
bool is_index_sdi() { return (dict_index_is_sdi(m_ctx->index())); }
|
|
|
|
/** Get the current BLOB page frame.
|
|
@return the current BLOB page frame. */
|
|
page_t *cur_page() const { return (buf_block_get_frame(m_cur_blob_block)); }
|
|
|
|
protected:
|
|
/** The BLOB operation context */
|
|
InsertContext *m_ctx;
|
|
|
|
/** Success or failure status of the operation so far. */
|
|
dberr_t m_err;
|
|
|
|
/** The mini trx used to write into blob pages */
|
|
mtr_t m_blob_mtr;
|
|
|
|
/** The previous BLOB page number. This is needed to maintain
|
|
the linked list of BLOB pages. */
|
|
page_no_t m_prev_page_no;
|
|
|
|
/** The current BLOB buf_block_t object. */
|
|
buf_block_t *m_cur_blob_block;
|
|
|
|
/** The current BLOB page number. */
|
|
page_no_t m_cur_blob_page_no;
|
|
};
|
|
|
|
/** Insert or write an uncompressed BLOB */
|
|
class Inserter : private BaseInserter {
|
|
public:
|
|
/** Constructor.
|
|
@param[in] ctx blob operation context. */
|
|
Inserter(InsertContext *ctx) : BaseInserter(ctx) {}
|
|
|
|
/** Destructor. */
|
|
~Inserter() {}
|
|
|
|
/** Write all the BLOBs of the clustered index record.
|
|
@return DB_SUCCESS on success, error code on failure. */
|
|
dberr_t write();
|
|
|
|
/** Write one blob field data.
|
|
@param[in] blob_j the blob field number
|
|
@return DB_SUCCESS on success, error code on failure. */
|
|
dberr_t write_one_blob(size_t blob_j);
|
|
|
|
/** Write one blob field data.
|
|
@param[in] blob_j the blob field number
|
|
@return DB_SUCCESS on success, error code on failure. */
|
|
dberr_t write_one_small_blob(size_t blob_j);
|
|
|
|
/** Write one blob page. This function will be repeatedly called
|
|
with an increasing nth_blob_page to completely write a BLOB.
|
|
@param[in] blob_j the jth blob object of the record.
|
|
@param[in] field the big record field.
|
|
@param[in] nth_blob_page count of the BLOB page (starting from 1).
|
|
@return DB_SUCCESS or DB_FAIL. */
|
|
dberr_t write_single_blob_page(size_t blob_j, big_rec_field_t &field,
|
|
ulint nth_blob_page);
|
|
|
|
/** Check if the BLOB operation has reported any errors.
|
|
@return true if BLOB operation is successful, false otherwise. */
|
|
bool is_ok() const { return (m_err == DB_SUCCESS); }
|
|
|
|
/** Make the current page as next page of previous page. In other
|
|
words, make the page m_cur_blob_page_no as the next page of page
|
|
m_prev_page_no. */
|
|
void set_page_next();
|
|
|
|
/** Write the page type of the current BLOB page and also generate the
|
|
redo log record. */
|
|
void log_page_type() {
|
|
page_type_t page_type;
|
|
page_t *blob_page = cur_page();
|
|
|
|
if (is_index_sdi()) {
|
|
page_type = FIL_PAGE_SDI_BLOB;
|
|
} else {
|
|
page_type = FIL_PAGE_TYPE_BLOB;
|
|
}
|
|
|
|
mlog_write_ulint(blob_page + FIL_PAGE_TYPE, page_type, MLOG_2BYTES,
|
|
&m_blob_mtr);
|
|
}
|
|
|
|
/** Calculate the payload size of the BLOB page.
|
|
@return payload size in bytes. */
|
|
ulint payload() const {
|
|
const page_size_t page_size = m_ctx->page_size();
|
|
const ulint payload_size =
|
|
page_size.physical() - FIL_PAGE_DATA - LOB_HDR_SIZE - FIL_PAGE_DATA_END;
|
|
return (payload_size);
|
|
}
|
|
|
|
/** Write contents into a single BLOB page.
|
|
@param[in] field the big record field. */
|
|
void write_into_single_page(big_rec_field_t &field);
|
|
|
|
/** Write first blob page.
|
|
@param[in] blob_j the jth blob object of the record.
|
|
@param[in] field the big record field.
|
|
@return DB_SUCCESS on success. */
|
|
dberr_t write_first_page(size_t blob_j, big_rec_field_t &field);
|
|
|
|
private:
|
|
/** The BLOB directory information. */
|
|
blob_dir_t m_dir;
|
|
|
|
/** Data remaining to be written. */
|
|
ulint m_remaining;
|
|
};
|
|
|
|
} // namespace lob
|
|
|
|
#endif /* lob0ins_h */
|