List:Commits« Previous MessageNext Message »
From:rsomla Date:April 21 2008 10:45am
Subject:bk commit into 6.0 tree (rafal:1.2611) WL#4347
View as plain text  
Below is the list of changes that have just been committed into a local
6.0 repository of rafal.  When rafal 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, 2008-04-21 12:45:39+02:00, rafal@quant.(none) +11 -0
  WL#4347 (backup kernel extension for handling tablespaces):
  
  This patch extends the current kernel so that it handles tables which use 
  tablespaces as specified in the WL. This patch assumes that required extensions 
  of server object services and backup stream library are already in the tree.
  
  The main changes are:
  
  - Extending Image_info class so that tablespaces can be stored inside the 
    catalogue.
  - Define/extend backup catalogue iterators to include tablespaces.
  - Take care of tables which use tablespaces when adding them to backup 
    catalogue.
  - Re-create tablespaces during restore.
  
  The patch also adds error reporting in places where it was missing.

  mysql-test/t/disabled.def@stripped, 2008-04-21 12:45:26+02:00, rafal@quant.(none) +0 -1
    Enable backup_tablespace test which now can be executed.

  sql/backup/backup_info.cc@stripped, 2008-04-21 12:45:26+02:00, rafal@quant.(none) +141 -5
    - Implementation of the tablespace hash.
    - Implementation of Backup_info::add_ts() method.
    - Add missing error reporting in Backup_info::add_db() method. 
    - Modification of Backup_info::add_db_items() to handle tablespaces if used by a table.

  sql/backup/backup_info.h@stripped, 2008-04-21 12:45:26+02:00, rafal@quant.(none) +11 -0
    Add Backup_info::ts_hash member and Backup_info::add_ts() method used to add a tablespace
    to backup catalogue.

  sql/backup/backup_kernel.h@stripped, 2008-04-21 12:45:26+02:00, rafal@quant.(none) +20 -5
    - Modify fatal_error() method so that it doesn't overwrite a reported error when called 
      for a second time. This is needed so that in tests we see a correct error number.
    - Rearange included headers because Backup_info and Restore_info classes need definition
      of Backup_restore_ctx.

  sql/backup/image_info.cc@stripped, 2008-04-21 12:45:26+02:00, rafal@quant.(none) +47 -13
    - Modify Image_info constructor and destructor to take care of tablespaces.
    - Implement Image_info::add_ts() method.
    - Update Image_info::find_obj() method to handle tablespaces.

  sql/backup/image_info.h@stripped, 2008-04-21 12:45:27+02:00, rafal@quant.(none) +278 -6
    - Add new class Image_info::Ts for storing tablespaces in the catalogue.
    - Add new iterators Ts_iterator and Global_iterator.
    - Add Image_info methods for manipulating tablespaces: ts_count(), add_ts(), get_ts() and get_tablespaces().
    - Add Image_info::m_ts_map member for storing mapping from tablespace numbers to Ts objects.

  sql/backup/kernel.cc@stripped, 2008-04-21 12:45:27+02:00, rafal@quant.(none) +79 -18
    - Extend bcat_add_item() to handle tablespaces.
    - In bcat_iterator_get(): 1) create tablespace iterator, 2) create dedicated iterator for global objects.
    - Also there, change error message to more appropriate ER_BACKUP_CAT_ENUM.
    - In bcat_create_item() add logic detecting whether a given tablespace already exists.
    - In places where THD structure is needed, use the one stored in Backup_restore_ctx object instead of current_thd.

  sql/backup/restore_info.h@stripped, 2008-04-21 12:45:27+02:00, rafal@quant.(none) +46 -1
    Add to Restore_info class wrappers around Image_info::add_*() methods. These wrappers
    report errors if any.

  sql/backup/stream_v1.h@stripped, 2008-04-21 12:45:27+02:00, rafal@quant.(none) +1 -1
    Fix a typo.

  sql/share/errmsg.txt@stripped, 2008-04-21 12:45:27+02:00, rafal@quant.(none) +11 -3
    - Fix format of ER_BACKUP_ADD_{DB,TABLE} to make it consistent with other messages.
    - Add error messages used by backup kernel tablespace support code.

  sql/si_objects.cc@stripped, 2008-04-21 12:45:26+02:00, rafal@quant.(none) +4 -4
    Adapt to the recent changes introduced in si_objects (post merge fix).

diff -Nrup a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def
--- a/mysql-test/t/disabled.def	2008-04-17 15:28:22 +02:00
+++ b/mysql-test/t/disabled.def	2008-04-21 12:45:26 +02:00
@@ -31,7 +31,6 @@ backup_progress       :BUG#34235 pending
 backup_security       :BUG#34235 pending replacement of test facility with WL#4259
 backup_snapshot       :BUG#34235 pending replacement of test facility with WL#4259
 backup_no_engine     : Bug#36021 2008-04-13 rsomla server crashes when openning table with unknown storage engine
-backup_tablespace    : WL#4347 2008-04-17 rsomla must wait for WL to get tablespace support in the backup kernel
 csv_alter_table      : Bug#33696 2008-01-21 pcrews no .result file - bug allows NULL columns in CSV tables
 ctype_latin2_ch      : BUG #33791 2008-01-18 mats Wrong ORDER BY with latin2_czech_cs
 
diff -Nrup a/sql/backup/backup_info.cc b/sql/backup/backup_info.cc
--- a/sql/backup/backup_info.cc	2008-03-21 09:43:43 +01:00
+++ b/sql/backup/backup_info.cc	2008-04-21 12:45:26 +02:00
@@ -126,6 +126,47 @@ Backup_info::find_backup_engine(const ba
 
  *************************************************/
 
+/*
+  Definition of Backup_info::Ts_hash_node structure used by Backup_info::ts_hash
+  HASH.
+ */ 
+
+struct Backup_info::Ts_hash_node
+{
+  const String *name;	///< Name of the tablespace.
+  Ts *it;               ///< Catalogue entry holding the tablespace (if exists).
+
+  Ts_hash_node(const String*);
+
+  static uchar* get_key(const uchar *record, size_t *key_length, my_bool);
+  static void free(void *record);
+};
+
+inline
+Backup_info::Ts_hash_node::Ts_hash_node(const String *name) :name(name), it(NULL)
+{}
+
+void Backup_info::Ts_hash_node::free(void *record)
+{
+  delete (Ts_hash_node*)record;
+}
+
+uchar* Backup_info::Ts_hash_node::get_key(const uchar *record, 
+                                          size_t *key_length, 
+                                          my_bool)
+{
+  Ts_hash_node *n= (Ts_hash_node*)record;
+
+  // ts_hash entries are indexed by tablespace name.
+
+  if (n->name && key_length)
+    *key_length= n->name->length();
+
+  return (uchar*)(n->name->ptr());
+}
+
+
+
 /**
   Create @c Backup_info instance and prepare it for populating with objects.
  
@@ -142,6 +183,9 @@ Backup_info::Backup_info(Backup_restore_
 
   bzero(m_snap, sizeof(m_snap));
 
+  hash_init(&ts_hash, &::my_charset_bin, 16, 0, 0,
+            Ts_hash_node::get_key, Ts_hash_node::free, MYF(0));
+
   /* 
     Create default and CS snapshot objects and add them to the snapshots list.
     Note that the default snapshot should be the last element on that list, as a
@@ -178,6 +222,8 @@ Backup_info::~Backup_info()
 
   while ((snap= it++))
     delete snap;
+
+  hash_free(&ts_hash);  
 }
 
 /**
@@ -204,6 +250,72 @@ int Backup_info::close()
 }  
 
 /**
+  Add tablespace to backup catalogue.
+
+  @param[in]	obj		sever object representing the tablespace
+  
+  If tablespace is already present in the catalogue, the existing catalogue entry
+  is returned. Otherwise a new entry is created and tablespace info stored in it.
+  
+  @return Pointer to (the new or existing) catalogue entry holding info about the
+  tablespace.  
+ */ 
+backup::Image_info::Ts* Backup_info::add_ts(obs::Obj *obj)
+{
+  const String *name;
+
+  DBUG_ASSERT(obj);
+  name= obj->get_name();
+  DBUG_ASSERT(name);
+
+  /* 
+    Check if tablespace with that name is already present in the catalogue using
+    ts_hash.
+  */
+
+  Ts_hash_node n0(name);
+  size_t klen;
+  uchar  *key= Ts_hash_node::get_key((const uchar*)&n0, &klen, TRUE);
+
+  Ts_hash_node *n1= (Ts_hash_node*) hash_search(&ts_hash, key, klen);
+
+  // if tablespace was found, return the catalogue entry stored in the hash
+  if (n1)
+    return n1->it;
+
+  // otherwise create a new catalogue entry
+
+  ulong pos= ts_count();
+
+  Ts *ts= Image_info::add_ts(*name, pos);
+
+  if (!ts)
+  {
+    m_ctx.fatal_error(ER_BACKUP_CATALOG_ADD_TS, name);
+    return NULL;
+  }
+
+  // store pointer to the server object instance
+
+  ts->m_obj_ptr= obj;
+
+  // add new entry to ts_hash
+
+  n1= new Ts_hash_node(n0);
+
+  if (!n1)
+  {
+    m_ctx.fatal_error(ER_OUT_OF_RESOURCES);
+    return NULL;
+  }
+
+  n1->it= ts;
+  my_hash_insert(&ts_hash, (uchar*)n1);
+
+  return ts;  
+}
+
+/**
   Select database object for backup.
   
   The object is added to the backup catalogue as an instance of 
@@ -218,11 +330,20 @@ backup::Image_info::Db* Backup_info::add
   ulong pos= db_count();
   
   DBUG_ASSERT(obj);
+
+  const ::String *name= obj->get_name();
   
-  Db *db= Image_info::add_db(*obj->get_name(), pos);  // reports errors
+  DBUG_ASSERT(name);  
+
+  Db *db= Image_info::add_db(*name, pos);
   
-  if (db)
-    db->m_obj_ptr= obj;
+  if (!db)
+  {
+    m_ctx.fatal_error(ER_BACKUP_CATALOG_ADD_DB, name->ptr());
+    return NULL;
+  }
+
+  db->m_obj_ptr= obj;
 
   return db;  
 }
@@ -429,6 +550,21 @@ int Backup_info::add_db_items(Db &db)
       delete obj;
       goto error;
     }
+
+    // If this table uses a tablespace, add this tablespace to the catalogue.
+
+    obj= get_tablespace_for_table(m_ctx.m_thd, &db.name(), &tbl->name());
+
+    if (obj)
+    {
+      Ts *ts= add_ts(obj); // reports errors
+
+      if (!ts)
+      {
+        delete obj;
+        goto error;
+      }
+    }
   }
 
   // Add other objects.
@@ -563,8 +699,8 @@ backup::Image_info::Table* Backup_info::
   
   if (!tbl)
   {
-    Tbl::describe_buf buf;
-    m_ctx.fatal_error(ER_BACKUP_CATALOG_ADD_TABLE, t.describe(buf));
+    m_ctx.fatal_error(ER_BACKUP_CATALOG_ADD_TABLE, 
+                      dbi.name().ptr(), t.name().ptr());
     return NULL;
   }
 
diff -Nrup a/sql/backup/backup_info.h b/sql/backup/backup_info.h
--- a/sql/backup/backup_info.h	2008-03-05 18:48:05 +01:00
+++ b/sql/backup/backup_info.h	2008-04-21 12:45:26 +02:00
@@ -52,6 +52,7 @@ class Backup_info: public backup::Image_
 
   backup::Snapshot_info* find_backup_engine(const backup::Table_ref&);
 
+  Ts* add_ts(obs::Obj*);
   Db* add_db(obs::Obj*);
   Dbobj* add_db_object(Db&, const obj_type, obs::Obj*);
   Table* add_table(Db&, obs::Obj*);
@@ -74,6 +75,16 @@ class Backup_info: public backup::Image_
     can be quickly located if it was already created. 
    */ 
   Map<storage_engine_ref, backup::Native_snapshot > native_snapshots;
+
+  struct Ts_hash_node;	///< Hash nodes used in @c ts_hash.
+
+  /**
+    Hash storing all tablespaces added to the backup catalogue.
+    
+    Used for quickly determining if the catalogue contains a given
+    tablespace or not.
+   */ 
+  HASH   ts_hash;
 
   String serialization_buf; ///< Used to store serialization strings of objects.
   
diff -Nrup a/sql/backup/backup_kernel.h b/sql/backup/backup_kernel.h
--- a/sql/backup/backup_kernel.h	2008-04-17 12:43:01 +02:00
+++ b/sql/backup/backup_kernel.h	2008-04-21 12:45:26 +02:00
@@ -1,8 +1,6 @@
 #ifndef _BACKUP_KERNEL_API_H
 #define _BACKUP_KERNEL_API_H
 
-#include <backup/backup_info.h>
-#include <backup/restore_info.h>
 #include <backup/logger.h>
 #include <backup/stream_services.h>
 
@@ -36,10 +34,15 @@ int execute_backup_command(THD*, LEX*);
 
 // forward declarations
 
+class Backup_info;
+class Restore_info;
+
 namespace backup {
 
 class Mem_allocator;
 class Stream;
+class Output_stream;
+class Input_stream;
 class Native_snapshot;
 
 int write_table_data(THD*, Logger&, Backup_info&, Output_stream&);
@@ -147,14 +150,18 @@ void Backup_restore_ctx::disable_fkey_co
   cannot be normally used. It still can be examined for saved error messages.
   The code of the error reported here is saved in m_error member.
   
-  When called multiple time, later calls overwrite error code saved by
-  the previous ones.
+  Only one fatal error can be reported. If context is already in error
+  state when this method is called, it does nothing.
   
-  @returns error code given as input.
+  @return error code given as input or stored in the context object if
+  a fatal error was reported before.
  */ 
 inline
 int Backup_restore_ctx::fatal_error(int error_code, ...)
 {
+  if (m_error)
+    return m_error;
+
   va_list args;
 
   m_error= error_code;
@@ -166,5 +173,13 @@ int Backup_restore_ctx::fatal_error(int 
 
   return error_code;
 }
+
+/*
+  Now, when Backup_restore_ctx is defined, include definitions
+  of Backup_info and Restore_info classes.
+*/
+
+#include <backup/backup_info.h>
+#include <backup/restore_info.h>
 
 #endif
diff -Nrup a/sql/backup/image_info.cc b/sql/backup/image_info.cc
--- a/sql/backup/image_info.cc	2008-04-17 12:43:53 +02:00
+++ b/sql/backup/image_info.cc	2008-04-21 12:45:26 +02:00
@@ -14,7 +14,7 @@
 namespace backup {
 
 Image_info::Image_info()
-  :data_size(0), m_table_count(0), m_dbs(16, 16)
+  :data_size(0), m_table_count(0), m_dbs(16, 16), m_ts_map(16,16)
 {
   init_alloc_root(&mem_root, 4 * 1024, 0);
 
@@ -51,15 +51,25 @@ Image_info::Image_info()
 
 Image_info::~Image_info()
 {
-  Db_iterator dbit(*this);
-  Db *db;
-
   /* 
     We need to explicitly call destructors for all objects in the catalogue
     since they are allocated using mem_root and thus destructors will not be
     invoked when the mem_root is freed.
   */
-  
+
+  // first tablespaces
+
+  Ts_iterator tsit(*this);
+  Ts *ts;
+
+  while ((ts= static_cast<Ts*>(tsit++)))
+    ts->~Ts();
+
+  Db_iterator dbit(*this);
+  Db *db;
+
+  // then databases and all objects inside each database
+
   while ((db= static_cast<Db*>(dbit++)))
   {
     // iterate over objects in the database
@@ -95,6 +105,10 @@ Image_info::add_db(const String &db_name
   if (!db)
     return NULL;
   
+  // call destructor if position is occupied
+  if (m_dbs[pos])
+    m_dbs[pos]->~Db();
+
   if (m_dbs.insert(pos, db))
     return NULL;
   
@@ -104,17 +118,34 @@ Image_info::add_db(const String &db_name
 }
 
 /**
-  Return database stored in the catalogue.
+  Add tablespace to the catalogue.
 
-  @param[in]  pos positon of the database in the catalogue
+  @param[in] ts_name  name of the tablespace
+  @param[in] pos      position at which this database should be stored
 
-  @returns Pointer to @c Image_info::Db instance storing information 
-  about the database or NULL if no database is stored at given position.
- */ 
-Image_info::Db* 
-Image_info::get_db(uint pos) const
+  @returns Pointer to @c Image_info::Ts instance storing information 
+  about the tablespace or NULL in case of error.
+
+  @see @c get_ts().
+ */
+Image_info::Ts* 
+Image_info::add_ts(const String &ts_name, uint pos)
 {
-  return m_dbs[pos];
+  Ts *ts= new (&mem_root) Ts(ts_name);
+  
+  if (!ts)
+    return NULL;
+  
+  // call destructor if position is occupied
+  if (m_ts_map[pos])
+    m_ts_map[pos]->~Ts();
+
+  if (m_ts_map.insert(pos, ts))
+    return NULL;
+  
+  ts->base.pos= pos;
+  
+  return ts;
 }
 
 /**
@@ -318,6 +349,9 @@ Image_info::Obj *find_obj(const Image_in
                           const st_bstream_item_info &item)
 {
   switch (item.type) {
+
+  case BSTREAM_IT_TABLESPACE:
+    return info.get_ts(item.pos);
 
   case BSTREAM_IT_DB:
     return info.get_db(item.pos);
diff -Nrup a/sql/backup/image_info.h b/sql/backup/image_info.h
--- a/sql/backup/image_info.h	2008-04-17 12:44:07 +02:00
+++ b/sql/backup/image_info.h	2008-04-21 12:45:27 +02:00
@@ -53,12 +53,15 @@ public: // public interface
    typedef enum_bstream_item_type obj_type;
 
    class Obj;   ///< Base for all object classes.
+   class Ts;    ///< Class representing a tablespace.
    class Db;    ///< Class representing a database.
    class Table; ///< Class representing a table.
    class Dbobj; ///< Class representing a per-database object other than table.
 
    class Iterator;      ///< Base for all iterators.
+   class Ts_iterator;   ///< Iterates over all tablespaces.
    class Db_iterator;   ///< Iterates over all databases.
+   class Global_iterator; ///< Iterates over global items (for which meta-data is stored).
    class Perdb_iterator;  ///< Iterates over all per-database objects (except tables).
    class Dbobj_iterator;  ///< Iterates over objects in a database.
 
@@ -70,6 +73,7 @@ public: // public interface
 
    ulong      table_count() const;
    uint       db_count() const;
+   uint       ts_count() const;
    ushort     snap_count() const;
 
    // Examine contents of the catalogue.
@@ -79,14 +83,17 @@ public: // public interface
    // Retrieve objects using their coordinates.
 
    Db*    get_db(uint pos) const;
+   Ts*    get_ts(uint pos) const;
    Dbobj* get_db_object(uint db_num, ulong pos) const;
    Table* get_table(ushort snap_num, ulong pos) const;
 
    // Iterators for enumerating the contents of the archive.
 
-   Db_iterator*    get_dbs();
-   Perdb_iterator* get_perdb();
-   Dbobj_iterator* get_db_objects(const Db &db);
+   Db_iterator*     get_dbs() const;
+   Ts_iterator*     get_tablespaces() const;
+   Global_iterator* get_global() const;
+   Perdb_iterator*  get_perdb() const;
+   Dbobj_iterator*  get_db_objects(const Db &db) const;
 
    /**
      Pointers to @c Snapshot_info objects corresponding to the snapshots
@@ -112,6 +119,7 @@ public: // public interface
   
   int    add_snapshot(Snapshot_info&);
   Db*    add_db(const String &db_name, uint pos);
+  Ts*    add_ts(const String &db_name, uint pos);
   Dbobj* add_db_object(Db &db, const obj_type type,
                        const ::String &name, ulong pos);
   Table* add_table(Db &db, const ::String &table_name, 
@@ -132,6 +140,7 @@ public: // public interface
 
   MEM_ROOT  mem_root;    ///< Memory root used to allocate @c Obj instances.
   Map<uint, Db>   m_dbs; ///< Pointers to Db instances.
+  Map<uint, Ts>   m_ts_map; ///< Pointers to Ts instances.
   String    m_binlog_file; ///< To store binlog file name at VP time.
 
   // friends
@@ -357,6 +366,33 @@ Image_info::Obj::~Obj()
   delete m_obj_ptr;
 }
 
+
+/**
+  Specialization of @c Image_info::Obj for storing info about a tablespace.
+*/
+class Image_info::Ts
+ : public st_bstream_ts_info,
+   public Image_info::Obj
+{
+ public:
+
+  Ts(const ::String&);
+
+  const st_bstream_item_info* info() const;
+  const st_bstream_ts_info* ts_info() const;
+  obs::Obj* materialize(uint ver, const ::String &sdata);
+  const char* describe(describe_buf&) const;
+};
+
+inline
+Image_info::Ts::Ts(const ::String &name)
+{
+  bzero(&base, sizeof(base));
+  base.type= BSTREAM_IT_TABLESPACE;
+  store_name(name);
+}
+
+
 /**
   Specialization of @c Image_info::Obj for storing info about a database.
 */
@@ -539,6 +575,35 @@ inline
 Image_info::Iterator::~Iterator() 
 {}
 
+
+/**
+  Used to iterate over all tablespaces stored in a backup image.
+
+  @note Backup stream library infers position of each tablespace in the catalogue
+  from the order in which they are enumerated by this iterator. Therefore it
+  is important that tablespaces are listed in correct order - first tablespace 
+  at position 0, then at position 1 and so on.
+ */ 
+class Image_info::Ts_iterator
+ : public Image_info::Iterator
+{
+ public:
+
+  Ts_iterator(const Image_info&);
+
+ protected:
+
+  uint pos;
+  Obj* get_ptr() const;
+  bool next();
+};
+
+inline
+Image_info::Ts_iterator::Ts_iterator(const Image_info &info)
+  :Iterator(info), pos(0)
+{}
+
+
 /**
   Used to iterate over all databases stored in a backup image.
 
@@ -625,6 +690,93 @@ Image_info::Dbobj_iterator::Dbobj_iterat
 {}
 
 
+/**
+  Used to iterate over all global objects for which we store information in the
+  neta-data section of backup image.
+
+  Currently only global objects handled are tablespaces and databases.
+ */
+class Image_info::Global_iterator
+ : public Image_info::Iterator
+{
+  /**
+    Indicates whether tablespaces or databases are being currently enumerated.
+   */ 
+  enum { TABLESPACES, DATABASES, DONE } mode;
+
+  Iterator *m_it;	///< Points at the currently used iterator.
+  Obj *m_obj;	        ///< Points at next object to be returned by this iterator.
+
+ public:
+
+  Global_iterator(const Image_info&);
+
+ private:
+
+  Obj* get_ptr() const;
+  bool next();
+};
+
+inline
+Image_info::Global_iterator::Global_iterator(const Image_info &info)
+ :Iterator(info), mode(TABLESPACES), m_it(NULL), m_obj(NULL)
+{
+  m_it= m_info.get_tablespaces();
+  next();
+}
+
+
+inline
+Image_info::Obj*
+Image_info::Global_iterator::get_ptr() const
+{
+  return m_obj;
+}
+
+inline
+bool
+Image_info::Global_iterator::next()
+{
+  if (mode == DONE)
+    return FALSE;
+
+  DBUG_ASSERT(m_it);
+
+  // get next object from the current iterator
+  m_obj= (*m_it)++;
+
+  if (m_obj)
+    return TRUE;
+
+  /*
+    If the current iterator has finished (m_obj == NULL) then, depending on
+    the mode, either switch to the next iterator or mark end of the sequence.
+  */
+
+  delete m_it;
+
+  switch (mode) {
+
+  case TABLESPACES:
+
+    // We have finished enumerating tablespaces, move on to databases.
+    mode= DATABASES;
+    m_it= m_info.get_dbs();
+    m_obj= (*m_it)++;
+    return m_obj != NULL;
+
+  case DATABASES:
+
+    mode= DONE;
+
+  case DONE:
+
+    break;
+  }
+
+  return FALSE;
+}
+
 /********************************************************************
  
    Inline members of Image_info class 
@@ -638,6 +790,13 @@ uint Image_info::db_count() const
   return m_dbs.count();
 }
 
+/// Returns number of tablespaces in the image.
+inline
+uint Image_info::ts_count() const
+{ 
+  return m_ts_map.count();
+}
+
 /// Returns total number of tables in the image.
 inline
 ulong Image_info::table_count() const
@@ -652,6 +811,36 @@ ushort Image_info::snap_count() const
   return st_bstream_image_header::snap_count;
 }
 
+
+/**
+  Return database stored in the catalogue.
+
+  @param[in]  pos positon of the database in the catalogue
+
+  @returns Pointer to @c Image_info::Db instance storing information 
+  about the database or NULL if no database is stored at given position.
+ */ 
+inline
+Image_info::Db* Image_info::get_db(uint pos) const
+{
+  return m_dbs[pos];
+}
+
+/**
+  Return tablespace stored in the catalogue.
+
+  @param[in]  pos positon of the tablespace in the catalogue
+
+  @returns Pointer to @c Image_info::Ts instance storing information 
+  about the tablespace or NULL if no tablespace is stored at given position.
+ */ 
+inline
+Image_info::Ts* Image_info::get_ts(uint pos) const
+{
+  return m_ts_map[pos];
+}
+
+
 /**
   Save time inside a @c bstream_time_t structure (helper function).
  */ 
@@ -711,24 +900,50 @@ void Image_info::save_binlog_pos(const :
   binlog_pos.file= const_cast<char*>(m_binlog_file.ptr());
 }
 
+/// Returns an iterator enumerating all databases stored in backup catalogue.
 inline
-Image_info::Db_iterator* Image_info::get_dbs()
+Image_info::Db_iterator* Image_info::get_dbs() const
 {
   return new Db_iterator(*this);
 }
 
+/// Returns an iterator enumerating all tablespaces stored in backup catalogue.
 inline
-Image_info::Perdb_iterator* Image_info::get_perdb()
+Image_info::Ts_iterator* Image_info::get_tablespaces() const
+{
+  return new Ts_iterator(*this);
+}
+
+/** 
+  Returns an iterator enumerating all per-database objects (from all databases)
+  for which we store meta-data.
+  
+  @note This iterator enumerates only non-table objects - tables are handled
+  separately.
+ */
+inline
+Image_info::Perdb_iterator* Image_info::get_perdb() const
 {
   return new Perdb_iterator(*this);
 }
 
+/// Returns an iterator enumerating all objects in a given database.
 inline
-Image_info::Dbobj_iterator* Image_info::get_db_objects(const Db &db)
+Image_info::Dbobj_iterator* Image_info::get_db_objects(const Db &db) const
 {
   return new Dbobj_iterator(*this, db);
 }
 
+/** 
+  Returns an iterator enumerating all global objects for which we need to store
+  some meta-data.
+ */
+inline
+Image_info::Global_iterator* Image_info::get_global() const
+{
+  return new Global_iterator(*this);
+}
+
 /********************************************************************
  
    Inline members of Image_info::Tables class.
@@ -804,6 +1019,20 @@ const st_bstream_db_info* Image_info::Db
 
 /// Implementation of @c Image_info::Obj virtual method.
 inline
+const st_bstream_item_info* Image_info::Ts::info() const 
+{
+  return &base; 
+}
+
+inline
+const st_bstream_ts_info* Image_info::Ts::ts_info() const 
+{
+  return this; 
+}
+
+
+/// Implementation of @c Image_info::Obj virtual method.
+inline
 const st_bstream_item_info* Image_info::Table::info() const 
 {
   return &base.base; 
@@ -819,6 +1048,14 @@ const st_bstream_item_info* Image_info::
 
 /// Implementation of @c Image_info::Obj virtual method.
 inline
+const char* Image_info::Ts::describe(describe_buf &buf) const
+{
+  my_snprintf(buf, sizeof(buf), "`%s`", Obj::m_name.ptr());
+  return buf;
+}
+
+/// Implementation of @c Image_info::Obj virtual method.
+inline
 const char* Image_info::Db::describe(describe_buf &buf) const
 {
   my_snprintf(buf, sizeof(buf), "`%s`", Obj::m_name.ptr());
@@ -842,6 +1079,14 @@ const char* Image_info::Dbobj::describe(
 
 /// Implementation of @c Image_info::Obj virtual method.
 inline
+obs::Obj* Image_info::Ts::materialize(uint ver, const ::String &sdata)
+{
+  delete m_obj_ptr;
+  return m_obj_ptr= obs::materialize_tablespace(&m_name, ver, &sdata); 
+}
+
+/// Implementation of @c Image_info::Obj virtual method.
+inline
 obs::Obj* Image_info::Db::materialize(uint ver, const ::String &sdata)
 {
   delete m_obj_ptr;
@@ -1003,6 +1248,33 @@ inline
 bool Image_info::Db_iterator::next()
 {
   if (pos < m_info.db_count())
+  {
+    pos++;
+    return TRUE;
+  }
+  else
+    return FALSE;
+}
+
+
+/// Implementation of @c Image_info::Iterator virtual method.
+inline
+Image_info::Obj* Image_info::Ts_iterator::get_ptr() const
+{
+  /*
+    There should be no "holes" in the sequence of tablespaces. That is,
+    if there are N tablespaces in the catalogue then for i=0,1,..,N-1, 
+    m_info.m_ts_map[i] should store pointer to the i-th database.
+   */ 
+  DBUG_ASSERT(pos >= m_info.ts_count() || m_info.m_ts_map[pos]);
+  return m_info.m_ts_map[pos];
+}
+
+/// Implementation of @c Image_info::Iterator virtual method.
+inline
+bool Image_info::Ts_iterator::next()
+{
+  if (pos < m_info.ts_count())
   {
     pos++;
     return TRUE;
diff -Nrup a/sql/backup/kernel.cc b/sql/backup/kernel.cc
--- a/sql/backup/kernel.cc	2008-04-17 15:28:22 +02:00
+++ b/sql/backup/kernel.cc	2008-04-21 12:45:27 +02:00
@@ -61,6 +61,8 @@
 #include "../si_objects.h"
 
 #include "backup_kernel.h"
+#include "backup_info.h"
+#include "restore_info.h"
 #include "logger.h"
 #include "stream.h"
 #include "debug.h"
@@ -1072,14 +1074,18 @@ int bcat_add_item(st_bstream_image_heade
 
   switch (item->type) {
 
+  case BSTREAM_IT_TABLESPACE:
+  {
+    Image_info::Ts *ts= info->add_ts(name_str, item->pos); // reports errors
+
+    return ts ? BSTREAM_OK : BSTREAM_ERROR;
+  }
+
   case BSTREAM_IT_DB:
   {
     Image_info::Db *db= info->add_db(name_str, item->pos); // reports errors
 
-    if (!db)
-      return BSTREAM_ERROR;
-
-    return BSTREAM_OK;
+    return db ? BSTREAM_OK : BSTREAM_ERROR;
   }
 
   case BSTREAM_IT_TABLE:
@@ -1112,10 +1118,7 @@ int bcat_add_item(st_bstream_image_heade
     Image_info::Table *tbl= info->add_table(*db, name_str, *snap, item->pos); 
                                                              // reports errors
     
-    if (!tbl)
-      return BSTREAM_ERROR;
-
-    return BSTREAM_OK;
+    return tbl ? BSTREAM_OK : BSTREAM_ERROR;
   }
 
   case BSTREAM_IT_VIEW:
@@ -1167,7 +1170,6 @@ void* bcat_iterator_get(st_bstream_image
   switch (type) {
 
   case BSTREAM_IT_PERTABLE: // per-table objects
-  case BSTREAM_IT_TABLESPACE: // tablespaces - not supported yet
     return &null_iter;
 
   case BSTREAM_IT_CHARSET:  // character sets
@@ -1177,13 +1179,39 @@ void* bcat_iterator_get(st_bstream_image
   case BSTREAM_IT_USER:     // users
     return &null_iter;
 
+  case BSTREAM_IT_TABLESPACE:     // table spaces
+  {
+    Backup_info::Ts_iterator *it= info->get_tablespaces();
+  
+    if (!it)
+    {
+      info->m_ctx.fatal_error(ER_BACKUP_CAT_ENUM);
+      return NULL;
+    }
+
+    return it;
+  }
+
+  case BSTREAM_IT_DB:       // all databases
+  {
+    Backup_info::Db_iterator *it= info->get_dbs();
+  
+    if (!it)
+    {
+      info->m_ctx.fatal_error(ER_BACKUP_CAT_ENUM);
+      return NULL;
+    }
+
+    return it;
+  }
+  
   case BSTREAM_IT_PERDB:    // per-db objects, except tables
   {
     Backup_info::Perdb_iterator *it= info->get_perdb();
   
     if (!it)
     {
-      info->m_ctx.fatal_error(ER_BACKUP_LIST_PERDB);
+      info->m_ctx.fatal_error(ER_BACKUP_CAT_ENUM);
       return NULL;
     }
 
@@ -1191,14 +1219,12 @@ void* bcat_iterator_get(st_bstream_image
   }
 
   case BSTREAM_IT_GLOBAL:   // all global objects
-    // note: only global items (for which meta-data is stored) are databases
-  case BSTREAM_IT_DB:       // all databases
   {
-    Backup_info::Db_iterator *it= info->get_dbs();
+    Backup_info::Global_iterator *it= info->get_global();
   
     if (!it)
     {
-      info->m_ctx.fatal_error(ER_BACKUP_LIST_DBS);
+      info->m_ctx.fatal_error(ER_BACKUP_CAT_ENUM);
       return NULL;
     }
 
@@ -1347,6 +1373,7 @@ int bcat_create_item(st_bstream_image_he
   DBUG_ASSERT(item);
 
   Restore_info *info= static_cast<Restore_info*>(catalogue);
+  THD *thd= info->m_ctx.thd();
   int create_err= 0;
 
   switch (item->type) {
@@ -1358,6 +1385,7 @@ int bcat_create_item(st_bstream_image_he
   case BSTREAM_IT_SFUNC:  create_err= ER_BACKUP_CANT_RESTORE_SROUT; break;
   case BSTREAM_IT_EVENT:  create_err= ER_BACKUP_CANT_RESTORE_EVENT; break;
   case BSTREAM_IT_TRIGGER: create_err= ER_BACKUP_CANT_RESTORE_TRIGGER; break;
+  case BSTREAM_IT_TABLESPACE: create_err= ER_BACKUP_CANT_RESTORE_TS; break;
   
   /*
     TODO: Decide what to do when we come across unknown item:
@@ -1389,16 +1417,48 @@ int bcat_create_item(st_bstream_image_he
   obs::Obj *sobj= obj->materialize(0, sdata);
 
   Image_info::Obj::describe_buf buf;
+  const char *desc= obj->describe(buf);
 
   if (!sobj)
   {
-    info->m_ctx.fatal_error(create_err, obj->describe(buf));
+    info->m_ctx.fatal_error(create_err, desc);
     return BSTREAM_ERROR;
   }
 
-  if (sobj->execute(::current_thd))
+  // If we are to create a tablespace, first check if it already exists.
+
+  if (item->type == BSTREAM_IT_TABLESPACE)
+  {
+    // if the tablespace exists, there is nothing more to do
+    if (obs::tablespace_exists(thd, sobj))
+    {
+      DBUG_PRINT("restore",(" skipping tablespace which exists"));
+      return BSTREAM_OK;
+    }
+
+    /* 
+      If there is a different tablespace with the same name then we can't 
+      re-create the original tablespace used by tables being restored. We report 
+      this and cancel restore process.
+    */ 
+
+    Obj *ts= obs::is_tablespace(thd, sobj->get_name()); 
+
+    if (ts)
+    {
+      DBUG_PRINT("restore",(" tablespace has changed on the server - aborting"));
+      info->m_ctx.fatal_error(ER_BACKUP_TS_CHANGE, desc,
+                              obs::describe_tablespace(sobj)->ptr(),
+                              obs::describe_tablespace(ts)->ptr());
+      return BSTREAM_ERROR;
+    }
+  }
+
+  // Create the object.
+
+  if (sobj->execute(thd))
   {
-    info->m_ctx.fatal_error(create_err, obj->describe(buf));
+    info->m_ctx.fatal_error(create_err, desc);
     return BSTREAM_ERROR;
   }
   
@@ -1440,6 +1500,7 @@ int bcat_get_item_create_query(st_bstrea
   case BSTREAM_IT_SFUNC:  meta_err= ER_BACKUP_GET_META_SROUT; break;
   case BSTREAM_IT_EVENT:  meta_err= ER_BACKUP_GET_META_EVENT; break;
   case BSTREAM_IT_TRIGGER: meta_err= ER_BACKUP_GET_META_TRIGGER; break;
+  case BSTREAM_IT_TABLESPACE: meta_err= ER_BACKUP_GET_META_TS; break;
   
   /*
     This can't happen - the item was obtained from the backup kernel.
@@ -1467,7 +1528,7 @@ int bcat_get_item_create_query(st_bstrea
   ::String *buf= &(info->serialization_buf);
   buf->length(0);
 
-  if (obj->m_obj_ptr->serialize(::current_thd, buf))
+  if (obj->m_obj_ptr->serialize(info->m_ctx.thd(), buf))
   {
     Image_info::Obj::describe_buf dbuf;
 
diff -Nrup a/sql/backup/restore_info.h b/sql/backup/restore_info.h
--- a/sql/backup/restore_info.h	2008-03-04 17:06:24 +01:00
+++ b/sql/backup/restore_info.h	2008-04-21 12:45:27 +02:00
@@ -1,10 +1,10 @@
 #ifndef RESTORE_INFO_H_
 #define RESTORE_INFO_H_
 
+#include <backup_kernel.h>
 #include <backup/image_info.h>
 #include <backup/stream_services.h>
 
-class Backup_restore_ctx;
 class Restore_info;
 
 namespace backup {
@@ -40,6 +40,11 @@ class Restore_info: public backup::Image
 
   bool is_valid() const;
 
+  Image_info::Ts* add_ts(const ::String&, uint);
+  Image_info::Db* add_db(const ::String&, uint);
+  Image_info::Table* add_table(Image_info::Db&, const ::String&, 
+                               backup::Snapshot_info&, ulong);
+
  private:
 
   friend int backup::restore_table_data(THD*, backup::Logger&, Restore_info&, 
@@ -67,6 +72,46 @@ inline
 bool Restore_info::is_valid() const
 {
   return TRUE; 
+}
+
+/// Wrapper around Image_info method which reports errors.
+inline
+backup::Image_info::Ts* 
+Restore_info::add_ts(const ::String &name, uint pos)
+{
+  Ts *ts= Image_info::add_ts(name, pos);
+
+  if (!ts)
+    m_ctx.fatal_error(ER_BACKUP_CATALOG_ADD_TS, name.ptr());
+
+  return ts;
+}
+
+/// Wrapper around Image_info method which reports errors.
+inline
+backup::Image_info::Db* 
+Restore_info::add_db(const ::String &name, uint pos)
+{
+  Db *db= Image_info::add_db(name, pos);
+
+  if (!db)
+    m_ctx.fatal_error(ER_BACKUP_CATALOG_ADD_DB, name.ptr());
+
+  return db;
+}
+
+/// Wrapper around Image_info method which reports errors.
+inline
+backup::Image_info::Table* 
+Restore_info::add_table(Image_info::Db &db, const ::String &name, 
+                        backup::Snapshot_info &snap, ulong pos)
+{
+  Table *t= Image_info::add_table(db, name, snap, pos);
+
+  if (!t)
+    m_ctx.fatal_error(ER_BACKUP_CATALOG_ADD_TABLE, db.name().ptr(), name.ptr());
+
+  return t;
 }
 
 #endif /*RESTORE_INFO_H_*/
diff -Nrup a/sql/backup/stream_v1.h b/sql/backup/stream_v1.h
--- a/sql/backup/stream_v1.h	2008-04-17 12:42:27 +02:00
+++ b/sql/backup/stream_v1.h	2008-04-21 12:45:27 +02:00
@@ -251,7 +251,7 @@ struct st_bstream_ts_info
 /**
   Describes database item.
 
-  Currently no data specific to database items is used.
+  Currently no data specific to database items are used.
 */
 struct st_bstream_db_info
 {
diff -Nrup a/sql/share/errmsg.txt b/sql/share/errmsg.txt
--- a/sql/share/errmsg.txt	2008-04-17 12:49:06 +02:00
+++ b/sql/share/errmsg.txt	2008-04-21 12:45:27 +02:00
@@ -6275,9 +6275,9 @@ ER_BACKUP_CANT_RESTORE_EVENT
 ER_BACKUP_CANT_RESTORE_TRIGGER
 	eng "Could not restore trigger %-.64s"
 ER_BACKUP_CATALOG_ADD_DB
-	eng "Failed to add database %-.64s to the catalog"
+	eng "Failed to add database `%-.64s` to the catalog"
 ER_BACKUP_CATALOG_ADD_TABLE
-	eng "Failed to add table %-.64s to the catalog"
+	eng "Failed to add table `%-.64s`.`%-.64s` to the catalog"
 ER_BACKUP_CATALOG_ADD_VIEW
 	eng "Failed to add view `%-.64s`.`%-.64s` to the catalog"
 ER_BACKUP_CATALOG_ADD_SROUT
@@ -6340,5 +6340,13 @@ ER_BACKUP_LOG_WRITE_ERROR
 ER_TABLESPACE_NOT_EMPTY
   eng "Tablespace '%-.192s' not empty"
 
+ER_BACKUP_CAT_ENUM
+        eng "Could not access the contents of the backup catalog when writing backup image preamble"
+ER_BACKUP_CANT_RESTORE_TS
+        eng "Could not create tablespace %-.64s needed by tables being restored."
 ER_BACKUP_TS_CHANGE
-        eng "Tablespace `%-.64s` needed by tables being restored has changed on the server. The original definition of the required tablespace is '%-.256s' while the same tablespace is defined on the server as '%-.256s'"
+        eng "Tablespace %-.64s needed by tables being restored has changed on the server. The original definition of the required tablespace is '%-.256s' while the same tablespace is defined on the server as '%-.256s'"
+ER_BACKUP_GET_META_TS
+        eng "Failed to obtain meta-data for tablespace %-.64s."
+ER_BACKUP_CATALOG_ADD_TS
+        eng "Failed to add tablespace `%-.64s` to the catalog"
diff -Nrup a/sql/si_objects.cc b/sql/si_objects.cc
--- a/sql/si_objects.cc	2008-04-17 12:42:26 +02:00
+++ b/sql/si_objects.cc	2008-04-21 12:45:26 +02:00
@@ -710,12 +710,12 @@ public:
   TablespaceObj(const String *ts_name);
   
 public:
-  virtual bool serialize(THD *thd, String *serialization);
+  virtual bool do_serialize(THD *thd, String *serialization);
 
   virtual bool materialize(uint serialization_version,
                            const String *serialization);
 
-  virtual bool execute(THD *thd);
+  virtual bool do_execute(THD *thd);
 
   const String *describe();
 
@@ -2433,7 +2433,7 @@ TablespaceObj::TablespaceObj(const Strin
     @retval FALSE on success
     @retval TRUE on error
 */
-bool TablespaceObj::serialize(THD *thd, String *serialization)
+bool TablespaceObj::do_serialize(THD *thd, String *serialization)
 {
   DBUG_ENTER("TablespaceObj::serialize()");
   build_serialization();
@@ -2528,7 +2528,7 @@ const String *TablespaceObj::build_seria
     @retval FALSE on success
     @retval TRUE on error
 */
-bool TablespaceObj::execute(THD *thd)
+bool TablespaceObj::do_execute(THD *thd)
 {
   DBUG_ENTER("TablespaceObj::execute()");
   build_serialization(); // Build the CREATE command.
Thread
bk commit into 6.0 tree (rafal:1.2611) WL#4347rsomla21 Apr