~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to storage/ndb/test/run-test/setup.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "atrt.hpp"
 
2
#include <ndb_global.h>
 
3
#include <my_sys.h>
 
4
#include <my_getopt.h>
 
5
#include <NdbOut.hpp>
 
6
 
 
7
static NdbOut& operator<<(NdbOut& out, const atrt_process& proc);
 
8
static atrt_host * find(const char * hostname, Vector<atrt_host*>&);
 
9
static bool load_process(atrt_config&, atrt_cluster&, atrt_process::Type, 
 
10
                         size_t idx, const char * hostname);
 
11
static bool load_options(int argc, char** argv, int type, atrt_options&);
 
12
 
 
13
enum {
 
14
  PO_NDB = atrt_options::AO_NDBCLUSTER
 
15
  
 
16
  ,PO_REP_SLAVE = 256
 
17
  ,PO_REP_MASTER = 512
 
18
  ,PO_REP = (atrt_options::AO_REPLICATION | PO_REP_SLAVE | PO_REP_MASTER)
 
19
};
 
20
 
 
21
struct proc_option
 
22
{
 
23
  const char * name;
 
24
  int type;
 
25
  int options;
 
26
};
 
27
 
 
28
static
 
29
struct proc_option f_options[] = {
 
30
  { "--FileSystemPath=",     atrt_process::AP_NDBD, 0 }
 
31
  ,{ "--PortNumber=",        atrt_process::AP_NDB_MGMD, 0 }
 
32
  ,{ "--datadir=",     atrt_process::AP_MYSQLD, 0 }
 
33
  ,{ "--socket=",      atrt_process::AP_MYSQLD | atrt_process::AP_CLIENT, 0 }
 
34
  ,{ "--port=",        atrt_process::AP_MYSQLD | atrt_process::AP_CLIENT, 0 }
 
35
  ,{ "--server-id=",   atrt_process::AP_MYSQLD, PO_REP }
 
36
  ,{ "--log-bin",      atrt_process::AP_MYSQLD, PO_REP_MASTER }
 
37
  ,{ "--master-host=", atrt_process::AP_MYSQLD, PO_REP_SLAVE }
 
38
  ,{ "--master-port=", atrt_process::AP_MYSQLD, PO_REP_SLAVE }
 
39
  ,{ "--master-user=", atrt_process::AP_MYSQLD, PO_REP_SLAVE }
 
40
  ,{ "--master-password=", atrt_process::AP_MYSQLD, PO_REP_SLAVE }
 
41
  ,{ "--ndb-connectstring=", atrt_process::AP_MYSQLD | atrt_process::AP_CLUSTER
 
42
     ,PO_NDB }
 
43
  ,{ "--ndbcluster", atrt_process::AP_MYSQLD, PO_NDB }
 
44
  ,{ 0, 0, 0 }
 
45
};
 
46
const char * ndbcs = "--ndb-connectstring=";
 
47
 
 
48
bool
 
49
setup_config(atrt_config& config)
 
50
{
 
51
  BaseString tmp(g_clusters);
 
52
  Vector<BaseString> clusters;
 
53
  tmp.split(clusters, ",");
 
54
 
 
55
  bool fqpn = clusters.size() > 1 || g_fqpn;
 
56
  
 
57
  size_t j,k;
 
58
  for (size_t i = 0; i<clusters.size(); i++)
 
59
  {
 
60
    struct atrt_cluster *cluster = new atrt_cluster;
 
61
    config.m_clusters.push_back(cluster);
 
62
 
 
63
    cluster->m_name = clusters[i];
 
64
    if (fqpn)
 
65
    {
 
66
      cluster->m_dir.assfmt("cluster%s/", cluster->m_name.c_str());
 
67
    }
 
68
    else
 
69
    {
 
70
      cluster->m_dir = "";
 
71
    }
 
72
    
 
73
    int argc = 1;
 
74
    const char * argv[] = { "atrt", 0, 0 };
 
75
 
 
76
    BaseString buf;
 
77
    buf.assfmt("--defaults-group-suffix=%s", clusters[i].c_str());
 
78
    argv[argc++] = buf.c_str();
 
79
    char ** tmp = (char**)argv;
 
80
    const char *groups[] = { "cluster_config", 0 };
 
81
    int ret = load_defaults(g_my_cnf, groups, &argc, &tmp);
 
82
    if (ret)
 
83
    {
 
84
      g_logger.error("Unable to load defaults for cluster: %s", 
 
85
                     clusters[i].c_str());
 
86
      return false;
 
87
    }
 
88
 
 
89
    struct 
 
90
    {
 
91
      atrt_process::Type type;
 
92
      const char * name;
 
93
      const char * value;
 
94
    } proc_args[] = {
 
95
      { atrt_process::AP_NDB_MGMD, "--ndb_mgmd=", 0 },
 
96
      { atrt_process::AP_NDBD, "--ndbd=", 0 },
 
97
      { atrt_process::AP_NDB_API, "--ndbapi=", 0 },
 
98
      { atrt_process::AP_NDB_API, "--api=", 0 },
 
99
      { atrt_process::AP_MYSQLD, "--mysqld=", 0 },
 
100
      { atrt_process::AP_ALL, 0, 0}
 
101
    };
 
102
 
 
103
    /**
 
104
     * Find all processes...
 
105
     */
 
106
    for (j = 0; j<(size_t)argc; j++)
 
107
    {
 
108
      for (k = 0; proc_args[k].name; k++)
 
109
      {
 
110
        if (!strncmp(tmp[j], proc_args[k].name, strlen(proc_args[k].name)))
 
111
        {
 
112
          proc_args[k].value = tmp[j] + strlen(proc_args[k].name);
 
113
          break;
 
114
        }
 
115
      }      
 
116
    }
 
117
 
 
118
    /**
 
119
     * Load each process
 
120
     */
 
121
    for (j = 0; proc_args[j].name; j++)
 
122
    {
 
123
      if (proc_args[j].value)
 
124
      {
 
125
        BaseString tmp(proc_args[j].value);
 
126
        Vector<BaseString> list;
 
127
        tmp.split(list, ",");
 
128
        for (k = 0; k<list.size(); k++)
 
129
          if (!load_process(config, *cluster, proc_args[j].type, 
 
130
                            k + 1, list[k].c_str()))
 
131
            return false;
 
132
      }
 
133
    }
 
134
 
 
135
    {
 
136
      /**
 
137
       * Load cluster options
 
138
       */
 
139
      
 
140
      argc = 1;
 
141
      argv[argc++] = buf.c_str();
 
142
      const char *groups[] = { "mysql_cluster", 0 };
 
143
      ret = load_defaults(g_my_cnf, groups, &argc, &tmp);
 
144
      
 
145
      if (ret)
 
146
      {
 
147
        g_logger.error("Unable to load defaults for cluster: %s", 
 
148
                       clusters[i].c_str());
 
149
        return false;
 
150
      }
 
151
      
 
152
      load_options(argc, tmp, atrt_process::AP_CLUSTER, cluster->m_options);
 
153
    }
 
154
  }
 
155
  return true;
 
156
}
 
157
 
 
158
static
 
159
atrt_host *
 
160
find(const char * hostname, Vector<atrt_host*> & hosts){
 
161
  for (size_t i = 0; i<hosts.size(); i++){
 
162
    if (hosts[i]->m_hostname == hostname){
 
163
      return hosts[i];
 
164
    }
 
165
  }
 
166
 
 
167
  atrt_host* host = new atrt_host;
 
168
  host->m_index = hosts.size();
 
169
  host->m_cpcd = new SimpleCpcClient(hostname, 1234);
 
170
  host->m_basedir = g_basedir;
 
171
  host->m_user = g_user;
 
172
  host->m_hostname = hostname;
 
173
  hosts.push_back(host);
 
174
  return host;
 
175
 
176
 
 
177
static 
 
178
bool 
 
179
load_process(atrt_config& config, atrt_cluster& cluster, 
 
180
             atrt_process::Type type, 
 
181
             size_t idx,
 
182
             const char * hostname)
 
183
{
 
184
  atrt_host * host_ptr = find(hostname, config.m_hosts);
 
185
  atrt_process *proc_ptr = new atrt_process;
 
186
  
 
187
  config.m_processes.push_back(proc_ptr);
 
188
  host_ptr->m_processes.push_back(proc_ptr);
 
189
  cluster.m_processes.push_back(proc_ptr);
 
190
  
 
191
  atrt_process& proc = *proc_ptr;
 
192
  
 
193
  const size_t proc_no = config.m_processes.size();
 
194
  proc.m_index = idx;
 
195
  proc.m_type = type;
 
196
  proc.m_host = host_ptr;
 
197
  proc.m_cluster = &cluster;
 
198
  proc.m_options.m_features = 0;
 
199
  proc.m_rep_src = 0;
 
200
  proc.m_proc.m_id = -1;
 
201
  proc.m_proc.m_type = "temporary";
 
202
  proc.m_proc.m_owner = "atrt";  
 
203
  proc.m_proc.m_group = cluster.m_name.c_str();
 
204
  proc.m_proc.m_stdout = "log.out";
 
205
  proc.m_proc.m_stderr = "2>&1";
 
206
  proc.m_proc.m_runas = proc.m_host->m_user;
 
207
  proc.m_proc.m_ulimit = "c:unlimited";
 
208
  proc.m_proc.m_env.assfmt("MYSQL_BASE_DIR=%s", g_prefix);
 
209
  proc.m_proc.m_env.appfmt(" MYSQL_HOME=%s", g_basedir);
 
210
  proc.m_proc.m_shutdown_options = "";
 
211
 
 
212
  int argc = 1;
 
213
  const char * argv[] = { "atrt", 0, 0 };
 
214
  
 
215
  BaseString buf[10];
 
216
  char ** tmp = (char**)argv;
 
217
  const char *groups[] = { 0, 0, 0, 0 };
 
218
  switch(type){
 
219
  case atrt_process::AP_NDB_MGMD:
 
220
    groups[0] = "cluster_config";
 
221
    buf[1].assfmt("cluster_config.ndb_mgmd.%d", idx);
 
222
    groups[1] = buf[1].c_str();
 
223
    buf[0].assfmt("--defaults-group-suffix=%s", cluster.m_name.c_str());
 
224
    argv[argc++] = buf[0].c_str();
 
225
    break;
 
226
  case atrt_process::AP_NDBD: 
 
227
    groups[0] = "cluster_config";
 
228
    buf[1].assfmt("cluster_config.ndbd.%d", idx);
 
229
    groups[1] = buf[1].c_str();
 
230
    buf[0].assfmt("--defaults-group-suffix=%s", cluster.m_name.c_str());
 
231
    argv[argc++] = buf[0].c_str();
 
232
    break;
 
233
  case atrt_process::AP_MYSQLD:
 
234
    groups[0] = "mysqld";
 
235
    groups[1] = "mysql_cluster";
 
236
    buf[0].assfmt("--defaults-group-suffix=.%d%s",idx,cluster.m_name.c_str());
 
237
    argv[argc++] = buf[0].c_str();
 
238
    break;
 
239
  case atrt_process::AP_CLIENT:
 
240
    buf[0].assfmt("client.%d%s", idx, cluster.m_name.c_str());
 
241
    groups[0] = buf[0].c_str();
 
242
    break;
 
243
  case atrt_process::AP_NDB_API:
 
244
    break;
 
245
  default:
 
246
    g_logger.critical("Unhandled process type: %d", type);
 
247
    return false;
 
248
  }
 
249
 
 
250
  int ret = load_defaults(g_my_cnf, groups, &argc, &tmp);
 
251
  if (ret)
 
252
  {
 
253
    g_logger.error("Unable to load defaults for cluster: %s", 
 
254
                   cluster.m_name.c_str());
 
255
    return false;
 
256
  }
 
257
  
 
258
  load_options(argc, tmp, type, proc.m_options);
 
259
  
 
260
  BaseString dir;
 
261
  dir.assfmt("%s/%s",
 
262
             proc.m_host->m_basedir.c_str(),
 
263
             cluster.m_dir.c_str());
 
264
  
 
265
  switch(type){
 
266
  case atrt_process::AP_NDB_MGMD:
 
267
  {
 
268
    proc.m_proc.m_name.assfmt("%d-%s", proc_no, "ndb_mgmd");
 
269
    proc.m_proc.m_path.assign(g_prefix).append("/libexec/ndb_mgmd");
 
270
    proc.m_proc.m_args.assfmt("--defaults-file=%s/my.cnf",
 
271
                              proc.m_host->m_basedir.c_str());
 
272
    proc.m_proc.m_args.appfmt(" --defaults-group-suffix=%s",
 
273
                              cluster.m_name.c_str());
 
274
    proc.m_proc.m_args.append(" --nodaemon --mycnf");
 
275
    proc.m_proc.m_cwd.assfmt("%sndb_mgmd.%d", dir.c_str(), proc.m_index);
 
276
    proc.m_proc.m_env.appfmt(" MYSQL_GROUP_SUFFIX=%s", 
 
277
                             cluster.m_name.c_str());
 
278
    break;
 
279
  } 
 
280
  case atrt_process::AP_NDBD:
 
281
  {
 
282
    proc.m_proc.m_name.assfmt("%d-%s", proc_no, "ndbd");
 
283
    proc.m_proc.m_path.assign(g_prefix).append("/libexec/ndbd");
 
284
    proc.m_proc.m_args.assfmt("--defaults-file=%s/my.cnf",
 
285
                              proc.m_host->m_basedir.c_str());
 
286
    proc.m_proc.m_args.appfmt(" --defaults-group-suffix=%s",
 
287
                              cluster.m_name.c_str());
 
288
    proc.m_proc.m_args.append(" --nodaemon -n");
 
289
    proc.m_proc.m_cwd.assfmt("%sndbd.%d", dir.c_str(), proc.m_index);
 
290
    proc.m_proc.m_env.appfmt(" MYSQL_GROUP_SUFFIX=%s", 
 
291
                             cluster.m_name.c_str());
 
292
    break;
 
293
  } 
 
294
  case atrt_process::AP_MYSQLD:
 
295
  {
 
296
    proc.m_proc.m_name.assfmt("%d-%s", proc_no, "mysqld");
 
297
    proc.m_proc.m_path.assign(g_prefix).append("/libexec/mysqld");
 
298
    proc.m_proc.m_args.assfmt("--defaults-file=%s/my.cnf",
 
299
                              proc.m_host->m_basedir.c_str());
 
300
    proc.m_proc.m_args.appfmt(" --defaults-group-suffix=.%d%s",
 
301
                              proc.m_index,
 
302
                              cluster.m_name.c_str());
 
303
    proc.m_proc.m_args.append(" --core-file");
 
304
    proc.m_proc.m_cwd.appfmt("%smysqld.%d", dir.c_str(), proc.m_index);
 
305
    proc.m_proc.m_shutdown_options = "SIGKILL"; // not nice
 
306
    proc.m_proc.m_env.appfmt(" MYSQL_GROUP_SUFFIX=.%d%s", 
 
307
                             proc.m_index,
 
308
                             cluster.m_name.c_str());
 
309
    break;
 
310
  } 
 
311
  case atrt_process::AP_NDB_API:
 
312
  {
 
313
    proc.m_proc.m_name.assfmt("%d-%s", proc_no, "ndb_api");
 
314
    proc.m_proc.m_path = "";
 
315
    proc.m_proc.m_args = "";
 
316
    proc.m_proc.m_cwd.appfmt("%sndb_api.%d", dir.c_str(), proc.m_index);
 
317
    proc.m_proc.m_env.appfmt(" MYSQL_GROUP_SUFFIX=%s", 
 
318
                             cluster.m_name.c_str());
 
319
    break;
 
320
  } 
 
321
  case atrt_process::AP_CLIENT:
 
322
  {
 
323
    proc.m_proc.m_name.assfmt("%d-%s", proc_no, "mysql");
 
324
    proc.m_proc.m_path = "";
 
325
    proc.m_proc.m_args = "";
 
326
    proc.m_proc.m_cwd.appfmt("%s/client.%d", dir.c_str(), proc.m_index);
 
327
    proc.m_proc.m_env.appfmt(" MYSQL_GROUP_SUFFIX=.%d%s", 
 
328
                             proc.m_index,
 
329
                             cluster.m_name.c_str());
 
330
    break;
 
331
  }
 
332
  case atrt_process::AP_ALL:
 
333
  case atrt_process::AP_CLUSTER:
 
334
    g_logger.critical("Unhandled process type: %d", proc.m_type);
 
335
    return false;
 
336
  }
 
337
  
 
338
  if (proc.m_proc.m_path.length())
 
339
  {
 
340
    proc.m_proc.m_env.appfmt(" CMD=\"%s", proc.m_proc.m_path.c_str());
 
341
    if (proc.m_proc.m_args.length())
 
342
      proc.m_proc.m_env.append(" ");
 
343
    proc.m_proc.m_env.append(proc.m_proc.m_args);
 
344
    proc.m_proc.m_env.append("\" ");
 
345
  }
 
346
  
 
347
  if (type == atrt_process::AP_MYSQLD)
 
348
  {
 
349
    /**
 
350
     * Add a client for each mysqld
 
351
     */
 
352
    if (!load_process(config, cluster, atrt_process::AP_CLIENT, idx, hostname))
 
353
    {
 
354
      return false;
 
355
    }
 
356
  }
 
357
  
 
358
  if (type == atrt_process::AP_CLIENT)
 
359
  {
 
360
    proc.m_mysqld = cluster.m_processes[cluster.m_processes.size()-2];
 
361
  }
 
362
  
 
363
  return true;
 
364
}
 
365
 
 
366
static 
 
367
bool
 
368
load_options(int argc, char** argv, int type, atrt_options& opts)
 
369
{
 
370
  for (size_t i = 0; i<(size_t)argc; i++)
 
371
  {
 
372
    for (size_t j = 0; f_options[j].name; j++)
 
373
    {
 
374
      const char * name = f_options[j].name;
 
375
      const size_t len = strlen(name);
 
376
      
 
377
      if ((f_options[j].type & type) && strncmp(argv[i], name, len) == 0)
 
378
      {
 
379
        opts.m_loaded.put(name, argv[i]+len, true);
 
380
        break;
 
381
      }
 
382
    }
 
383
  }
 
384
  return true;
 
385
}
 
386
 
 
387
struct proc_rule_ctx
 
388
{
 
389
  int m_setup;
 
390
  atrt_config* m_config;
 
391
  atrt_host * m_host;
 
392
  atrt_cluster* m_cluster;
 
393
  atrt_process* m_process;
 
394
};
 
395
 
 
396
struct proc_rule
 
397
{
 
398
  int type;
 
399
  bool (* func)(Properties& prop, proc_rule_ctx&, int extra);
 
400
  int extra;
 
401
};
 
402
 
 
403
static bool pr_check_replication(Properties&, proc_rule_ctx&, int);
 
404
static bool pr_check_features(Properties&, proc_rule_ctx&, int);
 
405
static bool pr_fix_client(Properties&, proc_rule_ctx&, int);
 
406
static bool pr_proc_options(Properties&, proc_rule_ctx&, int);
 
407
static bool pr_fix_ndb_connectstring(Properties&, proc_rule_ctx&, int);
 
408
static bool pr_set_ndb_connectstring(Properties&, proc_rule_ctx&, int);
 
409
static bool pr_check_proc(Properties&, proc_rule_ctx&, int);
 
410
 
 
411
static
 
412
proc_rule f_rules[] = 
 
413
{
 
414
  { atrt_process::AP_CLUSTER, pr_check_features, 0 }
 
415
  ,{ atrt_process::AP_MYSQLD, pr_check_replication, 0 }
 
416
  ,{ (atrt_process::AP_ALL & ~atrt_process::AP_CLIENT), pr_proc_options, 
 
417
     ~(PO_REP | PO_NDB) }
 
418
  ,{ (atrt_process::AP_ALL & ~atrt_process::AP_CLIENT), pr_proc_options, PO_REP }
 
419
  ,{ atrt_process::AP_CLIENT, pr_fix_client, 0 }
 
420
  ,{ atrt_process::AP_CLUSTER, pr_fix_ndb_connectstring, 0 }
 
421
  ,{ atrt_process::AP_MYSQLD, pr_set_ndb_connectstring, 0 }
 
422
  ,{ atrt_process::AP_ALL, pr_check_proc, 0 }
 
423
  ,{ 0, 0, 0 }
 
424
};
 
425
 
 
426
bool
 
427
configure(atrt_config& config, int setup)
 
428
{
 
429
  Properties props;
 
430
  
 
431
  for (size_t i = 0; f_rules[i].func; i++)
 
432
  {
 
433
    bool ok = true;
 
434
    proc_rule_ctx ctx;
 
435
    bzero(&ctx, sizeof(ctx));
 
436
    ctx.m_setup = setup;
 
437
    ctx.m_config = &config;
 
438
    
 
439
    for (size_t j = 0; j < config.m_clusters.size(); j++)
 
440
    {
 
441
      ctx.m_cluster = config.m_clusters[j];
 
442
      
 
443
      if (f_rules[i].type & atrt_process::AP_CLUSTER)
 
444
      {
 
445
        g_logger.debug("applying rule %d to cluster %s", i, 
 
446
                       ctx.m_cluster->m_name.c_str());
 
447
        if (! (* f_rules[i].func)(props, ctx, f_rules[i].extra))
 
448
          ok = false;
 
449
      }
 
450
      else
 
451
      {
 
452
        atrt_cluster& cluster = *config.m_clusters[j];
 
453
        for (size_t k = 0; k<cluster.m_processes.size(); k++)
 
454
        {
 
455
          atrt_process& proc = *cluster.m_processes[k];
 
456
          ctx.m_process = cluster.m_processes[k];
 
457
          if (proc.m_type & f_rules[i].type)
 
458
          {
 
459
            g_logger.debug("applying rule %d to %s", i, 
 
460
                           proc.m_proc.m_cwd.c_str());
 
461
            if (! (* f_rules[i].func)(props, ctx, f_rules[i].extra))
 
462
              ok = false;
 
463
          }
 
464
        }
 
465
      }
 
466
    }
 
467
    
 
468
    if (!ok)
 
469
    {
 
470
      return false;
 
471
    }
 
472
  }
 
473
 
 
474
  return true;
 
475
}
 
476
 
 
477
static
 
478
atrt_process*
 
479
find(atrt_config& config, int type, const char * name)
 
480
{
 
481
  BaseString tmp(name);
 
482
  Vector<BaseString> src;
 
483
  Vector<BaseString> dst;
 
484
  tmp.split(src, ".");
 
485
  
 
486
  if (src.size() != 2)
 
487
  {
 
488
    return 0;
 
489
  }
 
490
  atrt_cluster* cluster = 0;
 
491
  BaseString cl;
 
492
  cl.appfmt(".%s", src[1].c_str());
 
493
  for (size_t i = 0; i<config.m_clusters.size(); i++)
 
494
  {
 
495
    if (config.m_clusters[i]->m_name == cl)
 
496
    {
 
497
      cluster = config.m_clusters[i];
 
498
      break;
 
499
    }
 
500
  }   
 
501
  
 
502
  if (cluster == 0)
 
503
  {
 
504
    return 0;
 
505
  }
 
506
  
 
507
  int idx = atoi(src[0].c_str()) - 1;
 
508
  for (size_t i = 0; i<cluster->m_processes.size(); i++)
 
509
  {
 
510
    if (cluster->m_processes[i]->m_type & type)
 
511
    {
 
512
      if (idx == 0)
 
513
        return cluster->m_processes[i];
 
514
      else
 
515
        idx --;
 
516
    }
 
517
  }
 
518
  
 
519
  return 0;
 
520
}
 
521
 
 
522
static 
 
523
bool 
 
524
pr_check_replication(Properties& props, proc_rule_ctx& ctx, int)
 
525
{
 
526
  if (! (ctx.m_config->m_replication == ""))
 
527
  {
 
528
    Vector<BaseString> list;
 
529
    ctx.m_config->m_replication.split(list, ";");
 
530
    atrt_config& config = *ctx.m_config;
 
531
    
 
532
    ctx.m_config->m_replication = "";
 
533
    
 
534
    const char * msg = "Invalid replication specification";
 
535
    for (size_t i = 0; i<list.size(); i++)
 
536
    {
 
537
      Vector<BaseString> rep;
 
538
      list[i].split(rep, ":");
 
539
      if (rep.size() != 2)
 
540
      {
 
541
        g_logger.error("%s: %s (split: %d)", msg, list[i].c_str(), rep.size());
 
542
      return false;
 
543
      }
 
544
      
 
545
      atrt_process* src = find(config, atrt_process::AP_MYSQLD,rep[0].c_str());
 
546
      atrt_process* dst = find(config, atrt_process::AP_MYSQLD,rep[1].c_str());
 
547
      
 
548
      if (src == 0 || dst == 0)
 
549
      {
 
550
        g_logger.error("%s: %s (%d %d)",
 
551
                       msg, list[i].c_str(), src != 0, dst != 0);
 
552
        return false;
 
553
      }
 
554
      
 
555
      
 
556
      if (dst->m_rep_src != 0)
 
557
      {
 
558
        g_logger.error("%s: %s : %s already has replication src (%s)",
 
559
                       msg,
 
560
                       list[i].c_str(),
 
561
                       dst->m_proc.m_cwd.c_str(),
 
562
                       dst->m_rep_src->m_proc.m_cwd.c_str());
 
563
        return false;
 
564
      }
 
565
      
 
566
      dst->m_rep_src = src;
 
567
      src->m_rep_dst.push_back(dst);
 
568
      
 
569
      src->m_options.m_features |= PO_REP_MASTER;
 
570
      dst->m_options.m_features |= PO_REP_SLAVE;
 
571
    }
 
572
  }
 
573
  return true;
 
574
}
 
575
 
 
576
static 
 
577
bool 
 
578
pr_check_features(Properties& props, proc_rule_ctx& ctx, int)
 
579
{
 
580
  int features = 0;
 
581
  atrt_cluster& cluster = *ctx.m_cluster;
 
582
  for (size_t i = 0; i<cluster.m_processes.size(); i++)
 
583
  {
 
584
    if (cluster.m_processes[i]->m_type == atrt_process::AP_NDB_MGMD ||
 
585
        cluster.m_processes[i]->m_type == atrt_process::AP_NDB_API ||
 
586
        cluster.m_processes[i]->m_type == atrt_process::AP_NDBD)
 
587
    {
 
588
      features |= atrt_options::AO_NDBCLUSTER;
 
589
      break;
 
590
    }
 
591
  }
 
592
  
 
593
  if (features)
 
594
  {
 
595
    cluster.m_options.m_features |= features;
 
596
    for (size_t i = 0; i<cluster.m_processes.size(); i++)
 
597
    {
 
598
      cluster.m_processes[i]->m_options.m_features |= features;
 
599
    }
 
600
  }
 
601
  return true;
 
602
}
 
603
 
 
604
static 
 
605
bool 
 
606
pr_fix_client(Properties& props, proc_rule_ctx& ctx, int)
 
607
{
 
608
  for (size_t i = 0; f_options[i].name; i++)
 
609
  {
 
610
    proc_option& opt = f_options[i];
 
611
    const char * name = opt.name;
 
612
    if (opt.type & atrt_process::AP_CLIENT)
 
613
    {
 
614
      const char * val;
 
615
      atrt_process& proc = *ctx.m_process; 
 
616
      if (!proc.m_options.m_loaded.get(name, &val))
 
617
      {
 
618
        require(proc.m_mysqld->m_options.m_loaded.get(name, &val));
 
619
        proc.m_options.m_loaded.put(name, val);
 
620
        proc.m_options.m_generated.put(name, val);
 
621
      }
 
622
    }
 
623
  }
 
624
  
 
625
  return true;
 
626
}
 
627
 
 
628
static
 
629
Uint32
 
630
try_default_port(atrt_process& proc, const char * name)
 
631
{
 
632
  Uint32 port = 
 
633
    strcmp(name, "--port=") == 0 ? 3306 :
 
634
    strcmp(name, "--PortNumber=") == 0 ? 1186 : 
 
635
    0;
 
636
  
 
637
  atrt_host * host = proc.m_host;
 
638
  for (size_t i = 0; i<host->m_processes.size(); i++)
 
639
  {
 
640
    const char * val;
 
641
    if (host->m_processes[i]->m_options.m_loaded.get(name, &val))
 
642
    {
 
643
      if ((Uint32)atoi(val) == port)
 
644
        return 0;
 
645
    }
 
646
  }
 
647
  return port;
 
648
}
 
649
 
 
650
static
 
651
bool
 
652
generate(atrt_process& proc, const char * name, Properties& props)
 
653
{
 
654
  atrt_options& opts = proc.m_options;
 
655
  if (strcmp(name, "--port=") == 0 || 
 
656
      strcmp(name, "--PortNumber=") == 0)
 
657
  {
 
658
    Uint32 val;
 
659
    if (g_default_ports == 0 || (val = try_default_port(proc, name)) == 0)
 
660
    {
 
661
      val = g_baseport;
 
662
      props.get("--PortNumber=", &val);
 
663
      props.put("--PortNumber=", (val + 1), true);
 
664
    }
 
665
    
 
666
    char buf[255];
 
667
    snprintf(buf, sizeof(buf), "%u", val);
 
668
    opts.m_loaded.put(name, buf);
 
669
    opts.m_generated.put(name, buf);
 
670
    return true;
 
671
  }
 
672
  else if (strcmp(name, "--datadir=") == 0)
 
673
  {
 
674
    opts.m_loaded.put(name, proc.m_proc.m_cwd.c_str());
 
675
    opts.m_generated.put(name, proc.m_proc.m_cwd.c_str());
 
676
    return true;
 
677
  }
 
678
  else if (strcmp(name, "--FileSystemPath=") == 0)
 
679
  {
 
680
    BaseString dir;
 
681
    dir.append(proc.m_host->m_basedir);
 
682
    dir.append("/");
 
683
    dir.append(proc.m_cluster->m_dir);
 
684
    opts.m_loaded.put(name, dir.c_str());
 
685
    opts.m_generated.put(name, dir.c_str());
 
686
    return true;
 
687
  }
 
688
  else if (strcmp(name, "--socket=") == 0)
 
689
  {
 
690
    const char * sock = 0;
 
691
    if (g_default_ports)
 
692
    {
 
693
      sock = "/tmp/mysql.sock";
 
694
      atrt_host * host = proc.m_host;
 
695
      for (size_t i = 0; i<host->m_processes.size(); i++)
 
696
      {
 
697
        const char * val;
 
698
        if (host->m_processes[i]->m_options.m_loaded.get(name, &val))
 
699
        {
 
700
          if (strcmp(sock, val) == 0)
 
701
          {
 
702
            sock = 0;
 
703
            break;
 
704
          }
 
705
        }
 
706
      }
 
707
    }
 
708
    
 
709
    BaseString tmp;
 
710
    if (sock == 0)
 
711
    {
 
712
      tmp.assfmt("%s/mysql.sock", proc.m_proc.m_cwd.c_str());
 
713
      sock = tmp.c_str();
 
714
    }
 
715
    
 
716
    opts.m_loaded.put(name, sock);
 
717
    opts.m_generated.put(name, sock);
 
718
    return true;
 
719
  }
 
720
  else if (strcmp(name, "--server-id=") == 0)
 
721
  {
 
722
    Uint32 val = 1;
 
723
    props.get(name, &val);
 
724
    char buf[255];
 
725
    snprintf(buf, sizeof(buf), "%u", val);
 
726
    opts.m_loaded.put(name, buf);
 
727
    opts.m_generated.put(name, buf);
 
728
    props.put(name, (val + 1), true);
 
729
    return true;
 
730
  } 
 
731
  else if (strcmp(name, "--log-bin") == 0)
 
732
  {
 
733
    opts.m_loaded.put(name, "");
 
734
    opts.m_generated.put(name, "");
 
735
    return true;
 
736
  }
 
737
  else if (strcmp(name, "--master-host=") == 0)
 
738
  {
 
739
    require(proc.m_rep_src != 0);
 
740
    opts.m_loaded.put(name, proc.m_rep_src->m_host->m_hostname.c_str());
 
741
    opts.m_generated.put(name, proc.m_rep_src->m_host->m_hostname.c_str());
 
742
    return true;
 
743
  }
 
744
  else if (strcmp(name, "--master-port=") == 0)
 
745
  {
 
746
    const char* val;
 
747
    require(proc.m_rep_src->m_options.m_loaded.get("--port=", &val));
 
748
    opts.m_loaded.put(name, val);
 
749
    opts.m_generated.put(name, val);
 
750
    return true;
 
751
  }
 
752
  else if (strcmp(name, "--master-user=") == 0)
 
753
  {
 
754
    opts.m_loaded.put(name, "root");
 
755
    opts.m_generated.put(name, "root");
 
756
    return true;
 
757
  }
 
758
  else if (strcmp(name, "--master-password=") == 0)
 
759
  {
 
760
    opts.m_loaded.put(name, "\"\"");
 
761
    opts.m_generated.put(name, "\"\"");
 
762
    return true;
 
763
  }
 
764
  
 
765
  g_logger.warning("Unknown parameter: %s", name);
 
766
  return true;
 
767
}
 
768
 
 
769
static 
 
770
bool 
 
771
pr_proc_options(Properties& props, proc_rule_ctx& ctx, int extra)
 
772
{
 
773
  for (size_t i = 0; f_options[i].name; i++)
 
774
  {
 
775
    proc_option& opt = f_options[i];
 
776
    atrt_process& proc = *ctx.m_process; 
 
777
    const char * name = opt.name;
 
778
    if (opt.type & proc.m_type)
 
779
    {
 
780
      if (opt.options == 0 || 
 
781
          (opt.options & extra & proc.m_options.m_features))
 
782
      {
 
783
        const char * val;
 
784
        if (!proc.m_options.m_loaded.get(name, &val))
 
785
        {
 
786
          generate(proc, name, props);
 
787
        }
 
788
      }
 
789
    }
 
790
  }
 
791
  return true;
 
792
}
 
793
 
 
794
static 
 
795
bool 
 
796
pr_fix_ndb_connectstring(Properties& props, proc_rule_ctx& ctx, int)
 
797
{
 
798
  const char * val;
 
799
  atrt_cluster& cluster = *ctx.m_cluster;
 
800
 
 
801
  if (cluster.m_options.m_features & atrt_options::AO_NDBCLUSTER)
 
802
  {
 
803
    if (!cluster.m_options.m_loaded.get(ndbcs, &val))
 
804
    {
 
805
      /**
 
806
       * Construct connect string for this cluster
 
807
     */
 
808
      BaseString str;
 
809
      for (size_t i = 0; i<cluster.m_processes.size(); i++)
 
810
      {
 
811
        atrt_process* tmp = cluster.m_processes[i];
 
812
        if (tmp->m_type == atrt_process::AP_NDB_MGMD)
 
813
        {
 
814
          if (str.length())
 
815
          {
 
816
            str.append(";");
 
817
          }
 
818
          const char * port;
 
819
          require(tmp->m_options.m_loaded.get("--PortNumber=", &port));
 
820
          str.appfmt("%s:%s", tmp->m_host->m_hostname.c_str(), port);
 
821
        }
 
822
      }
 
823
      cluster.m_options.m_loaded.put(ndbcs, str.c_str());
 
824
      cluster.m_options.m_generated.put(ndbcs, str.c_str());
 
825
      cluster.m_options.m_loaded.get(ndbcs, &val);
 
826
    }
 
827
    
 
828
    for (size_t i = 0; i<cluster.m_processes.size(); i++)
 
829
    {
 
830
      cluster.m_processes[i]->m_proc.m_env.appfmt(" NDB_CONNECTSTRING=%s", 
 
831
                                                  val);
 
832
    }
 
833
  }
 
834
  return true;
 
835
}
 
836
 
 
837
static 
 
838
bool 
 
839
pr_set_ndb_connectstring(Properties& props, proc_rule_ctx& ctx, int)
 
840
{
 
841
  const char * val;
 
842
  
 
843
  atrt_process& proc = *ctx.m_process;
 
844
  if (proc.m_options.m_features & atrt_options::AO_NDBCLUSTER)
 
845
  {
 
846
    if (!proc.m_options.m_loaded.get(ndbcs, &val))
 
847
    {
 
848
      require(proc.m_cluster->m_options.m_loaded.get(ndbcs, &val));
 
849
      proc.m_options.m_loaded.put(ndbcs, val);
 
850
      proc.m_options.m_generated.put(ndbcs, val);
 
851
    }
 
852
    
 
853
    if (!proc.m_options.m_loaded.get("--ndbcluster", &val))
 
854
    {
 
855
      proc.m_options.m_loaded.put("--ndbcluster", "");
 
856
      proc.m_options.m_generated.put("--ndbcluster", "");
 
857
    }
 
858
  }
 
859
  return true;
 
860
}
 
861
 
 
862
static 
 
863
bool 
 
864
pr_check_proc(Properties& props, proc_rule_ctx& ctx, int)
 
865
{
 
866
  bool ok = true;
 
867
  bool generated = false;
 
868
  const int setup = ctx.m_setup;
 
869
  atrt_process& proc = *ctx.m_process; 
 
870
  for (size_t i = 0; f_options[i].name; i++)
 
871
  {
 
872
    proc_option& opt = f_options[i];
 
873
    const char * name = opt.name;
 
874
    if ((ctx.m_process->m_type & opt.type) &&
 
875
        (opt.options == 0 || (ctx.m_process->m_options.m_features & opt.options)))
 
876
    {
 
877
      const char * val;
 
878
      if (!proc.m_options.m_loaded.get(name, &val))
 
879
      {
 
880
        ok = false;
 
881
        g_logger.warning("Missing paramter: %s for %s",
 
882
                         name, proc.m_proc.m_cwd.c_str());
 
883
      }
 
884
      else if (proc.m_options.m_generated.get(name, &val))
 
885
      {
 
886
        if (setup == 0)
 
887
        {
 
888
          ok = false;
 
889
          g_logger.warning("Missing paramter: %s for %s",
 
890
                           name, proc.m_proc.m_cwd.c_str());
 
891
        }
 
892
        else
 
893
        {
 
894
          generated = true;
 
895
        }
 
896
      }
 
897
    }
 
898
  }
 
899
  
 
900
  if (generated)
 
901
  {
 
902
    ctx.m_config->m_generated = true;
 
903
  }
 
904
  
 
905
  //ndbout << proc << endl;
 
906
  
 
907
  return ok;
 
908
}
 
909
 
 
910
 
 
911
NdbOut&
 
912
operator<<(NdbOut& out, const atrt_process& proc)
 
913
{
 
914
  out << "[ atrt_process: ";
 
915
  switch(proc.m_type){
 
916
  case atrt_process::AP_NDB_MGMD:
 
917
    out << "ndb_mgmd";
 
918
    break;
 
919
  case atrt_process::AP_NDBD: 
 
920
    out << "ndbd";
 
921
    break;
 
922
  case atrt_process::AP_MYSQLD:
 
923
    out << "mysqld";
 
924
    break;
 
925
  case atrt_process::AP_NDB_API:
 
926
    out << "ndbapi";
 
927
    break;
 
928
  case atrt_process::AP_CLIENT:
 
929
    out << "client";
 
930
    break;
 
931
  default:
 
932
    out << "<unknown: " << (int)proc.m_type << " >";
 
933
  }
 
934
  
 
935
  out << " cluster: " << proc.m_cluster->m_name.c_str()
 
936
      << " host: " << proc.m_host->m_hostname.c_str()
 
937
      << endl << " cwd: " << proc.m_proc.m_cwd.c_str()
 
938
      << endl << " path: " << proc.m_proc.m_path.c_str()
 
939
      << endl << " args: " << proc.m_proc.m_args.c_str()
 
940
      << endl << " env: " << proc.m_proc.m_env.c_str() << endl;
 
941
  
 
942
  proc.m_options.m_generated.print(stdout, "generated: ");
 
943
  
 
944
  out << " ]";
 
945
  
 
946
#if 0  
 
947
  proc.m_index = 0; //idx;
 
948
  proc.m_host = host_ptr;
 
949
  proc.m_cluster = cluster;
 
950
  proc.m_proc.m_id = -1;
 
951
  proc.m_proc.m_type = "temporary";
 
952
  proc.m_proc.m_owner = "atrt";  
 
953
  proc.m_proc.m_group = cluster->m_name.c_str();
 
954
  proc.m_proc.m_cwd.assign(dir).append("/atrt/").append(cluster->m_dir);
 
955
  proc.m_proc.m_stdout = "log.out";
 
956
  proc.m_proc.m_stderr = "2>&1";
 
957
  proc.m_proc.m_runas = proc.m_host->m_user;
 
958
  proc.m_proc.m_ulimit = "c:unlimited";
 
959
  proc.m_proc.m_env.assfmt("MYSQL_BASE_DIR=%s", dir);
 
960
  proc.m_proc.m_shutdown_options = "";
 
961
#endif
 
962
  
 
963
  return out;
 
964
}
 
965