~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzleadmin.cc

  • Committer: Brian Aker
  • Date: 2009-02-10 00:14:40 UTC
  • Revision ID: brian@tangent.org-20090210001440-qjg8eofh3h93064b
Adding Multi-threaded Scheduler into the system.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 
3
 *
 
4
 *  Copyright (C) 2008 MySQL
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; either version 2 of the License, or
 
9
 *  (at your option) any later version.
 
10
 *
 
11
 *  This program is distributed in the hope that it will be useful,
 
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 *  GNU General Public License for more details.
 
15
 *
 
16
 *  You should have received a copy of the GNU General Public License
 
17
 *  along with this program; if not, write to the Free Software
 
18
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
19
 */
 
20
 
 
21
/* maintaince of drizzle databases */
 
22
 
 
23
#include "client_priv.h"
 
24
#include <signal.h>
 
25
#include <mysys/my_pthread.h>                           /* because of signal()  */
 
26
#include <sys/stat.h>
 
27
 
 
28
/* Added this for string translation. */
 
29
#include <drizzled/gettext.h>
 
30
 
 
31
#define ADMIN_VERSION "8.42"
 
32
#define SHUTDOWN_DEF_TIMEOUT 3600               /* Wait for shutdown */
 
33
 
 
34
char *host= NULL, *user= NULL, *opt_password= NULL;
 
35
static bool interrupted= false, opt_verbose= false,tty_password= false;
 
36
static uint32_t tcp_port= 0, option_wait= 0, option_silent= 0;
 
37
static uint32_t my_end_arg;
 
38
static uint32_t opt_connect_timeout, opt_shutdown_timeout;
 
39
 
 
40
using namespace std;
 
41
 
 
42
/*
 
43
  Forward declarations
 
44
*/
 
45
static void usage(void);
 
46
static void print_version(void);
 
47
extern "C" void endprog(int signal_number);
 
48
extern "C" bool get_one_option(int optid, const struct my_option *opt,
 
49
                               char *argument);
 
50
static int execute_commands(DRIZZLE *drizzle,int argc, char **argv);
 
51
static bool sql_connect(DRIZZLE *drizzle, uint wait);
 
52
 
 
53
/*
 
54
  The order of commands must be the same as command_names,
 
55
  except ADMIN_ERROR
 
56
*/
 
57
enum commands {
 
58
  ADMIN_ERROR,
 
59
  ADMIN_SHUTDOWN,
 
60
  ADMIN_PING
 
61
};
 
62
 
 
63
static const char *command_names[]= {
 
64
  "shutdown",
 
65
  "ping",
 
66
  NULL
 
67
};
 
68
 
 
69
static TYPELIB command_typelib=
 
70
{ array_elements(command_names)-1,"commands", command_names, NULL };
 
71
 
 
72
static struct my_option my_long_options[] =
 
73
{
 
74
  {"help", '?', N_("Display this help and exit."), 0, 0, 0, GET_NO_ARG,
 
75
   NO_ARG, 0, 0, 0, 0, 0, 0},
 
76
  {"host", 'h', N_("Connect to host."), (char**) &host, (char**) &host, 0, GET_STR,
 
77
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
78
  {"password", 'P',
 
79
   N_("Password to use when connecting to server. If password is not given it's asked from the tty."),
 
80
   0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
 
81
  {"port", 'p', N_("Port number to use for connection or 0 for default to, in "
 
82
   "order of preference, drizzle.cnf, $DRIZZLE_TCP_PORT, "
 
83
   "built-in default (" STRINGIFY_ARG(DRIZZLE_PORT) ")."),
 
84
   0, 0, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
85
  {"silent", 's', N_("Silently exit if one can't connect to server."),
 
86
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
87
#ifndef DONT_ALLOW_USER_CHANGE
 
88
  {"user", 'u', N_("User for login if not current user."), (char**) &user,
 
89
   (char**) &user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
90
#endif
 
91
  {"verbose", 'v', N_("Write more information."), (char**) &opt_verbose,
 
92
   (char**) &opt_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
93
  {"version", 'V', N_("Output version information and exit."), 0, 0, 0, GET_NO_ARG,
 
94
   NO_ARG, 0, 0, 0, 0, 0, 0},
 
95
  {"wait", 'w', N_("Wait and retry if connection is down."), 0, 0, 0, GET_UINT,
 
96
   OPT_ARG, 0, 0, 0, 0, 0, 0},
 
97
  {"connect_timeout", OPT_CONNECT_TIMEOUT, "", (char**) &opt_connect_timeout,
 
98
   (char**) &opt_connect_timeout, 0, GET_ULONG, REQUIRED_ARG, 3600*12, 0,
 
99
   3600*12, 0, 1, 0},
 
100
  {"shutdown_timeout", OPT_SHUTDOWN_TIMEOUT, "", (char**) &opt_shutdown_timeout,
 
101
   (char**) &opt_shutdown_timeout, 0, GET_ULONG, REQUIRED_ARG,
 
102
   SHUTDOWN_DEF_TIMEOUT, 0, 3600*12, 0, 1, 0},
 
103
  { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 
104
};
 
105
 
 
106
 
 
107
static const char *load_default_groups[]= { "drizzleadmin","client",0 };
 
108
 
 
109
bool
 
110
get_one_option(int optid, const struct my_option *, char *argument)
 
111
{
 
112
  char *endchar= NULL;
 
113
  uint64_t temp_drizzle_port= 0;
 
114
  int error = 0;
 
115
 
 
116
  switch(optid) {
 
117
  case 'p':
 
118
    temp_drizzle_port= (uint64_t) strtoul(argument, &endchar, 10);
 
119
    /* if there is an alpha character this is not a valid port */
 
120
    if (strlen(endchar) != 0)
 
121
    {
 
122
      fprintf(stderr, _("Non-integer value supplied for port.  If you are trying to enter a password please use --password instead.\n"));
 
123
      exit(1);
 
124
    }
 
125
    /* If the port number is > 65535 it is not a valid port
 
126
       This also helps with potential data loss casting unsigned long to a
 
127
       uint32_t. */
 
128
    if ((temp_drizzle_port == 0) || (temp_drizzle_port > 65535))
 
129
    {
 
130
      fprintf(stderr, _("Value supplied for port is not valid.\n"));
 
131
      exit(1);
 
132
    }
 
133
    else
 
134
    {
 
135
      tcp_port= (uint32_t) temp_drizzle_port;
 
136
    }
 
137
    break;
 
138
  case 'P':
 
139
    if (argument)
 
140
    {
 
141
      char *start=argument;
 
142
      if (opt_password)
 
143
        free(opt_password);
 
144
 
 
145
      opt_password= strdup(argument);
 
146
      if (opt_password == NULL)
 
147
      {
 
148
        fprintf(stderr, _("Memory allocation error while copying password. "
 
149
                          "Aborting.\n"));
 
150
        exit(ENOMEM);
 
151
      }
 
152
      while (*argument)
 
153
      {
 
154
        /* Overwriting password with 'x' */
 
155
        *argument++= 'x';
 
156
      }
 
157
      if (*start)
 
158
      {
 
159
        /* Cut length of argument */
 
160
        start[1]= 0;
 
161
      }
 
162
      tty_password= 0;
 
163
    }
 
164
    else
 
165
      tty_password= 1;
 
166
    break;
 
167
  case 's':
 
168
    option_silent++;
 
169
    break;
 
170
  case 'V':
 
171
    print_version();
 
172
    exit(0);
 
173
  case 'w':
 
174
    if (argument)
 
175
    {
 
176
      if ((option_wait=atoi(argument)) <= 0)
 
177
        option_wait=1;
 
178
    }
 
179
    else
 
180
      option_wait= ~(uint)0;
 
181
    break;
 
182
  case '?':
 
183
  case 'I':                                     /* Info */
 
184
    error++;
 
185
    break;
 
186
  }
 
187
 
 
188
  if (error)
 
189
  {
 
190
    usage();
 
191
    exit(1);
 
192
  }
 
193
  return 0;
 
194
}
 
195
 
 
196
int main(int argc,char *argv[])
 
197
{
 
198
  int error= 0, ho_error;
 
199
  DRIZZLE drizzle;
 
200
  char **commands, **save_argv;
 
201
 
 
202
  MY_INIT(argv[0]);
 
203
  drizzleclient_create(&drizzle);
 
204
  load_defaults("drizzle",load_default_groups,&argc,&argv);
 
205
  save_argv = argv;                             /* Save for free_defaults */
 
206
  if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
 
207
  {
 
208
    free_defaults(save_argv);
 
209
    exit(ho_error);
 
210
  }
 
211
 
 
212
  if (argc == 0)
 
213
  {
 
214
    usage();
 
215
    exit(1);
 
216
  }
 
217
 
 
218
  commands = argv;
 
219
  if (tty_password)
 
220
    opt_password = drizzleclient_get_tty_password(NULL);
 
221
 
 
222
  signal(SIGINT,endprog);                       /* Here if abort */
 
223
  signal(SIGTERM,endprog);              /* Here if abort */
 
224
 
 
225
  if (opt_connect_timeout)
 
226
  {
 
227
    uint tmp=opt_connect_timeout;
 
228
    drizzleclient_options(&drizzle,DRIZZLE_OPT_CONNECT_TIMEOUT, (char*) &tmp);
 
229
  }
 
230
 
 
231
  if (sql_connect(&drizzle, option_wait))
 
232
  {
 
233
    unsigned int err= drizzleclient_errno(&drizzle);
 
234
    if (err >= CR_MIN_ERROR && err <= CR_MAX_ERROR)
 
235
      error= 1;
 
236
    else
 
237
    {
 
238
      /* Return 0 if all commands are PING */
 
239
      for (; argc > 0; argv++, argc--)
 
240
      {
 
241
        if (find_type(argv[0], &command_typelib, 2) != ADMIN_PING)
 
242
        {
 
243
          error= 1;
 
244
          break;
 
245
        }
 
246
      }
 
247
    }
 
248
  }
 
249
  else
 
250
  {
 
251
    error=execute_commands(&drizzle,argc,commands);
 
252
    drizzleclient_close(&drizzle);
 
253
  }
 
254
  free(opt_password);
 
255
  free(user);
 
256
  free_defaults(save_argv);
 
257
  my_end(my_end_arg);
 
258
  return error ? 1 : 0;
 
259
}
 
260
 
 
261
void endprog(int)
 
262
{
 
263
  interrupted=1;
 
264
}
 
265
 
 
266
static bool sql_connect(DRIZZLE *drizzle, uint wait)
 
267
{
 
268
  bool info=0;
 
269
 
 
270
  for (;;)
 
271
  {
 
272
    if (drizzleclient_connect(drizzle,host,user,opt_password,NULL,tcp_port,NULL,0))
 
273
    {
 
274
      drizzle->reconnect= 1;
 
275
      if (info)
 
276
      {
 
277
        fputs("\n",stderr);
 
278
        (void) fflush(stderr);
 
279
      }
 
280
      return 0;
 
281
    }
 
282
 
 
283
    if (!wait)
 
284
    {
 
285
      if (!option_silent)
 
286
      {
 
287
        if (!host)
 
288
          host= (char*) LOCAL_HOST;
 
289
 
 
290
        fprintf(stderr,_("connect to server at '%s' failed\nerror: '%s'"),
 
291
                host, drizzleclient_error(drizzle));
 
292
 
 
293
        if (drizzleclient_errno(drizzle) == CR_CONN_HOST_ERROR ||
 
294
          drizzleclient_errno(drizzle) == CR_UNKNOWN_HOST)
 
295
        {
 
296
          fprintf(stderr,_("Check that drizzled is running on %s"),host);
 
297
          fprintf(stderr,_(" and that the port is %d.\n"),
 
298
          tcp_port ? tcp_port: drizzleclient_get_default_port());
 
299
          fprintf(stderr,_("You can check this by doing 'telnet %s %d'\n"),
 
300
                  host, tcp_port ? tcp_port: drizzleclient_get_default_port());
 
301
        }
 
302
      }
 
303
      return 1;
 
304
    }
 
305
    if (wait != UINT32_MAX)
 
306
      wait--;                           /* One less retry */
 
307
    if ((drizzleclient_errno(drizzle) != CR_CONN_HOST_ERROR) &&
 
308
        (drizzleclient_errno(drizzle) != CR_CONNECTION_ERROR))
 
309
    {
 
310
      fprintf(stderr,_("Got error: %s\n"), drizzleclient_error(drizzle));
 
311
    }
 
312
    else if (!option_silent)
 
313
    {
 
314
      if (!info)
 
315
      {
 
316
        info=1;
 
317
        fputs(_("Waiting for Drizzle server to answer"),stderr);
 
318
        (void) fflush(stderr);
 
319
      }
 
320
      else
 
321
      {
 
322
        putc('.',stderr);
 
323
        (void) fflush(stderr);
 
324
      }
 
325
    }
 
326
    sleep(5);
 
327
  }
 
328
}
 
329
 
 
330
/*
 
331
  Execute a command.
 
332
  Return 0 on ok
 
333
         -1 on retryable error
 
334
         1 on fatal error
 
335
*/
 
336
static int execute_commands(DRIZZLE *drizzle,int argc, char **argv)
 
337
{
 
338
 
 
339
  /*
 
340
    DRIZZLE documentation relies on the fact that drizzleadmin will
 
341
    execute commands in the order specified.
 
342
    If this behaviour is ever changed, Docs should be notified.
 
343
  */
 
344
  for (; argc > 0 ; argv++,argc--)
 
345
  {
 
346
    switch (find_type(argv[0],&command_typelib,2)) {
 
347
    case ADMIN_SHUTDOWN:
 
348
    {
 
349
      if (opt_verbose)
 
350
        printf(_("shutting down drizzled...\n"));
 
351
 
 
352
      if (drizzleclient_shutdown(drizzle))
 
353
      {
 
354
        fprintf(stderr, _("shutdown failed; error: '%s'"),
 
355
                drizzleclient_error(drizzle));
 
356
        return -1;
 
357
      }
 
358
      drizzleclient_close(drizzle);     /* Close connection to avoid error messages */
 
359
 
 
360
      if (opt_verbose)
 
361
        printf(_("done\n"));
 
362
 
 
363
      argc=1;             /* Force SHUTDOWN to be the last command */
 
364
      break;
 
365
    }
 
366
    case ADMIN_PING:
 
367
      drizzle->reconnect=0;     /* We want to know of reconnects */
 
368
      if (!drizzleclient_ping(drizzle))
 
369
      {
 
370
        if (option_silent < 2)
 
371
          puts(_("drizzled is alive"));
 
372
      }
 
373
      else
 
374
      {
 
375
        if (drizzleclient_errno(drizzle) == CR_SERVER_GONE_ERROR)
 
376
        {
 
377
          drizzle->reconnect=1;
 
378
          if (!drizzleclient_ping(drizzle))
 
379
            puts(_("connection was down, but drizzled is now alive"));
 
380
        }
 
381
        else
 
382
              {
 
383
          fprintf(stderr,_("drizzled doesn't answer to ping, error: '%s'"),
 
384
                  drizzleclient_error(drizzle));
 
385
          return -1;
 
386
        }
 
387
      }
 
388
      drizzle->reconnect=1;     /* Automatic reconnect is default */
 
389
      break;
 
390
 
 
391
    default:
 
392
      fprintf(stderr, _("Unknown command: '%-.60s'"), argv[0]);
 
393
      return 1;
 
394
    }
 
395
  }
 
396
  return 0;
 
397
}
 
398
 
 
399
static void print_version(void)
 
400
{
 
401
  printf(_("%s  Ver %s Distrib %s, for %s on %s\n"),my_progname,ADMIN_VERSION,
 
402
         drizzleclient_get_client_info(),SYSTEM_TYPE,MACHINE_TYPE);
 
403
}
 
404
 
 
405
static void usage(void)
 
406
{
 
407
  print_version();
 
408
  puts(_("Copyright (C) 2000-2008 MySQL AB"));
 
409
  puts(_("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n"));
 
410
  puts(_("Administration program for the drizzled daemon."));
 
411
  printf(_("Usage: %s [OPTIONS] command command....\n"), my_progname);
 
412
  my_print_help(my_long_options);
 
413
  puts(_("\
 
414
  ping         Check if server is down\n\
 
415
  shutdown     Take server down\n"));
 
416
}