void restartHandler(int signo) { // fork timestamp_t last = generate_timestamp(); pid_t currentPID = fork(); if (currentPID >= 0) { // Successful fork if (currentPID == 0) { // Child process timestamp_t current = generate_timestamp(); printf("%lld\n", current - last); // unblock the signal sigset_t signal_set; sigemptyset(&signal_set); sigaddset(&signal_set, SIGUSR1); sigaddset(&signal_set, SIGUSR2); // syscall sigprocmask(SIG_UNBLOCK, &signal_set, NULL); EveryTAS(); return; } else { // Parent just returns waitpid(-1, NULL, WNOHANG); return; } } else { printf("Fork error!\n"); return; } }
//----------------------------------------------------------------------------- // May be superfluous with above void publish_yield( void ) { // send the notification to the coordinator yield_note.ts = generate_timestamp(); write( yield_note ); }
void voterRestartHandler(void) { // Timer went off, so the timer_stop_index is the pipe which is awaiting a rep int p_index; debug_print("Caught Exec / Control loop error (%s)\n", controller_name); switch (rep_type) { case SMR: { #ifdef TIME_RESTART_REPLICA timestamp_t start_restart = generate_timestamp(); #endif // TIME_RESTART_REPLICA // Need to cold restart the replica last_dead = replicas[0].pid; cleanupReplica(replicas, 0); startReplicas(replicas, rep_count, &sd, controller_name, ext_pipes, pipe_count, replica_priority); // Resend last data for (p_index = 0; p_index < pipe_count; p_index++) { int read_fd = ext_pipes[p_index].fd_in; if (read_fd != 0) { processData(&(ext_pipes[p_index]), p_index); } } #ifdef TIME_RESTART_REPLICA timestamp_t end_restart = generate_timestamp(); printf("Restart time elapsed usec (%lf)\n", diff_time(end_restart, start_restart, CPU_MHZ)); #endif // TIME_RESTART_REPLICA break; } case DMR: { // Intentional fall-through to TMR } case TMR: { // The failed rep should be the one behind on the timer pipe int restartee = behindRep(replicas, rep_count, timer_stop_index); //last_dead = replicas[restartee].pid; int restarter = (restartee + (rep_count - 1)) % rep_count; debug_print("\tPID: %d\n", replicas[restartee].pid); restart_prep(restartee, restarter); break; } return; } }
//----------------------------------------------------------------------------- // Pub/Sub bool publish_command( void ) { // put data in the shared memory buffer // send the notification to the coordinator command_note.ts = generate_timestamp(); write( command_note ); // probably need to force a block here return true; }
//----------------------------------------------------------------------------- void timer_sighandler( int signum, siginfo_t *si, void *data ) { notification_t note; static int fd = FD_TIMER_TO_COORDINATOR_WRITE_CHANNEL; std::string err; note.ts = generate_timestamp(); note.source = notification_t::TIMER; ssize_t bytes_written = 0; if( __write( fd, ¬e, sizeof(notification_t), bytes_written ) != OS_ERROR_NONE ) { err = "(coordinator.cpp) timer_sighandler(...) failed making system call write(...)"; //error_log.write( error_string_bad_write( err, errno ) ); // TODO : determine if there is a need to recover } }
//----------------------------------------------------------------------------- // Request/Reply void request_state( void ) { // write the request information into the shared memory buffer // send the notification to the coordinator state_note.ts = generate_timestamp(); write( state_note ); // read( block ) the notification sent back from the coordinator read( server_note ); // read data from the shared memory buffer //return true; }
//////////////////////////////////////////////////////////////////////////////// // Process data void processData(struct vote_pipe *pipe, int pipe_index) { int r_index; if (pipe_index == timer_start_index) { if (!timer_started) { timer_started = true; watchdog = generate_timestamp(); } } balanceReps(replicas, rep_count, replica_priority); for (r_index = 0; r_index < rep_count; r_index++) { writeBuffer(replicas[r_index].vot_pipes[pipe_index].fd_out, pipe->buffer, pipe->buff_count); } }
//----------------------------------------------------------------------------- /// Arms the realtime timer using error correction. This code was inherited /// from initial pendulum experiment. Retesting has demonstrated that as it /// is here, its performance is circumspec and needs deeper evaluation. So /// while this text is here, use at own risk. /// @param type defines whether to arm as a one-shot or periodic timer. /// @param period_nsec the period in nanoseconds that the timer is requested /// to have. /// @param ts_req the requested time for the timer to arm. /// @param ts_arm a timestamp that is generated when the timer is armed. /// @param cpu_hz the speed of the processor. /// @return indicator of operation success or specified error. timer_c::error_e timer_c::arm( const type_e& type, const unsigned long long& period_nsec, const timestamp_t& ts_req, timestamp_t& ts_arm, const cpu_speed_t& cpu_hz ) { struct itimerspec its; timestamp_t ts_now; unsigned long long ts_err = 0; unsigned long long ns_err = 0; unsigned long long period = period_nsec; ts_now = generate_timestamp(); if( _first_arming ) { // cannot compute err correction _first_arming = false; } else { ts_err = ts_now - ts_prev_arm; ns_err = cycles_to_nanoseconds( ts_err, cpu_hz ); long long error = (long long) period - (long long) ns_err; agg_error += error; period += agg_error; } struct timespec tspec = nanoseconds_to_timespec( period ); //printf( "period[%llu]: secs[%d], nsecs[%d]\n", period, tspec.tv_sec, tspec.tv_nsec ); if( type == ONESHOT ) { its.it_interval.tv_sec = 0; its.it_interval.tv_nsec = 0; its.it_value.tv_sec = tspec.tv_sec; its.it_value.tv_nsec = tspec.tv_nsec; } else if( type == PERIODIC ) { its.it_interval.tv_sec = tspec.tv_sec; its.it_interval.tv_nsec = tspec.tv_nsec; its.it_value.tv_sec = tspec.tv_sec; its.it_value.tv_nsec = tspec.tv_nsec; } ts_arm = ts_req; ts_prev_arm = ts_now; if( timer_settime( _id, 0, &its, NULL ) == -1 ) { //printf( "dts: %lld, dns: %lld, nsec: %d\n", dts, dns, its.it_value.tv_nsec ); return ERROR_SETTIME; } return ERROR_NONE; }
//----------------------------------------------------------------------------- void* wakeup( void* ) { int allow_wakeup; while( 1 ) { allow_wakeup = wakeup_enabled.load( std::memory_order_seq_cst ); if( allow_wakeup ) { wakeup_note.ts = generate_timestamp(); // disable block detection notifications. Coordinator will reenable. wakeup_enabled.store( 0, std::memory_order_seq_cst ); if( write( wakeup_write_fd, &wakeup_note, sizeof(notification_t) ) == -1 ) { //printf( "(coordinator.cpp) wakeup() failed making system call write(...)\n" ); // TODO : determine if there is a need to bomb or recover } } } return NULL; }
//----------------------------------------------------------------------------- void timer_sighandler( int signum, siginfo_t *si, void *data ) { //std::string err, eno; // grab a timestamp immediately timer_note.ts = generate_timestamp(); // increment accounting actual_timer_events++; ssize_t bytes_written; // write the timer notification to the pipe if( __write( timer_write_fd, &timer_note, sizeof(notification_t), bytes_written ) != OS_ERROR_NONE ) { // TODO: restructure to reduce complexity here. /* if( errno == EPIPE ) eno = " errno: EPIPE"; else if( errno == EAGAIN || errno == EWOULDBLOCK ) eno = " errno: EWOULDBLOCK"; else if( errno == EBADF ) eno = " errno: EBADF"; else if( errno == EDESTADDRREQ ) eno = " errno: EDESTADDRREQ"; else if( errno == EDQUOT ) eno = " errno: EDQUOT"; else if( errno == EFAULT ) eno = " errno: EFAULT"; else if( errno == EFBIG ) eno = " errno: EFBIG"; else if( errno == EINTR ) eno = " errno: EINTR"; else if( errno == EINVAL ) eno = " errno: EINVAL"; else if( errno == EIO ) eno = " errno: EIO"; else if( errno == ENOSPC ) eno = " errno: ENOSPC"; err = "(coordinator.cpp) timer_sighandler(...) failed making system call write(...)" + eno; //sprintf( spstr, "(coordinator.cpp) timer_sighandler(...) failed making system call write(...) %s\n", eno ); printf( "%s\n", err ); // TODO : determine if there is a need to recover */ } }
bool suisto_add_post( std::string stream_name, std::string post_content ){ std::tr1::unordered_map< std::string, Stream >::iterator it; it = streams.find( stream_name ); if( it == streams.end() ){ return false; } entry_t *entry = new entry_t; entry->id = Clock::next(); entry->timestamp = generate_timestamp( entry->id ); posts[entry->id] = escape_string( post_content ); (it->second).add( entry ); return true; }
//----------------------------------------------------------------------------- void write( notification_t& note ) { char eno[16]; // update the timestamp on the note note.ts = generate_timestamp(); ssize_t bytes_written; os_error_e result; result = __write( write_fd, ¬e, sizeof(notification_t), bytes_written ); if( result != OS_ERROR_NONE ) { ///* if( result == OS_ERROR_PIPE ) sprintf( eno, "EPIPE" ); else if( result == OS_ERROR_AGAIN ) sprintf( eno, "EWOULDBLOCK" ); else if( result == OS_ERROR_BADF ) sprintf( eno, "EBADF" ); else if( result == OS_ERROR_DESTADDRREQ ) sprintf( eno, "EDESTADDRREQ" ); else if( result == OS_ERROR_DQUOT ) sprintf( eno, "EDQUOT" ); else if( result == OS_ERROR_FAULT ) sprintf( eno, "EFAULT" ); else if( result == OS_ERROR_FBIG ) sprintf( eno, "EFBIG" ); else if( result == OS_ERROR_INTR ) sprintf( eno, "EINTR" ); else if( result == OS_ERROR_INVAL ) sprintf( eno, "EINVAL" ); else if( result == OS_ERROR_IO ) sprintf( eno, "EIO" ); else if( result == OS_ERROR_NOSPC ) sprintf( eno, "ENOSPC" ); printf( "ERROR: (%s) failed making system call write(...) errno[%s]\n", mythread->name, eno ); //*/ } }
void doOneUpdate(void) { int p_index, r_index; int retval = 0; struct timeval select_timeout; fd_set select_set; if (rep_type == SMR) { // Detect replica that self-kills, has no timer (Load does this due to memory leak) #ifdef TIME_WAITPID timestamp_t start_restart = generate_timestamp(); #endif // TIME_WAITPID // can only waitpid for children (unless subreaper is used (prctl is not POSIX compliant)). int exit_pid = waitpid(-1, NULL, WNOHANG); // Seems to take a while for to clean up zombies #ifdef TIME_WAITPID timestamp_t end_restart = generate_timestamp(); if (exit_pid > 0 && exit_pid != last_dead) { printf("Waitpid for %d (%s) took usec (%lf)\n", exit_pid, REP_TYPE_T[rep_type], diff_time(end_restart, start_restart, CPU_MHZ)); } else { //printf("No zombie took (%lld)\n", end_restart - start_restart); } #endif // TIME_WAITPID if (exit_pid > 0 && exit_pid != last_dead) { debug_print("PID %d exited on its own.\n", exit_pid); voterRestartHandler(); timer_started = false; } } select_timeout.tv_sec = 0; select_timeout.tv_usec = 50000; if (timer_started) { timestamp_t current = generate_timestamp(); long remaining = voting_timeout - diff_time(current, watchdog, CPU_MHZ); if (remaining > 0) { select_timeout.tv_sec = 0; select_timeout.tv_usec = remaining; } else { // printf("Restart handler called, %s is %ld late\n", controller_name, remaining); voterRestartHandler(); } } // See if any of the read pipes have anything FD_ZERO(&select_set); // Check external in pipes bool check_inputs = checkSync(); if (check_inputs) { for (p_index = 0; p_index < pipe_count; p_index++) { if (ext_pipes[p_index].fd_in != 0) { int e_pipe_fd = ext_pipes[p_index].fd_in; FD_SET(e_pipe_fd, &select_set); } } } else if (voter_priority < 5 && ! timer_started) { // non-RT controller is now lagging behind. timer_started = true; watchdog = generate_timestamp(); } // Check pipes from replicas for (p_index = 0; p_index < pipe_count; p_index++) { for (r_index = 0; r_index < rep_count; r_index++) { int rep_pipe_fd = replicas[r_index].vot_pipes[p_index].fd_in; if (rep_pipe_fd != 0) { FD_SET(rep_pipe_fd, &select_set); } } } // This will wait at least timeout until return. Returns earlier if something has data. retval = select(FD_SETSIZE, &select_set, NULL, NULL, &select_timeout); if (retval > 0) { // Check for data from external sources for (p_index = 0; p_index < pipe_count; p_index++) { int read_fd = ext_pipes[p_index].fd_in; if (read_fd != 0) { if (FD_ISSET(read_fd, &select_set)) { ext_pipes[p_index].buff_count = TEMP_FAILURE_RETRY(read(read_fd, ext_pipes[p_index].buffer, MAX_VOTE_PIPE_BUFF)); if (ext_pipes[p_index].buff_count > 0) { // TODO: read may still have been interrupted processData(&(ext_pipes[p_index]), p_index); } else if (ext_pipes[p_index].buff_count < 0) { printf("Voter - Controller %s pipe %d\n", controller_name, p_index); perror("Voter - read error on external pipe"); } else { printf("Voter - Controller %s pipe %d\n", controller_name, p_index); perror("Voter - read == 0 on external pipe"); } } } } // Check all replicas for data for (p_index = 0; p_index < pipe_count; p_index++) { for (r_index = 0; r_index < rep_count; r_index++) { struct vote_pipe* curr_pipe = &(replicas[r_index].vot_pipes[p_index]); if (curr_pipe->fd_in !=0) { if (FD_ISSET(curr_pipe->fd_in, &select_set)) { processFromRep(r_index, p_index); } } } } } }
//----------------------------------------------------------------------------- /// API function to process notifications delivered to a thread. /// @param thread the current thread. /// @param runqueue the heap of threads ready to run for a given timesink. /// @param waitqueue the heap of threads pending on I/O for a given timesink. void process_notifications( const thread_p& caller, osthread_p& thread, thread_heap_c* runqueue, thread_heap_c* waitqueue ) { cycle_t reschedule_time; char spstr[512]; // assert that the thread is valid if( !thread ) return; //#ifdef DEBUG if( info && thread ) { sprintf( spstr, "process_notifications( caller=%s, thread=%s, ", caller->name, thread->name ); info->write( spstr ); if( thread->owner ) { sprintf( spstr, "owner=%s, ... )\n", thread->owner->name ); } else { sprintf( spstr, "owner=root, ... )\n" ); } info->write( spstr ); } else { sprintf( spstr, "process_notifications( caller=%s, thread=none, ... )\n", caller->name ); info->write( spstr ); } //#endif // assert that the message queue is not empty if( thread->message_queue.empty() ) { runqueue->push( thread ); return; } // peek at the message at the head of the queue notification_t msg = thread->message_queue.front(); // remove the message from the queue thread->message_queue.pop(); // if an idle message compute values and do updates if( msg.type == notification_t::IDLE ) { // compute when to reschedule the thread reschedule_time = thread->blocktill( msg.period ); // update the temporal progress thread->temporal_progress += msg.period; } //#ifdef DEBUG if( info ) { // print the notification for debugging char note_type[8]; char note_source[8]; if( msg.type == notification_t::IDLE ) sprintf( note_type, "IDLE" ); else if( msg.type == notification_t::OPEN ) sprintf( note_type, "OPEN" ); else if( msg.type == notification_t::CLOSE ) sprintf( note_type, "CLOSE" ); else if( msg.type == notification_t::READ ) sprintf( note_type, "READ" ); else if( msg.type == notification_t::WRITE ) sprintf( note_type, "WRITE" ); if( msg.source == notification_t::TIMER ) sprintf( note_source, "TIMER" ); else if( msg.source == notification_t::WAKEUP ) sprintf( note_source, "WAKEUP" ); else if( msg.source == notification_t::CLIENT ) sprintf( note_source, "CLIENT" ); sprintf( spstr, "notification: type[%s], source[%s], ts[%llu], period[%llu] thread: computational_progress[%llu], temporal_progress[%llu]\n", note_type, note_source, msg.ts, msg.period, thread->computational_progress, thread->temporal_progress ); info->write( spstr ); } //#endif // if an idle message, reschedule //if( msg.type == notification_t::IDLE && reschedule_time > thread->temporal_progress ) { // TODO (in test_coordinator): Not checking source here before type which may // result in erroneous action if( msg.type == notification_t::IDLE ) { if( info ) { sprintf( spstr, "handling idle notification for %s\n", thread->name ); info->write( spstr ); } /* // find the thread in the runqueue and remove it. for( unsigned i = 0; i < runqueue.size(); i++ ) { thread_p thd = runqueue.element(i); // if not the searched for thread continue searching if( thd != thread ) continue; // otherwise remove and stop searching runqueue.remove( i, thd ); break; } // to be comprehensive, might be inclined to check waitqueue, // but logically, it cannot be in the waitqueue if it was running // update its progress (forecasting in this way will account for 'idle time') */ thread->temporal_progress = reschedule_time; // add to the waitqueue waitqueue->push( thread ); if( info ) { sprintf( spstr, "slept %s\n", thread->name ); info->write( spstr ); } } else if( msg.type == notification_t::OPEN ) { // encapsulated process has fully initialized runqueue->push( thread ); } else if( msg.type == notification_t::CLOSE ) { // encapsulated process is dying, knows so, and had a chance to notify // * NO GUARANTEES THAT THIS NOTIFICATION IS RECEIVED * } else if( msg.type == notification_t::READ ) { // client needs to read data from shared memory. Please service the request. // TODO - Logic for getting data from dynamics runqueue->push( thread ); // !block queue may be more appropriate. // TODO WARNING: there may be significant asynchronos issues here because // the thread may not be at the head of the runqueue and if it is but into // the block queue we won't know when it gets brought to the front. The // root question is when to put data in the buffer and when to make the // client read. // once serviced, send a message back to the client int fd; ssize_t bytes; notification_t note; if( thread == prey_controller ) { fd = FD_COORDINATOR_TO_PREYCONTROLLER_WRITE_CHANNEL; note.source = notification_t::SERVER; note.type = notification_t::READ; // the instruction to the client note.ts = generate_timestamp(); if( __write( fd, ¬e, sizeof(notification_t), bytes ) != OS_ERROR_NONE ) { // TODO: Handle/Recover if( info ) { sprintf( spstr, "ERROR : (coordinator.cpp) process_notifications() failed calling __write(FD_COORDINATOR_TO_PREYCONTROLLER_WRITE_CHANNEL,...)\n" ); info->write( spstr ); } } } else if( thread == pred_controller ) { fd = FD_COORDINATOR_TO_PREDCONTROLLER_WRITE_CHANNEL; note.source = notification_t::SERVER; note.type = notification_t::READ; // the instruction to the client note.ts = generate_timestamp(); if( __write( fd, ¬e, sizeof(notification_t), bytes ) != OS_ERROR_NONE ) { // TODO: Handle/Recover if( info ) { sprintf( spstr, "ERROR : (coordinator.cpp) process_notifications() failed calling __write(FD_COORDINATOR_TO_PREDCONTROLLER_WRITE_CHANNEL,...)\n" ); info->write( spstr ); } } } else if( thread == pred_planner ) { fd = FD_COORDINATOR_TO_PREDPLANNER_WRITE_CHANNEL; note.source = notification_t::SERVER; note.type = notification_t::READ; // the instruction to the client note.ts = generate_timestamp(); if( __write( fd, ¬e, sizeof(notification_t), bytes ) != OS_ERROR_NONE ) { // TODO: Handle/Recover if( info ) { sprintf( spstr, "ERROR : (coordinator.cpp) process_notifications() failed calling __write(FD_COORDINATOR_TO_PREDPLANNER_WRITE_CHANNEL,...)\n" ); info->write( spstr ); } } } } else if( msg.type == notification_t::WRITE ) { // client has written data to shared memory. Please serve data to clients. // TODO - Logic for sending message to other threads if need be runqueue->push( thread ); } }
//----------------------------------------------------------------------------- int main( int argc, char* argv[] ) { // Due to realtime scheduling, et al, must have root access to run. if( geteuid() != 0 ) { sprintf( spstr, "This program requires root access. Re-run with sudo.\nExiting\n" ); printf( "%s", spstr ); exit( 1 ); } init( argc, argv ); // last before main loop, arm the timer timer.arm( timer_c::PERIODIC, TIMER_PERIOD_NSECS ); //while( !quit.load( std::memory_order_seq_cst ) ) { //while( !quit ) { bool preycontroller_idle = true; while( !quit.load( std::memory_order_relaxed ) ) { int fd; notification_t note; ssize_t bytes; while( !select() ); if( FD_ISSET( FD_TIMER_TO_COORDINATOR_READ_CHANNEL, &pending_fds ) != 0 ) { fd = FD_TIMER_TO_COORDINATOR_READ_CHANNEL; if( __read( fd, ¬e, sizeof(notification_t) ) == -1 ) { if( info ) { sprintf( spstr, "ERROR : (coordinator.cpp) read_messages() failed calling __read(FD_TIMER_TO_COORDINATOR_READ_CHANNEL,...)\n" ); info->write( spstr ); } } else { if( info ) { sprintf( spstr, "read_notifications( note.source=TIMER, caught_timer_events=%d, actual_timer_events=%d\n", ++caught_timer_events, actual_timer_events ); info->write( spstr ); } if( caught_timer_events >= MAX_TIMER_EVENTS ) { //quit.store( 1, std::memory_order_relaxed ); //quit.store( 1, std::memory_order_seq_cst ); //quit = true; //quit++; if( info ) { info->flush(); } kill( coordinator_pid, SIGTERM ); } if( preycontroller_idle ) { //pthread_kill( wakeup_thread, SIGSTOP ); prey_controller->raise_priority(); //pthread_kill( wakeup_thread, SIGCONT ); preycontroller_idle = false; sprintf( spstr, "raised_priority: pid=%d, _os_priority=%d)\n", prey_controller->pid, prey_controller->_os_priority ); info->write( spstr ); } } } // - check for client specific notifications - // prey controller if( FD_ISSET( FD_PREYCONTROLLER_TO_COORDINATOR_READ_CHANNEL, &pending_fds ) != 0) { fd = FD_PREYCONTROLLER_TO_COORDINATOR_READ_CHANNEL; if( __read( fd, ¬e, sizeof(notification_t) ) == -1 ) { if( info ) { sprintf( spstr, "ERROR : (coordinator.cpp) read_messages() failed calling __read(FD_PREYCONTROLLER_TO_COORDINATOR_READ_CHANNEL,...)\n" ); info->write( spstr ); } //printf( "%s\n", spstr ); } else { if( info ) { char note_type[8]; if( note.type == notification_t::IDLE ) sprintf( note_type, "IDLE" ); else if( note.type == notification_t::OPEN ) sprintf( note_type, "OPEN" ); else if( note.type == notification_t::CLOSE ) sprintf( note_type, "CLOSE" ); else if( note.type == notification_t::READ ) sprintf( note_type, "READ" ); else if( note.type == notification_t::WRITE ) sprintf( note_type, "WRITE" ); sprintf( spstr, "read_notifications( note.source=CLIENT, note.type=%s, client=prey_controller )\n", note_type ); info->write( spstr ); } if( note.type == notification_t::CLOSE ) { prey_controller->invalidated = true; } else { prey_controller->message_queue.push( note ); } } } // check block detection first. If client blocked, needs to be put into // blocking queue. If falls through, might get put into run queue instead. if( FD_ISSET( FD_WAKEUP_TO_COORDINATOR_READ_CHANNEL, &pending_fds) != 0 ) { fd = FD_WAKEUP_TO_COORDINATOR_READ_CHANNEL; if( __read( fd, ¬e, sizeof(notification_t) ) == -1 ) { if( info ) { sprintf( spstr, "ERROR : (coordinator.cpp) read_messages() failed calling __read(FD_WAKEUP_TO_COORDINATOR_READ_CHANNEL,...)\n" ); info->write( spstr ); } } else { if( info ) { sprintf( spstr, "read_notifications( note.source=WAKEUP\n" ); info->write( spstr ); } // reenable block detection notifications wakeup_enabled.store( 1, std::memory_order_seq_cst ); } } /* if( info ) { // print the notification for debugging char note_type[8]; char note_source[8]; if( note.source == notification_t::TIMER ) sprintf( note_source, "TIMER" ); else if( note.source == notification_t::WAKEUP ) sprintf( note_source, "WAKEUP" ); else if( note.source == notification_t::CLIENT ) sprintf( note_source, "CLIENT" ); if( note.type == notification_t::IDLE ) sprintf( note_type, "IDLE" ); else if( note.type == notification_t::OPEN ) sprintf( note_type, "OPEN" ); else if( note.type == notification_t::CLOSE ) sprintf( note_type, "CLOSE" ); else if( note.type == notification_t::READ ) sprintf( note_type, "READ" ); else if( note.type == notification_t::WRITE ) sprintf( note_type, "WRITE" ); sprintf( spstr, "notification: source[%s], type[%s], ts[%llu], period[%llu]\n", note_source, note_type, note.ts, note.period ); info->write( spstr ); } */ if( note.source == notification_t::CLIENT ) { if( note.type == notification_t::IDLE ) { //pthread_kill( wakeup_thread, SIGSTOP ); prey_controller->lower_priority(); //pthread_kill( wakeup_thread, SIGCONT ); preycontroller_idle = true; sprintf( spstr, "lowered_priority: pid=%d, _os_priority=%d)\n", prey_controller->pid, prey_controller->_os_priority ); info->write( spstr ); } else if( note.type == notification_t::OPEN ) { } else if( note.type == notification_t::CLOSE ) { } else if( note.type == notification_t::READ ) { fd = FD_COORDINATOR_TO_PREYCONTROLLER_WRITE_CHANNEL; note.source = notification_t::SERVER; note.type = notification_t::READ; // the instruction to the client sprintf( spstr, "server responding with notification: source[SERVER], type[READ]\n" ); info->write( spstr ); note.ts = generate_timestamp(); if( __write( fd, ¬e, sizeof(notification_t), bytes ) != OS_ERROR_NONE ) { // TODO: Handle/Recover if( info ) { sprintf( spstr, "ERROR : (coordinator.cpp) process_notifications() failed calling __write(FD_COORDINATOR_TO_PREYCONTROLLER_WRITE_CHANNEL,...)\n" ); info->write( spstr ); } } } else if( note.type == notification_t::WRITE ) { } } else if( note.source == notification_t::TIMER ) { } else if( note.source == notification_t::WAKEUP ) { } info->flush(); } shutdown(); return 0; }
void restart_prep(int restartee, int restarter) { int i; #ifdef TIME_RESTART_REPLICA timestamp_t start_restart = generate_timestamp(); #endif // TIME_RESTART_REPLICA // Normally the pipes are stolen, then written back. // Here, we want to fill the pipes to test the impact of large messages. // So we will write to them, and then steal them (so that the fake data isn't processed). // But probably won't work if real data is there... // Problem: normally steal once, write twice. Need a second write... use restarted rep? #ifdef PIPE_SMASH char pipe_fill[PIPE_FILL_SIZE] = {1}; for (i = 0; i < PIPE_LIMIT; i++) { if (replicas[restarter].vot_pipes[i].fd_out != 0) { writeBuffer(replicas[restarter].vot_pipes[i].fd_out, pipe_fill, sizeof(pipe_fill)); } } #endif // PIPE_SMASH char **restarter_buffer = (char **)malloc(sizeof(char *) * PIPE_LIMIT); if (restarter_buffer == NULL) { perror("Voter failed to malloc memory"); } for (i = 0; i < PIPE_LIMIT; i++) { restarter_buffer[i] = (char *)malloc(sizeof(char) * MAX_VOTE_PIPE_BUFF); if (restarter_buffer[i] == NULL) { perror("Voter failed to allocat memory"); } } int restarter_buff_count[PIPE_LIMIT] = {0}; // Steal the pipes from healthy reps. This stops them from processing mid restart (also need to copy data to new rep) stealPipes(restarter, restarter_buffer, restarter_buff_count); // reset timer timer_started = false; restartReplica(replicas, rep_count, &sd, ext_pipes, restarter, restartee, replica_priority); for (i = 0; i < replicas[restarter].pipe_count; i++) { if (replicas[restarter].vot_pipes[i].fd_in != 0) { copyPipe(&(replicas[restartee].vot_pipes[i]), &(replicas[restarter].vot_pipes[i])); sendPipe(i, restarter); // TODO: Need to check if available? } } #ifndef PIPE_SMASH // Give the buffers back returnPipes(restartee, restarter_buffer, restarter_buff_count); returnPipes(restarter, restarter_buffer, restarter_buff_count); // free the buffers for (i = 0; i < PIPE_LIMIT; i++) { free(restarter_buffer[i]); } free(restarter_buffer); #endif // !PIPE_SMASH // The second write #ifdef PIPE_SMASH for (i = 0; i < PIPE_LIMIT; i++) { if (replicas[restarter].vot_pipes[i].fd_out != 0) { writeBuffer(replicas[restarter].vot_pipes[i].fd_out, pipe_fill, sizeof(pipe_fill)); } } #endif // PIPE_SMASH #ifdef TIME_RESTART_REPLICA timestamp_t end_restart = generate_timestamp(); printf("Restart time elapsed usec (%lf)\n", diff_time(end_restart, start_restart, CPU_MHZ)); #endif // TIME_RESTART_REPLICA // Clean up by stealing the extra write. Not timed. #ifdef PIPE_SMASH if (restarter_buffer == NULL) { perror("Voter failed to malloc memory"); } for (i = 0; i < PIPE_LIMIT; i++) { restarter_buffer[i] = (char *)malloc(sizeof(char) * MAX_VOTE_PIPE_BUFF); if (restarter_buffer[i] == NULL) { perror("Voter failed to allocat memory"); } } stealPipes(restarter, restarter_buffer, restarter_buff_count); // free the buffers for (i = 0; i < PIPE_LIMIT; i++) { free(restarter_buffer[i]); } free(restarter_buffer); #endif // PIPE_SMASH return; }
/* sess_write: * writes formatted text line onto the session page * args: * @session - session to write text to; * @text_type - type of the text (error msg/private text/etc) * @text_fmt - format of the text: * %s - null terminated string; * %c - single char; * %h - channel name; * %n - user nickname; */ void sess_write( sess_id session, enum session_text_type text_type, const gchar * text_fmt, ...) { enum text_attr default_attr; gboolean prepend_stamp; GString * text, * entire_line; gchar * gentext; const gchar * fmt; gpointer event_v[2]; va_list vargs; va_start(vargs, text_fmt); g_assert(session && text_fmt); entire_line = g_string_sized_new(64); /* * check if we need to prepend a timestamp */ switch(PSESSION_T(session)->type) { case SESSTYPE_STATUS: prepend_stamp = prefs_bool(PREFS_SESS_STAMP_STATUS); break; case SESSTYPE_CHANNEL: prepend_stamp = prefs_bool(PREFS_SESS_STAMP_CHANNEL); break; case SESSTYPE_PRIVATE: prepend_stamp = prefs_bool(PREFS_SESS_STAMP_PRIVATE); break; } if(prepend_stamp) { gentext = generate_timestamp(); gui_page_write(session, ATTR_TIME, gentext, FALSE); g_string_append(entire_line, gentext); g_free(gentext); } /* * select default text attribute by @text_type */ switch(text_type) { case SESSTEXT_NORMAL: default_attr = ATTR_NORM; break; case SESSTEXT_NOTIFY: default_attr = ATTR_NOTIFY; break; case SESSTEXT_ERROR: default_attr = ATTR_ERR; break; case SESSTEXT_JOIN: default_attr = ATTR_NOTIFY; break; case SESSTEXT_LEAVE: default_attr = ATTR_NOTIFY; break; case SESSTEXT_MY_TEXT: default_attr = ATTR_MY_TEXT; break; case SESSTEXT_THEIR_TEXT:default_attr = ATTR_THEIR_TEXT;break; case SESSTEXT_MY_ME: default_attr = ATTR_ME_TEXT; break; case SESSTEXT_THEIR_ME: default_attr = ATTR_ME_TEXT; break; case SESSTEXT_TOPIC: default_attr = ATTR_TOPIC; break; } /* * parse format text */ fmt = text_fmt; text = g_string_sized_new(128); while(*fmt) { if(*fmt=='%') { fmt ++; switch(*fmt) { case '%': g_string_append_c(text, '%'); break; case 's': g_string_append(text, va_arg(vargs, char*)); break; case 'c': g_string_append_c(text, (char)va_arg(vargs, int)); break; case 'h': /* FALLTROUGH */ case 'n': /* special tags: need to flush the text first */ gui_page_write(session, default_attr, text->str, FALSE); g_string_append(entire_line, text->str); g_string_assign(text, ""); switch(*fmt) { case 'h': gentext = g_strdup_printf("#%s", va_arg(vargs, char *)); gui_page_write(session, ATTR_CHAN, gentext, FALSE); g_string_append(entire_line, gentext); g_free(gentext); break; case 'n': gentext = va_arg(vargs, char *); gui_page_write(session, ATTR_USER, gentext, FALSE); g_string_append(entire_line, gentext); break; } break; default: /* unknown tag; emit both % and the char that succeeds it */ g_string_append_c(text, '%'); g_string_append_c(text, *fmt); break; } } else {
int insert_data(const struct config *config, queue_t *data) { MYSQL *sql_object, *sql_conn; queue_t *ptr; station_data_t *station; rbfsum_t rs; int ret, i, station_id; const int timeout = 3; char *cmd, *timestamp, *breaks; sql_object = mysql_init(NULL); if (sql_object == NULL) return 255; ret = mysql_options(sql_object, MYSQL_OPT_CONNECT_TIMEOUT, &timeout); if (ret) { mysql_close(sql_object); return 3; } sql_conn = mysql_real_connect(sql_object, config->host, config->username, config->password, config->database, config->port, 0, 0); if (sql_conn == NULL) { mysql_close(sql_object); return 3; } ptr = data; while (ptr) { station = ptr->data; station_id = get_station_id(station->name); if (station_id <= 0 || station_info[station_id].state == 0 || station->ndata != 24) { ptr = ptr->next; continue; } for (i = 0; i < 24; i++) { rs = station->rs[i]; timestamp = generate_timestamp(rs.start); breaks = rs.breaks ? g_strdup_printf("%i", rs.breaks) : g_strdup("-"); cmd = g_strdup_printf("INSERT INTO tbldatarbf VALUES(NULL, %i, " "'%s', '%g', '%g', '%g', '%s')", station_id, timestamp, rs.data, rs.retx, rs.gap, breaks); ret = mysql_query(sql_object, cmd); g_free(breaks); g_free(cmd); g_free(timestamp); if (ret) { mysql_close(sql_object); return 6; } } switch (rbfsum_get_status(station->rs, station->ndata)) { case RBFSUM_STATUS_EQUAL: ret = 3; break; case RBFSUM_STATUS_GREATER: ret = 2; break; case RBFSUM_STATUS_LESS: ret = 4; break; case RBFSUM_STATUS_OFF: ret = 5; break; default: ret = 1; } rs = station->rs[0]; timestamp = generate_timestamp(rs.start); cmd = g_strdup_printf("INSERT INTO tblstatus VALUES(NULL, %i, " "'%s', %i)", station_id, timestamp, ret); ret = mysql_query(sql_object, cmd); g_free(cmd); g_free(timestamp); if (ret) { mysql_close(sql_object); return 6; } ptr = ptr->next; } mysql_close(sql_object); return 0; }