~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_binlog.cc

  • Committer: Lee
  • Date: 2008-10-30 22:02:01 UTC
  • mto: (572.1.2 devel)
  • mto: This revision was merged to the branch mainline in revision 573.
  • Revision ID: lbieber@lbieber-desktop-20081030220201-elb6qprbzpn7c5a4
add my name to the AUTHORS file

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2005-2006 MySQL AB
 
2
 
 
3
   This program is free software; you can redistribute it and/or modify
 
4
   it under the terms of the GNU General Public License as published by
 
5
   the Free Software Foundation; version 2 of the License.
 
6
 
 
7
   This program is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
   GNU General Public License for more details.
 
11
 
 
12
   You should have received a copy of the GNU General Public License
 
13
   along with this program; if not, write to the Free Software
 
14
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
 
15
 
 
16
#include <drizzled/server_includes.h>
 
17
#include <drizzled/rpl_rli.h>
 
18
#include <mysys/base64.h>
 
19
#include <drizzled/error.h>
 
20
#include <drizzled/slave.h>
 
21
 
 
22
/**
 
23
  Execute a BINLOG statement
 
24
 
 
25
  To execute the BINLOG command properly the server needs to know
 
26
  which format the BINLOG command's event is in.  Therefore, the first
 
27
  BINLOG statement seen must be a base64 encoding of the
 
28
  Format_description_log_event, as outputted by mysqlbinlog.  This
 
29
  Format_description_log_event is cached in
 
30
  rli->description_event_for_exec.
 
31
*/
 
32
 
 
33
void mysql_client_binlog_statement(Session* session)
 
34
{
 
35
  size_t coded_len= session->lex->comment.length + 1;
 
36
  size_t decoded_len= base64_needed_decoded_length(coded_len);
 
37
  assert(coded_len > 0);
 
38
 
 
39
  /*
 
40
    Allocation
 
41
  */
 
42
 
 
43
  /*
 
44
    If we do not have a Format_description_event, we create a dummy
 
45
    one here.  In this case, the first event we read must be a
 
46
    Format_description_event.
 
47
  */
 
48
  bool have_fd_event= true;
 
49
  if (!session->rli_fake)
 
50
  {
 
51
    session->rli_fake= new Relay_log_info;
 
52
#ifdef HAVE_purify
 
53
    session->rli_fake->is_fake= true;
 
54
#endif
 
55
    have_fd_event= false;
 
56
  }
 
57
  if (session->rli_fake && !session->rli_fake->relay_log.description_event_for_exec)
 
58
  {
 
59
    session->rli_fake->relay_log.description_event_for_exec=
 
60
      new Format_description_log_event(4);
 
61
    have_fd_event= false;
 
62
  }
 
63
 
 
64
  const char *error= 0;
 
65
  char *buf= (char *) my_malloc(decoded_len, MYF(MY_WME));
 
66
  Log_event *ev = 0;
 
67
 
 
68
  /*
 
69
    Out of memory check
 
70
  */
 
71
  if (!(session->rli_fake &&
 
72
        session->rli_fake->relay_log.description_event_for_exec &&
 
73
        buf))
 
74
  {
 
75
    my_error(ER_OUTOFMEMORY, MYF(0), 1);  /* needed 1 bytes */
 
76
    goto end;
 
77
  }
 
78
 
 
79
  session->rli_fake->sql_session= session;
 
80
  session->rli_fake->no_storage= true;
 
81
 
 
82
  for (char const *strptr= session->lex->comment.str ;
 
83
       strptr < session->lex->comment.str + session->lex->comment.length ; )
 
84
  {
 
85
    char const *endptr= 0;
 
86
    int bytes_decoded= base64_decode(strptr, coded_len, buf, &endptr);
 
87
 
 
88
    if (bytes_decoded < 0)
 
89
    {
 
90
      my_error(ER_BASE64_DECODE_ERROR, MYF(0));
 
91
      goto end;
 
92
    }
 
93
    else if (bytes_decoded == 0)
 
94
      break; // If no bytes where read, the string contained only whitespace
 
95
 
 
96
    assert(bytes_decoded > 0);
 
97
    assert(endptr > strptr);
 
98
    coded_len-= endptr - strptr;
 
99
    strptr= endptr;
 
100
 
 
101
    /*
 
102
      Now we have one or more events stored in the buffer. The size of
 
103
      the buffer is computed based on how much base64-encoded data
 
104
      there were, so there should be ample space for the data (maybe
 
105
      even too much, since a statement can consist of a considerable
 
106
      number of events).
 
107
 
 
108
      TODO: Switch to use a stream-based base64 encoder/decoder in
 
109
      order to be able to read exactly what is necessary.
 
110
    */
 
111
 
 
112
    /*
 
113
      Now we start to read events of the buffer, until there are no
 
114
      more.
 
115
    */
 
116
    for (char *bufptr= buf ; bytes_decoded > 0 ; )
 
117
    {
 
118
      /*
 
119
        Checking that the first event in the buffer is not truncated.
 
120
      */
 
121
      uint32_t event_len= uint4korr(bufptr + EVENT_LEN_OFFSET);
 
122
      if (bytes_decoded < EVENT_LEN_OFFSET || (uint) bytes_decoded < event_len)
 
123
      {
 
124
        my_error(ER_SYNTAX_ERROR, MYF(0));
 
125
        goto end;
 
126
      }
 
127
 
 
128
      /*
 
129
        If we have not seen any Format_description_event, then we must
 
130
        see one; it is the only statement that can be read in base64
 
131
        without a prior Format_description_event.
 
132
      */
 
133
      if (!have_fd_event)
 
134
      {
 
135
        int type = bufptr[EVENT_TYPE_OFFSET];
 
136
        if (type == FORMAT_DESCRIPTION_EVENT || type == START_EVENT_V3)
 
137
          have_fd_event= true;
 
138
        else
 
139
        {
 
140
          my_error(ER_NO_FORMAT_DESCRIPTION_EVENT_BEFORE_BINLOG_STATEMENT,
 
141
                   MYF(0), Log_event::get_type_str((Log_event_type)type));
 
142
          goto end;
 
143
        }
 
144
      }
 
145
 
 
146
      ev= Log_event::read_log_event(bufptr, event_len, &error,
 
147
                                    session->rli_fake->relay_log.
 
148
                                      description_event_for_exec);
 
149
 
 
150
      if (!ev)
 
151
      {
 
152
        /*
 
153
          This could actually be an out-of-memory, but it is more likely
 
154
          causes by a bad statement
 
155
        */
 
156
        my_error(ER_SYNTAX_ERROR, MYF(0));
 
157
        goto end;
 
158
      }
 
159
 
 
160
      bytes_decoded -= event_len;
 
161
      bufptr += event_len;
 
162
 
 
163
      ev->session= session;
 
164
      /*
 
165
        We go directly to the application phase, since we don't need
 
166
        to check if the event shall be skipped or not.
 
167
 
 
168
        Neither do we have to update the log positions, since that is
 
169
        not used at all: the rli_fake instance is used only for error
 
170
        reporting.
 
171
      */
 
172
      if (apply_event_and_update_pos(ev, session, session->rli_fake, false))
 
173
      {
 
174
        /*
 
175
          TODO: Maybe a better error message since the BINLOG statement
 
176
          now contains several events.
 
177
        */
 
178
        my_error(ER_UNKNOWN_ERROR, MYF(0), "Error executing BINLOG statement");
 
179
        goto end;
 
180
      }
 
181
 
 
182
      /*
 
183
        Format_description_log_event should not be deleted because it
 
184
        will be used to read info about the relay log's format; it
 
185
        will be deleted when the SQL thread does not need it,
 
186
        i.e. when this thread terminates.
 
187
      */
 
188
      if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
 
189
        delete ev;
 
190
      ev= 0;
 
191
    }
 
192
  }
 
193
 
 
194
  my_ok(session);
 
195
 
 
196
end:
 
197
  session->rli_fake->clear_tables_to_lock();
 
198
  free(buf);
 
199
  return;
 
200
}