~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzleadmin.cc

  • Committer: Monty Taylor
  • Date: 2008-08-01 23:59:59 UTC
  • mto: (236.1.42 codestyle)
  • mto: This revision was merged to the branch mainline in revision 261.
  • Revision ID: monty@inaugust.com-20080801235959-n8ypy9r5aohown77
Gettext error compiles and passes test!

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2008 Drizzle Open Source Project 
 
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
/* maintaince of drizzle databases */
 
17
 
 
18
#include "client_priv.h"
 
19
#include <signal.h>
 
20
#include <mysys/my_pthread.h>                           /* because of signal()  */
 
21
#include <sys/stat.h>
 
22
 
 
23
#define ADMIN_VERSION "8.42"
 
24
#define SHUTDOWN_DEF_TIMEOUT 3600               /* Wait for shutdown */
 
25
 
 
26
char *host= NULL, *user= NULL, *opt_password= NULL;
 
27
static bool interrupted= false, opt_verbose= false,tty_password= false; 
 
28
static uint8_t opt_protocol= DRIZZLE_PROTOCOL_TCP;  
 
29
static uint32_t tcp_port= 0, option_wait= 0, option_silent= 0;
 
30
static uint32_t my_end_arg;
 
31
static uint32_t opt_connect_timeout, opt_shutdown_timeout;
 
32
static myf error_flags; /* flags to pass to my_printf_error, like ME_BELL */
 
33
 
 
34
/*
 
35
  Forward declarations 
 
36
*/
 
37
static void usage(void);
 
38
static void print_version(void);
 
39
extern "C" sig_handler endprog(int signal_number);
 
40
extern "C" bool get_one_option(int optid, const struct my_option *opt,
 
41
                               char *argument);
 
42
static int execute_commands(DRIZZLE *drizzle,int argc, char **argv);
 
43
static bool sql_connect(DRIZZLE *drizzle, uint wait);
 
44
 
 
45
/*
 
46
  The order of commands must be the same as command_names,
 
47
  except ADMIN_ERROR
 
48
*/
 
49
enum commands {
 
50
  ADMIN_ERROR,
 
51
  ADMIN_SHUTDOWN,
 
52
  ADMIN_PING
 
53
};
 
54
 
 
55
static const char *command_names[]= {
 
56
  "shutdown",
 
57
  "ping",
 
58
  NullS
 
59
};
 
60
 
 
61
static TYPELIB command_typelib=
 
62
{ array_elements(command_names)-1,"commands", command_names, NULL };
 
63
 
 
64
static struct my_option my_long_options[] =
 
65
{
 
66
  {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG,
 
67
   NO_ARG, 0, 0, 0, 0, 0, 0},
 
68
  {"host", 'h', "Connect to host.", (char**) &host, (char**) &host, 0, GET_STR,
 
69
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
70
  {"password", 'p',
 
71
   "Password to use when connecting to server. If password is not given it's asked from the tty.",
 
72
   0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
 
73
  {"port", 'P', "Port number to use for connection or 0 for default to, in "
 
74
   "order of preference, my.cnf, $MYSQL_TCP_PORT, "
 
75
#if MYSQL_PORT_DEFAULT == 0
 
76
   "/etc/services, "
 
77
#endif
 
78
   "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
 
79
   (char**) &tcp_port,
 
80
   (char**) &tcp_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
81
  {"silent", 's', "Silently exit if one can't connect to server.",
 
82
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
83
#ifndef DONT_ALLOW_USER_CHANGE
 
84
  {"user", 'u', "User for login if not current user.", (char**) &user,
 
85
   (char**) &user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
86
#endif
 
87
  {"verbose", 'v', "Write more information.", (char**) &opt_verbose,
 
88
   (char**) &opt_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
89
  {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
 
90
   NO_ARG, 0, 0, 0, 0, 0, 0},
 
91
  {"wait", 'w', "Wait and retry if connection is down.", 0, 0, 0, GET_UINT,
 
92
   OPT_ARG, 0, 0, 0, 0, 0, 0},
 
93
  {"connect_timeout", OPT_CONNECT_TIMEOUT, "", (char**) &opt_connect_timeout,
 
94
   (char**) &opt_connect_timeout, 0, GET_ULONG, REQUIRED_ARG, 3600*12, 0,
 
95
   3600*12, 0, 1, 0},
 
96
  {"shutdown_timeout", OPT_SHUTDOWN_TIMEOUT, "", (char**) &opt_shutdown_timeout,
 
97
   (char**) &opt_shutdown_timeout, 0, GET_ULONG, REQUIRED_ARG,
 
98
   SHUTDOWN_DEF_TIMEOUT, 0, 3600*12, 0, 1, 0},
 
99
  { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 
100
};
 
101
 
 
102
 
 
103
static const char *load_default_groups[]= { "drizzleadmin","client",0 };
 
104
 
 
105
bool
 
106
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
 
107
               char *argument)
 
108
{
 
109
  int error = 0;
 
110
 
 
111
  switch(optid) {
 
112
  case 'p':
 
113
    if (argument)
 
114
    {
 
115
      char *start=argument;
 
116
      my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
 
117
      opt_password= my_strdup(argument,MYF(MY_FAE));
 
118
      while (*argument) *argument++= 'x';   /* Destroy argument */
 
119
      if (*start)
 
120
        start[1]=0; /* Cut length of argument */
 
121
      tty_password= 0;
 
122
    }
 
123
    else 
 
124
      tty_password= 1; 
 
125
    break;
 
126
  case 's':
 
127
    option_silent++;
 
128
    break;
 
129
  case 'V':
 
130
    print_version();
 
131
    exit(0);
 
132
    break;
 
133
  case 'w':
 
134
    if (argument)
 
135
    {
 
136
      if ((option_wait=atoi(argument)) <= 0)
 
137
        option_wait=1;
 
138
    }
 
139
    else
 
140
      option_wait= ~(uint)0;
 
141
    break;
 
142
  case '?':
 
143
  case 'I':                                     /* Info */
 
144
    error++;
 
145
    break;
 
146
  }
 
147
 
 
148
  if (error)
 
149
  {
 
150
    usage();
 
151
    exit(1);
 
152
  }
 
153
  return 0;
 
154
}
 
155
 
 
156
int main(int argc,char *argv[])
 
157
{
 
158
  int error= 0, ho_error;
 
159
  DRIZZLE drizzle;
 
160
  char **commands, **save_argv;
 
161
 
 
162
  MY_INIT(argv[0]);
 
163
  drizzle_create(&drizzle);
 
164
  load_defaults("my",load_default_groups,&argc,&argv);
 
165
  save_argv = argv;                             /* Save for free_defaults */
 
166
  if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
 
167
  {
 
168
    free_defaults(save_argv);
 
169
    exit(ho_error);
 
170
  }
 
171
 
 
172
  if (argc == 0)
 
173
  {
 
174
    usage();
 
175
    exit(1);
 
176
  }
 
177
 
 
178
  commands = argv;
 
179
  if (tty_password)
 
180
    opt_password = get_tty_password(NullS);
 
181
 
 
182
  VOID(signal(SIGINT,endprog));                 /* Here if abort */
 
183
  VOID(signal(SIGTERM,endprog));                /* Here if abort */
 
184
 
 
185
  if (opt_connect_timeout)
 
186
  {
 
187
    uint tmp=opt_connect_timeout;
 
188
    drizzle_options(&drizzle,DRIZZLE_OPT_CONNECT_TIMEOUT, (char*) &tmp);
 
189
  }
 
190
  /* force drizzleadmin to use TCP */
 
191
  drizzle_options(&drizzle, DRIZZLE_OPT_PROTOCOL, (char*)&opt_protocol);
 
192
 
 
193
  error_flags= (myf)0;
 
194
 
 
195
  if (sql_connect(&drizzle, option_wait))
 
196
  {
 
197
    unsigned int err= drizzle_errno(&drizzle);
 
198
    if (err >= CR_MIN_ERROR && err <= CR_MAX_ERROR)
 
199
      error= 1;
 
200
    else
 
201
    {
 
202
      /* Return 0 if all commands are PING */
 
203
      for (; argc > 0; argv++, argc--)
 
204
      {
 
205
        if (find_type(argv[0], &command_typelib, 2) != ADMIN_PING)
 
206
        {
 
207
          error= 1;
 
208
          break;
 
209
        }
 
210
      }
 
211
    }
 
212
  }
 
213
  else
 
214
  {
 
215
    error=execute_commands(&drizzle,argc,commands);
 
216
    drizzle_close(&drizzle);
 
217
  }
 
218
  my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
 
219
  my_free(user,MYF(MY_ALLOW_ZERO_PTR));
 
220
  free_defaults(save_argv);
 
221
  my_end(my_end_arg);
 
222
  exit(error ? 1 : 0);
 
223
}
 
224
 
 
225
sig_handler endprog(int signal_number __attribute__((unused)))
 
226
{
 
227
  interrupted=1;
 
228
}
 
229
 
 
230
static bool sql_connect(DRIZZLE *drizzle, uint wait)
 
231
{
 
232
  bool info=0;
 
233
 
 
234
  for (;;)
 
235
  {
 
236
    if (drizzle_connect(drizzle,host,user,opt_password,NullS,tcp_port,NULL,0))
 
237
    {
 
238
      drizzle->reconnect= 1;
 
239
      if (info)
 
240
      {
 
241
        fputs("\n",stderr);
 
242
        (void) fflush(stderr);
 
243
      }
 
244
      return 0;
 
245
    }
 
246
 
 
247
    if (!wait)
 
248
    {
 
249
      if (!option_silent)
 
250
      {
 
251
        if (!host)
 
252
          host= (char*) LOCAL_HOST;
 
253
 
 
254
        my_printf_error(0,"connect to server at '%s' failed\nerror: '%s'",
 
255
        error_flags, host, drizzle_error(drizzle));
 
256
 
 
257
        if (drizzle_errno(drizzle) == CR_CONN_HOST_ERROR ||
 
258
          drizzle_errno(drizzle) == CR_UNKNOWN_HOST)
 
259
        {
 
260
          fprintf(stderr,"Check that drizzled is running on %s",host);
 
261
          fprintf(stderr," and that the port is %d.\n",
 
262
          tcp_port ? tcp_port: drizzle_port);
 
263
          fprintf(stderr,"You can check this by doing 'telnet %s %d'\n",
 
264
                  host, tcp_port ? tcp_port: drizzle_port);
 
265
        }
 
266
      }
 
267
      return 1;
 
268
    }
 
269
    if (wait != (uint) ~0)
 
270
      wait--;                           /* One less retry */
 
271
    if ((drizzle_errno(drizzle) != CR_CONN_HOST_ERROR) &&
 
272
        (drizzle_errno(drizzle) != CR_CONNECTION_ERROR))
 
273
    {
 
274
      fprintf(stderr,"Got error: %s\n", drizzle_error(drizzle));
 
275
    }
 
276
    else if (!option_silent)
 
277
    {
 
278
      if (!info)
 
279
      {
 
280
        info=1;
 
281
        fputs("Waiting for Drizzle server to answer",stderr);
 
282
        (void) fflush(stderr);
 
283
      }
 
284
      else
 
285
      {
 
286
        putc('.',stderr);
 
287
        (void) fflush(stderr);
 
288
      }
 
289
    }
 
290
    sleep(5);
 
291
  }
 
292
}
 
293
 
 
294
/*
 
295
  Execute a command.
 
296
  Return 0 on ok
 
297
         -1 on retryable error
 
298
         1 on fatal error
 
299
*/
 
300
static int execute_commands(DRIZZLE *drizzle,int argc, char **argv)
 
301
{
 
302
 
 
303
  /*
 
304
    DRIZZLE documentation relies on the fact that drizzleadmin will
 
305
    execute commands in the order specified.
 
306
    If this behaviour is ever changed, Docs should be notified.
 
307
  */
 
308
  for (; argc > 0 ; argv++,argc--)
 
309
  {
 
310
    switch (find_type(argv[0],&command_typelib,2)) {
 
311
    case ADMIN_SHUTDOWN:
 
312
    {
 
313
      if (opt_verbose)
 
314
        printf("shutting down drizzled...\n");
 
315
 
 
316
      if (drizzle_shutdown(drizzle, SHUTDOWN_DEFAULT))
 
317
      {
 
318
        my_printf_error(0, "shutdown failed; error: '%s'", error_flags,
 
319
                        drizzle_error(drizzle));
 
320
        return -1;
 
321
      }
 
322
      drizzle_close(drizzle);   /* Close connection to avoid error messages */
 
323
 
 
324
      if (opt_verbose)
 
325
        printf("done\n");
 
326
 
 
327
      argc=1;             /* Force SHUTDOWN to be the last command */
 
328
      break;
 
329
    }
 
330
    case ADMIN_PING:
 
331
      drizzle->reconnect=0;     /* We want to know of reconnects */
 
332
      if (!drizzle_ping(drizzle))
 
333
      {
 
334
        if (option_silent < 2)
 
335
          puts("drizzled is alive");
 
336
      }
 
337
      else
 
338
      {
 
339
        if (drizzle_errno(drizzle) == CR_SERVER_GONE_ERROR)
 
340
        {
 
341
          drizzle->reconnect=1;
 
342
          if (!drizzle_ping(drizzle))
 
343
            puts("connection was down, but drizzled is now alive");
 
344
        }
 
345
        else
 
346
              {
 
347
          my_printf_error(0,"drizzled doesn't answer to ping, error: '%s'",
 
348
          error_flags, drizzle_error(drizzle));
 
349
          return -1;
 
350
        }
 
351
      }
 
352
      drizzle->reconnect=1;     /* Automatic reconnect is default */
 
353
      break;
 
354
 
 
355
    default:
 
356
      my_printf_error(0, "Unknown command: '%-.60s'", error_flags, argv[0]);
 
357
      return 1;
 
358
    }
 
359
  }
 
360
  return 0;
 
361
}
 
362
 
 
363
static void print_version(void)
 
364
{
 
365
  printf("%s  Ver %s Distrib %s, for %s on %s\n",my_progname,ADMIN_VERSION,
 
366
         MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
 
367
}
 
368
 
 
369
static void usage(void)
 
370
{
 
371
  print_version();
 
372
  puts("Copyright (C) 2000-2006 DRIZZLE AB");
 
373
  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");
 
374
  puts("Administration program for the drizzled daemon.");
 
375
  printf("Usage: %s [OPTIONS] command command....\n", my_progname);
 
376
  my_print_help(my_long_options);
 
377
  puts("\
 
378
  ping         Check if server is down\n\
 
379
  shutdown     Take server down\n");
 
380
}