int maintain_wops(struct wops_state *w) { struct timeval now, delta; while(w->w_line == NULL){ #ifdef DEBUG fprintf(stderr, "maintain: attemping reconnect\n"); #endif w->w_line = create_name_rpc_katcl(w->w_server); if(w->w_line == NULL){ gettimeofday(&now, NULL); if(cmp_time_katcp(&(w->w_when), &now) <= 0){ return -1; } sub_time_katcp(&delta, &(w->w_when), &now); if(delta.tv_sec > 0){ delta.tv_sec = 1; delta.tv_usec = 0; } select(0, NULL, NULL, NULL, &delta); } } return 0; }
int perform_wops(struct wops_state *w, char *op) { int delay; struct timeval delta, now; if((op == NULL) || (op[0] == '\0')){ return WOPS_ERROR_PERMANENT; } if(op[0] == '-'){ return WOPS_SKIP; } if(op[1] != ':'){ return WOPS_ERROR_PERMANENT; } switch(op[0]){ case 'p' : puts(op + 2); return WOPS_OK; case 't' : /* set the timeout for commands */ delay = atoi(op + 2); if(delay <= 0){ return WOPS_ERROR_PERMANENT; } #ifdef DEBUG fprintf(stderr, "t: setting new timeout in %ums\n", delay); #endif set_timeout_wops(w, delay); return WOPS_OK; case 'd' : /* delay until timeout */ gettimeofday(&now, NULL); if(cmp_time_katcp(&(w->w_when), &now) > 0){ sub_time_katcp(&delta, &(w->w_when), &now); #ifdef DEBUG fprintf(stderr, "d: waiting for %lu.%0lds\n", delta.tv_sec, delta.tv_usec); #endif select(0, NULL, NULL, NULL, &delta); #ifdef DEBUG } else { fprintf(stderr, "d: timeout already happened\n"); #endif } return WOPS_OK; case 'c' : /* check a value */ return perform_check_wops(w, op); case 'w' : /* write a value */ return perform_write_wops(w, op); default : #ifdef DEBUG fprintf(stderr, "unknown operation %c\n", op[0]); #endif break; } return WOPS_ERROR_PERMANENT; }
int run_generic_capture(struct katcp_dispatch *d, struct capture_poco *cp, int poke) { /* logic: */ /* zero poke means that we are being run from a timer, advance our state */ /* machine, by looking at state value (initial value zero, but never changed */ /* by subsequent api logic */ /* nonzero poke means that the user has changed a parameter */ #if 0 /* scary logic for client using the API: ping means that the user has changed some parameter - client has to figure out what to do on the basis of that, otherwise just run whatever client state machine, client can use c_state for that, where 0 is the starting condition (never gets reset by API logic, client responsible for that) */ #endif sane_capture(cp); log_message_katcp(d, KATCP_LEVEL_TRACE, NULL, "capture %s with notification %d and state %d", cp->c_name, poke, cp->c_state); switch(poke){ case CAPTURE_POKE_AUTO : /* automatic state machine runner */ switch(cp->c_state){ case IDLE_GENERIC_CAPTURE : log_message_katcp(d, KATCP_LEVEL_WARN, NULL, "running capture timer while idle is unexpected"); return -1; case PREP_GENERIC_CAPTURE : log_message_katcp(d, KATCP_LEVEL_DEBUG, NULL, "capture-prepare %s", cp->c_name); if(cp->c_fd < 0){ log_message_katcp(d, KATCP_LEVEL_ERROR, NULL, "no valid destination, not starting capture %s", cp->c_name); return -1; } if(cp->c_start.tv_sec == 0){ log_message_katcp(d, KATCP_LEVEL_FATAL, NULL, "no valid start time while prepping"); cp->c_state = IDLE_GENERIC_CAPTURE; return -1; } if(cp->c_toggle){ log_message_katcp(d, KATCP_LEVEL_DEBUG, NULL, "toggling start for %s", cp->c_name); if((*(cp->c_toggle))(d, cp->c_dump, 1) < 0){ log_message_katcp(d, KATCP_LEVEL_ERROR, NULL, "unable to trigger data collection"); cp->c_state = IDLE_GENERIC_CAPTURE; return -1; } } register_at_tv_katcp(d, &(cp->c_start), &timer_generic_capture, cp); cp->c_start.tv_sec = 0; cp->c_start.tv_sec = 0; meta_udp_poco(d, cp, START_STREAM_CONTROL_POCO); tx_udp_poco(d, cp); cp->c_state = START_GENERIC_CAPTURE; break; case START_GENERIC_CAPTURE : /* MAYBE: change from log to #capture-start ? */ log_message_katcp(d, KATCP_LEVEL_INFO, NULL, "capture-start %s", cp->c_name); if(cp->c_stop.tv_sec){ log_message_katcp(d, KATCP_LEVEL_INFO, NULL, "scheduling stop at %lu.%06lu", cp->c_stop.tv_sec, cp->c_stop.tv_usec); register_at_tv_katcp(d, &(cp->c_stop), &timer_generic_capture, cp); } cp->c_state = RUN_GENERIC_CAPTURE; break; case RUN_GENERIC_CAPTURE : log_message_katcp(d, KATCP_LEVEL_INFO, NULL, "capture-stop %s", cp->c_name); if(cp->c_toggle){ if((*(cp->c_toggle))(d, cp->c_dump, 0) < 0){ log_message_katcp(d, KATCP_LEVEL_WARN, NULL, "problems stopping %s", cp->c_name); } } else { log_message_katcp(d, KATCP_LEVEL_WARN, NULL, "no switch to stop capture for %s", cp->c_name); } meta_udp_poco(d, cp, STOP_STREAM_CONTROL_POCO); tx_udp_poco(d, cp); cp->c_stop.tv_sec = 0; cp->c_stop.tv_usec = 0; cp->c_state = IDLE_GENERIC_CAPTURE; break; default : log_message_katcp(d, KATCP_LEVEL_FATAL, NULL, "bad state %d for capture %s", cp->c_state, cp->c_name); cp->c_state = IDLE_GENERIC_CAPTURE; return -1; } break; case CAPTURE_POKE_START : /* user notification start */ switch(cp->c_state){ case IDLE_GENERIC_CAPTURE : break; case PREP_GENERIC_CAPTURE : log_message_katcp(d, KATCP_LEVEL_WARN, NULL, "overriding previously scheduled capture start for %s", cp->c_name); break; default : log_message_katcp(d, KATCP_LEVEL_ERROR, NULL, "capture for %s already running or scheduled to run", cp->c_name); return -1; } if(cp->c_prep.tv_sec == 0){ log_message_katcp(d, KATCP_LEVEL_FATAL, NULL, "no valid prep time given for %s", cp->c_name); return -1; } if(cmp_time_katcp(&(cp->c_prep), &(cp->c_start)) >= 0){ log_message_katcp(d, KATCP_LEVEL_FATAL, NULL, "prep time not before start time for %s", cp->c_name); return -1; } if((cp->c_stop.tv_sec != 0) && (cmp_time_katcp(&(cp->c_stop), &(cp->c_start)) < 0)){ log_message_katcp(d, KATCP_LEVEL_WARN, NULL, "overriding stale stop carelessly scheduled for %lu.%06lus", cp->c_stop.tv_sec, cp->c_stop.tv_usec); cp->c_stop.tv_sec = 0; cp->c_stop.tv_usec = 0; } if(cp->c_fd < 0){ log_message_katcp(d, KATCP_LEVEL_WARN, NULL, "hoping for that valid destination for %s will be set soon", cp->c_name); } register_at_tv_katcp(d, &(cp->c_prep), &timer_generic_capture, cp); cp->c_prep.tv_sec = 0; cp->c_prep.tv_usec = 0; cp->c_state = PREP_GENERIC_CAPTURE; break; case CAPTURE_POKE_STOP : /* user notification - stop */ if(cp->c_stop.tv_sec == 0){ log_message_katcp(d, KATCP_LEVEL_FATAL, NULL, "having no stop time set when requesting sto is a major logic failure"); } switch(cp->c_state){ case IDLE_GENERIC_CAPTURE : if(cp->c_start.tv_sec != 0) { log_message_katcp(d, KATCP_LEVEL_FATAL, NULL, "having a start time set in idle state is a major logic failure"); } log_message_katcp(d, KATCP_LEVEL_WARN, NULL, "setting a stop at %lu.%lus while idle on %s despite having no start time", cp->c_stop.tv_sec, cp->c_stop.tv_usec, cp->c_name); break; case PREP_GENERIC_CAPTURE : if(cmp_time_katcp(&(cp->c_stop), &(cp->c_start)) <= 0){ log_message_katcp(d, KATCP_LEVEL_WARN, NULL, "cancelling capture on %s as stop time preceeds start time", cp->c_name); cp->c_stop.tv_sec = 0; cp->c_stop.tv_usec = 0; cp->c_start.tv_sec = 0; cp->c_start.tv_usec = 0; discharge_timer_katcp(d, cp); } break; case RUN_GENERIC_CAPTURE : register_at_tv_katcp(d, &(cp->c_stop), &timer_generic_capture, cp); break; } break; default : log_message_katcp(d, KATCP_LEVEL_FATAL, NULL, "unknown poke state %d", poke); return -1; break; } return 0; /* time registration functions look at this code, but only for periodic events */ }