Example #1
0
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;
  }
}
Example #2
0
//-----------------------------------------------------------------------------
// May be superfluous with above
void publish_yield( void ) {

  // send the notification to the coordinator
  yield_note.ts = generate_timestamp();
  write( yield_note );

}
Example #3
0
File: voterd.c Project: Chryel/PINT
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;
  }
}
Example #4
0
//-----------------------------------------------------------------------------
// 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;
}
Example #5
0
//-----------------------------------------------------------------------------
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, &note, 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
  }
}
Example #6
0
//-----------------------------------------------------------------------------
// 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;
}
Example #7
0
File: voterd.c Project: Chryel/PINT
////////////////////////////////////////////////////////////////////////////////
// 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);
  }
}
Example #8
0
//-----------------------------------------------------------------------------
/// 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;
}
Example #9
0
//-----------------------------------------------------------------------------
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;
}
Example #10
0
//-----------------------------------------------------------------------------
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
*/
  }
}
Example #11
0
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;
	}
Example #12
0
//-----------------------------------------------------------------------------
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, &note, 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 );
//*/
  }
}
Example #13
0
File: voterd.c Project: Chryel/PINT
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);
          }
        }
      }
    }
  }
}
Example #14
0
//-----------------------------------------------------------------------------
/// 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, &note, 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, &note, 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, &note, 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 );
  } 
}
Example #15
0
//-----------------------------------------------------------------------------
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, &note, 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, &note, 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, &note, 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, &note, 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;
}
Example #16
0
File: voterd.c Project: Chryel/PINT
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 {
Example #18
0
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;
}