1 /* Copyright (c) 2003, 2021, Oracle and/or its affiliates. 2 3 This program is free software; you can redistribute it and/or modify 4 it under the terms of the GNU General Public License, version 2.0, 5 as published by the Free Software Foundation. 6 7 This program is also distributed with certain software (including 8 but not limited to OpenSSL) that is licensed under separate terms, 9 as designated in a particular file or component or in included license 10 documentation. The authors of MySQL hereby grant you an additional 11 permission to link the program and your derivative works with the 12 separately licensed software that they have included with MySQL. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License, version 2.0, for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 22 23 #include <zlib.h> 24 #include "azlib.h" 25 26 /* 27 Please read ha_archive.cc first. If you are looking for more general 28 answers on how storage engines work, look at ha_example.cc and 29 ha_example.h. 30 */ 31 32 typedef struct st_archive_record_buffer { 33 uchar *buffer; 34 uint32 length; 35 } archive_record_buffer; 36 37 38 class Archive_share : public Handler_share 39 { 40 public: 41 mysql_mutex_t mutex; 42 THR_LOCK lock; 43 azio_stream archive_write; /* Archive file we are working with */ 44 ha_rows rows_recorded; /* Number of rows in tables */ 45 char table_name[FN_REFLEN]; 46 char data_file_name[FN_REFLEN]; 47 bool in_optimize; 48 bool archive_write_open; 49 bool dirty; /* Flag for if a flush should occur */ 50 bool crashed; /* Meta file is crashed */ 51 Archive_share(); ~Archive_share()52 ~Archive_share() 53 { 54 DBUG_PRINT("ha_archive", ("~Archive_share: %p", 55 this)); 56 if (archive_write_open) 57 { 58 mysql_mutex_lock(&mutex); 59 (void) close_archive_writer(); 60 mysql_mutex_unlock(&mutex); 61 } 62 thr_lock_delete(&lock); 63 mysql_mutex_destroy(&mutex); 64 } 65 int init_archive_writer(); 66 void close_archive_writer(); 67 int write_v1_metafile(); 68 int read_v1_metafile(); 69 }; 70 71 /* 72 Version for file format. 73 1 - Initial Version (Never Released) 74 2 - Stream Compression, seperate blobs, no packing 75 3 - One steam (row and blobs), with packing 76 */ 77 #define ARCHIVE_VERSION 3 78 79 class ha_archive: public handler 80 { 81 THR_LOCK_DATA lock; /* MySQL lock */ 82 Archive_share *share; /* Shared lock info */ 83 84 azio_stream archive; /* Archive file we are working with */ 85 my_off_t current_position; /* The position of the row we just read */ 86 uchar byte_buffer[IO_SIZE]; /* Initial buffer for our string */ 87 String buffer; /* Buffer used for blob storage */ 88 ha_rows scan_rows; /* Number of rows left in scan */ 89 bool bulk_insert; /* If we are performing a bulk insert */ 90 const uchar *current_key; 91 uint current_key_len; 92 uint current_k_offset; 93 archive_record_buffer *record_buffer; 94 bool archive_reader_open; 95 96 archive_record_buffer *create_record_buffer(unsigned int length); 97 void destroy_record_buffer(archive_record_buffer *r); 98 int frm_copy(azio_stream *src, azio_stream *dst); 99 void frm_load(const char *name, azio_stream *dst); 100 unsigned int pack_row_v1(uchar *record); 101 102 public: 103 ha_archive(handlerton *hton, TABLE_SHARE *table_arg); ~ha_archive()104 ~ha_archive() 105 { 106 } table_type()107 const char *table_type() const { return "ARCHIVE"; } index_type(uint inx)108 const char *index_type(uint inx) { return "NONE"; } 109 const char **bas_ext() const; table_flags()110 ulonglong table_flags() const 111 { 112 return (HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_CAN_BIT_FIELD | 113 HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE | 114 HA_STATS_RECORDS_IS_EXACT | 115 HA_HAS_RECORDS | HA_CAN_REPAIR | 116 HA_FILE_BASED | HA_CAN_GEOMETRY); 117 } index_flags(uint idx,uint part,bool all_parts)118 ulong index_flags(uint idx, uint part, bool all_parts) const 119 { 120 return HA_ONLY_WHOLE_INDEX; 121 } 122 virtual void get_auto_increment(ulonglong offset, ulonglong increment, 123 ulonglong nb_desired_values, 124 ulonglong *first_value, 125 ulonglong *nb_reserved_values); max_supported_keys()126 uint max_supported_keys() const { return 1; } max_supported_key_length()127 uint max_supported_key_length() const { return sizeof(ulonglong); } max_supported_key_part_length(HA_CREATE_INFO * create_info MY_ATTRIBUTE ((unused)))128 uint max_supported_key_part_length(HA_CREATE_INFO 129 *create_info MY_ATTRIBUTE((unused))) const 130 { return sizeof(ulonglong); } records(ha_rows * num_rows)131 virtual int records(ha_rows *num_rows) 132 { 133 *num_rows= share->rows_recorded; 134 return 0; 135 } 136 int index_init(uint keynr, bool sorted); 137 virtual int index_read(uchar * buf, const uchar * key, 138 uint key_len, enum ha_rkey_function find_flag); 139 virtual int index_read_idx(uchar * buf, uint index, const uchar * key, 140 uint key_len, enum ha_rkey_function find_flag); 141 int index_next(uchar * buf); 142 int open(const char *name, int mode, uint test_if_locked); 143 int close(void); 144 int write_row(uchar * buf); 145 int real_write_row(uchar *buf, azio_stream *writer); 146 int truncate(); 147 int rnd_init(bool scan=1); 148 int rnd_next(uchar *buf); 149 int rnd_pos(uchar * buf, uchar *pos); 150 int get_row(azio_stream *file_to_read, uchar *buf); 151 int get_row_version2(azio_stream *file_to_read, uchar *buf); 152 int get_row_version3(azio_stream *file_to_read, uchar *buf); 153 Archive_share *get_share(const char *table_name, int *rc); 154 int init_archive_reader(); auto_repair()155 bool auto_repair() const { return 1; } // For the moment we just do this 156 int read_data_header(azio_stream *file_to_read); 157 void position(const uchar *record); 158 int info(uint); 159 int extra(enum ha_extra_function operation); 160 void update_create_info(HA_CREATE_INFO *create_info); 161 int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info); 162 int optimize(THD* thd, HA_CHECK_OPT* check_opt); 163 int repair(THD* thd, HA_CHECK_OPT* check_opt); 164 void start_bulk_insert(ha_rows rows); 165 int end_bulk_insert(); get_row_type()166 enum row_type get_row_type() const 167 { 168 return ROW_TYPE_COMPRESSED; 169 } 170 THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to, 171 enum thr_lock_type lock_type); 172 bool is_crashed() const; 173 int check_for_upgrade(HA_CHECK_OPT *check_opt); 174 int check(THD* thd, HA_CHECK_OPT* check_opt); 175 bool check_and_repair(THD *thd); 176 uint32 max_row_length(const uchar *buf); 177 bool fix_rec_buff(unsigned int length); 178 int unpack_row(azio_stream *file_to_read, uchar *record); 179 unsigned int pack_row(uchar *record, azio_stream *writer); 180 bool check_if_incompatible_data(HA_CREATE_INFO *info, uint table_changes); 181 }; 182 183