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