2
Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
4
This program is free software; you can redistribute it and/or modify
5
it under the terms of the GNU General Public License as published by
6
the Free Software Foundation; version 2 of the License.
8
This program is distributed in the hope that it will be useful,
9
but WITHOUT ANY WARRANTY; without even the implied warranty of
10
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
GNU General Public License for more details.
13
You should have received a copy of the GNU General Public License
14
along with this program; if not, write to the Free Software
15
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
#include <NDBT_ReturnCodes.h>
19
#include "consumer_restore.hpp"
20
#include <kernel/ndb_limits.h>
24
#include <Properties.hpp>
25
#include <NdbTypesUtil.hpp>
27
#include <ndb_internal.hpp>
28
#include <ndb_logevent.h>
29
#include "../src/ndbapi/NdbDictionaryImpl.hpp"
31
#define NDB_ANYVALUE_FOR_NOLOGGING 0x8000007f
33
extern FilteredNdbOut err;
34
extern FilteredNdbOut info;
35
extern FilteredNdbOut debug;
37
static void callback(int, NdbTransaction*, void*);
38
static Uint32 get_part_id(const NdbDictionary::Table *table,
41
extern BaseString g_options;
42
extern unsigned int opt_no_binlog;
43
extern bool ga_skip_broken_objects;
45
extern Properties g_rewrite_databases;
47
bool BackupRestore::m_preserve_trailing_spaces = false;
49
// ----------------------------------------------------------------------
50
// conversion handlers
51
// ----------------------------------------------------------------------
54
BackupRestore::convert_bitset(const void *source,
58
if (!source || !target)
62
const unsigned char * const s = (const unsigned char *)source;
63
char_n_padding_struct * const t = (char_n_padding_struct *)target;
66
if (t->n_new >= t->n_old)
69
memset(t->new_row, 0, t->n_new);
71
memcpy(t->new_row, s, t->n_old);
74
// set all bits, for parity with replication's demotion semantics
75
memset(t->new_row, 0xFF, t->n_new);
82
template< typename S, typename T >
84
BackupRestore::convert_array(const void * source,
88
if (!source || !target)
91
// shortcuts (note that all S::... and T::... are compile-time expr)
92
const unsigned char * const s = (const unsigned char *)source;
93
char_n_padding_struct * const t = (char_n_padding_struct *)target;
94
const Uint32 s_prefix_length = S::lengthPrefixSize();
95
const Uint32 t_prefix_length = T::lengthPrefixSize();
97
// read and adjust length
98
Uint32 length = (S::isFixedSized() ? t->n_old : S::readLengthPrefix(s));
99
const Uint32 max_length = t->n_new - t_prefix_length;
100
if (S::isFixedSized() && !m_preserve_trailing_spaces) {
101
const char s_padding_char = (S::isBinary() ? 0x00 : ' ');
102
// ignore padding chars for data copying or truncation reporting
103
while (length > 0 && s[length - 1] == s_padding_char) {
107
if (length <= max_length) {
114
// write length prefix
115
if (!T::isFixedSized()) {
116
T::writeLengthPrefix(t->new_row, length);
120
memcpy(t->new_row + t_prefix_length, s + s_prefix_length, length);
123
if (T::isFixedSized()) {
124
const char t_padding_char = (T::isBinary() ? 0x00 : ' ');
125
const Uint32 l = max_length - length;
126
memset(t->new_row + t_prefix_length + length, t_padding_char, l);
132
template< typename S, typename T >
134
BackupRestore::convert_integral(const void * source,
138
if (!source || !target)
141
// read the source value
142
typename S::DomainT s;
143
S::load(&s, (char *)source);
145
// Note: important to correctly handle mixed signedness comparisons.
147
// The problem: A straight-forward approach to convert value 's' into
148
// type 'T' might be to check into which of these subranges 's' falls
149
// ... < T's lower bound <= ... <= T's upper bound < ...
150
// However, this approach is _incorrect_ when applied to generic code
151
// if (s < T::lowest()) ... else if (s > T::highest()) ... else ...
152
// since 'S' and 'T' may be types of different signedness.
154
// Under ansi (and even more K&R) C promotion rules, if 'T' is unsigned
155
// and if there's no larger signed type available, the value 's' gets
156
// promoted to unsigned; then, a negative value of 's' becomes (large)
157
// positive -- with a wrong comparison outcome.
159
// Furthermore, the code should not trigger compiler warnings for any
160
// selection of integral types 'S', 'T' ("mixed signedness comparison",
161
// "comparison of unsigned expression <0 / >=0 is always false/true").
163
// The correct approach: do lower bound comparisons on signed types and
164
// upper bound comparisons on unsigned types only; this requires casts.
165
// For the casts to be safe, compare the value against the zero literal
166
// if (s <= 0) { check as signed } else { check as unsigned }
167
// which is a valid + nontrivial test for signed and unsigned types.
169
// This implies that correct, generic conversion code must test into
170
// which of these _four_ subranges value 's' falls
171
// ... < T's lower bound <= ... <= 0 < ... <= T's upper bound < ...
172
// while handling 's' as signed/unsigned where less-equal/greater zero.
174
// Obviously, simplifications are possible if 'S' is unsigned or known
175
// to be a subset of 'T'. This can be accomplished by a few additional
176
// compile-time expression tests, which allow code optimization to
177
// issue fewer checks for certain specializations of types 'S' and 'T'.
179
// write the target value
180
typename T::DomainT t;
183
// check value against lower bound as _signed_, safe since all <= 0
184
assert(S::lowest() <= 0 && T::lowest() <= 0 && s <= 0);
185
const typename S::SignedT s_l_s = S::asSigned(S::lowest());
186
const typename T::SignedT t_l_s = T::asSigned(T::lowest());
187
const typename S::SignedT s_s = S::asSigned(s);
188
if ((s_l_s < t_l_s) // compile-time expr
189
&& (s_s < t_l_s)) { // lower bound check
192
} else { // within both bounds
193
t = static_cast< typename T::DomainT >(s);
199
// check value against upper bound as _unsigned_, safe since all > 0
200
assert(S::highest() > 0 && T::highest() > 0 && s > 0);
201
const typename S::UnsignedT s_h_u = S::asUnsigned(S::highest());
202
const typename T::UnsignedT t_h_u = T::asUnsigned(T::highest());
203
const typename S::UnsignedT s_u = S::asUnsigned(s);
204
if ((s_h_u > t_h_u) // compile-time expr
205
&& (s_u > t_h_u)) { // upper bound check
208
} else { // within both bounds
209
t = static_cast< typename T::DomainT >(s);
214
T::store((char *)target, &t);
219
// ----------------------------------------------------------------------
221
// ----------------------------------------------------------------------
224
BackupRestore::m_allowed_promotion_attrs[] = {
225
// bitset promotions/demotions
226
{NDBCOL::Bit, NDBCOL::Bit, check_compat_sizes,
229
// char array promotions/demotions
230
{NDBCOL::Char, NDBCOL::Char, check_compat_sizes,
231
convert_array< Hchar, Hchar >},
232
{NDBCOL::Char, NDBCOL::Varchar, check_compat_sizes,
233
convert_array< Hchar, Hvarchar >},
234
{NDBCOL::Char, NDBCOL::Longvarchar, check_compat_sizes,
235
convert_array< Hchar, Hlongvarchar >},
236
{NDBCOL::Varchar, NDBCOL::Char, check_compat_sizes,
237
convert_array< Hvarchar, Hchar >},
238
{NDBCOL::Varchar, NDBCOL::Varchar, check_compat_sizes,
239
convert_array< Hvarchar, Hvarchar >},
240
{NDBCOL::Varchar, NDBCOL::Longvarchar, check_compat_sizes,
241
convert_array< Hvarchar, Hlongvarchar >},
242
{NDBCOL::Longvarchar, NDBCOL::Char, check_compat_sizes,
243
convert_array< Hlongvarchar, Hchar >},
244
{NDBCOL::Longvarchar, NDBCOL::Varchar, check_compat_sizes,
245
convert_array< Hlongvarchar, Hvarchar >},
246
{NDBCOL::Longvarchar, NDBCOL::Longvarchar, check_compat_sizes,
247
convert_array< Hlongvarchar, Hlongvarchar >},
249
// binary array promotions/demotions
250
{NDBCOL::Binary, NDBCOL::Binary, check_compat_sizes,
251
convert_array< Hbinary, Hbinary >},
252
{NDBCOL::Binary, NDBCOL::Varbinary, check_compat_sizes,
253
convert_array< Hbinary, Hvarbinary >},
254
{NDBCOL::Binary, NDBCOL::Longvarbinary, check_compat_sizes,
255
convert_array< Hbinary, Hlongvarbinary >},
256
{NDBCOL::Varbinary, NDBCOL::Binary, check_compat_sizes,
257
convert_array< Hvarbinary, Hbinary >},
258
{NDBCOL::Varbinary, NDBCOL::Varbinary, check_compat_sizes,
259
convert_array< Hvarbinary, Hvarbinary >},
260
{NDBCOL::Varbinary, NDBCOL::Longvarbinary, check_compat_sizes,
261
convert_array< Hvarbinary, Hlongvarbinary >},
262
{NDBCOL::Longvarbinary, NDBCOL::Binary, check_compat_sizes,
263
convert_array< Hlongvarbinary, Hbinary >},
264
{NDBCOL::Longvarbinary, NDBCOL::Varbinary, check_compat_sizes,
265
convert_array< Hlongvarbinary, Hvarbinary >},
266
{NDBCOL::Longvarbinary, NDBCOL::Longvarbinary, check_compat_sizes,
267
convert_array< Hlongvarbinary, Hlongvarbinary >},
269
// integral promotions
270
{NDBCOL::Tinyint, NDBCOL::Smallint, check_compat_promotion,
271
convert_integral< Hint8, Hint16>},
272
{NDBCOL::Tinyint, NDBCOL::Mediumint, check_compat_promotion,
273
convert_integral< Hint8, Hint24>},
274
{NDBCOL::Tinyint, NDBCOL::Int, check_compat_promotion,
275
convert_integral< Hint8, Hint32>},
276
{NDBCOL::Tinyint, NDBCOL::Bigint, check_compat_promotion,
277
convert_integral< Hint8, Hint64>},
278
{NDBCOL::Smallint, NDBCOL::Mediumint, check_compat_promotion,
279
convert_integral< Hint16, Hint24>},
280
{NDBCOL::Smallint, NDBCOL::Int, check_compat_promotion,
281
convert_integral< Hint16, Hint32>},
282
{NDBCOL::Smallint, NDBCOL::Bigint, check_compat_promotion,
283
convert_integral< Hint16, Hint64>},
284
{NDBCOL::Mediumint, NDBCOL::Int, check_compat_promotion,
285
convert_integral< Hint24, Hint32>},
286
{NDBCOL::Mediumint, NDBCOL::Bigint, check_compat_promotion,
287
convert_integral< Hint24, Hint64>},
288
{NDBCOL::Int, NDBCOL::Bigint, check_compat_promotion,
289
convert_integral< Hint32, Hint64>},
290
{NDBCOL::Tinyunsigned, NDBCOL::Smallunsigned, check_compat_promotion,
291
convert_integral< Huint8, Huint16>},
292
{NDBCOL::Tinyunsigned, NDBCOL::Mediumunsigned, check_compat_promotion,
293
convert_integral< Huint8, Huint24>},
294
{NDBCOL::Tinyunsigned, NDBCOL::Unsigned, check_compat_promotion,
295
convert_integral< Huint8, Huint32>},
296
{NDBCOL::Tinyunsigned, NDBCOL::Bigunsigned, check_compat_promotion,
297
convert_integral< Huint8, Huint64>},
298
{NDBCOL::Smallunsigned, NDBCOL::Mediumunsigned, check_compat_promotion,
299
convert_integral< Huint16, Huint24>},
300
{NDBCOL::Smallunsigned, NDBCOL::Unsigned, check_compat_promotion,
301
convert_integral< Huint16, Huint32>},
302
{NDBCOL::Smallunsigned, NDBCOL::Bigunsigned, check_compat_promotion,
303
convert_integral< Huint16, Huint64>},
304
{NDBCOL::Mediumunsigned, NDBCOL::Unsigned, check_compat_promotion,
305
convert_integral< Huint24, Huint32>},
306
{NDBCOL::Mediumunsigned, NDBCOL::Bigunsigned, check_compat_promotion,
307
convert_integral< Huint24, Huint64>},
308
{NDBCOL::Unsigned, NDBCOL::Bigunsigned, check_compat_promotion,
309
convert_integral< Huint32, Huint64>},
311
// integral demotions
312
{NDBCOL::Smallint, NDBCOL::Tinyint, check_compat_lossy,
313
convert_integral< Hint16, Hint8>},
314
{NDBCOL::Mediumint, NDBCOL::Tinyint, check_compat_lossy,
315
convert_integral< Hint24, Hint8>},
316
{NDBCOL::Mediumint, NDBCOL::Smallint, check_compat_lossy,
317
convert_integral< Hint24, Hint16>},
318
{NDBCOL::Int, NDBCOL::Tinyint, check_compat_lossy,
319
convert_integral< Hint32, Hint8>},
320
{NDBCOL::Int, NDBCOL::Smallint, check_compat_lossy,
321
convert_integral< Hint32, Hint16>},
322
{NDBCOL::Int, NDBCOL::Mediumint, check_compat_lossy,
323
convert_integral< Hint32, Hint24>},
324
{NDBCOL::Bigint, NDBCOL::Tinyint, check_compat_lossy,
325
convert_integral< Hint64, Hint8>},
326
{NDBCOL::Bigint, NDBCOL::Smallint, check_compat_lossy,
327
convert_integral< Hint64, Hint16>},
328
{NDBCOL::Bigint, NDBCOL::Mediumint, check_compat_lossy,
329
convert_integral< Hint64, Hint24>},
330
{NDBCOL::Bigint, NDBCOL::Int, check_compat_lossy,
331
convert_integral< Hint64, Hint32>},
332
{NDBCOL::Smallunsigned, NDBCOL::Tinyunsigned, check_compat_lossy,
333
convert_integral< Huint16, Huint8>},
334
{NDBCOL::Mediumunsigned, NDBCOL::Tinyunsigned, check_compat_lossy,
335
convert_integral< Huint24, Huint8>},
336
{NDBCOL::Mediumunsigned, NDBCOL::Smallunsigned, check_compat_lossy,
337
convert_integral< Huint24, Huint16>},
338
{NDBCOL::Unsigned, NDBCOL::Tinyunsigned, check_compat_lossy,
339
convert_integral< Huint32, Huint8>},
340
{NDBCOL::Unsigned, NDBCOL::Smallunsigned, check_compat_lossy,
341
convert_integral< Huint32, Huint16>},
342
{NDBCOL::Unsigned, NDBCOL::Mediumunsigned, check_compat_lossy,
343
convert_integral< Huint32, Huint24>},
344
{NDBCOL::Bigunsigned, NDBCOL::Tinyunsigned, check_compat_lossy,
345
convert_integral< Huint64, Huint8>},
346
{NDBCOL::Bigunsigned, NDBCOL::Smallunsigned, check_compat_lossy,
347
convert_integral< Huint64, Huint16>},
348
{NDBCOL::Bigunsigned, NDBCOL::Mediumunsigned, check_compat_lossy,
349
convert_integral< Huint64, Huint24>},
350
{NDBCOL::Bigunsigned, NDBCOL::Unsigned, check_compat_lossy,
351
convert_integral< Huint64, Huint32>},
353
// integral signedness conversions
354
{NDBCOL::Tinyint, NDBCOL::Tinyunsigned, check_compat_lossy,
355
convert_integral< Hint8, Huint8>},
356
{NDBCOL::Smallint, NDBCOL::Smallunsigned, check_compat_lossy,
357
convert_integral< Hint16, Huint16>},
358
{NDBCOL::Mediumint, NDBCOL::Mediumunsigned, check_compat_lossy,
359
convert_integral< Hint24, Huint24>},
360
{NDBCOL::Int, NDBCOL::Unsigned, check_compat_lossy,
361
convert_integral< Hint32, Huint32>},
362
{NDBCOL::Bigint, NDBCOL::Bigunsigned, check_compat_lossy,
363
convert_integral< Hint64, Huint64>},
364
{NDBCOL::Tinyunsigned, NDBCOL::Tinyint, check_compat_lossy,
365
convert_integral< Huint8, Hint8>},
366
{NDBCOL::Smallunsigned, NDBCOL::Smallint, check_compat_lossy,
367
convert_integral< Huint16, Hint16>},
368
{NDBCOL::Mediumunsigned, NDBCOL::Mediumint, check_compat_lossy,
369
convert_integral< Huint24, Hint24>},
370
{NDBCOL::Unsigned, NDBCOL::Int, check_compat_lossy,
371
convert_integral< Huint32, Hint32>},
372
{NDBCOL::Bigunsigned, NDBCOL::Bigint, check_compat_lossy,
373
convert_integral< Huint64, Hint64>},
375
// integral signedness+promotion conversions
376
{NDBCOL::Tinyint, NDBCOL::Smallunsigned, check_compat_lossy,
377
convert_integral< Hint8, Huint16>},
378
{NDBCOL::Tinyint, NDBCOL::Mediumunsigned, check_compat_lossy,
379
convert_integral< Hint8, Huint24>},
380
{NDBCOL::Tinyint, NDBCOL::Unsigned, check_compat_lossy,
381
convert_integral< Hint8, Huint32>},
382
{NDBCOL::Tinyint, NDBCOL::Bigunsigned, check_compat_lossy,
383
convert_integral< Hint8, Huint64>},
384
{NDBCOL::Smallint, NDBCOL::Mediumunsigned, check_compat_lossy,
385
convert_integral< Hint16, Huint24>},
386
{NDBCOL::Smallint, NDBCOL::Unsigned, check_compat_lossy,
387
convert_integral< Hint16, Huint32>},
388
{NDBCOL::Smallint, NDBCOL::Bigunsigned, check_compat_lossy,
389
convert_integral< Hint16, Huint64>},
390
{NDBCOL::Mediumint, NDBCOL::Unsigned, check_compat_lossy,
391
convert_integral< Hint24, Huint32>},
392
{NDBCOL::Mediumint, NDBCOL::Bigunsigned, check_compat_lossy,
393
convert_integral< Hint24, Huint64>},
394
{NDBCOL::Int, NDBCOL::Bigunsigned, check_compat_lossy,
395
convert_integral< Hint32, Huint64>},
396
{NDBCOL::Tinyunsigned, NDBCOL::Smallint, check_compat_lossy,
397
convert_integral< Huint8, Hint16>},
398
{NDBCOL::Tinyunsigned, NDBCOL::Mediumint, check_compat_lossy,
399
convert_integral< Huint8, Hint24>},
400
{NDBCOL::Tinyunsigned, NDBCOL::Int, check_compat_lossy,
401
convert_integral< Huint8, Hint32>},
402
{NDBCOL::Tinyunsigned, NDBCOL::Bigint, check_compat_lossy,
403
convert_integral< Huint8, Hint64>},
404
{NDBCOL::Smallunsigned, NDBCOL::Mediumint, check_compat_lossy,
405
convert_integral< Huint16, Hint24>},
406
{NDBCOL::Smallunsigned, NDBCOL::Int, check_compat_lossy,
407
convert_integral< Huint16, Hint32>},
408
{NDBCOL::Smallunsigned, NDBCOL::Bigint, check_compat_lossy,
409
convert_integral< Huint16, Hint64>},
410
{NDBCOL::Mediumunsigned, NDBCOL::Int, check_compat_lossy,
411
convert_integral< Huint24, Hint32>},
412
{NDBCOL::Mediumunsigned, NDBCOL::Bigint, check_compat_lossy,
413
convert_integral< Huint24, Hint64>},
414
{NDBCOL::Unsigned, NDBCOL::Bigint, check_compat_lossy,
415
convert_integral< Huint32, Hint64>},
417
// integral signedness+demotion conversions
418
{NDBCOL::Smallint, NDBCOL::Tinyunsigned, check_compat_lossy,
419
convert_integral< Hint16, Huint8>},
420
{NDBCOL::Mediumint, NDBCOL::Tinyunsigned, check_compat_lossy,
421
convert_integral< Hint24, Huint8>},
422
{NDBCOL::Mediumint, NDBCOL::Smallunsigned, check_compat_lossy,
423
convert_integral< Hint24, Huint16>},
424
{NDBCOL::Int, NDBCOL::Tinyunsigned, check_compat_lossy,
425
convert_integral< Hint32, Huint8>},
426
{NDBCOL::Int, NDBCOL::Smallunsigned, check_compat_lossy,
427
convert_integral< Hint32, Huint16>},
428
{NDBCOL::Int, NDBCOL::Mediumunsigned, check_compat_lossy,
429
convert_integral< Hint32, Huint24>},
430
{NDBCOL::Bigint, NDBCOL::Tinyunsigned, check_compat_lossy,
431
convert_integral< Hint64, Huint8>},
432
{NDBCOL::Bigint, NDBCOL::Smallunsigned, check_compat_lossy,
433
convert_integral< Hint64, Huint16>},
434
{NDBCOL::Bigint, NDBCOL::Mediumunsigned, check_compat_lossy,
435
convert_integral< Hint64, Huint24>},
436
{NDBCOL::Bigint, NDBCOL::Unsigned, check_compat_lossy,
437
convert_integral< Hint64, Huint32>},
438
{NDBCOL::Smallunsigned, NDBCOL::Tinyint, check_compat_lossy,
439
convert_integral< Huint16, Hint8>},
440
{NDBCOL::Mediumunsigned, NDBCOL::Tinyint, check_compat_lossy,
441
convert_integral< Huint24, Hint8>},
442
{NDBCOL::Mediumunsigned, NDBCOL::Smallint, check_compat_lossy,
443
convert_integral< Huint24, Hint16>},
444
{NDBCOL::Unsigned, NDBCOL::Tinyint, check_compat_lossy,
445
convert_integral< Huint32, Hint8>},
446
{NDBCOL::Unsigned, NDBCOL::Smallint, check_compat_lossy,
447
convert_integral< Huint32, Hint16>},
448
{NDBCOL::Unsigned, NDBCOL::Mediumint, check_compat_lossy,
449
convert_integral< Huint32, Hint24>},
450
{NDBCOL::Bigunsigned, NDBCOL::Tinyint, check_compat_lossy,
451
convert_integral< Huint64, Hint8>},
452
{NDBCOL::Bigunsigned, NDBCOL::Smallint, check_compat_lossy,
453
convert_integral< Huint64, Hint16>},
454
{NDBCOL::Bigunsigned, NDBCOL::Mediumint, check_compat_lossy,
455
convert_integral< Huint64, Hint24>},
456
{NDBCOL::Bigunsigned, NDBCOL::Int, check_compat_lossy,
457
convert_integral< Huint64, Hint32>},
459
{NDBCOL::Undefined, NDBCOL::Undefined, NULL, NULL}
463
BackupRestore::init(Uint32 tableChangesMask)
467
if (!m_restore && !m_restore_meta && !m_restore_epoch &&
468
!m_rebuild_indexes && !m_disable_indexes)
471
m_tableChangesMask = tableChangesMask;
472
m_cluster_connection = new Ndb_cluster_connection(m_ndb_connectstring,
474
if (m_cluster_connection == NULL)
476
err << "Failed to create cluster connection!!" << endl;
479
m_cluster_connection->set_name(g_options.c_str());
480
if(m_cluster_connection->connect(12, 5, 1) != 0)
485
m_ndb = new Ndb(m_cluster_connection);
491
if (m_ndb->waitUntilReady(30) != 0)
493
err << "Failed to connect to ndb!!" << endl;
496
info << "Connected to ndb!!" << endl;
498
m_callback = new restore_callback_t[m_parallelism];
502
err << "Failed to allocate callback structs" << endl;
506
m_free_callback= m_callback;
507
for (Uint32 i= 0; i < m_parallelism; i++) {
508
m_callback[i].restore= this;
509
m_callback[i].connection= 0;
511
m_callback[i-1].next= &(m_callback[i]);
513
m_callback[m_parallelism-1].next = 0;
518
void BackupRestore::release()
528
delete [] m_callback;
532
if (m_cluster_connection)
534
delete m_cluster_connection;
535
m_cluster_connection= 0;
539
BackupRestore::~BackupRestore()
546
match_blob(const char * name){
549
if((cnt = sscanf(name, "%[^/]/%[^/]/NDB$BLOB_%d_%d", buf, buf, &id1, &id2)) == 4){
557
* Extracts the database, schema, and table name from an internal table name;
558
* prints an error message and returns false in case of a format violation.
562
dissect_table_name(const char * qualified_table_name,
563
BaseString & db_name,
564
BaseString & schema_name,
565
BaseString & table_name) {
566
Vector<BaseString> split;
567
BaseString tmp(qualified_table_name);
568
if (tmp.split(split, "/") != 3) {
569
err << "Invalid table name format `" << qualified_table_name
574
schema_name = split[1];
575
table_name = split[2];
580
* Assigns the new name for a database, if and only if to be rewritten.
584
check_rewrite_database(BaseString & db_name) {
585
const char * new_db_name;
586
if (g_rewrite_databases.get(db_name.c_str(), &new_db_name))
587
db_name.assign(new_db_name);
590
const NdbDictionary::Table*
591
BackupRestore::get_table(const NdbDictionary::Table* tab){
592
if(m_cache.m_old_table == tab)
593
return m_cache.m_new_table;
594
m_cache.m_old_table = tab;
597
char db[256], schema[256];
598
if (strcmp(tab->getName(), "SYSTAB_0") == 0 ||
599
strcmp(tab->getName(), "sys/def/SYSTAB_0") == 0) {
601
Restore SYSTAB_0 to itself
603
m_cache.m_new_table = tab;
605
else if((cnt = sscanf(tab->getName(), "%[^/]/%[^/]/NDB$BLOB_%d_%d",
606
db, schema, &id1, &id2)) == 4){
607
m_ndb->setDatabaseName(db);
608
m_ndb->setSchemaName(schema);
610
BaseString::snprintf(db, sizeof(db), "NDB$BLOB_%d_%d",
611
m_new_tables[id1]->getTableId(), id2);
613
m_cache.m_new_table = m_ndb->getDictionary()->getTable(db);
616
m_cache.m_new_table = m_new_tables[tab->getTableId()];
618
assert(m_cache.m_new_table);
619
return m_cache.m_new_table;
623
BackupRestore::finalize_table(const TableS & table){
625
if (!m_restore && !m_restore_meta)
627
if (!table.have_auto_inc())
630
Uint64 max_val= table.get_max_auto_val();
633
Uint64 auto_val = ~(Uint64)0;
634
int r= m_ndb->readAutoIncrementValue(get_table(table.m_dictTable), auto_val);
635
if (r == -1 && m_ndb->getNdbError().status == NdbError::TemporaryError)
637
NdbSleep_MilliSleep(50);
640
else if (r == -1 && m_ndb->getNdbError().code != 626)
644
else if ((r == -1 && m_ndb->getNdbError().code == 626) ||
645
max_val+1 > auto_val || auto_val == ~(Uint64)0)
647
r= m_ndb->setAutoIncrementValue(get_table(table.m_dictTable),
650
m_ndb->getNdbError().status == NdbError::TemporaryError)
652
NdbSleep_MilliSleep(50);
662
BackupRestore::rebuild_indexes(const TableS& table)
664
const char *tablename = table.getTableName();
666
const NdbDictionary::Table * tab = get_table(table.m_dictTable);
667
Uint32 id = tab->getObjectId();
668
if (m_index_per_table.size() <= id)
671
BaseString db_name, schema_name, table_name;
672
if (!dissect_table_name(tablename, db_name, schema_name, table_name)) {
675
check_rewrite_database(db_name);
677
m_ndb->setDatabaseName(db_name.c_str());
678
m_ndb->setSchemaName(schema_name.c_str());
679
NdbDictionary::Dictionary* dict = m_ndb->getDictionary();
681
Vector<NdbDictionary::Index*> & indexes = m_index_per_table[id];
682
for(size_t i = 0; i<indexes.size(); i++)
684
const NdbDictionary::Index * const idx = indexes[i];
685
const char * const idx_name = idx->getName();
686
const char * const tab_name = idx->getTable();
687
Uint64 start = NdbTick_CurrentMillisecond();
688
info << "Rebuilding index `" << idx_name << "` on table `"
689
<< tab_name << "` ..." << flush;
690
if ((dict->getIndex(idx_name, tab_name) == NULL)
691
&& (dict->createIndex(* idx, 1) != 0))
693
info << "FAIL!" << endl;
694
err << "Rebuilding index `" << idx_name << "` on table `"
695
<< tab_name <<"` failed: ";
696
err << dict->getNdbError() << endl;
700
Uint64 stop = NdbTick_CurrentMillisecond();
701
info << "OK (" << ((stop - start)/1000) << "s)" <<endl;
708
static bool default_nodegroups(NdbDictionary::Table *table)
710
Uint16 *node_groups = (Uint16*)table->getFragmentData();
711
Uint32 no_parts = table->getFragmentDataLen() >> 1;
714
if (node_groups[0] != 0)
716
for (i = 1; i < no_parts; i++)
718
if (node_groups[i] != NDB_UNDEF_NODEGROUP)
726
static Uint32 get_no_fragments(Uint64 max_rows, Uint32 no_nodes)
729
Uint32 acc_row_size = 27;
730
Uint32 acc_fragment_size = 512*1024*1024;
731
Uint32 no_parts= Uint32((max_rows*acc_row_size)/acc_fragment_size + 1);
732
Uint32 reported_parts = no_nodes;
733
while (reported_parts < no_parts && ++i < 4 &&
734
(reported_parts + no_parts) < MAX_NDB_PARTITIONS)
735
reported_parts+= no_nodes;
736
if (reported_parts < no_parts)
738
err << "Table will be restored but will not be able to handle the maximum";
739
err << " amount of rows as requested" << endl;
741
return reported_parts;
745
static void set_default_nodegroups(NdbDictionary::Table *table)
747
Uint32 no_parts = table->getFragmentCount();
748
Uint32 node_group[MAX_NDB_PARTITIONS];
752
for (i = 1; i < no_parts; i++)
754
node_group[i] = NDB_UNDEF_NODEGROUP;
756
table->setFragmentData(node_group, no_parts);
759
Uint32 BackupRestore::map_ng(Uint32 ng)
761
NODE_GROUP_MAP *ng_map = m_nodegroup_map;
763
if (ng == NDB_UNDEF_NODEGROUP ||
764
ng_map[ng].map_array[0] == NDB_UNDEF_NODEGROUP)
771
Uint32 curr_inx = ng_map[ng].curr_index;
772
Uint32 new_curr_inx = curr_inx + 1;
774
assert(ng < MAX_NDB_PARTITIONS);
775
assert(curr_inx < MAX_MAPS_PER_NODE_GROUP);
776
assert(new_curr_inx < MAX_MAPS_PER_NODE_GROUP);
778
if (new_curr_inx >= MAX_MAPS_PER_NODE_GROUP)
780
else if (ng_map[ng].map_array[new_curr_inx] == NDB_UNDEF_NODEGROUP)
782
new_ng = ng_map[ng].map_array[curr_inx];
783
ng_map[ng].curr_index = new_curr_inx;
789
bool BackupRestore::map_nodegroups(Uint32 *ng_array, Uint32 no_parts)
793
DBUG_ENTER("map_nodegroups");
795
assert(no_parts < MAX_NDB_PARTITIONS);
796
for (i = 0; i < no_parts; i++)
799
ng = map_ng(ng_array[i]);
800
if (ng != ng_array[i])
808
static void copy_byte(const char **data, char **new_data, uint *len)
817
bool BackupRestore::search_replace(char *search_str, char **new_data,
818
const char **data, const char *end_data,
821
uint search_str_len = strlen(search_str);
823
bool in_delimiters = FALSE;
824
bool escape_char = FALSE;
825
char start_delimiter = 0;
826
DBUG_ENTER("search_replace");
831
copy_byte(data, new_data, new_data_len);
836
else if (in_delimiters)
838
if (c == start_delimiter)
839
in_delimiters = FALSE;
841
else if (c == '\'' || c == '\"')
843
in_delimiters = TRUE;
850
else if (c == search_str[inx])
853
if (inx == search_str_len)
857
while (*data != end_data)
862
number = (10 * number) + (**data);
863
if (number > MAX_NDB_NODES)
869
After long and tedious preparations we have actually found
870
a node group identifier to convert. We'll use the mapping
871
table created for node groups and then insert the new number
872
instead of the old number.
874
uint temp = map_ng(number);
879
digits[no_digits] = temp % 10;
883
for (no_digits--; no_digits >= 0; no_digits--)
885
**new_data = digits[no_digits];
899
} while (*data < end_data);
903
bool BackupRestore::map_in_frm(char *new_data, const char *data,
904
uint data_len, uint *new_data_len)
906
const char *end_data= data + data_len;
907
const char *end_part_data;
908
const char *part_data;
910
uint start_key_definition_len = uint2korr(data + 6);
911
uint key_definition_len = uint4korr(data + 47);
913
DBUG_ENTER("map_in_frm");
915
if (data_len < 4096) goto error;
916
extra_ptr = (char*)data + start_key_definition_len + key_definition_len;
917
if ((int)data_len < ((extra_ptr - data) + 2)) goto error;
918
extra_ptr = extra_ptr + 2 + uint2korr(extra_ptr);
919
if ((int)data_len < ((extra_ptr - data) + 2)) goto error;
920
extra_ptr = extra_ptr + 2 + uint2korr(extra_ptr);
921
if ((int)data_len < ((extra_ptr - data) + 4)) goto error;
922
part_info_len = uint4korr(extra_ptr);
923
part_data = extra_ptr + 4;
924
if ((int)data_len < ((part_data + part_info_len) - data)) goto error;
928
copy_byte(&data, &new_data, new_data_len);
929
} while (data < part_data);
930
end_part_data = part_data + part_info_len;
933
if (search_replace((char*)" NODEGROUP = ", &new_data, &data,
934
end_part_data, new_data_len))
936
} while (data != end_part_data);
939
copy_byte(&data, &new_data, new_data_len);
940
} while (data < end_data);
947
bool BackupRestore::translate_frm(NdbDictionary::Table *table)
949
uchar *pack_data, *data, *new_pack_data;
952
size_t data_len, new_pack_len;
953
uint no_parts, extra_growth;
954
DBUG_ENTER("translate_frm");
956
pack_data = (uchar*) table->getFrmData();
957
no_parts = table->getFragmentCount();
959
Add max 4 characters per partition to handle worst case
960
of mapping from single digit to 5-digit number.
961
Fairly future-proof, ok up to 99999 node groups.
963
extra_growth = no_parts * 4;
964
if (unpackfrm(&data, &data_len, pack_data))
968
if ((new_data = (char*) malloc(data_len + extra_growth)))
972
if (map_in_frm(new_data, (const char*)data, data_len, &new_data_len))
977
if (packfrm((uchar*) new_data, new_data_len,
978
&new_pack_data, &new_pack_len))
983
table->setFrm(new_pack_data, (Uint32)new_pack_len);
987
#include <signaldata/DictTabInfo.hpp>
990
BackupRestore::object(Uint32 type, const void * ptr)
995
NdbDictionary::Dictionary* dict = m_ndb->getDictionary();
997
case DictTabInfo::Tablespace:
999
NdbDictionary::Tablespace old(*(NdbDictionary::Tablespace*)ptr);
1001
Uint32 id = old.getObjectId();
1003
if (!m_no_restore_disk)
1005
NdbDictionary::LogfileGroup * lg = m_logfilegroups[old.getDefaultLogfileGroupId()];
1006
old.setDefaultLogfileGroup(* lg);
1007
info << "Creating tablespace: " << old.getName() << "..." << flush;
1008
int ret = dict->createTablespace(old);
1011
NdbError errobj= dict->getNdbError();
1012
info << "FAILED" << endl;
1013
err << "Create tablespace failed: " << old.getName() << ": " << errobj << endl;
1016
info << "done" << endl;
1019
NdbDictionary::Tablespace curr = dict->getTablespace(old.getName());
1020
NdbError errobj = dict->getNdbError();
1021
if ((int) errobj.classification == (int) ndberror_cl_none)
1023
NdbDictionary::Tablespace* currptr = new NdbDictionary::Tablespace(curr);
1024
NdbDictionary::Tablespace * null = 0;
1025
m_tablespaces.set(currptr, id, null);
1026
debug << "Retreived tablespace: " << currptr->getName()
1027
<< " oldid: " << id << " newid: " << currptr->getObjectId()
1028
<< " " << (void*)currptr << endl;
1033
err << "Failed to retrieve tablespace \"" << old.getName() << "\": "
1039
case DictTabInfo::LogfileGroup:
1041
NdbDictionary::LogfileGroup old(*(NdbDictionary::LogfileGroup*)ptr);
1043
Uint32 id = old.getObjectId();
1045
if (!m_no_restore_disk)
1047
info << "Creating logfile group: " << old.getName() << "..." << flush;
1048
int ret = dict->createLogfileGroup(old);
1051
NdbError errobj= dict->getNdbError();
1052
info << "FAILED" << endl;
1053
err << "Create logfile group failed: " << old.getName() << ": " << errobj << endl;
1056
info << "done" << endl;
1059
NdbDictionary::LogfileGroup curr = dict->getLogfileGroup(old.getName());
1060
NdbError errobj = dict->getNdbError();
1061
if ((int) errobj.classification == (int) ndberror_cl_none)
1063
NdbDictionary::LogfileGroup* currptr =
1064
new NdbDictionary::LogfileGroup(curr);
1065
NdbDictionary::LogfileGroup * null = 0;
1066
m_logfilegroups.set(currptr, id, null);
1067
debug << "Retreived logfile group: " << currptr->getName()
1068
<< " oldid: " << id << " newid: " << currptr->getObjectId()
1069
<< " " << (void*)currptr << endl;
1074
err << "Failed to retrieve logfile group \"" << old.getName() << "\": "
1080
case DictTabInfo::Datafile:
1082
if (!m_no_restore_disk)
1084
NdbDictionary::Datafile old(*(NdbDictionary::Datafile*)ptr);
1085
NdbDictionary::ObjectId objid;
1086
old.getTablespaceId(&objid);
1087
NdbDictionary::Tablespace * ts = m_tablespaces[objid.getObjectId()];
1088
debug << "Connecting datafile " << old.getPath()
1089
<< " to tablespace: oldid: " << objid.getObjectId()
1090
<< " newid: " << ts->getObjectId() << endl;
1091
old.setTablespace(* ts);
1092
info << "Creating datafile \"" << old.getPath() << "\"..." << flush;
1093
if (dict->createDatafile(old))
1095
NdbError errobj= dict->getNdbError();
1096
info << "FAILED" << endl;
1097
err << "Create datafile failed: " << old.getPath() << ": " << errobj << endl;
1100
info << "done" << endl;
1106
case DictTabInfo::Undofile:
1108
if (!m_no_restore_disk)
1110
NdbDictionary::Undofile old(*(NdbDictionary::Undofile*)ptr);
1111
NdbDictionary::ObjectId objid;
1112
old.getLogfileGroupId(&objid);
1113
NdbDictionary::LogfileGroup * lg = m_logfilegroups[objid.getObjectId()];
1114
debug << "Connecting undofile " << old.getPath()
1115
<< " to logfile group: oldid: " << objid.getObjectId()
1116
<< " newid: " << lg->getObjectId()
1117
<< " " << (void*)lg << endl;
1118
old.setLogfileGroup(* lg);
1119
info << "Creating undofile \"" << old.getPath() << "\"..." << flush;
1120
if (dict->createUndofile(old))
1122
NdbError errobj= dict->getNdbError();
1123
info << "FAILED" << endl;
1124
err << "Create undofile failed: " << old.getPath() << ": " << errobj << endl;
1127
info << "done" << endl;
1133
case DictTabInfo::HashMap:
1135
NdbDictionary::HashMap old(*(NdbDictionary::HashMap*)ptr);
1137
Uint32 id = old.getObjectId();
1141
int ret = dict->createHashMap(old);
1144
info << "Created hashmap: " << old.getName() << endl;
1148
NdbError errobj = dict->getNdbError();
1149
// We ignore schema already exists, this is fine
1150
if (errobj.code != 721)
1152
err << "Could not create hashmap \"" << old.getName() << "\": "
1159
NdbDictionary::HashMap curr;
1160
if (dict->getHashMap(curr, old.getName()) == 0)
1162
NdbDictionary::HashMap* currptr =
1163
new NdbDictionary::HashMap(curr);
1164
NdbDictionary::HashMap * null = 0;
1165
m_hashmaps.set(currptr, id, null);
1166
debug << "Retreived hashmap: " << currptr->getName()
1167
<< " oldid: " << id << " newid: " << currptr->getObjectId()
1168
<< " " << (void*)currptr << endl;
1172
NdbError errobj = dict->getNdbError();
1173
err << "Failed to retrieve hashmap \"" << old.getName() << "\": "
1180
err << "Unknown object type: " << type << endl;
1188
BackupRestore::has_temp_error(){
1189
return m_temp_error;
1193
BackupRestore::update_apply_status(const RestoreMetaData &metaData)
1195
if (!m_restore_epoch)
1199
unsigned apply_table_format= 0;
1201
m_ndb->setDatabaseName(NDB_REP_DB);
1202
m_ndb->setSchemaName("def");
1204
NdbDictionary::Dictionary *dict= m_ndb->getDictionary();
1205
const NdbDictionary::Table *ndbtab= dict->getTable(NDB_APPLY_TABLE);
1208
err << NDB_APPLY_TABLE << ": "
1209
<< dict->getNdbError() << endl;
1212
if (ndbtab->getColumn(0)->getType() == NdbDictionary::Column::Unsigned &&
1213
ndbtab->getColumn(1)->getType() == NdbDictionary::Column::Bigunsigned)
1215
if (ndbtab->getNoOfColumns() == 2)
1217
apply_table_format= 1;
1220
(ndbtab->getColumn(2)->getType() == NdbDictionary::Column::Varchar &&
1221
ndbtab->getColumn(3)->getType() == NdbDictionary::Column::Bigunsigned &&
1222
ndbtab->getColumn(4)->getType() == NdbDictionary::Column::Bigunsigned)
1224
apply_table_format= 2;
1227
if (apply_table_format == 0)
1229
err << NDB_APPLY_TABLE << " has wrong format\n";
1233
Uint32 server_id= 0;
1234
Uint64 epoch= Uint64(metaData.getStopGCP());
1235
Uint32 version= metaData.getNdbVersion();
1238
* Bug#XXX, stopGCP is not really stop GCP, but stopGCP - 1
1242
if (version >= NDBD_MICRO_GCP_63 ||
1243
(version >= NDBD_MICRO_GCP_62 && getMinor(version) == 2))
1245
epoch<<= 32; // Only gci_hi is saved...
1248
* Backup contains all epochs with those top bits,
1249
* so we indicate that with max setting
1251
epoch += (Uint64(1) << 32) - 1;
1255
char empty_string[1];
1257
NdbTransaction * trans= m_ndb->startTransaction();
1260
err << NDB_APPLY_TABLE << ": "
1261
<< m_ndb->getNdbError() << endl;
1264
NdbOperation * op= trans->getNdbOperation(ndbtab);
1267
err << NDB_APPLY_TABLE << ": "
1268
<< trans->getNdbError() << endl;
1271
if (op->writeTuple() ||
1272
op->equal(0u, (const char *)&server_id, sizeof(server_id)) ||
1273
op->setValue(1u, (const char *)&epoch, sizeof(epoch)))
1275
err << NDB_APPLY_TABLE << ": "
1276
<< op->getNdbError() << endl;
1279
if ((apply_table_format == 2) &&
1280
(op->setValue(2u, (const char *)&empty_string, 1) ||
1281
op->setValue(3u, (const char *)&zero, sizeof(zero)) ||
1282
op->setValue(4u, (const char *)&zero, sizeof(zero))))
1284
err << NDB_APPLY_TABLE << ": "
1285
<< op->getNdbError() << endl;
1288
if (trans->execute(NdbTransaction::Commit))
1290
err << NDB_APPLY_TABLE << ": "
1291
<< trans->getNdbError() << endl;
1296
m_ndb->closeTransaction(trans);
1301
BackupRestore::report_started(unsigned backup_id, unsigned node_id)
1306
data[0]= NDB_LE_RestoreStarted;
1309
Ndb_internal::send_event_report(false /* has lock */, m_ndb, data, 3);
1315
BackupRestore::report_meta_data(unsigned backup_id, unsigned node_id)
1320
data[0]= NDB_LE_RestoreMetaData;
1323
data[3]= m_n_tables;
1324
data[4]= m_n_tablespace;
1325
data[5]= m_n_logfilegroup;
1326
data[6]= m_n_datafile;
1327
data[7]= m_n_undofile;
1328
Ndb_internal::send_event_report(false /* has lock */, m_ndb, data, 8);
1333
BackupRestore::report_data(unsigned backup_id, unsigned node_id)
1338
data[0]= NDB_LE_RestoreData;
1341
data[3]= m_dataCount & 0xFFFFFFFF;
1343
data[5]= (Uint32)(m_dataBytes & 0xFFFFFFFF);
1344
data[6]= (Uint32)((m_dataBytes >> 32) & 0xFFFFFFFF);
1345
Ndb_internal::send_event_report(false /* has lock */, m_ndb, data, 7);
1351
BackupRestore::report_log(unsigned backup_id, unsigned node_id)
1356
data[0]= NDB_LE_RestoreLog;
1359
data[3]= m_logCount & 0xFFFFFFFF;
1361
data[5]= (Uint32)(m_logBytes & 0xFFFFFFFF);
1362
data[6]= (Uint32)((m_logBytes >> 32) & 0xFFFFFFFF);
1363
Ndb_internal::send_event_report(false /* has lock */, m_ndb, data, 7);
1369
BackupRestore::report_completed(unsigned backup_id, unsigned node_id)
1374
data[0]= NDB_LE_RestoreCompleted;
1377
Ndb_internal::send_event_report(false /* has lock */, m_ndb, data, 3);
1383
BackupRestore::column_compatible_check(const char* tableName,
1384
const NDBCOL* backupCol,
1385
const NDBCOL* dbCol)
1387
if (backupCol->equal(*dbCol))
1390
/* Something is different between the columns, but some differences don't
1392
* Investigate which parts are different, and inform user
1394
bool similarEnough = true;
1396
/* We check similar things to NdbColumnImpl::equal() here */
1397
if (strcmp(backupCol->getName(), dbCol->getName()) != 0)
1399
info << "Column " << tableName << "." << backupCol->getName()
1400
<< " has different name in DB (" << dbCol->getName() << ")"
1402
similarEnough = false;
1405
if (backupCol->getType() != dbCol->getType())
1407
info << "Column " << tableName << "." << backupCol->getName()
1408
<< (" has different type in DB; promotion or lossy type conversion"
1409
" (demotion, signed/unsigned) may be required.") << endl;
1410
similarEnough = false;
1413
if (backupCol->getPrimaryKey() != dbCol->getPrimaryKey())
1415
info << "Column " << tableName << "." << backupCol->getName()
1416
<< (dbCol->getPrimaryKey()?" is":" is not")
1417
<< " a primary key in the DB." << endl;
1418
similarEnough = false;
1422
if (backupCol->getPrimaryKey())
1424
if (backupCol->getDistributionKey() != dbCol->getDistributionKey())
1426
info << "Column " << tableName << "." << backupCol->getName()
1427
<< (dbCol->getDistributionKey()?" is":" is not")
1428
<< " a distribution key in the DB." << endl;
1429
/* Not a problem for restore though */
1434
if (backupCol->getNullable() != dbCol->getNullable())
1436
info << "Column " << tableName << "." << backupCol->getName()
1437
<< (dbCol->getNullable()?" is":" is not")
1438
<< " nullable in the DB." << endl;
1439
similarEnough = false;
1442
if (backupCol->getPrecision() != dbCol->getPrecision())
1444
info << "Column " << tableName << "." << backupCol->getName()
1445
<< " precision is different in the DB" << endl;
1446
similarEnough = false;
1449
if (backupCol->getScale() != dbCol->getScale())
1451
info << "Column " << tableName << "." << backupCol->getName()
1452
<< " scale is different in the DB" << endl;
1453
similarEnough = false;
1456
if (backupCol->getLength() != dbCol->getLength())
1458
info << "Column " << tableName << "." << backupCol->getName()
1459
<< " length is different in the DB" << endl;
1460
similarEnough = false;
1463
if (backupCol->getCharset() != dbCol->getCharset())
1465
info << "Column " << tableName << "." << backupCol->getName()
1466
<< " charset is different in the DB" << endl;
1467
similarEnough = false;
1470
if (backupCol->getAutoIncrement() != dbCol->getAutoIncrement())
1472
info << "Column " << tableName << "." << backupCol->getName()
1473
<< (dbCol->getAutoIncrement()?" is":" is not")
1474
<< " AutoIncrementing in the DB" << endl;
1475
/* TODO : Can this be ignored? */
1476
similarEnough = false;
1480
unsigned int backupDefaultLen, dbDefaultLen;
1481
const void *backupDefaultPtr, *dbDefaultPtr;
1482
backupDefaultPtr = backupCol->getDefaultValue(&backupDefaultLen);
1483
dbDefaultPtr = dbCol->getDefaultValue(&dbDefaultLen);
1485
if ((backupDefaultLen != dbDefaultLen) ||
1486
(memcmp(backupDefaultPtr, dbDefaultPtr, backupDefaultLen) != 0))
1488
info << "Column " << tableName << "." << backupCol->getName()
1489
<< " Default value is different in the DB" << endl;
1490
/* This doesn't matter */
1494
if (backupCol->getArrayType() != dbCol->getArrayType())
1496
info << "Column " << tableName << "." << backupCol->getName()
1497
<< " ArrayType is different in the DB" << endl;
1498
similarEnough = false;
1501
if (backupCol->getStorageType() != dbCol->getStorageType())
1503
info << "Column " << tableName << "." << backupCol->getName()
1504
<< " Storagetype is different in the DB" << endl;
1505
/* This doesn't matter */
1508
if (backupCol->getBlobVersion() != dbCol->getBlobVersion())
1510
info << "Column " << tableName << "." << backupCol->getName()
1511
<< " Blob version is different in the DB" << endl;
1512
similarEnough = false;
1515
if (backupCol->getDynamic() != dbCol->getDynamic())
1517
info << "Column " << tableName << "." << backupCol->getName()
1518
<< (dbCol->getDynamic()?" is":" is not")
1519
<< " Dynamic in the DB" << endl;
1520
/* This doesn't matter */
1524
info << " Difference(s) will be ignored during restore." << endl;
1526
info << " Difference(s) cannot be ignored. Cannot restore this column as is." << endl;
1528
return similarEnough;
1532
BackupRestore::table_compatible_check(const TableS & tableS)
1537
const char *tablename = tableS.getTableName();
1539
if(tableS.m_dictTable == NULL){
1540
ndbout<<"Table %s has no m_dictTable " << tablename << endl;
1544
* Ignore blob tables
1546
if(match_blob(tablename) >= 0)
1549
const NdbTableImpl & tmptab = NdbTableImpl::getImpl(* tableS.m_dictTable);
1550
if ((int) tmptab.m_indexType != (int) NdbDictionary::Index::Undefined){
1554
BaseString db_name, schema_name, table_name;
1555
if (!dissect_table_name(tablename, db_name, schema_name, table_name)) {
1558
check_rewrite_database(db_name);
1560
m_ndb->setDatabaseName(db_name.c_str());
1561
m_ndb->setSchemaName(schema_name.c_str());
1563
NdbDictionary::Dictionary* dict = m_ndb->getDictionary();
1564
const NdbDictionary::Table* tab = dict->getTable(table_name.c_str());
1566
err << "Unable to find table: " << table_name << endl;
1571
* remap column(s) based on column-names
1573
for (int i = 0; i<tableS.m_dictTable->getNoOfColumns(); i++)
1575
AttributeDesc * attr_desc = tableS.getAttributeDesc(i);
1576
const NDBCOL * col_in_backup = tableS.m_dictTable->getColumn(i);
1577
const NDBCOL * col_in_kernel = tab->getColumn(col_in_backup->getName());
1579
if (col_in_kernel == 0)
1581
if ((m_tableChangesMask & TCM_EXCLUDE_MISSING_COLUMNS) == 0)
1583
ndbout << "Missing column("
1584
<< tableS.m_dictTable->getName() << "."
1585
<< col_in_backup->getName()
1586
<< ") in DB and exclude-missing-columns not specified" << endl;
1590
info << "Column in backup ("
1591
<< tableS.m_dictTable->getName() << "."
1592
<< col_in_backup->getName()
1593
<< ") missing in DB. Excluding column from restore." << endl;
1595
attr_desc->m_exclude = true;
1599
attr_desc->attrId = col_in_kernel->getColumnNo();
1603
for (int i = 0; i<tab->getNoOfColumns(); i++)
1605
const NDBCOL * col_in_kernel = tab->getColumn(i);
1606
const NDBCOL * col_in_backup =
1607
tableS.m_dictTable->getColumn(col_in_kernel->getName());
1609
if (col_in_backup == 0)
1611
if ((m_tableChangesMask & TCM_EXCLUDE_MISSING_COLUMNS) == 0)
1613
ndbout << "Missing column("
1614
<< tableS.m_dictTable->getName() << "."
1615
<< col_in_kernel->getName()
1616
<< ") in backup and exclude-missing-columns not specified"
1622
* only nullable or defaulted non primary key columns can be missing from backup
1625
if (col_in_kernel->getPrimaryKey() ||
1626
((col_in_kernel->getNullable() == false) &&
1627
(col_in_kernel->getDefaultValue() == NULL)))
1629
ndbout << "Missing column("
1630
<< tableS.m_dictTable->getName() << "."
1631
<< col_in_kernel->getName()
1632
<< ") in backup is primary key or not nullable or defaulted in DB"
1637
info << "Column in DB ("
1638
<< tableS.m_dictTable->getName() << "."
1639
<< col_in_kernel->getName()
1640
<< ") missing in Backup. Will be set to "
1641
<< ((col_in_kernel->getDefaultValue() == NULL)?"Null":"Default value")
1646
AttrCheckCompatFunc attrCheckCompatFunc = NULL;
1647
for(int i = 0; i<tableS.m_dictTable->getNoOfColumns(); i++)
1649
AttributeDesc * attr_desc = tableS.getAttributeDesc(i);
1650
if (attr_desc->m_exclude)
1653
const NDBCOL * col_in_kernel = tab->getColumn(attr_desc->attrId);
1654
const NDBCOL * col_in_backup = tableS.m_dictTable->getColumn(i);
1656
if(column_compatible_check(tablename,
1663
NDBCOL::Type type_in_backup = col_in_backup->getType();
1664
NDBCOL::Type type_in_kernel = col_in_kernel->getType();
1665
attrCheckCompatFunc = get_attr_check_compatability(type_in_backup,
1668
= (attrCheckCompatFunc == NULL ? ACT_UNSUPPORTED
1669
: attrCheckCompatFunc(*col_in_backup, *col_in_kernel));
1671
case ACT_UNSUPPORTED:
1673
err << "Table: "<< tablename
1674
<< " column: " << col_in_backup->getName()
1675
<< " incompatible with kernel's definition" << endl;
1678
case ACT_PRESERVING:
1679
if ((m_tableChangesMask & TCM_ATTRIBUTE_PROMOTION) == 0)
1681
err << "Table: "<< tablename
1682
<< " column: " << col_in_backup->getName()
1683
<< " promotable to kernel's definition but option"
1684
<< " promote-attributes not specified" << endl;
1689
if ((m_tableChangesMask & TCM_ATTRIBUTE_DEMOTION) == 0)
1691
err << "Table: "<< tablename
1692
<< " column: " << col_in_backup->getName()
1693
<< " convertable to kernel's definition but option"
1694
<< " lossy-conversions not specified" << endl;
1699
err << "internal error: illegal value of compat = " << compat << endl;
1704
attr_desc->convertFunc = get_convert_func(type_in_backup,
1706
Uint32 m_attrSize = NdbColumnImpl::getImpl(*col_in_kernel).m_attrSize;
1707
Uint32 m_arraySize = NdbColumnImpl::getImpl(*col_in_kernel).m_arraySize;
1709
// use a char_n_padding_struct to pass length information to convert()
1710
if (type_in_backup == NDBCOL::Char ||
1711
type_in_backup == NDBCOL::Binary ||
1712
type_in_backup == NDBCOL::Bit ||
1713
type_in_backup == NDBCOL::Varchar ||
1714
type_in_backup == NDBCOL::Longvarchar ||
1715
type_in_backup == NDBCOL::Varbinary ||
1716
type_in_backup == NDBCOL::Longvarbinary)
1718
unsigned int size = sizeof(struct char_n_padding_struct) +
1719
m_attrSize * m_arraySize;
1720
struct char_n_padding_struct *s = (struct char_n_padding_struct *)
1724
err << "No more memory available!" << endl;
1727
s->n_old = (attr_desc->size * attr_desc->arraySize) / 8;
1728
s->n_new = m_attrSize * m_arraySize;
1729
memset(s->new_row, 0 , m_attrSize * m_arraySize + 2);
1730
attr_desc->parameter = s;
1734
unsigned int size = m_attrSize * m_arraySize;
1735
attr_desc->parameter = malloc(size + 2);
1736
if (!attr_desc->parameter)
1738
err << "No more memory available!" << endl;
1741
memset(attr_desc->parameter, 0, size + 2);
1744
info << "Data for column "
1746
<< col_in_backup->getName()
1747
<< " will be converted from Backup type into DB type." << endl;
1754
BackupRestore::createSystable(const TableS & tables){
1755
if (!m_restore && !m_restore_meta && !m_restore_epoch)
1757
const char *tablename = tables.getTableName();
1759
if( strcmp(tablename, NDB_REP_DB "/def/" NDB_APPLY_TABLE) != 0 &&
1760
strcmp(tablename, NDB_REP_DB "/def/" NDB_SCHEMA_TABLE) != 0 )
1765
BaseString db_name, schema_name, table_name;
1766
if (!dissect_table_name(tablename, db_name, schema_name, table_name)) {
1769
// do not rewrite database for system tables:
1770
// check_rewrite_database(db_name);
1772
m_ndb->setDatabaseName(db_name.c_str());
1773
m_ndb->setSchemaName(schema_name.c_str());
1775
NdbDictionary::Dictionary* dict = m_ndb->getDictionary();
1776
if( dict->getTable(table_name.c_str()) != NULL ){
1779
return table(tables);
1783
BackupRestore::table(const TableS & table){
1784
if (!m_restore && !m_restore_meta && !m_rebuild_indexes && !m_disable_indexes)
1787
const char * name = table.getTableName();
1790
* Ignore blob tables
1792
if(match_blob(name) >= 0)
1795
const NdbTableImpl & tmptab = NdbTableImpl::getImpl(* table.m_dictTable);
1796
if ((int) tmptab.m_indexType != (int) NdbDictionary::Index::Undefined){
1797
m_indexes.push_back(table.m_dictTable);
1801
BaseString db_name, schema_name, table_name;
1802
if (!dissect_table_name(name, db_name, schema_name, table_name)) {
1805
check_rewrite_database(db_name);
1807
m_ndb->setDatabaseName(db_name.c_str());
1808
m_ndb->setSchemaName(schema_name.c_str());
1810
NdbDictionary::Dictionary* dict = m_ndb->getDictionary();
1813
NdbDictionary::Table copy(*table.m_dictTable);
1815
copy.setName(table_name.c_str());
1817
if (copy.getTablespace(&id))
1819
debug << "Connecting " << name << " to tablespace oldid: " << id << flush;
1820
NdbDictionary::Tablespace* ts = m_tablespaces[id];
1821
debug << " newid: " << ts->getObjectId() << endl;
1822
copy.setTablespace(* ts);
1825
if (copy.getFragmentType() == NdbDictionary::Object::HashMapPartition)
1828
if (copy.getHashMap(&id))
1830
NdbDictionary::HashMap * hm = m_hashmaps[id];
1831
copy.setHashMap(* hm);
1834
else if (copy.getDefaultNoPartitionsFlag())
1837
Table was defined with default number of partitions. We can restore
1838
it with whatever is the default in this cluster.
1839
We use the max_rows parameter in calculating the default number.
1841
Uint32 no_nodes = m_cluster_connection->no_db_nodes();
1842
copy.setFragmentCount(get_no_fragments(copy.getMaxRows(),
1844
set_default_nodegroups(©);
1849
Table was defined with specific number of partitions. It should be
1850
restored with the same number of partitions. It will either be
1851
restored in the same node groups as when backup was taken or by
1852
using a node group map supplied to the ndb_restore program.
1854
Vector<Uint32> new_array;
1855
Uint16 no_parts = copy.getFragmentCount();
1856
new_array.assign(copy.getFragmentData(), no_parts);
1857
if (map_nodegroups(new_array.getBase(), no_parts))
1859
if (translate_frm(©))
1861
err << "Create table " << table.getTableName() << " failed: ";
1862
err << "Translate frm error" << endl;
1866
copy.setFragmentData(new_array.getBase(), no_parts);
1870
* Force of varpart was introduced in 5.1.18, telco 6.1.7 and 6.2.1
1871
* Since default from mysqld is to add force of varpart (disable with
1872
* ROW_FORMAT=FIXED) we force varpart onto tables when they are restored
1873
* from backups taken with older versions. This will be wrong if
1874
* ROW_FORMAT=FIXED was used on original table, however the likelyhood of
1875
* this is low, since ROW_FORMAT= was a NOOP in older versions.
1878
if (table.getBackupVersion() < MAKE_VERSION(5,1,18))
1879
copy.setForceVarPart(true);
1880
else if (getMajor(table.getBackupVersion()) == 6 &&
1881
(table.getBackupVersion() < MAKE_VERSION(6,1,7) ||
1882
table.getBackupVersion() == MAKE_VERSION(6,2,0)))
1883
copy.setForceVarPart(true);
1886
update min and max rows to reflect the table, this to
1887
ensure that memory is allocated properly in the ndb kernel
1889
copy.setMinRows(table.getNoOfRecords());
1890
if (table.getNoOfRecords() > copy.getMaxRows())
1892
copy.setMaxRows(table.getNoOfRecords());
1895
NdbTableImpl &tableImpl = NdbTableImpl::getImpl(copy);
1896
if (table.getBackupVersion() < MAKE_VERSION(5,1,0) && !m_no_upgrade){
1897
for(int i= 0; i < copy.getNoOfColumns(); i++)
1899
NdbDictionary::Column::Type t = copy.getColumn(i)->getType();
1901
if (t == NdbDictionary::Column::Varchar ||
1902
t == NdbDictionary::Column::Varbinary)
1903
tableImpl.getColumn(i)->setArrayType(NdbDictionary::Column::ArrayTypeShortVar);
1904
if (t == NdbDictionary::Column::Longvarchar ||
1905
t == NdbDictionary::Column::Longvarbinary)
1906
tableImpl.getColumn(i)->setArrayType(NdbDictionary::Column::ArrayTypeMediumVar);
1910
if (dict->createTable(copy) == -1)
1912
err << "Create table `" << table.getTableName() << "` failed: "
1913
<< dict->getNdbError() << endl;
1914
if (dict->getNdbError().code == 771)
1917
The user on the cluster where the backup was created had specified
1918
specific node groups for partitions. Some of these node groups
1919
didn't exist on this cluster. We will warn the user of this and
1920
inform him of his option.
1922
err << "The node groups defined in the table didn't exist in this";
1923
err << " cluster." << endl << "There is an option to use the";
1924
err << " the parameter ndb-nodegroup-map to define a mapping from";
1925
err << endl << "the old nodegroups to new nodegroups" << endl;
1930
info << "Successfully restored table `"
1931
<< table.getTableName() << "`" << endl;
1934
const NdbDictionary::Table* tab = dict->getTable(table_name.c_str());
1936
err << "Unable to find table: `" << table_name << "`" << endl;
1941
if (tab->getFrmData())
1943
// a MySQL Server table is restored, thus an event should be created
1944
BaseString event_name("REPL$");
1945
event_name.append(db_name.c_str());
1946
event_name.append("/");
1947
event_name.append(table_name.c_str());
1949
NdbDictionary::Event my_event(event_name.c_str());
1950
my_event.setTable(*tab);
1951
my_event.addTableEvent(NdbDictionary::Event::TE_ALL);
1952
my_event.setReport(NdbDictionary::Event::ER_DDL);
1954
// add all columns to the event
1955
bool has_blobs = false;
1956
for(int a= 0; a < tab->getNoOfColumns(); a++)
1958
my_event.addEventColumn(a);
1959
NdbDictionary::Column::Type t = tab->getColumn(a)->getType();
1960
if (t == NdbDictionary::Column::Blob ||
1961
t == NdbDictionary::Column::Text)
1965
my_event.mergeEvents(true);
1967
while ( dict->createEvent(my_event) ) // Add event to database
1969
if (dict->getNdbError().classification == NdbError::SchemaObjectExists)
1971
info << "Event for table " << table.getTableName()
1972
<< " already exists, removing.\n";
1973
if (!dict->dropEvent(my_event.getName(), 1))
1976
err << "Create table event for " << table.getTableName() << " failed: "
1977
<< dict->getNdbError() << endl;
1978
dict->dropTable(table_name.c_str());
1982
info << "Successfully restored table event " << event_name << endl ;
1985
const NdbDictionary::Table* null = 0;
1986
m_new_tables.fill(table.m_dictTable->getTableId(), null);
1987
m_new_tables[table.m_dictTable->getTableId()] = tab;
1995
BackupRestore::endOfTables(){
1996
if(!m_restore_meta && !m_rebuild_indexes && !m_disable_indexes)
1999
NdbDictionary::Dictionary* dict = m_ndb->getDictionary();
2000
for(size_t i = 0; i<m_indexes.size(); i++){
2001
NdbTableImpl & indtab = NdbTableImpl::getImpl(* m_indexes[i]);
2003
BaseString db_name, schema_name, table_name;
2004
if (!dissect_table_name(indtab.m_primaryTable.c_str(),
2005
db_name, schema_name, table_name)) {
2008
check_rewrite_database(db_name);
2010
m_ndb->setDatabaseName(db_name.c_str());
2011
m_ndb->setSchemaName(schema_name.c_str());
2013
const NdbDictionary::Table * prim = dict->getTable(table_name.c_str());
2015
err << "Unable to find base table `" << table_name
2017
<< indtab.getName() << "`" << endl;
2018
if (ga_skip_broken_objects)
2024
NdbTableImpl& base = NdbTableImpl::getImpl(*prim);
2026
Vector<BaseString> split_idx;
2028
BaseString tmp(indtab.getName());
2029
if (tmp.split(split_idx, "/") != 4)
2031
err << "Invalid index name format `" << indtab.getName() << "`" << endl;
2035
if(NdbDictInterface::create_index_obj_from_table(&idx, &indtab, &base))
2037
err << "Failed to create index `" << split_idx[3]
2038
<< "` on " << table_name << endl;
2041
idx->setName(split_idx[3].c_str());
2042
if (m_restore_meta && !m_disable_indexes && !m_rebuild_indexes)
2044
if (dict->createIndex(* idx) != 0)
2047
err << "Failed to create index `" << split_idx[3].c_str()
2048
<< "` on `" << table_name << "`" << endl
2049
<< dict->getNdbError() << endl;
2053
info << "Successfully created index `" << split_idx[3].c_str()
2054
<< "` on `" << table_name << "`" << endl;
2056
else if (m_disable_indexes)
2058
int res = dict->dropIndex(idx->getName(), prim->getName());
2061
info << "Dropped index `" << split_idx[3].c_str()
2062
<< "` on `" << table_name << "`" << endl;
2065
Uint32 id = prim->getObjectId();
2066
if (m_index_per_table.size() <= id)
2068
Vector<NdbDictionary::Index*> tmp;
2069
m_index_per_table.fill(id + 1, tmp);
2071
Vector<NdbDictionary::Index*> & list = m_index_per_table[id];
2072
list.push_back(idx);
2077
void BackupRestore::tuple(const TupleS & tup, Uint32 fragmentId)
2079
const TableS * tab = tup.getTable();
2084
while (m_free_callback == 0)
2086
assert(m_transactions == m_parallelism);
2087
// send-poll all transactions
2088
// close transaction is done in callback
2089
m_ndb->sendPollNdb(3000, 1);
2092
restore_callback_t * cb = m_free_callback;
2098
cb->fragId = fragmentId;
2099
cb->tup = tup; // must do copy!
2101
if (tab->isSYSTAB_0())
2103
tuple_SYSTAB_0(cb, *tab);
2107
m_free_callback = cb->next;
2112
void BackupRestore::tuple_a(restore_callback_t *cb)
2114
Uint32 partition_id = cb->fragId;
2116
while (cb->retries < 10)
2119
* start transactions
2121
cb->connection = m_ndb->startTransaction();
2122
if (cb->connection == NULL)
2124
if (errorHandler(cb))
2126
m_ndb->sendPollNdb(3000, 1);
2129
err << "Cannot start transaction" << endl;
2133
const TupleS &tup = cb->tup;
2134
const NdbDictionary::Table * table = get_table(tup.getTable()->m_dictTable);
2136
NdbOperation * op = cb->connection->getNdbOperation(table);
2140
if (errorHandler(cb))
2142
err << "Cannot get operation: " << cb->connection->getNdbError() << endl;
2146
if (op->writeTuple() == -1)
2148
if (errorHandler(cb))
2150
err << "Error defining op: " << cb->connection->getNdbError() << endl;
2156
if (table->getFragmentType() == NdbDictionary::Object::UserDefined)
2158
if (table->getDefaultNoPartitionsFlag())
2161
This can only happen for HASH partitioning with
2162
user defined hash function where user hasn't
2163
specified the number of partitions and we
2164
have to calculate it. We use the hash value
2165
stored in the record to calculate the partition
2168
int i = tup.getNoOfAttributes() - 1;
2169
const AttributeData *attr_data = tup.getData(i);
2170
Uint32 hash_value = *attr_data->u_int32_value;
2171
op->setPartitionId(get_part_id(table, hash_value));
2176
Either RANGE or LIST (with or without subparts)
2177
OR HASH partitioning with user defined hash
2178
function but with fixed set of partitions.
2180
op->setPartitionId(partition_id);
2184
for (int j = 0; j < 2; j++)
2186
for (int i = 0; i < tup.getNoOfAttributes(); i++)
2188
AttributeDesc * attr_desc = tup.getDesc(i);
2189
const AttributeData * attr_data = tup.getData(i);
2190
int size = attr_desc->size;
2191
int arraySize = attr_desc->arraySize;
2192
char * dataPtr = attr_data->string_value;
2195
if (attr_desc->m_exclude)
2198
if (!attr_data->null)
2200
const unsigned char * src = (const unsigned char *)dataPtr;
2201
switch(attr_desc->m_column->getType()){
2202
case NdbDictionary::Column::Varchar:
2203
case NdbDictionary::Column::Varbinary:
2204
length = src[0] + 1;
2206
case NdbDictionary::Column::Longvarchar:
2207
case NdbDictionary::Column::Longvarbinary:
2208
length = src[0] + (src[1] << 8) + 2;
2211
length = attr_data->size;
2215
if (j == 0 && tup.getTable()->have_auto_inc(i))
2216
tup.getTable()->update_max_auto_val(dataPtr,size*arraySize);
2218
if (attr_desc->convertFunc)
2220
if ((attr_desc->m_column->getPrimaryKey() && j == 0) ||
2221
(j == 1 && !attr_data->null))
2223
bool truncated = true; // assume data truncation until overridden
2224
dataPtr = (char*)attr_desc->convertFunc(dataPtr,
2225
attr_desc->parameter,
2229
err << "Error: Convert data failed when restoring tuples!" << endl;
2234
// wl5421: option to report data truncation on tuple of desired
2235
//err << "====== data truncation detected for column: "
2236
// << attr_desc->m_column->getName() << endl;
2237
attr_desc->truncation_detected = true;
2242
if (attr_desc->m_column->getPrimaryKey())
2244
if (j == 1) continue;
2245
ret = op->equal(attr_desc->attrId, dataPtr, length);
2249
if (j == 0) continue;
2250
if (attr_data->null)
2251
ret = op->setValue(attr_desc->attrId, NULL, 0);
2253
ret = op->setValue(attr_desc->attrId, dataPtr, length);
2256
ndbout_c("Column: %d type %d %d %d %d",i,
2257
attr_desc->m_column->getType(),
2258
size, arraySize, length);
2268
if (errorHandler(cb))
2270
err << "Error defining op: " << cb->connection->getNdbError() << endl;
2276
op->setAnyValue(NDB_ANYVALUE_FOR_NOLOGGING);
2279
// Prepare transaction (the transaction is NOT yet sent to NDB)
2280
cb->n_bytes= n_bytes;
2281
cb->connection->executeAsynchPrepare(NdbTransaction::Commit,
2286
err << "Retried transaction " << cb->retries << " times.\nLast error"
2287
<< m_ndb->getNdbError(cb->error_code) << endl
2288
<< "...Unable to recover from errors. Exiting..." << endl;
2292
void BackupRestore::tuple_SYSTAB_0(restore_callback_t *cb,
2295
const TupleS & tup = cb->tup;
2299
if (tab.get_auto_data(tup, &syskey, &nextid))
2302
We found a valid auto_increment value in SYSTAB_0
2303
where syskey is a table_id and nextid is next auto_increment
2306
if (restoreAutoIncrement(cb, syskey, nextid) == -1)
2311
int BackupRestore::restoreAutoIncrement(restore_callback_t *cb,
2312
Uint32 tableId, Uint64 value)
2315
Restore the auto_increment value found in SYSTAB_0 from
2316
backup. First map the old table id to the new table while
2317
also checking that it is an actual table will some auto_increment
2318
column. Note that the SYSTAB_0 table in the backup can contain
2319
stale information from dropped tables.
2322
const NdbDictionary::Table* tab = (tableId < m_new_tables.size())? m_new_tables[tableId] : NULL;
2323
if (tab && tab->getNoOfAutoIncrementColumns() > 0)
2326
Write the auto_increment value back into SYSTAB_0.
2327
This is done in a separate transaction and could possibly
2328
fail, so we retry if a temporary error is received.
2330
while (cb->retries < 10)
2332
if ((result = m_ndb->setAutoIncrementValue(tab, value, false) == -1))
2334
if (errorHandler(cb))
2345
void BackupRestore::cback(int result, restore_callback_t *cb)
2352
* Error. temporary or permanent?
2354
if (errorHandler(cb))
2355
tuple_a(cb); // retry
2358
err << "Restore: Failed to restore data due to a unrecoverable error. Exiting..." << endl;
2365
* OK! close transaction
2367
m_ndb->closeTransaction(cb->connection);
2369
cb->next= m_free_callback;
2370
m_free_callback= cb;
2371
m_dataBytes+= cb->n_bytes;
2377
* returns true if is recoverable,
2378
* Error handling based on hugo
2379
* false if it is an error that generates an abort.
2381
bool BackupRestore::errorHandler(restore_callback_t *cb)
2386
error= cb->connection->getNdbError();
2387
m_ndb->closeTransaction(cb->connection);
2392
error= m_ndb->getNdbError();
2395
Uint32 sleepTime = 100 + cb->retries * 300;
2398
cb->error_code = error.code;
2400
switch(error.status)
2402
case NdbError::Success:
2403
err << "Success error: " << error << endl;
2407
case NdbError::TemporaryError:
2408
err << "Temporary error: " << error << endl;
2409
m_temp_error = true;
2410
NdbSleep_MilliSleep(sleepTime);
2414
case NdbError::UnknownResult:
2415
err << "Unknown: " << error << endl;
2420
case NdbError::PermanentError:
2422
err << "Permanent: " << error << endl;
2425
err << "No error status" << endl;
2429
void BackupRestore::exitHandler()
2432
NDBT_ProgramExit(NDBT_FAILED);
2438
BackupRestore::tuple_free()
2443
// Poll all transactions
2444
while (m_transactions)
2446
m_ndb->sendPollNdb(3000);
2451
BackupRestore::endOfTuples()
2457
static bool use_part_id(const NdbDictionary::Table *table)
2459
if (table->getDefaultNoPartitionsFlag() &&
2460
(table->getFragmentType() == NdbDictionary::Object::UserDefined))
2467
static Uint32 get_part_id(const NdbDictionary::Table *table,
2470
Uint32 no_frags = table->getFragmentCount();
2472
if (table->getLinearFlag())
2476
while (no_frags > mask) mask <<= 1;
2478
part_id = hash_value & mask;
2479
if (part_id >= no_frags)
2480
part_id = hash_value & (mask >> 1);
2484
return (hash_value % no_frags);
2489
NdbTransaction* pTrans;
2490
TransGuard(NdbTransaction* p) : pTrans(p) {}
2491
~TransGuard() { if (pTrans) pTrans->close();}
2495
BackupRestore::logEntry(const LogEntry & tup)
2506
err << "execute failed: " << errobj << endl;
2509
else if (retries > 0)
2511
NdbSleep_MilliSleep(100 + (retries - 1) * 100);
2516
NdbTransaction * trans = m_ndb->startTransaction();
2519
errobj = m_ndb->getNdbError();
2520
if (errobj.status == NdbError::TemporaryError)
2524
err << "Cannot start transaction: " << errobj << endl;
2528
TransGuard g(trans);
2529
const NdbDictionary::Table * table = get_table(tup.m_table->m_dictTable);
2530
NdbOperation * op = trans->getNdbOperation(table);
2533
err << "Cannot get operation: " << trans->getNdbError() << endl;
2540
case LogEntry::LE_INSERT:
2541
check = op->insertTuple();
2543
case LogEntry::LE_UPDATE:
2544
check = op->updateTuple();
2546
case LogEntry::LE_DELETE:
2547
check = op->deleteTuple();
2550
err << "Log entry has wrong operation type."
2557
err << "Error defining op: " << trans->getNdbError() << endl;
2561
if (table->getFragmentType() == NdbDictionary::Object::UserDefined)
2563
if (table->getDefaultNoPartitionsFlag())
2565
const AttributeS * attr = tup[tup.size()-1];
2566
Uint32 hash_value = *(Uint32*)attr->Data.string_value;
2567
op->setPartitionId(get_part_id(table, hash_value));
2570
op->setPartitionId(tup.m_frag_id);
2575
for (Uint32 i= 0; i < tup.size(); i++)
2577
const AttributeS * attr = tup[i];
2578
int size = attr->Desc->size;
2579
int arraySize = attr->Desc->arraySize;
2580
const char * dataPtr = attr->Data.string_value;
2582
if (attr->Desc->m_exclude)
2585
if (tup.m_table->have_auto_inc(attr->Desc->attrId))
2586
tup.m_table->update_max_auto_val(dataPtr,size*arraySize);
2588
const Uint32 length = (size / 8) * arraySize;
2591
if (attr->Desc->convertFunc)
2593
bool truncated = true; // assume data truncation until overridden
2594
dataPtr = (char*)attr->Desc->convertFunc(dataPtr,
2595
attr->Desc->parameter,
2599
err << "Error: Convert data failed when restoring tuples!" << endl;
2604
// wl5421: option to report data truncation on tuple of desired
2605
//err << "****** data truncation detected for column: "
2606
// << attr->Desc->m_column->getName() << endl;
2607
attr->Desc->truncation_detected = true;
2611
if (attr->Desc->m_column->getPrimaryKey())
2613
if(!keys.get(attr->Desc->attrId))
2615
keys.set(attr->Desc->attrId);
2616
check= op->equal(attr->Desc->attrId, dataPtr, length);
2620
check= op->setValue(attr->Desc->attrId, dataPtr, length);
2624
err << "Error defining op: " << trans->getNdbError() << endl;
2631
op->setAnyValue(NDB_ANYVALUE_FOR_NOLOGGING);
2633
const int ret = trans->execute(NdbTransaction::Commit);
2636
// Both insert update and delete can fail during log running
2639
errobj= trans->getNdbError();
2640
if (errobj.status == NdbError::TemporaryError)
2645
case LogEntry::LE_INSERT:
2646
if(errobj.status == NdbError::PermanentError &&
2647
errobj.classification == NdbError::ConstraintViolation)
2650
case LogEntry::LE_UPDATE:
2651
case LogEntry::LE_DELETE:
2652
if(errobj.status == NdbError::PermanentError &&
2653
errobj.classification == NdbError::NoDataFound)
2659
err << "execute failed: " << errobj << endl;
2664
m_logBytes+= n_bytes;
2669
BackupRestore::endOfLogEntrys()
2675
info << "Restored " << m_dataCount << " tuples and "
2676
<< m_logCount << " log entries" << endl;
2680
* callback : This is called when the transaction is polled
2682
* (This function must have three arguments:
2683
* - The result of the transaction,
2684
* - The NdbTransaction object, and
2685
* - A pointer to an arbitrary object.)
2689
callback(int result, NdbTransaction* trans, void* aObject)
2691
restore_callback_t *cb = (restore_callback_t *)aObject;
2692
(cb->restore)->cback(result, cb);
2697
BackupRestore::get_attr_check_compatability(const NDBCOL::Type &old_type,
2698
const NDBCOL::Type &new_type)
2701
NDBCOL::Type first_item = m_allowed_promotion_attrs[0].old_type;
2702
NDBCOL::Type second_item = m_allowed_promotion_attrs[0].new_type;
2704
while (first_item != old_type || second_item != new_type)
2706
if (first_item == NDBCOL::Undefined)
2710
first_item = m_allowed_promotion_attrs[i].old_type;
2711
second_item = m_allowed_promotion_attrs[i].new_type;
2713
if (first_item == old_type && second_item == new_type)
2714
return m_allowed_promotion_attrs[i].attr_check_compatability;
2719
BackupRestore::get_convert_func(const NDBCOL::Type &old_type,
2720
const NDBCOL::Type &new_type)
2723
NDBCOL::Type first_item = m_allowed_promotion_attrs[0].old_type;
2724
NDBCOL::Type second_item = m_allowed_promotion_attrs[0].new_type;
2726
while (first_item != old_type || second_item != new_type)
2728
if (first_item == NDBCOL::Undefined)
2731
first_item = m_allowed_promotion_attrs[i].old_type;
2732
second_item = m_allowed_promotion_attrs[i].new_type;
2734
if (first_item == old_type && second_item == new_type)
2735
return m_allowed_promotion_attrs[i].attr_convert;
2742
BackupRestore::check_compat_promotion(const NDBCOL &old_col,
2743
const NDBCOL &new_col)
2745
return ACT_PRESERVING;
2749
BackupRestore::check_compat_lossy(const NDBCOL &old_col,
2750
const NDBCOL &new_col)
2756
BackupRestore::check_compat_sizes(const NDBCOL &old_col,
2757
const NDBCOL &new_col)
2759
// the size (width) of the element type
2760
Uint32 new_size = new_col.getSize();
2761
Uint32 old_size = old_col.getSize();
2762
// the fixed/max array length (1 for scalars)
2763
Uint32 new_length = new_col.getLength();
2764
Uint32 old_length = old_col.getLength();
2766
// identity conversions have been handled by column_compatible_check()
2767
assert(new_size != old_size
2768
|| new_length != old_length
2769
|| new_col.getArrayType() != old_col.getArrayType());
2771
// test for loss of element width or array length
2772
if (new_size < old_size || new_length < old_length) {
2776
// not tested: conversions varying in both, array length and element width
2777
if (new_size != old_size && new_length != old_length) {
2778
return ACT_UNSUPPORTED;
2781
assert(new_size >= old_size && new_length >= old_length);
2782
return ACT_PRESERVING;
2785
// ----------------------------------------------------------------------
2786
// explicit template instantiations
2787
// ----------------------------------------------------------------------
2789
template class Vector<NdbDictionary::Table*>;
2790
template class Vector<const NdbDictionary::Table*>;
2791
template class Vector<NdbDictionary::Tablespace*>;
2792
template class Vector<NdbDictionary::LogfileGroup*>;
2793
template class Vector<NdbDictionary::HashMap*>;
2794
template class Vector<NdbDictionary::Index*>;
2795
template class Vector<Vector<NdbDictionary::Index*> >;
2797
// char array promotions/demotions
2798
template void * BackupRestore::convert_array< Hchar, Hchar >(const void *, void *, bool &);
2799
template void * BackupRestore::convert_array< Hchar, Hvarchar >(const void *, void *, bool &);
2800
template void * BackupRestore::convert_array< Hchar, Hlongvarchar >(const void *, void *, bool &);
2801
template void * BackupRestore::convert_array< Hvarchar, Hchar >(const void *, void *, bool &);
2802
template void * BackupRestore::convert_array< Hvarchar, Hvarchar >(const void *, void *, bool &);
2803
template void * BackupRestore::convert_array< Hvarchar, Hlongvarchar >(const void *, void *, bool &);
2804
template void * BackupRestore::convert_array< Hlongvarchar, Hchar >(const void *, void *, bool &);
2805
template void * BackupRestore::convert_array< Hlongvarchar, Hvarchar >(const void *, void *, bool &);
2806
template void * BackupRestore::convert_array< Hlongvarchar, Hlongvarchar >(const void *, void *, bool &);
2808
// binary array promotions/demotions
2809
template void * BackupRestore::convert_array< Hbinary, Hbinary >(const void *, void *, bool &);
2810
template void * BackupRestore::convert_array< Hbinary, Hvarbinary >(const void *, void *, bool &);
2811
template void * BackupRestore::convert_array< Hbinary, Hlongvarbinary >(const void *, void *, bool &);
2812
template void * BackupRestore::convert_array< Hvarbinary, Hbinary >(const void *, void *, bool &);
2813
template void * BackupRestore::convert_array< Hvarbinary, Hvarbinary >(const void *, void *, bool &);
2814
template void * BackupRestore::convert_array< Hvarbinary, Hlongvarbinary >(const void *, void *, bool &);
2815
template void * BackupRestore::convert_array< Hlongvarbinary, Hbinary >(const void *, void *, bool &);
2816
template void * BackupRestore::convert_array< Hlongvarbinary, Hvarbinary >(const void *, void *, bool &);
2817
template void * BackupRestore::convert_array< Hlongvarbinary, Hlongvarbinary >(const void *, void *, bool &);
2819
// integral promotions
2820
template void * BackupRestore::convert_integral<Hint8, Hint16>(const void *, void *, bool &);
2821
template void * BackupRestore::convert_integral<Hint8, Hint24>(const void *, void *, bool &);
2822
template void * BackupRestore::convert_integral<Hint8, Hint32>(const void *, void *, bool &);
2823
template void * BackupRestore::convert_integral<Hint8, Hint64>(const void *, void *, bool &);
2824
template void * BackupRestore::convert_integral<Hint16, Hint24>(const void *, void *, bool &);
2825
template void * BackupRestore::convert_integral<Hint16, Hint32>(const void *, void *, bool &);
2826
template void * BackupRestore::convert_integral<Hint16, Hint64>(const void *, void *, bool &);
2827
template void * BackupRestore::convert_integral<Hint24, Hint32>(const void *, void *, bool &);
2828
template void * BackupRestore::convert_integral<Hint24, Hint64>(const void *, void *, bool &);
2829
template void * BackupRestore::convert_integral<Hint32, Hint64>(const void *, void *, bool &);
2830
template void * BackupRestore::convert_integral<Huint8, Huint16>(const void *, void *, bool &);
2831
template void * BackupRestore::convert_integral<Huint8, Huint24>(const void *, void *, bool &);
2832
template void * BackupRestore::convert_integral<Huint8, Huint32>(const void *, void *, bool &);
2833
template void * BackupRestore::convert_integral<Huint8, Huint64>(const void *, void *, bool &);
2834
template void * BackupRestore::convert_integral<Huint16, Huint24>(const void *, void *, bool &);
2835
template void * BackupRestore::convert_integral<Huint16, Huint32>(const void *, void *, bool &);
2836
template void * BackupRestore::convert_integral<Huint16, Huint64>(const void *, void *, bool &);
2837
template void * BackupRestore::convert_integral<Huint24, Huint32>(const void *, void *, bool &);
2838
template void * BackupRestore::convert_integral<Huint24, Huint64>(const void *, void *, bool &);
2839
template void * BackupRestore::convert_integral<Huint32, Huint64>(const void *, void *, bool &);
2841
// integral demotions
2842
template void * BackupRestore::convert_integral<Hint16, Hint8>(const void *, void *, bool &);
2843
template void * BackupRestore::convert_integral<Hint24, Hint8>(const void *, void *, bool &);
2844
template void * BackupRestore::convert_integral<Hint24, Hint16>(const void *, void *, bool &);
2845
template void * BackupRestore::convert_integral<Hint32, Hint8>(const void *, void *, bool &);
2846
template void * BackupRestore::convert_integral<Hint32, Hint16>(const void *, void *, bool &);
2847
template void * BackupRestore::convert_integral<Hint32, Hint24>(const void *, void *, bool &);
2848
template void * BackupRestore::convert_integral<Hint64, Hint8>(const void *, void *, bool &);
2849
template void * BackupRestore::convert_integral<Hint64, Hint16>(const void *, void *, bool &);
2850
template void * BackupRestore::convert_integral<Hint64, Hint24>(const void *, void *, bool &);
2851
template void * BackupRestore::convert_integral<Hint64, Hint32>(const void *, void *, bool &);
2852
template void * BackupRestore::convert_integral<Huint16, Huint8>(const void *, void *, bool &);
2853
template void * BackupRestore::convert_integral<Huint24, Huint8>(const void *, void *, bool &);
2854
template void * BackupRestore::convert_integral<Huint24, Huint16>(const void *, void *, bool &);
2855
template void * BackupRestore::convert_integral<Huint32, Huint8>(const void *, void *, bool &);
2856
template void * BackupRestore::convert_integral<Huint32, Huint16>(const void *, void *, bool &);
2857
template void * BackupRestore::convert_integral<Huint32, Huint24>(const void *, void *, bool &);
2858
template void * BackupRestore::convert_integral<Huint64, Huint8>(const void *, void *, bool &);
2859
template void * BackupRestore::convert_integral<Huint64, Huint16>(const void *, void *, bool &);
2860
template void * BackupRestore::convert_integral<Huint64, Huint24>(const void *, void *, bool &);
2861
template void * BackupRestore::convert_integral<Huint64, Huint32>(const void *, void *, bool &);
2863
// integral signedness BackupRestore::conversions
2864
template void * BackupRestore::convert_integral<Hint8, Huint8>(const void *, void *, bool &);
2865
template void * BackupRestore::convert_integral<Hint16, Huint16>(const void *, void *, bool &);
2866
template void * BackupRestore::convert_integral<Hint24, Huint24>(const void *, void *, bool &);
2867
template void * BackupRestore::convert_integral<Hint32, Huint32>(const void *, void *, bool &);
2868
template void * BackupRestore::convert_integral<Hint64, Huint64>(const void *, void *, bool &);
2869
template void * BackupRestore::convert_integral<Huint8, Hint8>(const void *, void *, bool &);
2870
template void * BackupRestore::convert_integral<Huint16, Hint16>(const void *, void *, bool &);
2871
template void * BackupRestore::convert_integral<Huint24, Hint24>(const void *, void *, bool &);
2872
template void * BackupRestore::convert_integral<Huint32, Hint32>(const void *, void *, bool &);
2873
template void * BackupRestore::convert_integral<Huint64, Hint64>(const void *, void *, bool &);
2875
// integral signedness+promotion BackupRestore::conversions
2876
template void * BackupRestore::convert_integral<Hint8, Huint16>(const void *, void *, bool &);
2877
template void * BackupRestore::convert_integral<Hint8, Huint24>(const void *, void *, bool &);
2878
template void * BackupRestore::convert_integral<Hint8, Huint32>(const void *, void *, bool &);
2879
template void * BackupRestore::convert_integral<Hint8, Huint64>(const void *, void *, bool &);
2880
template void * BackupRestore::convert_integral<Hint16, Huint24>(const void *, void *, bool &);
2881
template void * BackupRestore::convert_integral<Hint16, Huint32>(const void *, void *, bool &);
2882
template void * BackupRestore::convert_integral<Hint16, Huint64>(const void *, void *, bool &);
2883
template void * BackupRestore::convert_integral<Hint24, Huint32>(const void *, void *, bool &);
2884
template void * BackupRestore::convert_integral<Hint24, Huint64>(const void *, void *, bool &);
2885
template void * BackupRestore::convert_integral<Hint32, Huint64>(const void *, void *, bool &);
2886
template void * BackupRestore::convert_integral<Huint8, Hint16>(const void *, void *, bool &);
2887
template void * BackupRestore::convert_integral<Huint8, Hint24>(const void *, void *, bool &);
2888
template void * BackupRestore::convert_integral<Huint8, Hint32>(const void *, void *, bool &);
2889
template void * BackupRestore::convert_integral<Huint8, Hint64>(const void *, void *, bool &);
2890
template void * BackupRestore::convert_integral<Huint16, Hint24>(const void *, void *, bool &);
2891
template void * BackupRestore::convert_integral<Huint16, Hint32>(const void *, void *, bool &);
2892
template void * BackupRestore::convert_integral<Huint16, Hint64>(const void *, void *, bool &);
2893
template void * BackupRestore::convert_integral<Huint24, Hint32>(const void *, void *, bool &);
2894
template void * BackupRestore::convert_integral<Huint24, Hint64>(const void *, void *, bool &);
2895
template void * BackupRestore::convert_integral<Huint32, Hint64>(const void *, void *, bool &);
2897
// integral signedness+demotion BackupRestore::conversions
2898
template void * BackupRestore::convert_integral<Hint16, Huint8>(const void *, void *, bool &);
2899
template void * BackupRestore::convert_integral<Hint24, Huint8>(const void *, void *, bool &);
2900
template void * BackupRestore::convert_integral<Hint24, Huint16>(const void *, void *, bool &);
2901
template void * BackupRestore::convert_integral<Hint32, Huint8>(const void *, void *, bool &);
2902
template void * BackupRestore::convert_integral<Hint32, Huint16>(const void *, void *, bool &);
2903
template void * BackupRestore::convert_integral<Hint32, Huint24>(const void *, void *, bool &);
2904
template void * BackupRestore::convert_integral<Hint64, Huint8>(const void *, void *, bool &);
2905
template void * BackupRestore::convert_integral<Hint64, Huint16>(const void *, void *, bool &);
2906
template void * BackupRestore::convert_integral<Hint64, Huint24>(const void *, void *, bool &);
2907
template void * BackupRestore::convert_integral<Hint64, Huint32>(const void *, void *, bool &);
2908
template void * BackupRestore::convert_integral<Huint16, Hint8>(const void *, void *, bool &);
2909
template void * BackupRestore::convert_integral<Huint24, Hint8>(const void *, void *, bool &);
2910
template void * BackupRestore::convert_integral<Huint24, Hint16>(const void *, void *, bool &);
2911
template void * BackupRestore::convert_integral<Huint32, Hint8>(const void *, void *, bool &);
2912
template void * BackupRestore::convert_integral<Huint32, Hint16>(const void *, void *, bool &);
2913
template void * BackupRestore::convert_integral<Huint32, Hint24>(const void *, void *, bool &);
2914
template void * BackupRestore::convert_integral<Huint64, Hint8>(const void *, void *, bool &);
2915
template void * BackupRestore::convert_integral<Huint64, Hint16>(const void *, void *, bool &);
2916
template void * BackupRestore::convert_integral<Huint64, Hint24>(const void *, void *, bool &);
2917
template void * BackupRestore::convert_integral<Huint64, Hint32>(const void *, void *, bool &);