📄 stonithd.c
字号:
executing_queue = g_hash_table_new_full(g_int_hash, g_int_equal, destory_key_of_op_htable, free_common_op_t); /* To avoid the warning message when app_interval is very small. */ MY_APPHB_HB /* drop_privs(0, 0); */ /* very important. cpu limit */ stonithd_log(LOG_DEBUG, "Enter g_mainloop\n"); stonithd_log(LOG_NOTICE, "%s %s", argv[0], M_STARTUP ); g_main_run(mainloop); MY_APPHB_HB if (SIGNONED_TO_APPHBD == TRUE) { apphb_unregister(); SIGNONED_TO_APPHBD = FALSE; }signoff_quit: if (hb != NULL && hb->llc_ops->signoff(hb) != HA_OK) { stonithd_log(LOG_ERR, "Cannot sign off from heartbeat."); stonithd_log(LOG_ERR, "REASON: %s", hb->llc_ops->errmsg(hb)); main_rc = LSB_EXIT_GENERIC; }delhb_quit: if (hb != NULL) { if (hb->llc_ops->delete(hb) != HA_OK) { stonithd_log(LOG_ERR, "Cannot delete API object."); stonithd_log(LOG_ERR, "REASON: %s", hb->llc_ops->errmsg(hb)); main_rc = LSB_EXIT_GENERIC; } } g_list_free(client_list); /* important. Others! free each item! pls check */ g_hash_table_destroy(executing_queue); /* ? */ if (unlink(PID_FILE) != 0) { stonithd_log(LOG_ERR, "it failed to remove pidfile %s.", PIDFILE); main_rc = LSB_EXIT_GENERIC; } if (0 == main_rc) { stonithd_log(LOG_NOTICE, "%s %s", argv[0], M_QUIT ); } else { stonithd_log(LOG_NOTICE, "%s %s", argv[0], M_ABORT ); } return (STARTUP_ALONE == TRUE) ? main_rc : MAGIC_EC;}/* * Notes: * 1) Not use daemon() API for its portibility, any comment?*/static voidbecome_daemon(gboolean startup_alone){ pid_t pid; int j; if (startup_alone == TRUE) { pid = fork(); if (pid < 0) { /* in parent process and fork failed. */ stonithd_log(LOG_ERR, "become_daemon: forking a child failed."); stonithd_log(LOG_ERR, "exit due to not becoming a daemon."); exit(LSB_EXIT_GENERIC); } else if (pid > 0) { /* in parent process and fork is ok */ exit(LSB_EXIT_OK); } } chdir("/"); umask(022); setsid(); for (j=0; j < 3; ++j) { close(j); (void)open("/dev/null", j == 0 ? O_RDONLY : O_RDONLY); } CL_IGNORE_SIG(SIGINT); CL_IGNORE_SIG(SIGHUP); CL_SIGNAL(SIGTERM, stonithd_quit); CL_SIGNAL(SIGQUIT, stonithd_quit); CL_SIGNAL(SIGCHLD, child_quit); if (0 != create_pidfile(PIDFILE)) { stonithd_log(LOG_ERR, "%s %s", stonithd_name, M_ABORT); exit((STARTUP_ALONE == TRUE) ? LSB_EXIT_GENERIC : MAGIC_EC); }}static voidstonithd_quit(int signo){ if (mainloop != NULL && g_main_is_running(mainloop)) { g_main_quit(mainloop); } else { /*apphb_unregister();*/ exit((STARTUP_ALONE == TRUE) ? LSB_EXIT_OK : MAGIC_EC); }}/* * The following three functions are for GSourceFuncs. This type of * source is for dealing with child signal - exit from child. * This method is used to avoid high cpu usage or reentrance issue. */static gbooleanon_polled_input_prepare(GSource * source, gint * timeout){ return childs_quit;}static gbooleanon_polled_input_check(GSource * source){ return childs_quit;}/* handle the child quit event */static gbooleanon_polled_input_dispatch(GSource * source, GSourceFunc callback, gpointer user_data){ int exit_status; pid_t pid = 0; int num_of_quitted_childs = 0; gboolean rc; common_op_t * op = NULL; int * orignal_key = NULL; stonithd_log(LOG_DEBUG, "on_polled_input_dispatch: begin"); while ((pid = wait(&exit_status)) > 0) { num_of_quitted_childs++; stonithd_log(LOG_DEBUG, "child %d exit code : %d", pid, WEXITSTATUS(exit_status)); rc = g_hash_table_lookup_extended(executing_queue, &pid, (gpointer *)&orignal_key, (gpointer *)&op); if (rc == FALSE ) { /* || op == NULL) */ stonithd_log(LOG_ERR, "received child quit signal, " "but no this child pid in excuting list."); continue; } if ( op == NULL) { stonithd_log(LOG_ERR, "received child quit signal: " "but op==NULL"); continue; } if ( op->scenario == STONITH_RA_OP ) { if (op->op_union.ra_op == NULL || op->result_receiver == NULL) { stonithd_log(LOG_ERR, "on_polled_input_dispatch: " "op->op_union.ra_op == NULL or " "op->result_receiver == NULL"); continue; } op->op_union.ra_op->call_id = pid; op->op_union.ra_op->op_result = exit_status; send_stonithRAop_final_result(op->op_union.ra_op, op->result_receiver); post_handle_raop(op->op_union.ra_op); g_hash_table_remove(executing_queue, &pid); continue; } /* next is stonith operation related */ if ( op->scenario == STONITH_INIT || op->scenario == STONITH_REQ ) { if (op->op_union.st_op == NULL || op->result_receiver == NULL ) { stonithd_log(LOG_ERR, "on_polled_input_dispatch: " "op->op_union.st_op == NULL or " "op->result_receiver == NULL"); continue; } if (WEXITSTATUS(exit_status) == S_OK) { op->op_union.st_op->op_result = STONITH_SUCCEEDED; send_stonithop_final_result(op); g_hash_table_remove(executing_queue, &pid); continue; } /* Go ahead when WEXITSTATUS(exit_status) != S_OK */ if (ST_OK == continue_local_stonithop(pid)) { continue; } else { if (changeto_remote_stonithop(pid) != ST_OK) { op->op_union.st_op->op_result = STONITH_GENERIC; send_stonithop_final_result(op); g_hash_table_remove(executing_queue, &pid); } } } } /* important, or incorrectly go here repeatly */ childs_quit = FALSE; if ( num_of_quitted_childs == 0) { stonithd_log(LOG_ERR, "on_polled_input_dispatch: why no " "child to quit."); /* To handle ? */ } return TRUE;}static voidchild_quit(int signo){ childs_quit = TRUE;}static intinit_hb_msg_handler(void){ IPC_Channel * hbapi_ipc = NULL; unsigned int msg_mask; stonithd_log(LOG_DEBUG, "init_hb_msg_handler: begin"); /* Set message callback */ if (hb->llc_ops->set_msg_callback(hb, T_WHOCANST, handle_msg_twhocan, hb) != HA_OK) { stonithd_log(LOG_ERR, "Cannot set msg T_WHOCAN callback"); stonithd_log(LOG_ERR, "REASON: %s", hb->llc_ops->errmsg(hb)); return LSB_EXIT_GENERIC; } if (hb->llc_ops->set_msg_callback(hb, T_ICANST, handle_msg_ticanst, hb) != HA_OK) { stonithd_log(LOG_ERR, "Cannot set msg T_ICANST callback"); stonithd_log(LOG_ERR, "REASON: %s", hb->llc_ops->errmsg(hb)); return LSB_EXIT_GENERIC; } if (hb->llc_ops->set_msg_callback(hb, T_STIT, handle_msg_tstit, hb) != HA_OK) { stonithd_log(LOG_ERR, "Cannot set msg T_STIT callback"); stonithd_log(LOG_ERR, "REASON: %s", hb->llc_ops->errmsg(hb)); return LSB_EXIT_GENERIC; } if (hb->llc_ops->set_msg_callback(hb, T_RSTIT, handle_msg_trstit, hb) != HA_OK) { stonithd_log(LOG_ERR, "Cannot set msg t_WHOCAN callback"); stonithd_log(LOG_ERR, "REASON: %s", hb->llc_ops->errmsg(hb)); return LSB_EXIT_GENERIC; } msg_mask = LLC_FILTER_DEFAULT; cl_log(LOG_DEBUG, "Setting message filter mode"); if (hb->llc_ops->setfmode(hb, msg_mask) != HA_OK) { stonithd_log(LOG_ERR, "Cannot set filter mode"); stonithd_log(LOG_ERR, "REASON: %s", hb->llc_ops->errmsg(hb)); return LSB_EXIT_GENERIC; } if (NULL == (hbapi_ipc = hb->llc_ops->ipcchan(hb))) { stonithd_log(LOG_ERR,"Cannot get hb's client IPC channel."); return LSB_EXIT_GENERIC; } /* Watch the hearbeat API's IPC channel for input */ G_main_add_IPC_Channel(G_PRIORITY_HIGH, hbapi_ipc, FALSE, stonithd_hb_msg_dispatch, (gpointer)hb, stonithd_hb_msg_dispatch_destroy); return 0;}static gbooleanstonithd_hb_msg_dispatch(IPC_Channel * ipcchan, gpointer user_data){ ll_cluster_t *hb = (ll_cluster_t*)user_data; while (hb->llc_ops->msgready(hb)) { /* FIXME: This should be a higher-level API function (broken API) */ if (hb->llc_ops->ipcchan(hb)->ch_status == IPC_DISCONNECT) { stonithd_quit(0); } /* invoke the callbacks with none-block mode */ stonithd_log(LOG_DEBUG, "there are hb msg received."); hb->llc_ops->rcvmsg(hb, 0); } /* deal with some abnormal errors/bugs? */ return TRUE;}static voidstonithd_hb_msg_dispatch_destroy(gpointer user_data){ return;}static voidhandle_msg_twhocan(const struct ha_msg* msg, void* private_data){ const char * target = NULL; const char * from = NULL; int call_id; stonithd_log(LOG_DEBUG, "I got T_WHOCANST msg."); if ( (from = cl_get_string(msg, F_ORIG)) == NULL) { stonithd_log(LOG_ERR, "handle_msg_twhocan: no F_ORIG field."); return; } /* Don't handle the message sent by myself */ if ( strncmp(from, local_nodename, strlen(local_nodename)) == 0) { stonithd_log(LOG_DEBUG, "received a T_WHOCAN msg from myself."); return; } if ( (target = cl_get_string(msg, F_STONITHD_NODE)) == NULL) { stonithd_log(LOG_ERR, "handle_msg_twhocan: no F_STONITHD_NODE " "field."); return; } if (HA_OK != ha_msg_value_int(msg, F_STONITHD_CALLID, &call_id)) { stonithd_log(LOG_ERR, "handle_msg_twhocan: no F_STONITHD_CALLID " "field."); return; } if (get_local_stonithobj_can_stonith(target, NULL) != NULL ) { struct ha_msg * reply; if ((reply = ha_msg_new(1)) == NULL) { stonithd_log(LOG_ERR, "handle_msg_twhocan: " "out of memory"); return; } if ( (ha_msg_add(reply, F_TYPE, T_ICANST) != HA_OK) ||(ha_msg_add(reply, F_ORIG, local_nodename) != HA_OK) ||(ha_msg_add_int(reply, F_STONITHD_CALLID, call_id) != HA_OK)) { stonithd_log(LOG_ERR, "handle_msg_twhocan: " "cannot add field."); ZAPMSG(reply); return; } if (hb == NULL) { stonithd_log(LOG_ERR, "handle_msg_twhocan: hb==NULL"); ZAPMSG(reply); return; } if (HA_OK!=hb->llc_ops->sendnodemsg(hb, reply, from)) { stonithd_log(LOG_ERR, "handle_msg_twhocan: " "sendnodermsg failed."); return; } ZAPMSG(reply); stonithd_log(LOG_DEBUG,"handle_msg_twhocan: " "send reply successfully."); }}static voidhandle_msg_ticanst(const struct ha_msg* msg, void* private_data){ const char * from = NULL; int call_id; int * orig_key = NULL; common_op_t * op = NULL; stonithd_log(LOG_DEBUG, "handle_msg_ticanst: got T_ICANST msg."); if ( (from = cl_get_string(msg, F_ORIG)) == NULL) { stonithd_log(LOG_ERR, "handle_msg_ticanst: no F_ORIG field."); return; } /* Don't handle the message sent by myself */ if ( strncmp(from, local_nodename, strlen(local_nodename)) == 0) { stonithd_log(LOG_DEBUG, "received a T_ICANST msg from myself."); return; } if ( HA_OK != ha_msg_value_int(msg, F_STONITHD_CALLID, &call_id) ) { stonithd_log(LOG_ERR, "handle_msg_ticanst: no F_STONITHD_CALLID" " field."); return; } my_hash_table_find(executing_queue, (gpointer *)&orig_key, (gpointer *)&op, &call_id); if ( op != NULL && /* QUERY only */ (op->scenario == STONITH_INIT || op->scenario == STONITH_REQ)) { /* add the separator blank space */ op->op_union.st_op->node_list = g_string_append(op->op_union.st_op->node_list, " "); op->op_union.st_op->node_list = g_string_append(op->op_union.st_op->node_list, from); stonithd_log(LOG_DEBUG, "handle_msg_ticanst: QUERY operation " "(call_id=%d): added a node's name who can stonith " "another node.", call_id); } /* wait the timeout function to send back the result */}static voidhandle_msg_tstit(const struct ha_msg* msg, void* private_data){ const char * target = NULL; const char * from = NULL; int call_id; int timeout; int optype; stonith_rsc_t * srsc = NULL; stonith_ops_t * st_op = NULL; stonithd_log(LOG_DEBUG, "handle_msg_tstit: got T_STIT msg."); if ( (from = cl_get_string(msg, F_ORIG)) == NULL) { stonithd_log(LOG_ERR, "handle_msg_tstit: no F_ORIG field."); return; } /* Don't handle the message sent by myself */ if ( strncmp(from, local_nodename, strlen(local_nodename)) == 0 && TEST == FALSE ) { stonithd_log(LOG_DEBUG, "received a T_STIT msg from myself, " "will abandon it."); return; } if ( (target = cl_get_string(msg, F_STONITHD_NODE)) == NULL) { stonithd_log(LOG_ERR, "handle_msg_tstit: no F_STONITHD_NODE " "field."); return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -