~jlukas79/+junk/mysql-server

« back to all changes in this revision

Viewing changes to sql/backup/be_default.cc

manual merge 6.0-main --> 6.0-bka-review

Show diffs side-by-side

added added

removed removed

Lines of Context:
80
80
 
81
81
using namespace backup;
82
82
 
83
 
Engine::Engine(THD *t_thd)
84
 
{
85
 
  m_thd= t_thd;
86
 
}
87
 
 
88
 
/**
89
 
  * Create a default backup backup driver.
90
 
  *
91
 
  * Given a list of tables to be backed-up, create instance of backup
92
 
  * driver which will create backup image of these tables.
93
 
  *
94
 
  * @param  tables (in) list of tables to be backed-up.
95
 
  * @param  eng    (out) pointer to backup driver instance.
96
 
  *
97
 
  * @retval  ERROR  if cannot create backup driver class.
98
 
  * @retval  OK     on success.
99
 
  */
100
 
result_t Engine::get_backup(const uint32, const Table_list &tables,
101
 
                            Backup_driver* &drv)
102
 
{
103
 
  DBUG_ENTER("Engine::get_backup");
104
 
  Backup *ptr= new default_backup::Backup(tables, m_thd, TL_READ_NO_INSERT);
105
 
  if (!ptr)
106
 
    DBUG_RETURN(ERROR);
107
 
  drv= ptr;
108
 
  DBUG_RETURN(OK);
109
 
}
110
 
 
111
 
Backup::Backup(const Table_list &tables, THD *t_thd, thr_lock_type lock_type): 
112
 
               Backup_thread_driver(tables)
 
83
 
 
84
Backup::Backup(const Table_list &tables, THD *t_thd, thr_lock_type lock_type)
 
85
  :Backup_thread_driver(tables)
113
86
{
114
87
  DBUG_PRINT("default_backup",("Creating backup driver"));
115
88
  locking_thd->m_thd= t_thd;  /* save current thread */
122
95
     Create a TABLE_LIST * list for iterating through the tables.
123
96
     Initialize the list for opening the tables in read mode.
124
97
  */
125
 
  locking_thd->tables_in_backup= build_table_list(tables, lock_type);
126
 
  all_tables= locking_thd->tables_in_backup;
 
98
  all_tables= (TABLE_LIST*)my_malloc(tables.count()*sizeof(TABLE_LIST), MYF(MY_WME));
 
99
  DBUG_ASSERT(all_tables); // TODO: report error instead
 
100
  bzero(all_tables, tables.count()*sizeof(TABLE_LIST));
 
101
 
 
102
  for (uint i=0; i < tables.count(); ++i)
 
103
  {
 
104
    backup::set_table_list(all_tables[i], tables[i], lock_type, t_thd->mem_root);
 
105
 
 
106
    // link previous entry to this one
 
107
    if (i > 0)
 
108
      backup::link_table_list(all_tables[i-1], &all_tables[i]);
 
109
  }
 
110
 
 
111
  locking_thd->tables_in_backup= all_tables;
127
112
  init_phase_complete= FALSE;
128
113
  locks_acquired= FALSE;
129
 
}
 
114
  hdl= NULL;
 
115
  m_cleanup= TRUE;
 
116
}
 
117
 
 
118
/**
 
119
  Cleanup backup
 
120
 
 
121
  This method provides a means to stop a current backup by allowing
 
122
  the driver to shutdown gracefully. The method call ends the current
 
123
  table read then attempts to kill the locking thread if it is still
 
124
  running.
 
125
*/
 
126
result_t Backup::cleanup()
 
127
{
 
128
  DBUG_ENTER("Default_backup::cleanup()");
 
129
  DBUG_PRINT("backup",("Default driver - stop backup"));
 
130
  if (m_cleanup)
 
131
  {
 
132
    m_cleanup= FALSE;
 
133
    if (hdl)
 
134
      end_tbl_read();
 
135
    if (locking_thd)
 
136
      locking_thd->kill_locking_thread();
 
137
  }
 
138
  DBUG_RETURN(OK);
 
139
}
 
140
 
 
141
 
 
142
Backup::~Backup()
 
143
{
 
144
  /*
 
145
    Since objects representing metadata lock requests for tables open
 
146
    by locking thread use same chunks of memory as elements of
 
147
    'all_tables' table list it is essential to ensure that locking
 
148
    thread has finished before freeing elements of this table list.
 
149
  */
 
150
  locking_thd->kill_locking_thread();
 
151
  locking_thd->wait_until_locking_thread_dies();
 
152
  my_free(all_tables, MYF(0)); 
 
153
}
 
154
 
130
155
 
131
156
/**
132
157
  * @brief Prelock call to setup locking.
159
184
  hdl= tbl->file;
160
185
  last_read_res= hdl->ha_rnd_init(1);
161
186
  if (last_read_res != 0)
 
187
  {
 
188
    hdl= NULL;
162
189
    DBUG_RETURN(ERROR);
 
190
  }
163
191
  DBUG_RETURN(OK);
164
192
}
165
193
 
176
204
  int last_read_res;
177
205
 
178
206
  DBUG_ENTER("Default_backup::end_tbl_read)");
 
207
 
 
208
  if (!hdl)
 
209
    DBUG_RETURN(OK);
 
210
 
179
211
  last_read_res= hdl->ha_rnd_end();
 
212
  hdl= NULL;
180
213
  if (last_read_res != 0)
181
214
    DBUG_RETURN(ERROR);
182
215
  DBUG_RETURN(OK);
289
322
  if (!locks_acquired)
290
323
  {
291
324
    buf.size= 0;
292
 
    buf.table_no= 0; 
 
325
    buf.table_num= 0; 
293
326
    buf.last= TRUE;
294
327
    switch (locking_thd->lock_state) {
295
328
    case LOCK_ERROR:             // Something ugly happened in locking
297
330
    case LOCK_ACQUIRED:          // First time lock ready for validity point
298
331
    {
299
332
      locks_acquired= TRUE;
300
 
      BACKUP_BREAKPOINT("locking_thread_added");
 
333
      DEBUG_SYNC(locking_thd->m_thd, "default_locking_thread_added");
301
334
      DBUG_RETURN(READY);
302
335
    }
303
336
    default:                     // If first call, signal end of init phase
311
344
    }
312
345
  }
313
346
 
314
 
  buf.table_no= tbl_num;
 
347
  buf.table_num= tbl_num;
315
348
  buf.last= FALSE;
316
349
 
317
350
  /* 
 
351
    get_data() should not be called after cancel has been called.
 
352
  */
 
353
  DBUG_ASSERT(mode != CANCEL);
 
354
 
 
355
  /* 
318
356
    Determine mode of operation and execute mode.
319
357
  */
320
358
  switch (mode) {
330
368
  */
331
369
  case GET_NEXT_TABLE:
332
370
  {
 
371
    if (tbl_num >= m_tables.count())
 
372
    {
 
373
      buf.last= TRUE;
 
374
      buf.size= 0;
 
375
      buf.table_num= 0;
 
376
      DBUG_RETURN(DONE);
 
377
    }
 
378
 
 
379
    cur_table= all_tables[tbl_num++].table;
 
380
    DBUG_ASSERT(cur_table); // tables should be opened at that time
 
381
    read_set=  cur_table->read_set;
 
382
    start_tbl_read(cur_table);
 
383
 
 
384
    buf.table_num= tbl_num;
333
385
    mode= READ_RCD;
334
 
    int res= next_table();
335
 
    /*
336
 
      If no more tables in list, tell backup algorithm we're done else
337
 
      fall through to reading mode.
338
 
    */
339
 
    if (res)
340
 
    {
341
 
      buf.last= TRUE;
342
 
      buf.size= 0;
343
 
      buf.table_no= 0;
344
 
      DBUG_RETURN(OK);
345
 
    }
346
 
    else
347
 
    {
348
 
      start_tbl_read(cur_table);
349
 
      tbl_num++;
350
 
      buf.table_no= tbl_num;
351
 
    }
352
386
  }
353
387
 
354
388
  /*
362
396
    cur_blob= 0;
363
397
    cur_table->use_all_columns();
364
398
    last_read_res = hdl->rnd_next(cur_table->record[0]);
 
399
    /*
 
400
      Skip all records marked as deleted.
 
401
    */
 
402
    while (last_read_res == HA_ERR_RECORD_DELETED)
 
403
      last_read_res= hdl->rnd_next(cur_table->record[0]);
365
404
    DBUG_EXECUTE_IF("SLEEP_DRIVER", sleep(4););
366
405
    /*
367
406
      If we are end of file, stop the read process and signal the
536
575
  DBUG_RETURN(OK); 
537
576
}
538
577
 
539
 
/**
540
 
  * Create a default backup restore driver.
541
 
  *
542
 
  * Given a list of tables to be restored, create instance of restore
543
 
  * driver which will restore these tables from a backup image.
544
 
  *
545
 
  * @param  version  (in) version of the backup image.
546
 
  * @param  tables   (in) list of tables to be restored.
547
 
  * @param  eng      (out) pointer to restore driver instance.
548
 
  *
549
 
  * @retval ERROR  if cannot create restore driver class.
550
 
  * @retval OK     on success.
551
 
  */
552
 
result_t Engine::get_restore(version_t, const uint32, 
553
 
                             const Table_list &tables, Restore_driver* &drv)
554
 
{
555
 
  DBUG_ENTER("Engine::get_restore");
556
 
  Restore *ptr= new default_backup::Restore(tables, m_thd);
557
 
  if (!ptr)
558
 
    DBUG_RETURN(ERROR);
559
 
  drv= ptr;
560
 
  DBUG_RETURN(OK);
561
 
}
562
578
 
563
 
Restore::Restore(const Table_list &tables, THD *t_thd): Restore_driver(tables)
 
579
Restore::Restore(const backup::Logical_snapshot &snap, THD *t_thd) 
 
580
  :Restore_driver(snap.get_table_list()), m_snap(snap)
564
581
{
565
582
  DBUG_PRINT("default_backup",("Creating restore driver"));
566
583
  m_thd= t_thd;         /* save current thread */
568
585
  tbl_num= 0;           /* set table number to 0 */
569
586
  mode= INITIALIZE;     /* initialize write */
570
587
 
571
 
  /*
572
 
     Create a TABLE_LIST * list for iterating through the tables.
573
 
     Initialize the list for opening the tables in write mode.
574
 
  */
575
 
  tables_in_backup= build_table_list(tables, TL_WRITE);
576
 
  all_tables= tables_in_backup;
577
588
  for (int i=0; i < MAX_FIELDS; i++)
578
589
    blob_ptrs[i]= 0;
579
590
  blob_ptr_index= 0;
 
591
  m_cleanup= TRUE;
 
592
}
 
593
 
 
594
/**
 
595
  Cleanup restore
 
596
 
 
597
  This method provides a means to stop a current restore by allowing
 
598
  the driver to shutdown gracefully. The method call closes the
 
599
  table list by calling end() method.
 
600
*/
 
601
result_t Restore::cleanup()
 
602
{
 
603
  DBUG_ENTER("Default_backup::cleanup()");
 
604
  DBUG_PRINT("backup",("Default driver - stop restore"));
 
605
  if (m_cleanup)
 
606
  {
 
607
    m_cleanup= FALSE;
 
608
    end();
 
609
  }
 
610
  DBUG_RETURN(OK);
580
611
}
581
612
 
582
613
/**
588
619
  * @retval OK     rows deleted.
589
620
  * @retval ERROR  problem with deleting rows.
590
621
  */
591
 
result_t Restore::truncate_table(TABLE *tbl)
592
 
{
593
 
  int last_write_res; 
594
622
 
595
 
  DBUG_ENTER("Default_backup::truncate_table)");
596
 
  DBUG_ASSERT(tbl->file);
597
 
  hdl= tbl->file;
598
 
  last_write_res= cur_table->file->ha_delete_all_rows();
599
 
  /*
600
 
    Check to see if delete all rows was ok. Ignore if the handler
601
 
    doesn't support it.
602
 
  */
603
 
  if ((last_write_res != 0) && (last_write_res != HA_ERR_WRONG_COMMAND))
604
 
    DBUG_RETURN(ERROR);
605
 
  num_rows= 0;
606
 
  DBUG_RETURN(OK);
607
 
}
608
623
 
609
624
/**
610
625
  * @brief End restore process.
616
631
result_t Restore::end()
617
632
{
618
633
  DBUG_ENTER("Restore::end");
619
 
  close_thread_tables(m_thd);
620
634
  DBUG_RETURN(OK);
621
635
}
622
636
 
629
643
  * @retval 0   no errors.
630
644
  * @retval -1  no more tables in list.
631
645
  */
632
 
int Restore::next_table()
633
 
{
634
 
  DBUG_ENTER("Restore::next_table()");
635
 
  if (cur_table == NULL)
636
 
    cur_table= tables_in_backup->table;
637
 
  else
638
 
  {
639
 
    tables_in_backup= tables_in_backup->next_global;
640
 
    if (tables_in_backup != NULL)
641
 
    {
642
 
      DBUG_ASSERT(tables_in_backup->table);
643
 
      cur_table= tables_in_backup->table;
644
 
    }
645
 
    else
646
 
    {
647
 
      cur_table= NULL;
648
 
      DBUG_RETURN(-1);
649
 
    }
650
 
  } 
651
 
  DBUG_RETURN(0);
652
 
}
 
646
 
653
647
 
654
648
/**
655
649
  * @brief Unpack the data for a row in the table.
681
675
    error= unpack_row(NULL, cur_table, n_fields, packed_row, &cols, &cur_row_end, &length);
682
676
    if (!use_bitbuf)
683
677
      bitmap_free(&cols);
684
 
    num_rows++;
685
678
  }
686
679
  DBUG_RETURN(error);
687
680
}
718
711
 
719
712
  DBUG_ENTER("Restore::send_data");
720
713
  DBUG_PRINT("default_restore",("Got packet with %lu bytes from stream %u",
721
 
                                (unsigned long)buf.size, buf.table_no));
 
714
                                (unsigned long)buf.size, buf.table_num));
722
715
  
723
716
  /* 
 
717
    get_data() should not be called after cancel has been called.
 
718
  */
 
719
  DBUG_ASSERT(mode != CANCEL);
 
720
 
 
721
  /* 
724
722
    Determine mode of operation and execute mode.
725
723
  */
726
724
  switch (mode) {
727
725
 
728
726
  /*
729
 
    Nothing to do in Initialize, continue to GET_NEXT_TABLE.
 
727
    Nothing to do in Initialize, continue to WRITE_RCD.
730
728
  */
731
729
  case INITIALIZE:
732
730
 
733
731
  /*
734
 
    If class has been initialized and we need to read the next table,
735
 
    advance the current table pointer and initialize read process.
736
 
  */
737
 
  case GET_NEXT_TABLE:
738
 
  {
739
 
    int res;
740
 
 
741
 
    mode= WRITE_RCD;
742
 
    /*
743
 
      It is possible for the backup system to send data to this
744
 
      engine out of sequence from the table list. When a non-sequential
745
 
      access is detected, start the table list at the beginning and
746
 
      find the table in question. This is needed if any tables (more
747
 
      than MAX_RETRIES are empty!
748
 
    */
749
 
    if ((tbl_num + 1) == buf.table_no) //do normal sequential lookup
750
 
      res= next_table();
751
 
    else                                //do linear search
752
 
    {
753
 
      uint i= 0;
754
 
 
755
 
      cur_table= NULL;
756
 
      tables_in_backup= all_tables;
757
 
      do
758
 
      {
759
 
        i++;
760
 
        res= next_table();
761
 
      }
762
 
      while ((i != buf.table_no) && !res);
763
 
      tbl_num= i - 1;
764
 
    }
765
 
    if (res)
766
 
    {
767
 
      buf.last= TRUE;
768
 
      buf.size= 0;
769
 
      buf.table_no= 0;
770
 
      DBUG_RETURN(OK);
771
 
    }
772
 
    else
773
 
    {
774
 
      truncate_table(cur_table); /* delete all rows from table */
775
 
      tbl_num++;
776
 
    }
777
 
  }
778
 
 
779
 
  /*
780
732
    Write a row to the table from the data in the buffer.
781
733
  */
782
734
  case WRITE_RCD:
784
736
    cur_blob= 0;
785
737
    max_blob_size= 0;
786
738
 
787
 
    /*
788
 
      If the table number is different from the stream number, we're
789
 
      receiving data from the backup for a different table. Set the mode to
790
 
      get the next table in the list.
791
 
    */
792
 
    if (tbl_num != buf.table_no)
793
 
    {
794
 
      mode= GET_NEXT_TABLE;
795
 
      DBUG_RETURN(PROCESSING);
796
 
    }
797
 
    else
 
739
    // We don't process any data on stream #0
 
740
    if (buf.table_num == 0)
 
741
      DBUG_RETURN(OK);
 
742
 
 
743
    // We only proccess data for the tables we are restoring.
 
744
    if (buf.table_num > m_tables.count())
 
745
      DBUG_RETURN(OK);
 
746
 
 
747
    /*
 
748
     Get the opened table instance corresponding to buf.table_num. Note that
 
749
     tables are opened (and locked) by the kernel.
 
750
    */
 
751
    cur_table= m_snap.get_opened_table(buf.table_num - 1);
 
752
    DBUG_ASSERT(cur_table); // All tables we are processing should be opened.
 
753
 
 
754
    /*
 
755
      Change timestamp autoset type to TIMESTAMP_NO_AUTO_SET
 
756
      so that any restored data with timestamp fields will not have their values
 
757
      reset on write.
 
758
    */
 
759
    if (cur_table->timestamp_field)
 
760
      cur_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
 
761
 
 
762
    hdl= cur_table->file;
 
763
    DBUG_ASSERT(hdl); // table should be opened
 
764
 
798
765
    {
799
766
      uint32 size= buf.size - META_SIZE;
800
767
      block_type= *buf.data;