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