List:Commits« Previous MessageNext Message »
From:cbell Date:March 9 2007 3:36pm
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 10:36:07-05:00, cbell@mysql_cab_desk. +1 -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/default_driver.cc@stripped, 2007-03-09 10:35:56-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 10:35:56-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 10:35:56
#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


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