MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
semisync_slave_plugin.cc
1 /* Copyright (C) 2007 Google Inc.
2  Copyright (C) 2008 MySQL AB
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
16 
17 
18 #include "semisync_slave.h"
19 #include <mysql.h>
20 
21 ReplSemiSyncSlave repl_semisync;
22 
23 /*
24  indicate whether or not the slave should send a reply to the master.
25 
26  This is set to true in repl_semi_slave_read_event if the current
27  event read is the last event of a transaction. And the value is
28  checked in repl_semi_slave_queue_event.
29 */
30 bool semi_sync_need_reply= false;
31 
32 C_MODE_START
33 
34 int repl_semi_reset_slave(Binlog_relay_IO_param *param)
35 {
36  // TODO: reset semi-sync slave status here
37  return 0;
38 }
39 
40 int repl_semi_slave_request_dump(Binlog_relay_IO_param *param,
41  uint32 flags)
42 {
43  MYSQL *mysql= param->mysql;
44  MYSQL_RES *res= 0;
45  MYSQL_ROW row;
46  const char *query;
47 
48  if (!repl_semisync.getSlaveEnabled())
49  return 0;
50 
51  /* Check if master server has semi-sync plugin installed */
52  query= "SHOW VARIABLES LIKE 'rpl_semi_sync_master_enabled'";
53  if (mysql_real_query(mysql, query, strlen(query)) ||
54  !(res= mysql_store_result(mysql)))
55  {
56  sql_print_error("Execution failed on master: %s", query);
57  return 1;
58  }
59 
60  row= mysql_fetch_row(res);
61  if (!row)
62  {
63  /* Master does not support semi-sync */
64  sql_print_warning("Master server does not support semi-sync, "
65  "fallback to asynchronous replication");
66  rpl_semi_sync_slave_status= 0;
67  mysql_free_result(res);
68  return 0;
69  }
70  mysql_free_result(res);
71 
72  /*
73  Tell master dump thread that we want to do semi-sync
74  replication
75  */
76  query= "SET @rpl_semi_sync_slave= 1";
77  if (mysql_real_query(mysql, query, strlen(query)))
78  {
79  sql_print_error("Set 'rpl_semi_sync_slave=1' on master failed");
80  return 1;
81  }
82  mysql_free_result(mysql_store_result(mysql));
83  rpl_semi_sync_slave_status= 1;
84  return 0;
85 }
86 
87 int repl_semi_slave_read_event(Binlog_relay_IO_param *param,
88  const char *packet, unsigned long len,
89  const char **event_buf, unsigned long *event_len)
90 {
91  if (rpl_semi_sync_slave_status)
92  return repl_semisync.slaveReadSyncHeader(packet, len,
93  &semi_sync_need_reply,
94  event_buf, event_len);
95  *event_buf= packet;
96  *event_len= len;
97  return 0;
98 }
99 
100 int repl_semi_slave_queue_event(Binlog_relay_IO_param *param,
101  const char *event_buf,
102  unsigned long event_len,
103  uint32 flags)
104 {
105  if (rpl_semi_sync_slave_status && semi_sync_need_reply)
106  {
107  /*
108  We deliberately ignore the error in slaveReply, such error
109  should not cause the slave IO thread to stop, and the error
110  messages are already reported.
111  */
112  (void) repl_semisync.slaveReply(param->mysql,
113  param->master_log_name,
114  param->master_log_pos);
115  }
116  return 0;
117 }
118 
119 int repl_semi_slave_io_start(Binlog_relay_IO_param *param)
120 {
121  return repl_semisync.slaveStart(param);
122 }
123 
124 int repl_semi_slave_io_end(Binlog_relay_IO_param *param)
125 {
126  return repl_semisync.slaveStop(param);
127 }
128 
129 C_MODE_END
130 
131 static void fix_rpl_semi_sync_slave_enabled(MYSQL_THD thd,
132  SYS_VAR *var,
133  void *ptr,
134  const void *val)
135 {
136  *(char *)ptr= *(char *)val;
137  repl_semisync.setSlaveEnabled(rpl_semi_sync_slave_enabled != 0);
138  return;
139 }
140 
141 static void fix_rpl_semi_sync_trace_level(MYSQL_THD thd,
142  SYS_VAR *var,
143  void *ptr,
144  const void *val)
145 {
146  *(unsigned long *)ptr= *(unsigned long *)val;
147  repl_semisync.setTraceLevel(rpl_semi_sync_slave_trace_level);
148  return;
149 }
150 
151 /* plugin system variables */
152 static MYSQL_SYSVAR_BOOL(enabled, rpl_semi_sync_slave_enabled,
153  PLUGIN_VAR_OPCMDARG,
154  "Enable semi-synchronous replication slave (disabled by default). ",
155  NULL, // check
156  &fix_rpl_semi_sync_slave_enabled, // update
157  0);
158 
159 static MYSQL_SYSVAR_ULONG(trace_level, rpl_semi_sync_slave_trace_level,
160  PLUGIN_VAR_OPCMDARG,
161  "The tracing level for semi-sync replication.",
162  NULL, // check
163  &fix_rpl_semi_sync_trace_level, // update
164  32, 0, ~0UL, 1);
165 
166 static SYS_VAR* semi_sync_slave_system_vars[]= {
167  MYSQL_SYSVAR(enabled),
168  MYSQL_SYSVAR(trace_level),
169  NULL,
170 };
171 
172 
173 /* plugin status variables */
174 static SHOW_VAR semi_sync_slave_status_vars[]= {
175  {"Rpl_semi_sync_slave_status",
176  (char*) &rpl_semi_sync_slave_status, SHOW_BOOL},
177  {NULL, NULL, SHOW_BOOL},
178 };
179 
180 Binlog_relay_IO_observer relay_io_observer = {
181  sizeof(Binlog_relay_IO_observer), // len
182 
183  repl_semi_slave_io_start, // start
184  repl_semi_slave_io_end, // stop
185  repl_semi_slave_request_dump, // request_transmit
186  repl_semi_slave_read_event, // after_read_event
187  repl_semi_slave_queue_event, // after_queue_event
188  repl_semi_reset_slave, // reset
189 };
190 
191 static int semi_sync_slave_plugin_init(void *p)
192 {
193  if (repl_semisync.initObject())
194  return 1;
195  if (register_binlog_relay_io_observer(&relay_io_observer, p))
196  return 1;
197  return 0;
198 }
199 
200 static int semi_sync_slave_plugin_deinit(void *p)
201 {
202  if (unregister_binlog_relay_io_observer(&relay_io_observer, p))
203  return 1;
204  return 0;
205 }
206 
207 
208 struct Mysql_replication semi_sync_slave_plugin= {
209  MYSQL_REPLICATION_INTERFACE_VERSION
210 };
211 
212 /*
213  Plugin library descriptor
214 */
215 mysql_declare_plugin(semi_sync_slave)
216 {
217  MYSQL_REPLICATION_PLUGIN,
218  &semi_sync_slave_plugin,
219  "rpl_semi_sync_slave",
220  "He Zhenxing",
221  "Semi-synchronous replication slave",
222  PLUGIN_LICENSE_GPL,
223  semi_sync_slave_plugin_init, /* Plugin Init */
224  semi_sync_slave_plugin_deinit, /* Plugin Deinit */
225  0x0100 /* 1.0 */,
226  semi_sync_slave_status_vars, /* status variables */
227  semi_sync_slave_system_vars, /* system variables */
228  NULL, /* config options */
229  0, /* flags */
230 }
231 mysql_declare_plugin_end;