List:Commits« Previous MessageNext Message »
From:cbell Date:March 9 2007 4:07pm
Subject:bk commit into 5.1 tree (cbell:1.2482)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of cbell. When cbell does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2007-03-09 11:07:12-05:00, cbell@mysql_cab_desk. +4 -0
  WL#3570 - Default backup
  
  This patch contains the initial prototype code for the default
  backup algorithm. Additional patches will be submitted once
  the code is fully tested and debugged.

  sql/backup.cc@stripped, 2007-03-09 11:07:03-05:00, cbell@mysql_cab_desk. +26 -3
    WL#3570 - Default backup	
    
    This code adds the default backup and restore to the backup kernel code.

  sql/backup_private.h@stripped, 2007-03-09 11:07:04-05:00, cbell@mysql_cab_desk. +52 -0
    WL#3570 - Default backup	
    
    This code adds the default backup and restore to the backup kernel code.

  sql/backup_prototype.cc@stripped, 2007-03-09 11:07:04-05:00, cbell@mysql_cab_desk. +30 -2
    WL#3570 - Default backup	
    
    This code adds the default backup and restore to the backup kernel code.

  sql/default_driver.cc@stripped, 2007-03-09 11:07:05-05:00, cbell@mysql_cab_desk. +397 -0
    WL#3570 - Default backup
    
    The following code adds the default backup algorithm to online backup.

  sql/default_driver.cc@stripped, 2007-03-09 11:07:05-05:00, cbell@mysql_cab_desk. +0 -0

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	cbell
# Host:	mysql_cab_desk.
# Root:	C:/source/c++/mysql-5.1_WL_3570
--- New file ---
+++ sql/default_driver.cc	07/03/09 11:07:05
#include "mysql_priv.h"
#include "backup.h"
#include "backup_private.h"

/*
  The file layout of the data for the default backup algorithm is:

blknum   contents
------------------------------------------------------
  1      (byte)   copy record_buffer read from handler
------------------------------------------------------
  2...n  (uint32) size of blob data to read
         (byte)   blob data for blob
------------------------------------------------------

.. repeat above for each row in the table ... 

Thus, each row consumes at least one block containing the data for the row. 
The blob fields follow each in a separate block containing the size of the blob
data to read, and the blob data.

*/
namespace default_backup {

using backup::byte;
using backup::result_t;
using backup::version_t;
using backup::Table_list;
using backup::Table_ref;
using backup::Buffer;

Engine::Engine(THD *t_thd)
{
  m_thd= t_thd;
}

result_t Engine::get_backup(const Table_list &tables, Backup_driver* &drv)
{
  DBUG_ENTER("Engine::get_backup");
  Backup *ptr= new default_backup::Backup(tables, m_thd);
  if (!ptr) 
    DBUG_RETURN(backup::ERROR);
  drv= ptr;
  DBUG_RETURN(backup::OK);
}

Backup::Backup(const Table_list &tables, THD *t_thd): Backup_driver(tables)
{
  DBUG_PRINT("default_backup",("Creating backup driver"));
  m_thd= t_thd;
  initialized= 0;
  cur_table= NULL;
  get_next_table= 1;
  tables_in_backup= build_table_list(tables, TL_READ);
  all_tables= tables_in_backup;
}

Backup::~Backup()
{
}

result_t Backup::start_tbl_read(TABLE *tbl)
{
  DBUG_ENTER("Default_backup::start_tbl_read)");
  hdl= tbl->file;
  hdl->ha_rnd_init(1);
  DBUG_RETURN(backup::OK);
}

result_t Backup::end_tbl_read()
{
  DBUG_ENTER("Default_backup::end_tbl_read)");
  hdl->ha_rnd_end();
  DBUG_RETURN(backup::OK);
}

result_t Backup::begin()
{
  DBUG_ENTER("Default_backup::start_backup");
  if (open_and_lock_tables(m_thd, all_tables)) 
  {
    DBUG_PRINT("backup", ( "error!" )); 
    DBUG_RETURN(backup::ERROR);
  }
  DBUG_RETURN(backup::OK);
}

result_t Backup::end()
{
  DBUG_ENTER("Default_backup::end");
  if (m_thd->lock)
  {
    mysql_unlock_tables(m_thd, m_thd->lock);
    m_thd->lock=0;
  }
  DBUG_RETURN(backup::OK);
}

int Backup::next_table()
{
  DBUG_ENTER("Default_backup::next_table()");
  if (cur_table == NULL)
  {
    cur_table= tables_in_backup->table;
    read_set= cur_table->read_set;
  }
  else
  {
    tables_in_backup= tables_in_backup->next_global;
    if (tables_in_backup != NULL)
    {
      cur_table= tables_in_backup->table;
      read_set= cur_table->read_set;
    }
    else
    {
      cur_table= NULL;
      DBUG_RETURN(-1);
    }
  }
  DBUG_RETURN(0);
}

result_t Backup::get_data(Buffer &buf)
{
  last_read_res = 0;
  DBUG_ENTER("Default_backup::get_data(Buffer &buf)");

  buf.stream_no= tbl_num;
  if (initialized && get_next_table)
  {
    int res;

    get_next_table= 0;
    res= next_table();
    if (res)
    {
      if (cur_table == NULL)
      {
        buf.size= 0;
        buf.last= TRUE;
      }
      DBUG_RETURN(backup::OK);
    }
    else
    {
      start_tbl_read(cur_table);
      tbl_num++;
      buf.stream_no= tbl_num;
    }
  }
  if (!initialized)
  {
    buf.size= 0;
    buf.stream_no= 0;
    initialized= 1;
    tbl_num= 0;
    reading= 1;
    DBUG_RETURN(backup::INIT_DONE);
  }
  /*
    Reading data section
  */
  else if (reading)
  {
    // If buffer isn't large enough for a record, abort.
    if (buf.size < cur_table->s->reclength)
      DBUG_RETURN(backup::ERROR);
    //Get another record and process it.
    last_read_res = hdl->rnd_next(buf.data);
    // Check for end of file read.
    buf.last= FALSE;
    buf.size= cur_table->s->reclength;
    if (last_read_res == HA_ERR_END_OF_FILE)
    {
      end_tbl_read();
      buf.size= 0;
      buf.last= TRUE;
      get_next_table= 1;
      DBUG_RETURN(backup::OK);
    }
    else
    {
      //If no blobs, we're finished reading data.
      reading= !(last_read_res == HA_ERR_END_OF_FILE);
      read_blobs= (cur_table->s->blob_fields > 0);
      if (read_blobs)
      {
        cur_blob= cur_table->s->blob_field;
        last_blob_ptr = cur_blob + cur_table->s->blob_fields;
      }
      DBUG_RETURN(backup::OK);
    }
  }
  /*
    Buffering section
  */
  else if (read_blobs)
  {
    int meta_size= sizeof(uint32);
    uint32 size= ((Field_blob*) cur_table->field[*cur_blob])->get_length();
    if ((size + meta_size) >= buf.size)
    {
      memcpy((byte *)buf.data, (byte *)size, sizeof(uint32));
      ((Field_blob*) cur_table->field[*cur_blob])->get_ptr((char **)&buf.data 
       + meta_size);
      buf.size = size + meta_size;
    }
    else //abort!
      DBUG_RETURN(backup::ERROR);
    cur_blob++; 
    //if no more blobs, stop.
    if (cur_blob == last_blob_ptr)
    {
      buf.size= 0; ///?????? do you need this here?
      reading= 0;
      read_blobs= 0;
    }
    else
      read_blobs= 1;
  }
  DBUG_RETURN(backup::ERROR); //something horrible lurks here abort backup
}

result_t Backup::lock()   
{ 
  DBUG_ENTER("Default_backup::lock()");
  DBUG_RETURN(backup::OK);     
}

result_t Backup::unlock() 
{ 
  DBUG_ENTER("Default_backup::unlock()");
  DBUG_RETURN(backup::OK);
}

result_t Engine::get_restore(version_t ver, const Table_list &tables, Restore_driver* &drv)
{
  DBUG_ENTER("Engine::get_restore");
  Restore *ptr= new default_backup::Restore(tables, m_thd);
  if (!ptr) 
    DBUG_RETURN(backup::ERROR);
  drv= ptr;
  DBUG_RETURN(backup::OK);
}

Restore::Restore(const Table_list &tables, THD *t_thd): Restore_driver(tables)
{
  DBUG_PRINT("default_backup",("Creating restore driver"));
  m_thd= t_thd;
  initialized= 0;
  cur_table= NULL;
  get_next_table= 1;
  tables_in_backup= build_table_list(tables, TL_READ);
  all_tables= tables_in_backup;
}

Restore::~Restore()
{
}

/*
  Here is where we truncate the file and then start the write process.
*/
result_t Restore::start_tbl_write(TABLE *tbl)
{
  DBUG_ENTER("Default_backup::start_tbl_write)");
  cur_table->file->delete_all_rows();
  hdl= tbl->file;
  hdl->ha_rnd_init(1);
  DBUG_RETURN(backup::OK);
}

result_t Restore::end_tbl_write()
{
  DBUG_ENTER("Default_backup::end_tbl_write)");
  hdl->ha_rnd_end();
  DBUG_RETURN(backup::OK);
}

result_t Restore::begin()
{
  DBUG_ENTER("Restore::begin");
  if (open_and_lock_tables(m_thd, all_tables)) 
  {
    DBUG_PRINT("restore", ( "error!" )); 
    DBUG_RETURN(backup::ERROR);
  }
  DBUG_RETURN(backup::OK);
}

result_t Restore::end()
{
  DBUG_ENTER("Restore::end");
  if (m_thd->lock)
  {
    mysql_unlock_tables(m_thd, m_thd->lock);
    m_thd->lock=0;
  }
  DBUG_RETURN(backup::OK);
}

int Restore::next_table()
{
  DBUG_ENTER("Default_backup::next_table()");
  if (cur_table == NULL)
    cur_table= tables_in_backup->table;
  else
  {
    tables_in_backup= tables_in_backup->next_global;
    if (tables_in_backup != NULL)
      cur_table= tables_in_backup->table;
    else
    {
      cur_table= NULL;
      DBUG_RETURN(-1);
    }
  }
  DBUG_RETURN(0);
}

result_t Restore::send_data(Buffer &buf)
{
  DBUG_ENTER("Restore::send_data");
  DBUG_PRINT("default/restore",("Got packet with %d bytes from stream %d",
                                buf.size, buf.stream_no));
                                
  if (initialized && get_next_table)
  {
    int res;

    get_next_table= 0;
    res= next_table();
    if (res)
    {
      if (cur_table == NULL)
      {
        buf.size= 0;
        buf.last= TRUE;
      }
      DBUG_RETURN(backup::OK);
    }
    else
    {
      start_tbl_write(cur_table);
      tbl_num++;
    }
  }
  if (!initialized)
  {
    initialized= 1;
    writing= 1;
    DBUG_RETURN(backup::WAIT);
  }
  else if (writing)
  {
    /*
      Read the record buffer and write it to the table.
      Then read the number of blobs that are saved in subsequent blocks.
    */
    last_write_res = hdl->write_row(buf.data);
    if (last_write_res == HA_ERR_END_OF_FILE)
    {
      writing= 1;
      end_tbl_write();
      get_next_table= 1;
      DBUG_RETURN(backup::OK);
    }
    else
    {
      writing= !(last_write_res == HA_ERR_END_OF_FILE);
      memcpy((byte *)num_blobs, (byte *)buf.data + cur_table->s->reclength, sizeof(uint32));
      write_blobs= (num_blobs > 0);
      DBUG_RETURN(backup::OK);
    }
  }
  else if (write_blobs)
  {
    uint32 size;
    int meta_size= sizeof(uint32);

    memcpy((byte *)size, (byte *)buf.data, sizeof(uint32));
    ((Field_blob*) cur_table->field[*cur_blob])->set_ptr(size, (char *)buf.data + meta_size);
    cur_blob++; 
    if (cur_blob == last_blob_ptr)
    {
      buf.size= 0; ///?????? do you need this here?
      writing= 0;
      write_blobs= 0;
    }
    else
      write_blobs= 1;
  }
  DBUG_RETURN(backup::ERROR);  //should never get here.
}

} // default_backup namespace


--- 1.7/sql/backup.cc	2007-03-09 11:07:31 -05:00
+++ 1.8/sql/backup.cc	2007-03-09 11:07:31 -05:00
@@ -196,9 +196,28 @@
                         ::ha_resolve_storage_engine_name(hton),
                         hton->get_backup_engine) );
 
+   Backup_subimage *img;
+
+   #ifdef USE_DEFAULT_BACKUP
+   
+   // Point 4
+   
+   img = images.head();
+     
+   if (!img)  
+   {
+     img= new Default_backup_info();
+     images.push_back(img);
+   }
+   
+   DBUG_ASSERT(img);
+   
+   return img->add(tbl,hton);
+   
+   #else
+   
    // Point 3
 
-   Backup_subimage *img;
    List_iterator<Backup_subimage> it(images);
       
    while( (img= it++) )
@@ -224,6 +243,8 @@
 
    DBUG_PRINT("backup",("Table ignored."));
    return FALSE;
+   
+   #endif
 }
 
 
@@ -395,13 +416,15 @@
   
   s.read2int(ver);
   
+  #ifdef USE_DEFAULT_BACKUP
+  return Default_restore_info::create_from_stream(ver,s);
+  #else
   // assume this is Native engine format
   return Native_restore_info::create_from_stream(ver,s);
+  #endif
 }
 
 //////////////////////////////////////////////////////////////////////////////
-
-TABLE_LIST *build_table_list(const Tables&, thr_lock_type);
 
 
 // Writing/reading table definitions

--- 1.3/sql/backup_private.h	2007-03-09 11:07:31 -05:00
+++ 1.4/sql/backup_private.h	2007-03-09 11:07:31 -05:00
@@ -1,8 +1,11 @@
 #ifndef BACKUP_INT_H
 #define BACKUP_INT_H
 
+#define USE_DEFAULT_BACKUP
+
 #include "backup_util.h"
 #include "backup_stream.h"
+#include "default_driver.h"
 
 #define TEST_STR_RES(H,R) \
   do { \
@@ -107,6 +110,8 @@
 
 namespace backup {
 
+TABLE_LIST *build_table_list(const Table_list&, thr_lock_type);
+
 class Tables: public Table_list
 { 
   public: 
@@ -226,6 +231,53 @@
    
  ************************************************************/   
 
+// Defaul backup image: using default (blocking) backup/restore algorithm.
+
+
+class Default_backup_info: public Backup_subimage
+{
+  Backup_driver *m_drv;
+ 
+ public: 
+  Default_backup_info(): m_drv(NULL) 
+  {}
+  
+  version_t ver() const
+  { return 1; }
+  
+  Backup_driver&  driver() 
+  { 
+    
+    if (!m_drv)
+      m_drv= new default_backup::Backup(tables, ::current_thd);
+
+    DBUG_ASSERT(m_drv);  
+    return *m_drv;
+  }
+  
+  bool add(const Table_ref&, const ::handlerton*);
+  bool do_write_description(OStream&);
+};
+
+class Default_restore_info: public Restore_subimage
+{
+  Restore_driver      *m_drv;
+ 
+ public: 
+  Default_restore_info(version_t ver): Restore_subimage(ver), m_drv(NULL)
+  {}
+  
+  Restore_driver*  driver() 
+  {   
+    if (!m_drv)
+      m_drv= new default_backup::Restore(tables, ::current_thd);
+
+    return m_drv;
+  }
+
+  static Default_restore_info* create_from_stream(version_t, IStream&);
+};
+  
 // Native backup image: created by backup-capable storage engine
 
 class Native_backup_info: public Backup_subimage

--- 1.5/sql/backup_prototype.cc	2007-03-09 11:07:31 -05:00
+++ 1.6/sql/backup_prototype.cc	2007-03-09 11:07:31 -05:00
@@ -80,6 +80,33 @@
   
 }
 
+// Implementation of default backup image type
+
+namespace backup {
+
+bool Default_backup_info::add(const Table_ref &tbl, const ::handlerton*)
+{
+  // accept any table ...
+  DBUG_PRINT("backup",("adding table %s to subimage",tbl.name().ptr()));  
+  tables.add(tbl);
+  return TRUE;
+}
+
+
+bool Default_backup_info::do_write_description(OStream &)
+{
+  // no extra information needed
+  return(false);
+}
+
+Default_restore_info* 
+Default_restore_info::create_from_stream(version_t ver, IStream &)
+{
+  return new Default_restore_info(ver);
+}
+
+} // backup namespace
+
 
 // Implementation of native backup image type
 
@@ -343,7 +370,7 @@
 // Actually, should work fine with reversed list as long as we use the reversed 
 // list both in table writing and reading.
 
-TABLE_LIST *build_table_list(const Tables &tables, thr_lock_type lock)
+TABLE_LIST *build_table_list(const Table_list &tables, thr_lock_type lock)
 {
   TABLE_LIST *tl= NULL;
 
@@ -363,7 +390,8 @@
     
     ptr->next_global= ptr->next_local= 
       ptr->next_name_resolution_table= tl;
-    tl= ptr;  
+    tl= ptr; 
+    tl->table= ptr->table; 
   }
 
   return tl;    

Thread
bk commit into 5.1 tree (cbell:1.2482)cbell9 Mar