summaryrefslogtreecommitdiffstats
path: root/storage/maria/test_ma_backup.c
diff options
context:
space:
mode:
Diffstat (limited to 'storage/maria/test_ma_backup.c')
-rw-r--r--storage/maria/test_ma_backup.c444
1 files changed, 444 insertions, 0 deletions
diff --git a/storage/maria/test_ma_backup.c b/storage/maria/test_ma_backup.c
new file mode 100644
index 00000000..c57ec6ec
--- /dev/null
+++ b/storage/maria/test_ma_backup.c
@@ -0,0 +1,444 @@
+/* Copyright (C) 2018, 2021, MariaDB corporation.
+
+ 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 Street, Fifth Floor, Boston, MA 02111-1301 USA */
+
+/* Code for doing backups of Aria tables */
+
+/******************************************************************************
+ Testing ma_backup interface
+ Table creation code is taken from ma_test1
+******************************************************************************/
+
+#define ROWS_IN_TEST 100000
+
+#include "maria_def.h"
+#include "ma_blockrec.h" /* PAGE_SUFFIX_SIZE */
+#include "ma_checkpoint.h"
+#include <aria_backup.h>
+
+static int silent;
+static int create_test_table(const char *table_name, int stage);
+static int copy_table(const char *table_name, int stage);
+static void create_record(uchar *record,uint rownr);
+
+int main(int argc __attribute__((unused)), char *argv[])
+{
+ int error= 1;
+ int i;
+ char buff[FN_REFLEN];
+#ifdef SAFE_MUTEX
+ safe_mutex_deadlock_detector= 1;
+#endif
+ MY_INIT(argv[0]);
+ maria_data_root= ".";
+
+ /* Maria requires that we always have a page cache */
+ if (maria_init() ||
+ (init_pagecache(maria_pagecache, maria_block_size * 2000, 0, 0,
+ maria_block_size, 0, MY_WME) == 0) ||
+ ma_control_file_open(TRUE, TRUE, TRUE) ||
+ (init_pagecache(maria_log_pagecache,
+ TRANSLOG_PAGECACHE_SIZE, 0, 0,
+ TRANSLOG_PAGE_SIZE, 0, MY_WME) == 0) ||
+ translog_init(maria_data_root, TRANSLOG_FILE_SIZE,
+ 0, 0, maria_log_pagecache,
+ TRANSLOG_DEFAULT_FLAGS, 0) ||
+ (trnman_init(0) || ma_checkpoint_init(0)))
+ {
+ fprintf(stderr, "Error in initialization\n");
+ exit(1);
+ }
+ init_thr_lock();
+
+ fn_format(buff, "test_copy", maria_data_root, "", MYF(0));
+
+ for (i= 0; i < 5 ; i++)
+ {
+ printf("Stage: %d\n", i);
+ fflush(stdout);
+ if (create_test_table(buff, i))
+ goto err;
+ if (copy_table(buff, i))
+ goto err;
+ }
+ error= 0;
+ printf("test ok\n");
+err:
+ if (error)
+ fprintf(stderr, "Test %i failed\n", i);
+ maria_end();
+ my_uuid_end();
+ my_end(MY_CHECK_ERROR);
+ exit(error);
+}
+
+
+/**
+ Example of how to read an Aria table
+*/
+
+static int copy_table(const char *table_name, int stage)
+{
+ char old_name[FN_REFLEN];
+ uchar *copy_buffer= 0;
+ ARIA_TABLE_CAPABILITIES cap;
+ ulonglong block;
+ File org_file= -1;
+ int error= 1;
+
+ strxmov(old_name, table_name, ".MAI", NullS);
+
+ if ((org_file= my_open(old_name,
+ O_RDONLY | O_SHARE | O_NOFOLLOW | O_CLOEXEC,
+ MYF(MY_WME))) < 0)
+ goto err;
+ if ((error= aria_get_capabilities(org_file, &cap)))
+ {
+ fprintf(stderr, "aria_get_capabilities failed: %d\n", error);
+ goto err;
+ }
+
+ printf("- Capabilities read. oneline_backup_safe: %d\n",
+ cap.online_backup_safe);
+ printf("- Copying index file\n");
+
+ copy_buffer= my_malloc(PSI_NOT_INSTRUMENTED, cap.block_size, MYF(0));
+ for (block= 0 ; ; block++)
+ {
+ if ((error= aria_read_index(org_file, &cap, block, copy_buffer) ==
+ HA_ERR_END_OF_FILE))
+ break;
+ if (error)
+ {
+ fprintf(stderr, "aria_read_index failed: %d\n", error);
+ goto err;
+ }
+ }
+ my_close(org_file, MYF(MY_WME));
+
+
+ printf("- Copying data file\n");
+ strxmov(old_name, table_name, ".MAD", NullS);
+ if ((org_file= my_open(old_name, O_RDONLY | O_SHARE | O_NOFOLLOW | O_CLOEXEC,
+ MYF(MY_WME))) < 0)
+ goto err;
+
+ for (block= 0 ; ; block++)
+ {
+ size_t length;
+ if ((error= aria_read_data(org_file, &cap, block, copy_buffer,
+ &length) == HA_ERR_END_OF_FILE))
+ break;
+ if (error)
+ {
+ fprintf(stderr, "aria_read_index failed: %d\n", error);
+ goto err;
+ }
+ }
+ error= 0;
+
+err:
+ my_free(copy_buffer);
+ if (org_file >= 0)
+ my_close(org_file, MYF(MY_WME));
+ if (error)
+ fprintf(stderr, "Failed in copy_table stage: %d\n", stage);
+ return error;
+}
+
+
+/* Code extracted from ma_test1.c */
+#define MAX_REC_LENGTH 1024
+
+static MARIA_COLUMNDEF recinfo[4];
+static MARIA_KEYDEF keyinfo[10];
+static HA_KEYSEG keyseg[10];
+static HA_KEYSEG uniqueseg[10];
+
+
+/**
+ Create a test table and fill it with some data
+*/
+
+static int create_test_table(const char *table_name, int type_of_table)
+{
+ MARIA_HA *file;
+ int i,error,uniques=0;
+ int key_field=FIELD_SKIP_PRESPACE,extra_field=FIELD_SKIP_ENDSPACE;
+ int key_type=HA_KEYTYPE_NUM;
+ int create_flag=0;
+ uint pack_seg=0, pack_keys= 0;
+ uint key_length;
+ uchar record[MAX_REC_LENGTH];
+ MARIA_UNIQUEDEF uniquedef;
+ MARIA_CREATE_INFO create_info;
+ enum data_file_type record_type= DYNAMIC_RECORD;
+ my_bool null_fields= 0, unique_key= 0;
+ my_bool opt_unique= 0;
+ my_bool transactional= 0;
+
+ key_length= 12;
+ switch (type_of_table) {
+ case 0:
+ break;
+ case 1:
+ create_flag|= HA_CREATE_CHECKSUM | HA_CREATE_PAGE_CHECKSUM;
+ break;
+ case 2: /* transactional */
+ create_flag|= HA_CREATE_CHECKSUM | HA_CREATE_PAGE_CHECKSUM;
+ record_type= BLOCK_RECORD;
+ transactional= 1;
+ break;
+ case 3: /* transactional */
+ create_flag|= HA_CREATE_CHECKSUM | HA_CREATE_PAGE_CHECKSUM;
+ record_type= BLOCK_RECORD;
+ transactional= 1;
+ key_field=FIELD_VARCHAR; /* varchar keys */
+ extra_field= FIELD_VARCHAR;
+ key_type= HA_KEYTYPE_VARTEXT1;
+ pack_seg|= HA_VAR_LENGTH_PART;
+ null_fields= 1;
+ break;
+ case 4: /* transactional */
+ create_flag|= HA_CREATE_CHECKSUM | HA_CREATE_PAGE_CHECKSUM;
+ record_type= BLOCK_RECORD;
+ transactional= 1;
+ key_field=FIELD_BLOB; /* blob key */
+ extra_field= FIELD_BLOB;
+ pack_seg|= HA_BLOB_PART;
+ key_type= HA_KEYTYPE_VARTEXT1;
+ break;
+ }
+
+
+ bzero((char*) recinfo,sizeof(recinfo));
+ bzero((char*) &create_info,sizeof(create_info));
+
+ /* First define 2 columns */
+ create_info.null_bytes= 1;
+ recinfo[0].type= key_field;
+ recinfo[0].length= (key_field == FIELD_BLOB ? 4+portable_sizeof_char_ptr :
+ key_length);
+ if (key_field == FIELD_VARCHAR)
+ recinfo[0].length+= HA_VARCHAR_PACKLENGTH(key_length);
+ recinfo[1].type=extra_field;
+ recinfo[1].length= (extra_field == FIELD_BLOB ? 4 + portable_sizeof_char_ptr : 24);
+ if (extra_field == FIELD_VARCHAR)
+ recinfo[1].length+= HA_VARCHAR_PACKLENGTH(recinfo[1].length);
+ recinfo[1].null_bit= null_fields ? 2 : 0;
+
+ if (opt_unique)
+ {
+ recinfo[2].type=FIELD_CHECK;
+ recinfo[2].length=MARIA_UNIQUE_HASH_LENGTH;
+ }
+
+ if (key_type == HA_KEYTYPE_VARTEXT1 &&
+ key_length > 255)
+ key_type= HA_KEYTYPE_VARTEXT2;
+
+ /* Define a key over the first column */
+ keyinfo[0].seg=keyseg;
+ keyinfo[0].keysegs=1;
+ keyinfo[0].block_length= 0; /* Default block length */
+ keyinfo[0].key_alg=HA_KEY_ALG_BTREE;
+ keyinfo[0].seg[0].type= key_type;
+ keyinfo[0].seg[0].flag= pack_seg;
+ keyinfo[0].seg[0].start=1;
+ keyinfo[0].seg[0].length=key_length;
+ keyinfo[0].seg[0].null_bit= null_fields ? 2 : 0;
+ keyinfo[0].seg[0].null_pos=0;
+ keyinfo[0].seg[0].language= default_charset_info->number;
+ if (pack_seg & HA_BLOB_PART)
+ {
+ keyinfo[0].seg[0].bit_start=4; /* Length of blob length */
+ }
+ keyinfo[0].flag = (uint8) (pack_keys | unique_key);
+
+ if (opt_unique)
+ {
+ uint start;
+ uniques=1;
+ bzero((char*) &uniquedef,sizeof(uniquedef));
+ bzero((char*) uniqueseg,sizeof(uniqueseg));
+ uniquedef.seg=uniqueseg;
+ uniquedef.keysegs=2;
+
+ /* Make a unique over all columns (except first NULL fields) */
+ for (i=0, start=1 ; i < 2 ; i++)
+ {
+ uniqueseg[i].start=start;
+ start+=recinfo[i].length;
+ uniqueseg[i].length=recinfo[i].length;
+ uniqueseg[i].language= default_charset_info->number;
+ }
+ uniqueseg[0].type= key_type;
+ uniqueseg[0].null_bit= null_fields ? 2 : 0;
+ uniqueseg[1].type= HA_KEYTYPE_TEXT;
+ if (extra_field == FIELD_BLOB)
+ {
+ uniqueseg[1].length=0; /* The whole blob */
+ uniqueseg[1].bit_start=4; /* long blob */
+ uniqueseg[1].flag|= HA_BLOB_PART;
+ }
+ else if (extra_field == FIELD_VARCHAR)
+ {
+ uniqueseg[1].flag|= HA_VAR_LENGTH_PART;
+ uniqueseg[1].type= (HA_VARCHAR_PACKLENGTH(recinfo[1].length-1) == 1 ?
+ HA_KEYTYPE_VARTEXT1 : HA_KEYTYPE_VARTEXT2);
+ }
+ }
+ else
+ uniques=0;
+
+ if (!silent)
+ printf("- Creating Aria file\n");
+ create_info.max_rows= 0;
+ create_info.transactional= transactional;
+ if (maria_create(table_name, record_type, 1, keyinfo,2+opt_unique,recinfo,
+ uniques, &uniquedef, &create_info,
+ create_flag))
+ goto err;
+ if (!(file=maria_open(table_name,2,HA_OPEN_ABORT_IF_LOCKED, 0)))
+ goto err;
+ if (!silent)
+ printf("- Writing key:s\n");
+
+ if (maria_begin(file))
+ goto err;
+ my_errno=0;
+ for (i= 0 ; i < ROWS_IN_TEST ; i++)
+ {
+ create_record(record,i);
+ if ((error=maria_write(file,record)))
+ goto err;
+ }
+
+ if (maria_commit(file) | maria_close(file))
+ goto err;
+ printf("- Data copied\n");
+ return 0;
+
+err:
+ printf("got error: %3d when using maria-database\n",my_errno);
+ return 1; /* skip warning */
+}
+
+
+static void create_key_part(uchar *key,uint rownr)
+{
+ if (keyinfo[0].seg[0].type == HA_KEYTYPE_NUM)
+ {
+ sprintf((char*) key,"%*d",keyinfo[0].seg[0].length,rownr);
+ }
+ else if (keyinfo[0].seg[0].type == HA_KEYTYPE_VARTEXT1 ||
+ keyinfo[0].seg[0].type == HA_KEYTYPE_VARTEXT2)
+ { /* Alpha record */
+ /* Create a key that may be easily packed */
+ bfill(key,keyinfo[0].seg[0].length,rownr < 10 ? 'A' : 'B');
+ sprintf((char*) key+keyinfo[0].seg[0].length-2,"%-2d",rownr % 100);
+ if ((rownr & 7) == 0)
+ {
+ /* Change the key to force a unpack of the next key */
+ bfill(key+3,keyinfo[0].seg[0].length-5,rownr < 10 ? 'a' : 'b');
+ }
+ }
+ else
+ { /* Alpha record */
+ if (keyinfo[0].seg[0].flag & HA_SPACE_PACK)
+ sprintf((char*) key,"%-*d",keyinfo[0].seg[0].length,rownr);
+ else
+ {
+ /* Create a key that may be easily packed */
+ bfill(key,keyinfo[0].seg[0].length,rownr < 10 ? 'A' : 'B');
+ sprintf((char*) key+keyinfo[0].seg[0].length-2,"%-2d",rownr % 100);
+ if ((rownr & 7) == 0)
+ {
+ /* Change the key to force a unpack of the next key */
+ key[1]= (rownr < 10 ? 'a' : 'b');
+ }
+ }
+ }
+}
+
+
+static uchar blob_key[MAX_REC_LENGTH];
+static uchar blob_record[MAX_REC_LENGTH+20*20];
+
+
+static void create_record(uchar *record,uint rownr)
+{
+ uchar *pos;
+ bzero((char*) record,MAX_REC_LENGTH);
+ record[0]=1; /* delete marker */
+ if (rownr == 0 && keyinfo[0].seg[0].null_bit)
+ record[0]|=keyinfo[0].seg[0].null_bit; /* Null key */
+
+ pos=record+1;
+ if (recinfo[0].type == FIELD_BLOB)
+ {
+ size_t tmp;
+ uchar *ptr;
+ create_key_part(blob_key,rownr);
+ tmp=strlen((char*) blob_key);
+ int4store(pos,tmp);
+ ptr=blob_key;
+ memcpy(pos+4,&ptr,sizeof(char*));
+ pos+=recinfo[0].length;
+ }
+ else if (recinfo[0].type == FIELD_VARCHAR)
+ {
+ size_t tmp, pack_length= HA_VARCHAR_PACKLENGTH(recinfo[0].length-1);
+ create_key_part(pos+pack_length,rownr);
+ tmp= strlen((char*) pos+pack_length);
+ if (pack_length == 1)
+ *(uchar*) pos= (uchar) tmp;
+ else
+ int2store(pos,tmp);
+ pos+= recinfo[0].length;
+ }
+ else
+ {
+ create_key_part(pos,rownr);
+ pos+=recinfo[0].length;
+ }
+ if (recinfo[1].type == FIELD_BLOB)
+ {
+ size_t tmp;
+ uchar *ptr;;
+ sprintf((char*) blob_record,"... row: %d", rownr);
+ strappend((char*) blob_record, rownr % MAX_REC_LENGTH,'x');
+ tmp=strlen((char*) blob_record);
+ int4store(pos,tmp);
+ ptr=blob_record;
+ memcpy(pos+4,&ptr,sizeof(char*));
+ }
+ else if (recinfo[1].type == FIELD_VARCHAR)
+ {
+ size_t tmp, pack_length= HA_VARCHAR_PACKLENGTH(recinfo[1].length-1);
+ sprintf((char*) pos+pack_length, "... row: %d", rownr);
+ tmp= strlen((char*) pos+pack_length);
+ if (pack_length == 1)
+ *pos= (uchar) tmp;
+ else
+ int2store(pos,tmp);
+ }
+ else
+ {
+ sprintf((char*) pos,"... row: %d", rownr);
+ strappend((char*) pos,recinfo[1].length,' ');
+ }
+}
+
+#include "ma_check_standalone.h"