static bool ed_pull_source(varg_T *arg, Plugin *caller) { if (!caller || !caller->hndl) return false; Buffer *buf = caller->hndl->buf; *arg = buf_select(buf, "name", NULL); buf_end_sel(buf); return arg->argc; }
void run_worker() { while (true) { /* Select among controller port, and connections to routers */ FD_ZERO(&cset); maxcfd = 0; add_cfd(controller_fd); unsigned ridx; for (ridx = 0; ridx < nrouters; ridx++) add_cfd(router_fd_array[ridx]); buf_select(maxcfd+1, &cset, NULL, NULL, NULL); int fd; for (fd = 0; fd <= maxcfd; fd++) { if (!FD_ISSET(fd, &cset)) continue; bool eof; chunk_ptr msg = chunk_read(fd, &eof); if (eof) { /* Unexpected EOF */ if (fd == controller_fd) { err(true, "Unexpected EOF from controller (fatal)"); } else { err(false, "Unexpected EOF from router with fd %d (shutting down)", fd); finish_cmd(); exit(0); } close(fd); continue; } if (msg == NULL) { err(false, "Could not read chunk from fd %d (ignored)", fd); continue; } word_t h = chunk_get_word(msg, 0); /* Rely on fact that following message fields in same location for both single and double-word headers */ unsigned code = msg_get_header_code(h); unsigned agent = msg_get_header_agent(h); unsigned opcode = msg_get_header_opcode(h); if (fd == controller_fd) { /* Message from controller */ switch(code) { case MSG_KILL: chunk_free(msg); #if RPT >= 1 report(1, "Received kill message from controller"); #endif quit_agent(0, NULL); return; case MSG_DO_FLUSH: chunk_free(msg); #if RPT >= 5 report(5, "Received flush message from controller"); #endif if (flush_helper) { chunk_ptr msg = flush_helper(); if (!msg) break; if (chunk_write(controller_fd, msg)) { #if RPT >= 5 report(5, "Sent statistics information to controller"); #endif } else { err(false, "Failed to send statistics information to controller"); } chunk_free(msg); } break; case MSG_CLIOP_DATA: report(5, "Received client operation data. Agent = %u", agent); word_t *data = &msg->words[1]; unsigned nword = msg->length - 1; if (gop_start_helper) gop_start_helper(agent, opcode, nword, data); chunk_free(msg); chunk_ptr rmsg = msg_new_cliop_ack(agent); if (chunk_write(controller_fd, rmsg)) { #if RPT >= 5 report(5, "Acknowledged client operation data. Agent = %u", agent); #endif } else { err(false, "Failed to acknowledge client operation data. Agent = %u", agent); } chunk_free(rmsg); break; case MSG_CLIOP_ACK: #if RPT >= 5 report(5, "Received client operation ack. Agent = %u", agent); #endif if (gop_finish_helper) gop_finish_helper(agent); chunk_free(msg); break; case MSG_GC_START: chunk_free(msg); gc_start(code); break; case MSG_GC_FINISH: chunk_free(msg); gc_finish(code); break; default: chunk_free(msg); err(false, "Unknown message code %u from controller (ignored)", code); } } else { /* Must be message from router */ switch (code) { case MSG_OPERATION: receive_operation(msg); break; case MSG_OPERAND: receive_operand(msg); break; default: chunk_free(msg); err(false, "Received message with unknown code %u (ignored)", code); } } } } quit_agent(0, NULL); }
/* Fire an operation and wait for returned operand */ chunk_ptr fire_and_wait_defer(chunk_ptr msg) { chunk_ptr rval = NULL; if (!send_op(msg)) { err(false, "Failed to send message"); return NULL; } bool local_done = false; while (!(local_done || cmd_done())) { /* Select among controller port, and connections to routers. Do not accept console input */ FD_ZERO(&rset); maxrfd = 0; add_rfd(controller_fd); unsigned ridx; for (ridx = 0; ridx < nrouters; ridx++) add_rfd(router_fd_array[ridx]); buf_select(maxrfd+1, &rset, NULL, NULL, NULL); int fd; for (fd = 0; fd <= maxrfd; fd++) { if (!FD_ISSET(fd, &rset)) continue; bool eof; chunk_ptr msg = chunk_read(fd, &eof); if (eof) { /* Unexpected EOF */ if (fd == controller_fd) { err(true, "Unexpected EOF from controller (fatal)"); } else { err(false, "Unexpected EOF from router with fd %d (shutting down)", fd); finish_cmd(); exit(0); } close(fd); continue; } if (msg == NULL) { err(false, "Could not read chunk from fd %d (ignored)", fd); continue; } word_t h = chunk_get_word(msg, 0); unsigned code = msg_get_header_code(h); if (fd == controller_fd) { /* Message from controller */ switch(code) { case MSG_KILL: chunk_free(msg); #if RPT >= 1 report(1, "Received kill message from controller"); #endif quit_agent(0, NULL); break; case MSG_DO_FLUSH: chunk_free(msg); #if RPT >= 2 report(2, "Received flush message from controller"); #endif if (flush_helper) { flush_helper(0, NULL); } break; case MSG_GC_START: /* Got notice that should initiate garbage collection. Defer until current operation done */ #if RPT >= 3 report(3, "Deferring GC start"); #endif chunk_free(msg); gc_state = GC_DEFER; break; case MSG_GC_FINISH: #if RPT >= 3 report(3, "Unexpected GC_FINISH message from controller when waiting for result (ignored)"); #endif chunk_free(msg); break; default: chunk_free(msg); err(false, "Unknown message code %u from controller (ignored)", code); } } else { dword_t dh; word_t id = 0; /* Must be message from router */ switch (code) { case MSG_OPERATION: chunk_free(msg); err(false, "Received unexpected operation. Ignored."); local_done = true; break; case MSG_OPERAND: #if RPT >= 5 dh = chunk_get_dword(msg, 0); id = msg_get_dheader_op_id(dh); report(5, "Received operand with id 0x%lx", id); #endif rval = msg; local_done = true; break; default: chunk_free(msg); err(false, "Received message with unknown code %u (ignored)", code); local_done = true; } } } } return rval; }