📄 sel_clnt.c
字号:
seln_null_holder; return result; } return result;}/* VARARGS0 */Seln_resultseln_debug(va_alist)va_dcl{ Seln_request buffer; va_list valist; char **requestp; if (service == (CLIENT *)NULL) { if ((service = seln_get_service(&service_socket)) == (CLIENT *) NULL) { return SELN_FAILED; } } buffer.replier = 0; buffer.requester.consume = 0; buffer.requester.context = 0; buffer.addressee = service_holder.access.client; buffer.rank = SELN_UNKNOWN; buffer.status = SELN_SUCCESS; va_start(valist); if (attr_make_count((char **)(LINT_CAST(buffer.data)), SELN_BUFSIZE / sizeof(char *), valist, (int *)(LINT_CAST(&(buffer.buf_size)))) == NULL) { complain("Debug request wouldn't fit in buffer"); return SELN_FAILED; } va_end(valist); if (clnt_call(service, SELN_CLNT_REQUEST, xdr_seln_request, &buffer, xdr_seln_reply, &buffer, seln_std_timeout) != RPC_SUCCESS) { return SELN_FAILED; } requestp = (char **) (LINT_CAST(buffer.data)); if (*requestp++ != (char *) SELN_REQ_YIELD) { return SELN_FAILED; } return (Seln_result) *requestp;}voidseln_use_test_service(){ seln_svc_program |= SELN_SVC_TEST;}voidseln_use_timeout(secs) int secs;{ seln_std_timeout.tv_sec = secs;}/* * Clear_functions: tell the service all function keys are up */voidseln_clear_functions(){ if (service == (CLIENT *)NULL) { if ((service = seln_get_service(&service_socket)) == (CLIENT *)NULL) { return; } } if (clnt_call(service, SELN_SVC_CLEAR_FUNCTIONS, xdr_void, 0, xdr_void, 0, seln_std_timeout) != RPC_SUCCESS) { clnt_perror(service, "Couldn't tell service to clear functions"); }}Seln_resultseln_stop(auth) int auth;{ if (service == (CLIENT *)NULL) { if ((service = seln_get_service(&service_socket)) == (CLIENT *)NULL) { return SELN_FAILED; } } if (clnt_call(service, SELN_SVC_STOP, xdr_enum, &auth, xdr_void, 0, seln_std_timeout) != RPC_SUCCESS) { clnt_perror(service, "Couldn't tell service to stop"); return SELN_FAILED; } else { return SELN_SUCCESS; }}/* Now calls to other holders * * Send a request concerning the selection to its holder */Seln_resultseln_request(holder, buffer) Seln_holder *holder; Seln_request *buffer;{ CLIENT *client; Seln_access *access; int sock = RPC_ANYSOCK; enum clnt_stat result; if (seln_holder_same_process(holder)) { return seln_local_request(holder, buffer); } access = &holder->access; if (kill(access->pid, 0) == -1 && errno == ESRCH) { return SELN_NON_EXIST; } client = clnttcp_create(&access->tcp_address, access->program, SELN_VERSION, &sock, sizeof (Seln_request), sizeof (Seln_request)); if (client == NULL) { clnt_pcreateerror("Seln_request"); complain("Couldn't get client handle for current holder"); return SELN_FAILED; } result = clnt_call(client, SELN_CLNT_REQUEST, xdr_seln_request, buffer, xdr_seln_reply, buffer, seln_std_timeout); if (result != RPC_SUCCESS) { clnt_perror(client, "Request to current holder failed"); clnt_destroy(client); (void)close(sock); return SELN_FAILED; } clnt_destroy(client); (void)close(sock); return SELN_SUCCESS;}/* short-circuit net if holder of selection is * in the same process as requester *//*ARGSUSED*/static Seln_resultseln_local_request(holder, buffer) Seln_holder *holder; Seln_request *buffer;{ Seln_request request; Seln_replier_data replier_info; request = *buffer; (void)seln_init_reply(&request, buffer, &replier_info); if (buffer->requester.consume) { do { if (seln_get_reply_buffer(buffer) != SELN_SUCCESS) { return SELN_FAILED; } if (buffer->requester.consume(buffer) == SELN_CANCEL) { *buffer->replier->request_pointer = (char *) SELN_REQ_END_REQUEST; (void) seln_get_reply_buffer(buffer); return SELN_SUCCESS; } } while (buffer->status == SELN_CONTINUED); return SELN_SUCCESS; } if (seln_get_reply_buffer(buffer) != SELN_SUCCESS) { return SELN_FAILED; } if (buffer->status == SELN_CONTINUED) { (void) seln_get_reply_buffer(buffer); return SELN_FAILED; } return SELN_SUCCESS;}/* * Procedures which get called remotely *//* seln_dispatch is called by rpc dispatcher, and in turn calls * the appropriate response function below; * that will (typically) call a client callback proc. */static voidseln_dispatch(request, transport) struct svc_req *request; SVCXPRT *transport;{ switch (request->rq_proc) { case SELN_SVC_NULLPROC: if (!svc_sendreply(transport, xdr_void, (char *)0)) { complain("Couldn't reply to RPC call"); } return; case SELN_CLNT_DO_FUNCTION: seln_do_function(transport); return; case SELN_CLNT_REQUEST: seln_do_reply(transport); return; default: svcerr_noproc(transport); return; }}/* * Client internal routines */static voidseln_update_service(rank) Seln_rank rank;{ Seln_holder holder; Seln_result result; holder = seln_null_holder; holder.rank = rank; (void) clnt_call(service, SELN_SVC_ACQUIRE, xdr_seln_holder, &holder, xdr_enum, &result, seln_std_timeout);}static Seln_seize_resultseln_seize(client_data, asked, given) char *client_data; Seln_rank asked, *given;{ Seln_result result; Seln_holder holder; *given = asked; /* Ask the current holder for it */ holder = seln_holder_of_rank(given); if (holder.state != SELN_EXISTS) { return Seln_seized_ok; } if (seln_holder_same_client(&holder, client_data)) { return Seln_seized_self; } if (kill(holder.access.pid, 0) == -1 && errno == ESRCH) { seln_update_service(holder.rank); return Seln_seized_ok; } switch (result = seln_send_yield(holder.rank, &holder, FALSE)) { case SELN_SUCCESS: return Seln_seized_ok; case SELN_WRONG_RANK: /* server's behind; try again */ if (*given == SELN_PRIMARY && asked != SELN_SECONDARY) { *given = SELN_SECONDARY; holder = seln_holder_of_rank(given); if (holder.state != SELN_EXISTS) { return Seln_seized_ok; } if (seln_holder_same_client(&holder, client_data)) { return Seln_seized_self; } result = seln_send_yield(holder.rank, &holder, TRUE); } else { complain("Other holder confused about selection ranks"); return Seln_seized_blind; } if (result == SELN_SUCCESS) { return Seln_seized_ok; } /* else FALL THROUGH */ } return Seln_seized_blind;}/* * Initialize the per-process communication information */static intseln_init_holder_process(){ if ((service = seln_get_service(&service_socket)) == (CLIENT *) NULL) { return FALSE; } if (seln_get_service_holder(&service_holder) != SELN_SUCCESS) { clnt_destroy(service); (void)close(service_socket); service = (CLIENT *) NULL; service_socket = 0; return FALSE; } if ((seln_my_udp_transport = svcudp_bufcreate(RPC_ANYSOCK, SELN_RPC_BUFSIZE, SELN_RPC_BUFSIZE)) == (SVCXPRT *) NULL) { complain("Couldn't get a UDP transport for requesters to talk to us"); return FALSE; } seln_my_udp_socket = seln_my_udp_transport->xp_sock; if (seln_get_access(&seln_my_access) == SELN_FAILED) { return FALSE; } if (!svc_register(seln_my_udp_transport, seln_my_access.program, SELN_VERSION, seln_dispatch, NO_PMAP)) { complain("Couldn't register transport for requesters to talk to us"); svc_destroy(seln_my_udp_transport); (void)close(seln_my_udp_socket); return FALSE; } (void) notify_set_input_func((Notify_client) seln_my_udp_transport, seln_listener, seln_my_udp_socket); if (seln_get_tcp(seln_my_access.program, seln_dispatch) != SELN_SUCCESS) { complain("Couldn't TCP transport for requesters to talk to us"); svc_destroy(seln_my_udp_transport); (void)close(seln_my_udp_socket); return FALSE; } return TRUE;}static CLIENT *seln_get_service(s) int *s;{ struct sockaddr_in address; *s = RPC_ANYSOCK; get_myaddress(&address); address.sin_port = 0; return clntudp_bufcreate(&address, seln_svc_program, SELN_VERSION, seln_std_timeout, s, SELN_RPC_BUFSIZE, SELN_RPC_BUFSIZE);}static Seln_resultseln_get_service_holder(holder) Seln_holder *holder;{ if (clnt_call(service, SELN_SVC_GET_HOLDER, xdr_void, 0, xdr_seln_holder, holder, seln_std_timeout) != RPC_SUCCESS) { clnt_perror(service, "No selection service available"); return SELN_FAILED; } else { return SELN_SUCCESS; }}static Seln_resultseln_get_access(access) Seln_access *access;{ struct sockaddr_in *addr; access->pid = getpid(); addr = &access->udp_address; get_myaddress(addr); addr->sin_port = htons(seln_my_udp_transport->xp_port); access->program = SELN_LIB_PROGRAM; return SELN_SUCCESS;}static Seln_holderseln_holder_of_rank(rank) Seln_rank *rank;{ enum clnt_stat result; Seln_holder holder; result = clnt_call(service, SELN_SVC_INQUIRE, xdr_enum, rank, xdr_seln_holder, &holder, seln_std_timeout); if (result != RPC_SUCCESS) { clnt_perror(service, "Couldn't get current holder from service"); return seln_null_holder; } *rank = holder.rank; return holder;}static voidseln_client_remove(target) Seln_client_node *target;{ register Seln_client_node *prev; for (prev = &clients; prev->next != (Seln_client_node *) NULL; prev = prev->next) { if (prev->next == target) { prev->next = target->next; free((char *)(LINT_CAST(target))); return; } } complain("Destroying a non-existent client?");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -