~mathiaz/ubuntu/lucid/mysql-dfsg-5.1/zap-bug-552053

1 by Chuck Short
Import upstream version 5.1.30
1
/* Copyright (C) 2004 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
#if defined(__GNUC__) && defined(USE_PRAGMA_IMPLEMENTATION)
17
#pragma implementation
18
#endif
19
20
#include <my_global.h>
21
#include <mysql.h>
22
23
#include <signal.h>
24
#ifndef __WIN__
25
#include <sys/wait.h>
26
#endif
27
28
#include "manager.h"
29
#include "guardian.h"
30
#include "instance.h"
31
#include "log.h"
32
#include "mysql_manager_error.h"
33
#include "portability.h"
34
#include "priv.h"
35
#include "thread_registry.h"
36
#include "instance_map.h"
37
38
39
/*************************************************************************
40
  {{{ Platform-specific functions.
41
*************************************************************************/
42
43
#ifndef __WIN__
44
typedef pid_t My_process_info;
45
#else
46
typedef PROCESS_INFORMATION My_process_info;
47
#endif
48
49
/*
50
  Wait for an instance
51
52
  SYNOPSIS
53
    wait_process()
54
    pi                   Pointer to the process information structure
55
                         (platform-dependent).
56
57
  RETURN
58
   0  -  Success
59
   1  -  Error
60
*/
61
62
#ifndef __WIN__
63
static int wait_process(My_process_info *pi)
64
{
65
  /*
66
    Here we wait for the child created. This process differs for systems
67
    running LinuxThreads and POSIX Threads compliant systems. This is because
68
    according to POSIX we could wait() for a child in any thread of the
69
    process. While LinuxThreads require that wait() is called by the thread,
70
    which created the child.
71
    On the other hand we could not expect mysqld to return the pid, we
72
    got in from fork(), to wait4() fucntion when running on LinuxThreads.
73
    This is because MySQL shutdown thread is not the one, which was created
74
    by our fork() call.
75
    So basically we have two options: whether the wait() call returns only in
76
    the creator thread, but we cannot use waitpid() since we have no idea
77
    which pid we should wait for (in fact it should be the pid of shutdown
78
    thread, but we don't know this one). Or we could use waitpid(), but
79
    couldn't use wait(), because it could return in any wait() in the program.
80
  */
81
82
  if (Manager::is_linux_threads())
83
    wait(NULL);                               /* LinuxThreads were detected */
84
  else
85
    waitpid(*pi, NULL, 0);
86
87
  return 0;
88
}
89
#else
90
static int wait_process(My_process_info *pi)
91
{
92
  /* Wait until child process exits. */
93
  WaitForSingleObject(pi->hProcess, INFINITE);
94
95
  DWORD exitcode;
96
  ::GetExitCodeProcess(pi->hProcess, &exitcode);
97
98
  /* Close process and thread handles. */
99
  CloseHandle(pi->hProcess);
100
  CloseHandle(pi->hThread);
101
102
  /*
103
    GetExitCodeProces returns zero on failure. We should revert this value
104
    to report an error.
105
  */
106
  return (!exitcode);
107
}
108
#endif
109
110
/*
111
  Launch an instance
112
113
  SYNOPSIS
114
    start_process()
115
    instance_options     Pointer to the options of the instance to be
116
                         launched.
117
    pi                   Pointer to the process information structure
118
                         (platform-dependent).
119
120
  RETURN
121
   FALSE - Success
122
   TRUE  - Cannot create an instance
123
*/
124
125
#ifndef __WIN__
126
static bool start_process(Instance_options *instance_options,
127
                          My_process_info *pi)
128
{
129
#ifndef __QNX__
130
  *pi= fork();
131
#else
132
  /*
133
     On QNX one cannot use fork() in multithreaded environment and we
134
     should use spawn() or one of it's siblings instead.
135
     Here we use spawnv(), which  is a combination of fork() and execv()
136
     in one call. It returns the pid of newly created process (>0) or -1
137
  */
138
  *pi= spawnv(P_NOWAIT, instance_options->mysqld_path, instance_options->argv);
139
#endif
140
141
  switch (*pi) {
142
  case 0:                                       /* never happens on QNX */
143
    execv(instance_options->mysqld_path.str, instance_options->argv);
144
    /* exec never returns */
145
    exit(1);
146
  case -1:
147
    log_error("Instance '%s': can not start mysqld: fork() failed.",
148
              (const char *) instance_options->instance_name.str);
149
    return TRUE;
150
  }
151
152
  return FALSE;
153
}
154
#else
155
static bool start_process(Instance_options *instance_options,
156
                          My_process_info *pi)
157
{
158
  STARTUPINFO si;
159
160
  ZeroMemory(&si, sizeof(STARTUPINFO));
161
  si.cb= sizeof(STARTUPINFO);
162
  ZeroMemory(pi, sizeof(PROCESS_INFORMATION));
163
164
  int cmdlen= 0;
165
  for (int i= 0; instance_options->argv[i] != 0; i++)
0.2.1 by Norbert Tretkowski
Import upstream version 5.1.34
166
    cmdlen+= (uint) strlen(instance_options->argv[i]) + 3;
1 by Chuck Short
Import upstream version 5.1.30
167
  cmdlen++;   /* make room for the null */
168
169
  char *cmdline= new char[cmdlen];
170
  if (cmdline == NULL)
171
    return TRUE;
172
173
  cmdline[0]= 0;
174
  for (int i= 0; instance_options->argv[i] != 0; i++)
175
  {
176
    strcat(cmdline, "\"");
177
    strcat(cmdline, instance_options->argv[i]);
178
    strcat(cmdline, "\" ");
179
  }
180
181
  /* Start the child process */
182
  BOOL result=
183
    CreateProcess(NULL,          /* Put it all in cmdline */
184
                  cmdline,       /* Command line */
185
                  NULL,          /* Process handle not inheritable */
186
                  NULL,          /* Thread handle not inheritable */
187
                  FALSE,         /* Set handle inheritance to FALSE */
188
                  0,             /* No creation flags */
189
                  NULL,          /* Use parent's environment block */
190
                  NULL,          /* Use parent's starting directory */
191
                  &si,           /* Pointer to STARTUPINFO structure */
192
                  pi);           /* Pointer to PROCESS_INFORMATION structure */
193
  delete cmdline;
194
195
  return !result;
196
}
197
#endif
198
199
#ifdef __WIN__
200
201
BOOL SafeTerminateProcess(HANDLE hProcess, UINT uExitCode)
202
{
203
  DWORD dwTID, dwCode, dwErr= 0;
204
  HANDLE hProcessDup= INVALID_HANDLE_VALUE;
205
  HANDLE hRT= NULL;
206
  HINSTANCE hKernel= GetModuleHandle("Kernel32");
207
  BOOL bSuccess= FALSE;
208
209
  BOOL bDup= DuplicateHandle(GetCurrentProcess(),
210
                             hProcess, GetCurrentProcess(), &hProcessDup,
211
                             PROCESS_ALL_ACCESS, FALSE, 0);
212
213
  // Detect the special case where the process is
214
  // already dead...
215
  if (GetExitCodeProcess((bDup) ? hProcessDup : hProcess, &dwCode) &&
216
      (dwCode == STILL_ACTIVE))
217
  {
218
    FARPROC pfnExitProc;
219
220
    pfnExitProc= GetProcAddress(hKernel, "ExitProcess");
221
222
    hRT= CreateRemoteThread((bDup) ? hProcessDup : hProcess, NULL, 0,
223
                            (LPTHREAD_START_ROUTINE)pfnExitProc,
224
                            (PVOID)uExitCode, 0, &dwTID);
225
226
    if (hRT == NULL)
227
      dwErr= GetLastError();
228
  }
229
  else
230
    dwErr= ERROR_PROCESS_ABORTED;
231
232
  if (hRT)
233
  {
234
    // Must wait process to terminate to
235
    // guarantee that it has exited...
236
    WaitForSingleObject((bDup) ? hProcessDup : hProcess, INFINITE);
237
238
    CloseHandle(hRT);
239
    bSuccess= TRUE;
240
  }
241
242
  if (bDup)
243
    CloseHandle(hProcessDup);
244
245
  if (!bSuccess)
246
    SetLastError(dwErr);
247
248
  return bSuccess;
249
}
250
251
int kill(pid_t pid, int signum)
252
{
253
  HANDLE processhandle= ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
254
  if (signum == SIGTERM)
255
    ::SafeTerminateProcess(processhandle, 0);
256
  else
257
    ::TerminateProcess(processhandle, -1);
258
  return 0;
259
}
260
#endif
261
262
/*************************************************************************
263
  }}}
264
*************************************************************************/
265
266
267
/*************************************************************************
268
  {{{ Static constants.
269
*************************************************************************/
270
271
const LEX_STRING
272
Instance::DFLT_INSTANCE_NAME= { C_STRING_WITH_LEN("mysqld") };
273
274
/*************************************************************************
275
  }}}
276
*************************************************************************/
277
278
279
/*************************************************************************
280
  {{{ Instance Monitor thread.
281
*************************************************************************/
282
283
/**
284
  Proxy thread is a simple way to avoid all pitfalls of the threads
285
  implementation in the OS (e.g. LinuxThreads). With such a thread we
286
  don't have to process SIGCHLD, which is a tricky business if we want
287
  to do it in a portable way.
288
289
  Instance Monitor Thread forks a child process, execs mysqld and waits for
290
  the child to die.
291
292
  Instance Monitor assumes that the monitoring instance will not be dropped.
293
  This is guaranteed by having flag monitoring_thread_active and
294
  Instance::is_active() operation.
295
*/
296
297
class Instance_monitor: public Thread
298
{
299
public:
300
  Instance_monitor(Instance *instance_arg) :instance(instance_arg) {}
301
protected:
302
  virtual void run();
303
  void start_and_monitor_instance();
304
private:
305
  Instance *instance;
306
};
307
308
309
void Instance_monitor::run()
310
{
311
  start_and_monitor_instance();
312
  delete this;
313
}
314
315
316
void Instance_monitor::start_and_monitor_instance()
317
{
318
  Thread_registry *thread_registry= Manager::get_thread_registry();
319
  Guardian *guardian= Manager::get_guardian();
320
321
  My_process_info mysqld_process_info;
322
  Thread_info monitor_thread_info;
323
324
  log_info("Instance '%s': Monitor: started.",
325
           (const char *) instance->get_name()->str);
326
327
  /*
328
    For guarded instance register the thread in Thread_registry to wait for
329
    the thread to stop on shutdown (nonguarded instances are not stopped on
330
    shutdown, so the thread will no finish).
331
  */
332
333
  if (instance->is_guarded())
334
  {
335
    thread_registry->register_thread(&monitor_thread_info, FALSE);
336
  }
337
338
  /* Starting mysqld. */
339
340
  log_info("Instance '%s': Monitor: starting mysqld...",
341
           (const char *) instance->get_name()->str);
342
343
  if (start_process(&instance->options, &mysqld_process_info))
344
  {
345
    instance->lock();
346
    instance->monitoring_thread_active= FALSE;
347
    instance->unlock();
348
349
    return;
350
  }
351
352
  /* Waiting for mysqld to die. */
353
354
  log_info("Instance '%s': Monitor: waiting for mysqld to stop...",
355
           (const char *) instance->get_name()->str);
356
357
  wait_process(&mysqld_process_info); /* Don't check for return value. */
358
359
  log_info("Instance '%s': Monitor: mysqld stopped.",
360
           (const char *) instance->get_name()->str);
361
362
  /* Update instance status. */
363
364
  instance->lock();
365
366
  if (instance->is_guarded())
367
    thread_registry->unregister_thread(&monitor_thread_info);
368
369
  instance->crashed= TRUE;
370
  instance->monitoring_thread_active= FALSE;
371
372
  log_info("Instance '%s': Monitor: finished.",
373
           (const char *) instance->get_name()->str);
374
375
  instance->unlock();
376
377
  /* Wake up guardian. */
378
379
  guardian->ping();
380
}
381
382
/**************************************************************************
383
  }}}
384
**************************************************************************/
385
386
387
/**************************************************************************
388
  {{{ Static operations.
389
**************************************************************************/
390
391
/**
392
  The operation is intended to check whether string is a well-formed
393
  instance name or not.
394
395
  SYNOPSIS
396
    is_name_valid()
397
    name  string to check
398
399
  RETURN
400
    TRUE    string is a valid instance name
401
    FALSE   string is not a valid instance name
402
403
  TODO: Move to Instance_name class: Instance_name::is_valid().
404
*/
405
406
bool Instance::is_name_valid(const LEX_STRING *name)
407
{
408
  const char *name_suffix= name->str + DFLT_INSTANCE_NAME.length;
409
410
  if (strncmp(name->str, Instance::DFLT_INSTANCE_NAME.str,
411
              Instance::DFLT_INSTANCE_NAME.length) != 0)
412
    return FALSE;
413
414
  return *name_suffix == 0 || my_isdigit(default_charset_info, *name_suffix);
415
}
416
417
418
/**
419
  The operation is intended to check if the given instance name is
420
  mysqld-compatible or not.
421
422
  SYNOPSIS
423
    is_mysqld_compatible_name()
424
    name  name to check
425
426
  RETURN
427
    TRUE    name is mysqld-compatible
428
    FALSE   otherwise
429
430
  TODO: Move to Instance_name class: Instance_name::is_mysqld_compatible().
431
*/
432
433
bool Instance::is_mysqld_compatible_name(const LEX_STRING *name)
434
{
435
  return strcmp(name->str, DFLT_INSTANCE_NAME.str) == 0;
436
}
437
438
439
/**
440
  Return client state name. Must not be used outside the class.
441
  Use Instance::get_state_name() instead.
442
*/
443
444
const char * Instance::get_instance_state_name(enum_instance_state state)
445
{
446
  switch (state) {
447
  case STOPPED:
448
    return "offline";
449
450
  case NOT_STARTED:
451
    return "not started";
452
453
  case STARTING:
454
    return "starting";
455
456
  case STARTED:
457
    return "online";
458
459
  case JUST_CRASHED:
460
    return "failed";
461
462
  case CRASHED:
463
    return "crashed";
464
465
  case CRASHED_AND_ABANDONED:
466
    return "abandoned";
467
468
  case STOPPING:
469
    return "stopping";
470
  }
471
472
  return NULL; /* just to ignore compiler warning. */
473
}
474
475
/**************************************************************************
476
  }}}
477
**************************************************************************/
478
479
480
/**************************************************************************
481
  {{{ Initialization & deinitialization.
482
**************************************************************************/
483
484
Instance::Instance()
485
  :monitoring_thread_active(FALSE),
486
  crashed(FALSE),
487
  configured(FALSE),
488
  /* mysqld_compatible is initialized in init() */
489
  state(NOT_STARTED),
490
  restart_counter(0),
491
  crash_moment(0),
492
  last_checked(0)
493
{
494
  pthread_mutex_init(&LOCK_instance, 0);
495
}
496
497
498
Instance::~Instance()
499
{
500
  log_info("Instance '%s': destroying...", (const char *) get_name()->str);
501
502
  pthread_mutex_destroy(&LOCK_instance);
503
}
504
505
506
/**
507
  Initialize instance options.
508
509
  SYNOPSIS
510
    init()
511
    name_arg      name of the instance
512
513
  RETURN:
514
    FALSE - ok
515
    TRUE  - error
516
*/
517
518
bool Instance::init(const LEX_STRING *name_arg)
519
{
520
  mysqld_compatible= is_mysqld_compatible_name(name_arg);
521
522
  return options.init(name_arg);
523
}
524
525
526
/**
527
  @brief Complete instance options initialization.
528
529
  @return Error status.
530
    @retval FALSE ok
531
    @retval TRUE error
532
*/
533
534
bool Instance::complete_initialization()
535
{
536
  configured= ! options.complete_initialization();
537
  return !configured;
538
}
539
540
/**************************************************************************
541
  }}}
542
**************************************************************************/
543
544
545
/**************************************************************************
546
  {{{ Instance: public interface implementation.
547
**************************************************************************/
548
549
/**
550
  Determine if there is some activity with the instance.
551
552
  SYNOPSIS
553
    is_active()
554
555
  DESCRIPTION
556
    An instance is active if one of the following conditions is true:
557
      - Instance-monitoring thread is running;
558
      - Instance is guarded and its state is other than STOPPED;
559
      - Corresponding mysqld-server accepts connections.
560
561
    MT-NOTE: instance must be locked before calling the operation.
562
563
  RETURN
564
    TRUE  - instance is active
565
    FALSE - otherwise.
566
*/
567
568
bool Instance::is_active()
569
{
570
  if (monitoring_thread_active)
571
    return TRUE;
572
573
  if (is_guarded() && get_state() != STOPPED)
574
    return TRUE;
575
576
  return is_mysqld_running();
577
}
578
579
580
/**
581
  Determine if mysqld is accepting connections.
582
583
  SYNOPSIS
584
    is_mysqld_running()
585
586
  DESCRIPTION
587
    Try to connect to mysqld with fake login/password to check whether it is
588
    accepting connections or not.
589
590
    MT-NOTE: instance must be locked before calling the operation.
591
592
  RETURN
593
    TRUE  - mysqld is alive and accept connections
594
    FALSE - otherwise.
595
*/
596
597
bool Instance::is_mysqld_running()
598
{
599
  MYSQL mysql;
600
  uint port= options.get_mysqld_port(); /* 0 if not specified. */
601
  const char *socket= NULL;
602
  static const char *password= "check_connection";
603
  static const char *username= "MySQL_Instance_Manager";
604
  static const char *access_denied_message= "Access denied for user";
605
  bool return_val;
606
607
  if (options.mysqld_socket)
608
    socket= options.mysqld_socket;
609
610
  /* no port was specified => instance falled back to default value */
611
  if (!port && !options.mysqld_socket)
612
    port= SERVER_DEFAULT_PORT;
613
614
  mysql_init(&mysql);
615
  /* try to connect to a server with a fake username/password pair */
616
  if (mysql_real_connect(&mysql, LOCAL_HOST, username,
617
                         password,
618
                         NullS, port,
619
                         socket, 0))
620
  {
621
    /*
622
      We have successfully connected to the server using fake
623
      username/password. Write a warning to the logfile.
624
    */
625
    log_error("Instance '%s': was able to log into mysqld.",
626
              (const char *) get_name()->str);
627
    return_val= TRUE;                           /* server is alive */
628
  }
629
  else
630
    return_val= test(!strncmp(access_denied_message, mysql_error(&mysql),
631
                              sizeof(access_denied_message) - 1));
632
633
  mysql_close(&mysql);
634
635
  return return_val;
636
}
637
638
639
/**
640
  @brief Start mysqld.
641
642
  Reset flags and start Instance Monitor thread, which will start mysqld.
643
644
  @note Instance must be locked before calling the operation.
645
646
  @return Error status code
647
    @retval FALSE Ok
648
    @retval TRUE Could not start instance
649
*/
650
651
bool Instance::start_mysqld()
652
{
653
  Instance_monitor *instance_monitor;
654
655
  if (!configured)
656
    return TRUE;
657
658
  /*
659
    Prepare instance to start Instance Monitor thread.
660
661
    NOTE: It's important to set these actions here in order to avoid
662
    race conditions -- these actions must be done under acquired lock on
663
    Instance.
664
  */
665
666
  crashed= FALSE;
667
  monitoring_thread_active= TRUE;
668
669
  remove_pid();
670
671
  /* Create and start the Instance Monitor thread. */
672
673
  instance_monitor= new Instance_monitor(this);
674
675
  if (instance_monitor == NULL || instance_monitor->start(Thread::DETACHED))
676
  {
677
    delete instance_monitor;
678
    monitoring_thread_active= FALSE;
679
680
    log_error("Instance '%s': can not create instance monitor thread.",
681
              (const char *) get_name()->str);
682
683
    return TRUE;
684
  }
685
686
  ++restart_counter;
687
688
  /* The Instance Monitor thread will delete itself when it's finished. */
689
690
  return FALSE;
691
}
692
693
694
/**
695
  Stop mysqld.
696
697
  SYNOPSIS
698
    stop_mysqld()
699
700
  DESCRIPTION
701
    Try to stop mysqld gracefully. Otherwise kill it with SIGKILL.
702
703
    MT-NOTE: instance must be locked before calling the operation.
704
705
  RETURN
706
    FALSE - ok
707
    TRUE  - could not stop the instance
708
*/
709
710
bool Instance::stop_mysqld()
711
{
712
  log_info("Instance '%s': stopping mysqld...",
713
           (const char *) get_name()->str);
714
715
  kill_mysqld(SIGTERM);
716
717
  if (!wait_for_stop())
718
  {
719
    log_info("Instance '%s': mysqld stopped gracefully.",
720
             (const char *) get_name()->str);
721
    return FALSE;
722
  }
723
724
  log_info("Instance '%s': mysqld failed to stop gracefully within %d seconds.",
725
           (const char *) get_name()->str,
726
           (int) options.get_shutdown_delay());
727
728
  log_info("Instance'%s': killing mysqld...",
729
           (const char *) get_name()->str);
730
731
  kill_mysqld(SIGKILL);
732
733
  if (!wait_for_stop())
734
  {
735
    log_info("Instance '%s': mysqld has been killed.",
736
             (const char *) get_name()->str);
737
    return FALSE;
738
  }
739
740
  log_info("Instance '%s': can not kill mysqld within %d seconds.",
741
           (const char *) get_name()->str,
742
           (int) options.get_shutdown_delay());
743
744
  return TRUE;
745
}
746
747
748
/**
749
  Send signal to mysqld.
750
751
  SYNOPSIS
752
    kill_mysqld()
753
754
  DESCRIPTION
755
    Load pid from the pid file and send the given signal to that process.
756
    If the signal is SIGKILL, remove the pid file after sending the signal.
757
758
    MT-NOTE: instance must be locked before calling the operation.
759
760
  TODO
761
    This too low-level and OS-specific operation for public interface.
762
    Also, it has some implicit behaviour for SIGKILL signal. Probably, we
763
    should have the following public operations instead:
764
      - start_mysqld() -- as is;
765
      - stop_mysqld -- request mysqld to shutdown gracefully (send SIGTERM);
766
        don't wait for complete shutdown;
767
      - wait_for_stop() (or join_mysqld()) -- wait for mysqld to stop within
768
        time interval;
769
      - kill_mysqld() -- request to terminate mysqld; don't wait for
770
        completion.
771
    These operations should also be used in Guardian to manage instances.
772
*/
773
774
bool Instance::kill_mysqld(int signum)
775
{
776
  pid_t mysqld_pid= options.load_pid();
777
778
  if (mysqld_pid == 0)
779
  {
780
    log_info("Instance '%s': no pid file to send a signal (%d).",
781
             (const char *) get_name()->str,
782
             (int) signum);
783
    return TRUE;
784
  }
785
786
  log_info("Instance '%s': sending %d to %d...",
787
           (const char *) get_name()->str,
788
           (int) signum,
789
           (int) mysqld_pid);
790
791
  if (kill(mysqld_pid, signum))
792
  {
793
    log_info("Instance '%s': kill() failed.",
794
             (const char *) get_name()->str);
795
    return TRUE;
796
  }
797
798
  /* Kill suceeded */
799
  if (signum == SIGKILL)      /* really killed instance with SIGKILL */
800
  {
801
    log_error("Instance '%s': killed.",
802
              (const char *) options.instance_name.str);
803
804
    /* After sucessful hard kill the pidfile need to be removed */
805
    options.unlink_pidfile();
806
  }
807
808
  return FALSE;
809
}
810
811
812
/**
813
  Lock instance.
814
*/
815
816
void Instance::lock()
817
{
818
  pthread_mutex_lock(&LOCK_instance);
819
}
820
821
822
/**
823
  Unlock instance.
824
*/
825
826
void Instance::unlock()
827
{
828
  pthread_mutex_unlock(&LOCK_instance);
829
}
830
831
832
/**
833
  Return instance state name.
834
835
  SYNOPSIS
836
    get_state_name()
837
838
  DESCRIPTION
839
    The operation returns user-friendly state name. The operation can be
840
    used both for guarded and non-guarded instances.
841
842
    MT-NOTE: instance must be locked before calling the operation.
843
844
  TODO: Replace with the static get_state_name(state_code) function.
845
*/
846
847
const char *Instance::get_state_name()
848
{
849
  if (!is_configured())
850
    return "misconfigured";
851
852
  if (is_guarded())
853
  {
854
    /* The instance is managed by Guardian: we can report precise state. */
855
856
    return get_instance_state_name(get_state());
857
  }
858
859
  /* The instance is not managed by Guardian: we can report status only.  */
860
861
  return is_active() ? "online" : "offline";
862
}
863
864
865
/**
866
  Reset statistics.
867
868
  SYNOPSIS
869
    reset_stat()
870
871
  DESCRIPTION
872
    The operation resets statistics used for guarding the instance.
873
874
    MT-NOTE: instance must be locked before calling the operation.
875
876
  TODO: Make private.
877
*/
878
879
void Instance::reset_stat()
880
{
881
  restart_counter= 0;
882
  crash_moment= 0;
883
  last_checked= 0;
884
}
885
886
/**************************************************************************
887
  }}}
888
**************************************************************************/
889
890
891
/**************************************************************************
892
  {{{ Instance: implementation of private operations.
893
**************************************************************************/
894
895
/**
896
  Remove pid file.
897
*/
898
899
void Instance::remove_pid()
900
{
901
  int mysqld_pid= options.load_pid();
902
903
  if (mysqld_pid == 0)
904
    return;
905
906
  if (options.unlink_pidfile())
907
  {
908
    log_error("Instance '%s': can not unlink pid file.",
909
              (const char *) options.instance_name.str);
910
  }
911
}
912
913
914
/**
915
  Wait for mysqld to stop within shutdown interval.
916
*/
917
918
bool Instance::wait_for_stop()
919
{
920
  int start_time= (int) time(NULL);
921
  int finish_time= start_time + options.get_shutdown_delay();
922
923
  log_info("Instance '%s': waiting for mysqld to stop "
924
           "(timeout: %d seconds)...",
925
           (const char *) get_name()->str,
926
           (int) options.get_shutdown_delay());
927
928
  while (true)
929
  {
930
    if (options.load_pid() == 0 && !is_mysqld_running())
931
      return FALSE;
932
933
    if (time(NULL) >= finish_time)
934
      return TRUE;
935
936
    /* Sleep for 0.3 sec and check again. */
937
938
    my_sleep(300000);
939
  }
940
}
941
942
/**************************************************************************
943
  }}}
944
**************************************************************************/