/* Copyright (c) 2011, 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 as published by the Free Software Foundation; version 2 of the License. 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 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 */ #include "ndb_event_data.h" #include Ndb_event_data::Ndb_event_data(NDB_SHARE *the_share) : shadow_table(NULL), share(the_share), pk_bitmap(NULL) { ndb_value[0]= NULL; ndb_value[1]= NULL; } Ndb_event_data::~Ndb_event_data() { if (shadow_table) closefrm(shadow_table, 1); shadow_table= NULL; delete pk_bitmap; pk_bitmap = NULL; free_root(&mem_root, MYF(0)); share= NULL; /* ndbvalue[] allocated with my_multi_malloc -> only first pointer need to be freed */ my_free(ndb_value[0]); } void Ndb_event_data::print(const char* where, FILE* file) const { fprintf(file, "%s shadow_table: %p '%s.%s'\n", where, shadow_table, shadow_table->s->db.str, shadow_table->s->table_name.str); // Print stats for the MEM_ROOT where Ndb_event_data // has allocated the shadow_table etc. { USED_MEM *mem_block; size_t mem_root_used = 0; size_t mem_root_size = 0; /* iterate through (partially) free blocks */ for (mem_block= mem_root.free; mem_block; mem_block= mem_block->next) { const size_t block_used = mem_block->size - // Size of block ALIGN_SIZE(sizeof(USED_MEM)) - // Size of header mem_block->left; // What's unused in block mem_root_used += block_used; mem_root_size += mem_block->size; } /* iterate through the used blocks */ for (mem_block= mem_root.used; mem_block; mem_block= mem_block->next) { const size_t block_used = mem_block->size - // Size of block ALIGN_SIZE(sizeof(USED_MEM)) - // Size of header mem_block->left; // What's unused in block mem_root_used += block_used; mem_root_size += mem_block->size; } fprintf(file, " - mem_root size: %lu\n", mem_root_size); fprintf(file, " - mem_root used: %lu\n", mem_root_used); } } /* * While writing an UPDATE_ROW event to the binlog, a bitmap is * used to indicate which columns should be written. An * UPDATE_ROW event contains 2 versions of the row: a Before Image * of the row before the update was done, and an After Image of * the row after the update. Column bitmaps are used to decide * which columns will be written to both images. The Before * Image and After Image can contain different columns. * * For the binlog formats UPDATED_ONLY_USE_UPDATE_MINIMAL and * FULL_USE_UPDATE_MINIMAL, it is necessary to write only primary * key columns to the Before Image, and to remove all primary key * columns from the After Image. A bitmap of primary key columns is * created for this purpose. */ void Ndb_event_data::init_pk_bitmap() { if (shadow_table->s->primary_key == MAX_KEY) { // Table without pk, no need for pk_bitmap since minimal is full return; } pk_bitmap = new MY_BITMAP(); bitmap_init(pk_bitmap, pk_bitbuf, shadow_table->s->fields, FALSE); KEY* key = shadow_table->key_info + shadow_table->s->primary_key; KEY_PART_INFO* key_part_info = key->key_part; const uint key_parts = key->user_defined_key_parts; for (uint i = 0; i < key_parts; i++, key_part_info++) { bitmap_set_bit(pk_bitmap, key_part_info->fieldnr - 1); } assert(!bitmap_is_clear_all(pk_bitmap)); } /* * Modify the column bitmaps generated for UPDATE_ROW as per * the MINIMAL binlog format type. Expected arguments: * * @before: empty bitmap to be populated with PK columns * @after: bitmap with updated cols, if ndb_log_updated_only=TRUE * bitmap with all cols, if ndb_log_updated_only=FALSE * * If no PK is defined, bitmaps revert to default behaviour: * - before and after bitmaps are identical * - bitmaps contain all/updated cols as per ndb_log_updated_only */ void Ndb_event_data::generate_minimal_bitmap(MY_BITMAP *before, MY_BITMAP *after) { if (pk_bitmap) { assert(!bitmap_is_clear_all(pk_bitmap)); // set Before Image to contain only primary keys bitmap_copy(before, pk_bitmap); // remove primary keys from After Image bitmap_subtract(after, pk_bitmap); } else { // no usable PK bitmap, set Before Image = After Image bitmap_copy(before, after); } }