~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/replication/mi.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) 2000-2003 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
 
 
16
 
#include <drizzled/server_includes.h>
17
 
#include <drizzled/replication/mi.h>
18
 
#include <drizzled/gettext.h>
19
 
#include <drizzled/slave.h>
20
 
#include <drizzled/data_home.h>
21
 
 
22
 
#include <iostream>
23
 
#include <fstream>
24
 
 
25
 
using namespace std;
26
 
 
27
 
#define DEFAULT_CONNECT_RETRY 60
28
 
 
29
 
// Defined in slave.cc
30
 
int init_intvar_from_file(int* var, IO_CACHE* f, int default_val);
31
 
int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
32
 
                          const char *default_val);
33
 
int init_floatvar_from_file(float* var, IO_CACHE* f, float default_val);
34
 
 
35
 
Master_info::Master_info()
36
 
  :Slave_reporting_capability("I/O"),
37
 
   connect_retry(DEFAULT_CONNECT_RETRY), heartbeat_period(0),
38
 
   received_heartbeats(0), inited(0),
39
 
   abort_slave(0), slave_running(0), slave_run_id(0)
40
 
{
41
 
  host[0] = 0; user[0] = 0; password[0] = 0;
42
 
  io_session= NULL;
43
 
  port= DRIZZLE_PORT;
44
 
 
45
 
  pthread_mutex_init(&run_lock, MY_MUTEX_INIT_FAST);
46
 
  pthread_mutex_init(&data_lock, MY_MUTEX_INIT_FAST);
47
 
  pthread_cond_init(&data_cond, NULL);
48
 
  pthread_cond_init(&start_cond, NULL);
49
 
  pthread_cond_init(&stop_cond, NULL);
50
 
}
51
 
 
52
 
Master_info::~Master_info()
53
 
{
54
 
  pthread_mutex_destroy(&run_lock);
55
 
  pthread_mutex_destroy(&data_lock);
56
 
  pthread_cond_destroy(&data_cond);
57
 
  pthread_cond_destroy(&start_cond);
58
 
  pthread_cond_destroy(&stop_cond);
59
 
}
60
 
 
61
 
bool Master_info::setPassword(const char *pword)
62
 
{
63
 
  password.assign(pword);
64
 
 
65
 
  return true;
66
 
}
67
 
 
68
 
const char *Master_info::getPassword()
69
 
{
70
 
  return password.c_str();
71
 
}
72
 
 
73
 
bool Master_info::setUsername(const char *username)
74
 
{
75
 
  user.assign(username);
76
 
 
77
 
  return true;
78
 
}
79
 
 
80
 
const char *Master_info::getUsername()
81
 
{
82
 
  return user.c_str();
83
 
}
84
 
 
85
 
bool Master_info::setHost(const char *hostname, uint16_t new_port)
86
 
{
87
 
  host.assign(hostname);
88
 
  port= new_port;
89
 
 
90
 
  return true;
91
 
}
92
 
 
93
 
const char *Master_info::getHostname()
94
 
{
95
 
  return host.c_str();
96
 
}
97
 
 
98
 
uint16_t Master_info::getPort()
99
 
{
100
 
  return port;
101
 
}
102
 
 
103
 
off_t Master_info::getLogPosition()
104
 
{
105
 
  return log_pos;
106
 
}
107
 
 
108
 
bool Master_info::setLogPosition(off_t position)
109
 
{
110
 
  log_pos= position;
111
 
 
112
 
  return true;
113
 
}
114
 
 
115
 
void Master_info::incrementLogPosition(off_t position)
116
 
{
117
 
  log_pos+= position;
118
 
}
119
 
 
120
 
const char *Master_info::getLogName()
121
 
{
122
 
  return log_name.c_str();
123
 
}
124
 
 
125
 
bool Master_info::setLogName(const char *name)
126
 
{
127
 
 log_name.assign(name);
128
 
 
129
 
  return true;
130
 
}
131
 
 
132
 
uint32_t Master_info::getConnectionRetry()
133
 
{
134
 
  return connect_retry;
135
 
}
136
 
 
137
 
bool Master_info::setConnectionRetry(uint32_t retry)
138
 
{
139
 
  connect_retry= retry;
140
 
 
141
 
  return true;
142
 
}
143
 
 
144
 
 
145
 
void Master_info::reset()
146
 
{
147
 
  log_name.clear();
148
 
  log_pos= 0;
149
 
}
150
 
 
151
 
 
152
 
int Master_info::init_master_info(const char* master_info_fname,
153
 
                                  const char* slave_info_fname,
154
 
                                  int thread_mask)
155
 
{
156
 
  int error;
157
 
 
158
 
  if (inited)
159
 
  {
160
 
    /*
161
 
      We have to reset read position of relay-log-bin as we may have
162
 
      already been reading from 'hotlog' when the slave was stopped
163
 
      last time. If this case pos_in_file would be set and we would
164
 
      get a crash when trying to read the signature for the binary
165
 
      relay log.
166
 
 
167
 
      We only rewind the read position if we are starting the SQL
168
 
      thread. The handle_slave_sql thread assumes that the read
169
 
      position is at the beginning of the file, and will read the
170
 
      "signature" and then fast-forward to the last position read.
171
 
    */
172
 
    if (thread_mask & SLAVE_SQL)
173
 
    {
174
 
      my_b_seek(rli.cur_log, (my_off_t) 0);
175
 
    }
176
 
    return(0);
177
 
  }
178
 
 
179
 
  drizzle= 0;
180
 
  file_id= 1;
181
 
  {
182
 
    char fname[FN_REFLEN+128];
183
 
 
184
 
    fn_format(fname, master_info_fname, drizzle_data_home, "", 4+32);
185
 
    info_filename.assign(fname);
186
 
  }
187
 
 
188
 
  /*
189
 
    We need a mutex while we are changing master info parameters to
190
 
    keep other threads from reading bogus info
191
 
  */
192
 
 
193
 
  pthread_mutex_lock(&data_lock);
194
 
 
195
 
  /* does master.info exist ? */
196
 
 
197
 
  if (access(info_filename.c_str(), F_OK))
198
 
  {
199
 
    drizzle::MasterList_Record *record;
200
 
 
201
 
    reset();
202
 
 
203
 
    /* Write new Master info file here (from info_filename) */
204
 
    record= list.add_record();
205
 
    record->set_hostname(host);
206
 
    record->set_username(user);
207
 
    record->set_password(password);
208
 
    record->set_port(port);
209
 
    record->set_connect_retry(connect_retry);
210
 
    record->set_log_name(log_name);
211
 
    record->set_log_position(log_pos);
212
 
 
213
 
    fstream output(info_filename.c_str(), ios::out | ios::trunc | ios::binary);
214
 
    if (!list.SerializeToOstream(&output))
215
 
    {
216
 
      assert(0);
217
 
      return -1;
218
 
    }
219
 
  }
220
 
  else // file exists
221
 
  {
222
 
    /* Read Master info file here (from info_filename) */
223
 
    fstream input(info_filename.c_str(), ios::in | ios::binary);
224
 
    if (!list.ParseFromIstream(&input))
225
 
    {
226
 
      assert(0);
227
 
      return -1;
228
 
    }
229
 
 
230
 
    /* We do not support multi-master just yet */
231
 
    assert(list.record_size() == 1);
232
 
    const drizzle::MasterList_Record record= list.record(0);
233
 
 
234
 
    if (record.has_username())
235
 
      user= record.username();
236
 
    if (record.has_password())
237
 
      password= record.password();
238
 
    if (record.has_port())
239
 
      port= record.port();
240
 
    if (record.has_connect_retry())
241
 
      connect_retry= record.connect_retry();
242
 
    if (record.has_log_name())
243
 
      log_name= record.log_name();
244
 
    if (record.has_log_position())
245
 
      log_pos= record.log_position();
246
 
  }
247
 
 
248
 
  rli.mi = this;
249
 
  if (init_relay_log_info(&rli, slave_info_fname))
250
 
    goto err;
251
 
 
252
 
  inited= 1;
253
 
  if ((error= test(flush())))
254
 
    errmsg_printf(ERRMSG_LVL_ERROR, _("Failed to flush master info file"));
255
 
  pthread_mutex_unlock(&data_lock);
256
 
  return(error);
257
 
 
258
 
err:
259
 
  pthread_mutex_unlock(&data_lock);
260
 
  return 1;
261
 
}
262
 
 
263
 
 
264
 
/*
265
 
  RETURN
266
 
     2 - flush relay log failed
267
 
     1 - flush master info failed
268
 
     0 - all ok
269
 
*/
270
 
int Master_info::flush()
271
 
{
272
 
  /*
273
 
    Flush the relay log to disk. If we don't do it, then the relay log while
274
 
    have some part (its last kilobytes) in memory only, so if the slave server
275
 
    dies now, with, say, from master's position 100 to 150 in memory only (not
276
 
    on disk), and with position 150 in master.info, then when the slave
277
 
    restarts, the I/O thread will fetch binlogs from 150, so in the relay log
278
 
    we will have "[0, 100] U [150, infinity[" and nobody will notice it, so the
279
 
    SQL thread will jump from 100 to 150, and replication will silently break.
280
 
 
281
 
    When we come to this place in code, relay log may or not be initialized;
282
 
    the caller is responsible for setting 'flush_relay_log_cache' accordingly.
283
 
  */
284
 
 
285
 
  /* Write Master info file here (from info_filename) */
286
 
  assert(info_filename.length());
287
 
  assert(list.record_size() == 1);
288
 
  drizzle::MasterList_Record *record= list.mutable_record(0);
289
 
 
290
 
  record->set_hostname(host);
291
 
  record->set_username(user);
292
 
  record->set_password(password);
293
 
  record->set_port(port);
294
 
  record->set_connect_retry(connect_retry);
295
 
  record->set_log_name(log_name);
296
 
  record->set_log_position(log_pos);
297
 
 
298
 
  fstream output(info_filename.c_str(), ios::out | ios::trunc | ios::binary);
299
 
  if (!list.SerializeToOstream(&output))
300
 
  {
301
 
    assert(0);
302
 
    return 1;
303
 
  }
304
 
 
305
 
  return 0;
306
 
}
307
 
 
308
 
 
309
 
void Master_info::end_master_info()
310
 
{
311
 
  if (!inited)
312
 
    return;
313
 
  end_relay_log_info(&rli);
314
 
  inited = 0;
315
 
 
316
 
  return;
317
 
}