~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/replication/binlog.cc

  • Committer: Brian Aker
  • Date: 2009-01-23 02:15:04 UTC
  • mfrom: (798.2.32 drizzle)
  • Revision ID: brian@tangent.org-20090123021504-2j99e6hxab1ew601
Merge for replication removal.

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