1 /*
2 Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 // Restore
26
27 #ifndef RESTORE_H
28 #define RESTORE_H
29
30 #include <ndb_global.h>
31 #include <NdbOut.hpp>
32 #include "../src/kernel/blocks/backup/BackupFormat.hpp"
33 #include <NdbApi.hpp>
34 #include <util/ndbzio.h>
35 #include <util/UtilBuffer.hpp>
36
37 #include <ndb_version.h>
38 #include <version.h>
39
40 #define NDB_RESTORE_STAGING_SUFFIX "$ST"
41 #ifdef ERROR_INSERT
42 #define NDB_RESTORE_ERROR_INSERT_SMALL_BUFFER 1
43 #endif
44
45 enum TableChangesMask
46 {
47 /**
48 * Allow attribute type promotion
49 */
50 TCM_ATTRIBUTE_PROMOTION = 0x1,
51
52 /**
53 * Allow missing columns
54 */
55 TCM_EXCLUDE_MISSING_COLUMNS = 0x2,
56
57 /**
58 * Allow attribute type demotion and integral signed/unsigned type changes.
59 */
60 TCM_ATTRIBUTE_DEMOTION = 0x4
61 };
62
63 inline
64 bool
isDrop6(Uint32 version)65 isDrop6(Uint32 version)
66 {
67 return (getMajor(version) == 5 && getMinor(version) == 2);
68 }
69
70 typedef NdbDictionary::Table NDBTAB;
71 typedef NdbDictionary::Column NDBCOL;
72 typedef void* (*AttrConvertFunc)(const void *old_data,
73 void *parameter,
74 bool &truncated);
75
76 struct AttributeData {
77 bool null;
78 Uint32 size;
79 union {
80 Int8 * int8_value;
81 Uint8 * u_int8_value;
82
83 Int16 * int16_value;
84 Uint16 * u_int16_value;
85
86 Int32 * int32_value;
87 Uint32 * u_int32_value;
88
89 Int64 * int64_value;
90 Uint64 * u_int64_value;
91
92 char * string_value;
93
94 void* void_value;
95 };
96 };
97
98 struct AttributeDesc {
99 //private:
100 friend class TupleS;
101 friend class TableS;
102 friend class RestoreDataIterator;
103 friend class RestoreMetaData;
104 friend class AttributeS;
105 Uint32 size; // bits
106 Uint32 arraySize;
107 Uint32 attrId;
108 NdbDictionary::Column *m_column;
109
110 bool m_exclude;
111 Uint32 m_nullBitIndex;
112 AttrConvertFunc convertFunc;
113 void *parameter;
114 Uint32 parameterSz;
115 bool truncation_detected;
116 bool staging;
117
118 public:
119
120 AttributeDesc(NdbDictionary::Column *column);
121 AttributeDesc();
122
getSizeInWordsAttributeDesc123 Uint32 getSizeInWords() const { return (size * arraySize + 31)/ 32;}
getSizeInBytesAttributeDesc124 Uint32 getSizeInBytes() const {
125 assert(size >= 8);
126 return (size / 8) * arraySize;
127 }
128 }; // AttributeDesc
129
130 class AttributeS {
131 public:
132 AttributeDesc * Desc;
133 AttributeData Data;
134 };
135
136 class TupleS {
137 private:
138 friend class RestoreDataIterator;
139
140 class TableS *m_currentTable;
141 AttributeData *allAttrData;
142 bool prepareRecord(TableS &);
143
144 public:
TupleS()145 TupleS() {
146 m_currentTable= 0;
147 allAttrData= 0;
148 };
~TupleS()149 ~TupleS()
150 {
151 if (allAttrData)
152 delete [] allAttrData;
153 };
154 TupleS(const TupleS& tuple); // disable copy constructor
155 TupleS & operator=(const TupleS& tuple);
156 int getNoOfAttributes() const;
157 TableS * getTable() const;
158 AttributeDesc * getDesc(int i) const;
159 AttributeData * getData(int i) const;
160 }; // class TupleS
161
162 struct FragmentInfo
163 {
164 Uint32 fragmentNo;
165 Uint64 noOfRecords;
166 Uint32 filePosLow;
167 Uint32 filePosHigh;
168 };
169
170 class TableS {
171
172 friend class TupleS;
173 friend class RestoreMetaData;
174 friend class RestoreDataIterator;
175
176 Uint32 schemaVersion;
177 Uint32 backupVersion;
178 Vector<AttributeDesc *> allAttributesDesc;
179 Vector<AttributeDesc *> m_fixedKeys;
180 //Vector<AttributeDesc *> m_variableKey;
181 Vector<AttributeDesc *> m_fixedAttribs;
182 Vector<AttributeDesc *> m_variableAttribs;
183
184 Uint32 m_noOfNullable;
185 Uint32 m_nullBitmaskSize;
186
187 AttributeDesc * m_auto_val_attrib;
188 Uint64 m_max_auto_val;
189
190 bool m_isSysTable;
191 bool m_isSYSTAB_0;
192 bool m_broken;
193
194 TableS *m_main_table;
195 Uint32 m_main_column_id;
196 Uint32 m_local_id;
197
198 Uint64 m_noOfRecords;
199 Vector<FragmentInfo *> m_fragmentInfo;
200
201 void createAttr(NdbDictionary::Column *column);
202
203 public:
204 class NdbDictionary::Table* m_dictTable;
205 TableS (Uint32 version, class NdbTableImpl* dictTable);
206 ~TableS();
207
getTableId() const208 Uint32 getTableId() const {
209 return m_dictTable->getTableId();
210 }
getLocalId() const211 Uint32 getLocalId() const {
212 return m_local_id;
213 }
getNoOfRecords() const214 Uint64 getNoOfRecords() const {
215 return m_noOfRecords;
216 }
217 /*
218 void setMysqlTableName(char * tableName) {
219 strpcpy(mysqlTableName, tableName);
220 }
221
222 char *
223 void setMysqlDatabaseName(char * databaseName) {
224 strpcpy(mysqlDatabaseName, databaseName);
225 }
226
227 table.setMysqlDatabaseName(database);
228 */
setBackupVersion(Uint32 version)229 void setBackupVersion(Uint32 version) {
230 backupVersion = version;
231 }
232
getBackupVersion() const233 Uint32 getBackupVersion() const {
234 return backupVersion;
235 }
236
getTableName() const237 const char * getTableName() const {
238 return m_dictTable->getName();
239 }
240
getNoOfAttributes() const241 int getNoOfAttributes() const {
242 return allAttributesDesc.size();
243 };
244
have_auto_inc() const245 bool have_auto_inc() const {
246 return m_auto_val_attrib != 0;
247 };
248
have_auto_inc(Uint32 id) const249 bool have_auto_inc(Uint32 id) const {
250 return (m_auto_val_attrib ? m_auto_val_attrib->attrId == id : false);
251 };
252
get_max_auto_val() const253 Uint64 get_max_auto_val() const {
254 return m_max_auto_val;
255 };
256
update_max_auto_val(const char * data,int size)257 void update_max_auto_val(const char *data, int size) {
258 union {
259 Uint8 u8;
260 Uint16 u16;
261 Uint32 u32;
262 } val;
263 Uint64 v;
264 switch(size){
265 case 64:
266 memcpy(&v,data,8);
267 break;
268 case 32:
269 memcpy(&val.u32,data,4);
270 v= val.u32;
271 break;
272 case 24:
273 v= uint3korr((unsigned char*)data);
274 break;
275 case 16:
276 memcpy(&val.u16,data,2);
277 v= val.u16;
278 break;
279 case 8:
280 memcpy(&val.u8,data,1);
281 v= val.u8;
282 break;
283 default:
284 return;
285 };
286 if(v > m_max_auto_val)
287 m_max_auto_val= v;
288 };
289
290 bool get_auto_data(const TupleS & tuple, Uint32 * syskey, Uint64 * nextid) const;
291
292 /**
293 * Get attribute descriptor
294 */
operator [](int attributeId) const295 const AttributeDesc * operator[](int attributeId) const {
296 return allAttributesDesc[attributeId];
297 }
298
getAttributeDesc(int attributeId) const299 AttributeDesc *getAttributeDesc(int attributeId) const {
300 return allAttributesDesc[attributeId];
301 }
302
getSysTable() const303 bool getSysTable() const {
304 return m_isSysTable;
305 }
306
getMainTable() const307 const TableS *getMainTable() const {
308 return m_main_table;
309 }
310
getMainColumnId() const311 Uint32 getMainColumnId() const {
312 return m_main_column_id;
313 }
314
315 TableS& operator=(TableS& org) ;
316
isSYSTAB_0() const317 bool isSYSTAB_0() const {
318 return m_isSYSTAB_0;
319 }
320
321 inline
isBroken() const322 bool isBroken() const {
323 return m_broken || (m_main_table && m_main_table->isBroken());
324 }
325
326 bool m_staging;
327 BaseString m_stagingName;
328 NdbDictionary::Table* m_stagingTable;
329 int m_stagingFlags;
330 }; // TableS;
331
332 class RestoreLogIterator;
333
334 class BackupFile {
335 protected:
336 ndbzio_stream m_file;
337 char m_path[PATH_MAX];
338 char m_fileName[PATH_MAX];
339 bool m_hostByteOrder;
340 BackupFormat::FileHeader m_fileHeader;
341 BackupFormat::FileHeader m_expectedFileHeader;
342
343 Uint32 m_nodeId;
344
345 void * m_buffer;
346 void * m_buffer_ptr;
347 Uint32 m_buffer_sz;
348 Uint32 m_buffer_data_left;
349 #ifdef ERROR_INSERT
350 unsigned m_error_insert;
351 #endif
352 Uint64 m_file_size;
353 Uint64 m_file_pos;
354
355 UtilBuffer m_twiddle_buffer;
356
357 bool m_is_undolog;
358
359 void (* free_data_callback)();
reset_buffers()360 virtual void reset_buffers() {}
361
362 bool openFile();
363 void setCtlFile(Uint32 nodeId, Uint32 backupId, const char * path);
364 void setDataFile(const BackupFile & bf, Uint32 no);
365 void setLogFile(const BackupFile & bf, Uint32 no);
366
367 Uint32 buffer_get_ptr(void **p_buf_ptr, Uint32 size, Uint32 nmemb);
368 Uint32 buffer_read(void *ptr, Uint32 size, Uint32 nmemb);
369 Uint32 buffer_get_ptr_ahead(void **p_buf_ptr, Uint32 size, Uint32 nmemb);
370 Uint32 buffer_read_ahead(void *ptr, Uint32 size, Uint32 nmemb);
371
372 void setName(const char * path, const char * name);
373
374 BackupFile(void (* free_data_callback)() = 0);
375 virtual ~BackupFile();
376
377 public:
378 bool readHeader();
379 bool validateFooter();
380
getPath() const381 const char * getPath() const { return m_path;}
getFilename() const382 const char * getFilename() const { return m_fileName;}
getNodeId() const383 Uint32 getNodeId() const { return m_nodeId;}
getFileHeader() const384 const BackupFormat::FileHeader & getFileHeader() const { return m_fileHeader;}
385 bool Twiddle(const AttributeDesc * const attr_desc,
386 AttributeData * attr_data);
387
get_file_size() const388 Uint64 get_file_size() const { return m_file_size; }
get_file_pos() const389 Uint64 get_file_pos() const { return m_file_pos; }
390 #ifdef ERROR_INSERT
391 void error_insert(unsigned int code);
392 #endif
393
394 private:
395 void
396 twiddle_atribute(const AttributeDesc * const attr_desc,
397 AttributeData* attr_data);
398 };
399
400 struct DictObject {
401 Uint32 m_objType;
402 void * m_objPtr;
403 };
404
405 class RestoreMetaData : public BackupFile {
406
407 Vector<TableS *> allTables;
408 bool readMetaFileHeader();
409 bool readMetaTableDesc();
410 bool markSysTables();
411 bool fixBlobs();
412
413 bool readGCPEntry();
414 bool readFragmentInfo();
415 Uint32 readMetaTableList();
416
417 Uint32 m_startGCP;
418 Uint32 m_stopGCP;
419
420 bool parseTableDescriptor(const Uint32 * data, Uint32 len);
421
422 Vector<DictObject> m_objects;
423
424 public:
425 RestoreMetaData(const char * path, Uint32 nodeId, Uint32 bNo);
426 virtual ~RestoreMetaData();
427
428 int loadContent();
429
getNoOfTables() const430 Uint32 getNoOfTables() const { return allTables.size();}
431
operator [](int i) const432 const TableS * operator[](int i) const { return allTables[i];}
operator [](int i)433 TableS * operator[](int i) { return allTables[i];}
434 TableS * getTable(Uint32 tableId) const;
435
getNoOfObjects() const436 Uint32 getNoOfObjects() const { return m_objects.size();}
getObjType(Uint32 i) const437 Uint32 getObjType(Uint32 i) const { return m_objects[i].m_objType; }
getObjPtr(Uint32 i) const438 void* getObjPtr(Uint32 i) const { return m_objects[i].m_objPtr; }
439
440 Uint32 getStopGCP() const;
getNdbVersion() const441 Uint32 getNdbVersion() const { return m_fileHeader.NdbVersion; };
442 }; // RestoreMetaData
443
444
445 class RestoreDataIterator : public BackupFile {
446 const RestoreMetaData & m_metaData;
447 Uint32 m_count;
448 TableS* m_currentTable;
449 TupleS m_tuple;
450
451 public:
452
453 // Constructor
454 RestoreDataIterator(const RestoreMetaData &,
455 void (* free_data_callback)());
456 virtual ~RestoreDataIterator();
457
458 // Read data file fragment header
459 bool readFragmentHeader(int & res, Uint32 *fragmentId);
460 bool validateFragmentFooter();
461
462 const TupleS *getNextTuple(int & res);
463 TableS *getCurrentTable();
464
465 private:
466 void init_bitfield_storage(const NdbDictionary::Table*);
467 void free_bitfield_storage();
468 void reset_bitfield_storage();
469 Uint32* get_bitfield_storage(Uint32 len);
470 Uint32 get_free_bitfield_storage() const;
471
472 Uint32 m_row_bitfield_len; // in words
473 Uint32* m_bitfield_storage_ptr;
474 Uint32* m_bitfield_storage_curr_ptr;
475 Uint32 m_bitfield_storage_len; // In words
476
477 protected:
reset_buffers()478 virtual void reset_buffers() { reset_bitfield_storage();}
479
480 int readTupleData_old(Uint32 *buf_ptr, Uint32 dataLength);
481 int readTupleData_packed(Uint32 *buf_ptr, Uint32 dataLength);
482
483 int readVarData(Uint32 *buf_ptr, Uint32 *ptr, Uint32 dataLength);
484 int readVarData_drop6(Uint32 *buf_ptr, Uint32 *ptr, Uint32 dataLength);
485 };
486
487 class LogEntry {
488 public:
489 enum EntryType {
490 LE_INSERT,
491 LE_DELETE,
492 LE_UPDATE
493 };
494 Uint32 m_frag_id;
495 EntryType m_type;
496 TableS * m_table;
497 Vector<AttributeS*> m_values;
498 Vector<AttributeS*> m_values_e;
add_attr()499 AttributeS *add_attr() {
500 AttributeS * attr;
501 if (m_values_e.size() > 0) {
502 attr = m_values_e[m_values_e.size()-1];
503 m_values_e.erase(m_values_e.size()-1);
504 }
505 else
506 {
507 attr = new AttributeS;
508 }
509 m_values.push_back(attr);
510 return attr;
511 }
clear()512 void clear() {
513 for(Uint32 i= 0; i < m_values.size(); i++)
514 m_values_e.push_back(m_values[i]);
515 m_values.clear();
516 }
LogEntry()517 LogEntry() {}
~LogEntry()518 ~LogEntry()
519 {
520 Uint32 i;
521 for(i= 0; i< m_values.size(); i++)
522 delete m_values[i];
523 for(i= 0; i< m_values_e.size(); i++)
524 delete m_values_e[i];
525 }
size() const526 Uint32 size() const { return m_values.size(); }
operator [](int i) const527 const AttributeS * operator[](int i) const { return m_values[i];}
528 };
529
530 class RestoreLogIterator : public BackupFile {
531 private:
532 const RestoreMetaData & m_metaData;
533
534 Uint32 m_count;
535 Uint32 m_last_gci;
536 LogEntry m_logEntry;
537 public:
538 RestoreLogIterator(const RestoreMetaData &);
~RestoreLogIterator()539 virtual ~RestoreLogIterator() {};
540
541 const LogEntry * getNextLogEntry(int & res);
542 };
543
544 NdbOut& operator<<(NdbOut& ndbout, const TableS&);
545 NdbOut& operator<<(NdbOut& ndbout, const TupleS&);
546 NdbOut& operator<<(NdbOut& ndbout, const LogEntry&);
547 NdbOut& operator<<(NdbOut& ndbout, const RestoreMetaData&);
548
549 bool readSYSTAB_0(const TupleS & tup, Uint32 * syskey, Uint64 * nextid);
550
551 #endif
552
553
554