~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/statement/savepoint.cc

This patch significantly reworks the way that
savepoints are handled:

1) Memory management

   Removes the trans_prealloc_size and trans_block_size
   variables which set up a separate mem_root for storing
   "savepoint data".  Without the binlog, this separate
   memory root, which by default allocated 1M *for every
   single transaction regardless of whether savepoints
   were used*, was not useful any more.

2) No more DIY linked lists of SAVEPOINT pointers

   The Session::transaction struct used to contain a 
   member "savepoints" which was of type pointer to
   SAVEPOINT.  This has been replaced with an STL
   std::deque<drizzled::NamedSavepoint> and the pointeri and
   linked-list fiddling is gone, replaced with STL conventions.

3) SAVEPOINT struct is now drizzled::NamedSavepoint

   The SAVEPOINT struct has been converted to an STL container-
   safe class called drizzled::NamedSavepoint.

4) RollbackToSavepoint, Savepoint, and ReleaseSavepoint

   RollbackToSavepoint, Savepoint, and ReleaseSavepoint classes
   have had their logic revamped and documented.

5) The innodb.test case had (has?) an error in it

   The innodb.test case was testing a wrong assertion that
   a ROLLBACK TO SAVEPOINT x; should result in an error if
   called twice in a row.  This is incorrect behaviour.  If
   a ROLLBACK TO SAVEPOINT x; is executed, the savepoint x
   should stay on the top of the savepoint stack.

6) XID and XID_STATE classes made STL-container-safe

   Places proper initializer lists and constructors for
   the XID and XID_STATE classes and removes use of the
   horrible memset(this, 0, sizeof(*this)); usage.

7) The various savepoint-handling routines use references

   A switch was made to the various savepoint-handling routines
   of TransactionServices to ensure only references to a 
   drizzled::NamedSavepoint were being passed, and not void pointers.

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
#include <drizzled/session.h>
24
24
#include <drizzled/statement/savepoint.h>
25
25
#include "drizzled/transaction_services.h"
 
26
#include "drizzled/named_savepoint.h"
 
27
 
 
28
#include <string>
 
29
#include <deque>
 
30
 
 
31
using namespace std;
26
32
 
27
33
namespace drizzled
28
34
{
35
41
  }
36
42
  else
37
43
  {
38
 
    SAVEPOINT **sv, *newsv;
39
 
    for (sv= &session->transaction.savepoints; *sv; sv= &(*sv)->prev)
 
44
    /*
 
45
     * Look through the savepoints.  If we find one with
 
46
     * the same name, delete it.
 
47
     */
 
48
    TransactionServices &transaction_services= TransactionServices::singleton();
 
49
    deque<NamedSavepoint> &savepoints= session->transaction.savepoints;
 
50
    deque<NamedSavepoint>::iterator iter;
 
51
 
 
52
    for (iter= savepoints.begin();
 
53
         iter != savepoints.end();
 
54
         ++iter)
40
55
    {
 
56
      NamedSavepoint &sv= *iter;
 
57
      const string &sv_name= sv.getName();
41
58
      if (my_strnncoll(system_charset_info,
42
59
                       (unsigned char *) session->lex->ident.str,
43
60
                       session->lex->ident.length,
44
 
                       (unsigned char *) (*sv)->name,
45
 
                       (*sv)->length) == 0)
46
 
        return false;
47
 
    }
48
 
    TransactionServices &transaction_services= TransactionServices::singleton();
49
 
    if (*sv) /* old savepoint of the same name exists */
50
 
    {
51
 
      newsv= *sv;
52
 
      transaction_services.ha_release_savepoint(session, *sv); // it cannot fail
53
 
      *sv= (*sv)->prev;
54
 
    }
55
 
    else if ((newsv= (SAVEPOINT *) alloc_root(&session->transaction.mem_root,
56
 
                                              savepoint_alloc_size)) == 0)
57
 
    {
58
 
      my_error(ER_OUT_OF_RESOURCES, MYF(0));
59
 
      return false;
60
 
    }
61
 
    newsv->name= strmake_root(&session->transaction.mem_root,
62
 
                              session->lex->ident.str,
63
 
                              session->lex->ident.length);
64
 
    newsv->length= session->lex->ident.length;
65
 
    /*
66
 
       if we'll get an error here, don't add new savepoint to the list.
67
 
       we'll lose a little bit of memory in transaction mem_root, but it'll
68
 
       be free'd when transaction ends anyway
69
 
     */
 
61
                       (unsigned char *) sv_name.c_str(),
 
62
                       sv_name.size()) == 0)
 
63
        break;
 
64
    }
 
65
    if (iter != savepoints.end())
 
66
    {
 
67
      NamedSavepoint &sv= *iter;
 
68
      (void) transaction_services.ha_release_savepoint(session, sv);
 
69
      savepoints.erase(iter);
 
70
    }
 
71
    
 
72
    NamedSavepoint newsv(session->lex->ident.str, session->lex->ident.length);
 
73
 
70
74
    if (transaction_services.ha_savepoint(session, newsv))
71
75
    {
72
76
      return true;
73
77
    }
74
78
    else
75
79
    {
76
 
      newsv->prev= session->transaction.savepoints;
77
 
      session->transaction.savepoints= newsv;
 
80
      savepoints.push_front(newsv);
78
81
      session->my_ok();
79
82
    }
80
83
  }