int wd_am_I_oldest(void) { WdInfo * p = WD_List; p++; while (p->status != WD_END) { if ((p->status == WD_NORMAL) || (p->status == WD_MASTER)) { if (WD_TIME_BEFORE(p->tv, WD_MYSELF->tv)) { return WD_NG; } } p++; } return WD_OK; }
pid_t wd_hb_receiver(int fork_wait_time, WdHbIf hb_if) { int sock; pid_t pid = 0; WdHbPacket pkt; struct timeval tv; char from[WD_MAX_HOST_NAMELEN]; char buf[(MD5_PASSWD_LEN+1)*2]; char pack_str[WD_MAX_PACKET_STRING]; int pack_str_len; WdInfo * p; pid = fork(); if (pid != 0) { if (pid == -1) pool_error("wd_hb_receiver: fork() failed."); return pid; } if (fork_wait_time > 0) { sleep(fork_wait_time); } myargv = save_ps_display_args(myargc, myargv); POOL_SETMASK(&UnBlockSig); signal(SIGTERM, hb_receiver_exit); signal(SIGINT, hb_receiver_exit); signal(SIGQUIT, hb_receiver_exit); signal(SIGCHLD, SIG_IGN); signal(SIGHUP, SIG_IGN); signal(SIGUSR1, SIG_IGN); signal(SIGUSR2, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGALRM, SIG_IGN); init_ps_display("", "", "", ""); if ( (sock = wd_create_hb_recv_socket(hb_if)) < 0) { pool_error("wd_hb_receiver: socket create failed"); hb_receiver_exit(SIGTERM); } set_ps_display("heartbeat receiver", false); for(;;) { if (wd_hb_recv(sock, &pkt) == WD_OK) { /* authentication */ if (strlen(pool_config->wd_authkey)) { /* calculate hash from packet */ pack_str_len = packet_to_string_hb(pkt, pack_str, sizeof(pack_str)); wd_calc_hash(pack_str, pack_str_len, buf); if (strcmp(pkt.hash, buf)) { pool_log("wd_hb_receiver: authentication failed"); continue; } } /* get current time */ gettimeofday(&tv, NULL); /* who send this packet? */ strlcpy(from, pkt.from, sizeof(from)); p = WD_List; while (p->status != WD_END) { if (!strcmp(p->hostname, from)) { /* this is the first packet or the latest packet */ if (!WD_TIME_ISSET(p->hb_send_time) || WD_TIME_BEFORE(p->hb_send_time, pkt.send_time)) { pool_debug("wd_hb_receiver: received heartbeat signal from %s", from); p->hb_send_time = pkt.send_time; p->hb_last_recv_time = tv; } break; } p++; } } } return pid; }
/* fork heartbeat receiver child */ pid_t wd_hb_receiver(int fork_wait_time, WdHbIf *hb_if) { int sock; pid_t pid = 0; WdHbPacket pkt; struct timeval tv; char from[WD_MAX_HOST_NAMELEN]; int from_pgpool_port; char buf[(MD5_PASSWD_LEN+1)*2]; char pack_str[WD_MAX_PACKET_STRING]; int pack_str_len; sigjmp_buf local_sigjmp_buf; WdInfo * p; pid = fork(); if (pid != 0) { if (pid == -1) ereport(PANIC, (errmsg("failed to fork a heartbeat receiver child"))); return pid; } on_exit_reset(); processType = PT_HB_RECEIVER; if (fork_wait_time > 0) { sleep(fork_wait_time); } POOL_SETMASK(&UnBlockSig); signal(SIGTERM, hb_receiver_exit); signal(SIGINT, hb_receiver_exit); signal(SIGQUIT, hb_receiver_exit); signal(SIGCHLD, SIG_IGN); signal(SIGHUP, SIG_IGN); signal(SIGUSR1, SIG_IGN); signal(SIGUSR2, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGALRM, SIG_IGN); init_ps_display("", "", "", ""); /* Create per loop iteration memory context */ ProcessLoopContext = AllocSetContextCreate(TopMemoryContext, "wdhb_hb_receiver", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); MemoryContextSwitchTo(TopMemoryContext); sock = wd_create_hb_recv_socket(hb_if); set_ps_display("heartbeat receiver", false); if (sigsetjmp(local_sigjmp_buf, 1) != 0) { /* Since not using PG_TRY, must reset error stack by hand */ error_context_stack = NULL; EmitErrorReport(); MemoryContextSwitchTo(TopMemoryContext); FlushErrorState(); } /* We can now handle ereport(ERROR) */ PG_exception_stack = &local_sigjmp_buf; for(;;) { MemoryContextSwitchTo(ProcessLoopContext); MemoryContextResetAndDeleteChildren(ProcessLoopContext); /* receive heartbeat signal */ wd_hb_recv(sock, &pkt); /* authentication */ if (strlen(pool_config->wd_authkey)) { /* calculate hash from packet */ pack_str_len = packet_to_string_hb(&pkt, pack_str, sizeof(pack_str)); wd_calc_hash(pack_str, pack_str_len, buf); if (strcmp(pkt.hash, buf)) ereport(ERROR, (errmsg("watchdog heartbeat receive"), errdetail("authentication failed"))); } /* get current time */ gettimeofday(&tv, NULL); /* who send this packet? */ strlcpy(from, pkt.from, sizeof(from)); from_pgpool_port = pkt.from_pgpool_port; p = WD_List; while (p->status != WD_END) { if (!strcmp(p->hostname, from) && p->pgpool_port == from_pgpool_port) { /* ignore the packet from down pgpool */ if (pkt.status == WD_DOWN) { ereport(DEBUG1, (errmsg("watchdog heartbeat: received heartbeat signal from \"%s:%d\" whose status is down. ignored", from, from_pgpool_port))); break; } /* this is the first packet or the latest packet */ if (!WD_TIME_ISSET(p->hb_send_time) || WD_TIME_BEFORE(p->hb_send_time, pkt.send_time)) { ereport(DEBUG1, (errmsg("watchdog heartbeat: received heartbeat signal from \"%s:%d\"", from, from_pgpool_port))); p->hb_send_time = pkt.send_time; p->hb_last_recv_time = tv; } else { ereport(DEBUG1, (errmsg("watchdog heartbeat: received heartbeat signal is older than the latest, ignored"))); } break; } p++; } } return pid; }