int main(int argc, char **argv) { /* Slave threads */ sgcomm_thread *st_rd; // Reader sgcomm_thread *st_tx; // Transmitter shared_buffer *sbtx; // shared buffer for read+transmit /* Reader message parameters */ char *fmtstr = "/mnt/disks/%u/%u/data/%s"; char *pattern_read = "input.vdif"; char *host = "localhost"; uint16_t port = 61234; int n_mod = 4; int mod_list[4] = { 1, 2, 3, 4}; int n_disk = 8; int disk_list_read[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; int disk_list_write[8] = { 1, 0, 2, 3, 4, 5, 6, 7 }; /* Transmitter message parameters */ if (argc > 1) pattern_read = argv[1]; if (argc > 2) fmtstr = argv[2]; if (argc > 3) host = argv[3]; if (argc > 4) port = atoi(argv[4]); log_message(RL_NOTICE,"%s:Using input file '%s' matching pattern '%s'",__FUNCTION__,pattern_read,fmtstr); log_message(RL_NOTICE,"%s:Transmitting to %s:%u",__FUNCTION__,host,port); /* This thread */ sgcomm_thread *st = &st_main; ctrl_state state; log_message(RL_DEBUG,"%s:Creating shared buffer",__FUNCTION__); /* Initialize shared data buffer */ sbtx = create_shared_buffer(SHARED_BUFFER_SIZE_TX); if (sbtx == NULL) set_thread_state(st,CS_ERROR,"%s(%d):Cannot create shared buffer for read+transmit",__FUNCTION__,__LINE__); log_message(RL_DEBUG,"%s:Creating slave threads",__FUNCTION__); /* Create thread instances */ st_rd = create_thread(TT_READER); if (st_rd == NULL) set_thread_state(st,CS_ERROR,"%s(%d):Cannot create reader thread",__FUNCTION__,__LINE__); st_tx = create_thread(TT_TRANSMITTER); if (st_tx == NULL) set_thread_state(st,CS_ERROR,"%s(%d):Cannot create transmitter thread",__FUNCTION__,__LINE__); log_message(RL_DEBUG,"%s:Initializing thread messages",__FUNCTION__); /* Initialize thread messages */ init_reader_msg((reader_msg *)st_rd->type_msg, sbtx, pattern_read, fmtstr, mod_list, n_mod, disk_list_read, n_disk); init_transmitter_msg((transmitter_msg *)st_tx->type_msg, sbtx, host, port); /* Start transmitter thread */ if (start_thread(st_tx) != 0) set_thread_state(st,CS_ERROR,"%s(%d):Cannot start transmitter thread",__FUNCTION__,__LINE__); /* Pause, then see if transmitter has error, if so, abort */ usleep(MAIN_WAIT_PERIOD_US); if ((get_thread_state(st_tx,&state) == 0) && (state >= CS_STOP)) { set_thread_state(st,CS_ERROR,"%s(%d):Transmitter terminated prematurely, aborting start.",__FUNCTION__,__LINE__); } else { if (start_thread(st_rd) != 0) set_thread_state(st,CS_ERROR,"%s(%d):Cannot start reader thread",__FUNCTION__,__LINE__); } //~ log_message(RL_DEBUG,"%s:Entering main thread run loop",__FUNCTION__); if ((get_thread_state(st,&state) == 0) && !(state >= CS_STOP)) set_thread_state(st,CS_RUN,"%s:Thread running",__FUNCTION__); while ((get_thread_state(st,&state) == 0) && !(state >= CS_STOP)) { // TODO: do something usleep(MAIN_WAIT_PERIOD_US); /* If any thread has a problem, stop all of them */ if ( ((get_thread_state(st_rd,&state) == 0) && (state >= CS_ERROR)) || ((get_thread_state(st_tx,&state) == 0) && (state >= CS_ERROR)) ) { // TODO: Some cleanup? break; } /* If all threads are stopped, break */ if ( ((get_thread_state(st_rd,&state) == 0) && (state >= CS_STOP)) && ((get_thread_state(st_tx,&state) == 0) && (state >= CS_STOP)) ) { log_message(RL_NOTICE,"%s:All threads stopped of their own volition",__FUNCTION__); break; } /* If reader thread is done, stop transmitter */ if ( (get_thread_state(st_rd,&state) == 0) && (state >= CS_STOP) && (get_thread_state(st_tx,&state) == 0) && (state < CS_STOP)) { log_message(RL_NOTICE,"%s:Reader is done, stop transmitter",__FUNCTION__); /* Two wait periods should be enough - reader is the only * other thread that can cause transmitter to wait on a * resource, and then it will only be a single wait. */ usleep(MAIN_WAIT_PERIOD_US); usleep(MAIN_WAIT_PERIOD_US); if (stop_thread(st_tx) != 0) set_thread_state(st,CS_ERROR,"%s(%d):Cannot stop transmitter thread",__FUNCTION__,__LINE__); } } log_message(RL_DEBUG,"%s:Stopping slave threads",__FUNCTION__); /* Stop slave threads on tx side */ if ( (get_thread_state(st_rd,&state) == 0) && (state < CS_STOP) && (state > CS_INIT) && stop_thread(st_rd) != 0) set_thread_state(st,CS_ERROR,"%s(%d):Cannot stop reader thread",__FUNCTION__,__LINE__); log_message(RL_DEBUGVVV,"%s:Reader thread stopped",__FUNCTION__); if ( (get_thread_state(st_tx,&state) == 0) && (state < CS_STOP) && (state > CS_INIT) && stop_thread(st_tx) != 0) set_thread_state(st,CS_ERROR,"%s(%d):Cannot stop transmitter thread",__FUNCTION__,__LINE__); log_message(RL_DEBUGVVV,"%s:Transmitter thread stopped",__FUNCTION__); log_message(RL_DEBUG,"%s:Destroying shared buffer",__FUNCTION__); /* Destroy shared data buffer */ if (destroy_shared_buffer(&sbtx) != 0) set_thread_state(st,CS_ERROR,"%s(%d):Cannot destroy shared buffer for read+transmit",__FUNCTION__,__LINE__); log_message(RL_DEBUG,"%s:Destroying slave threads",__FUNCTION__); /* Destroy threads */ destroy_thread(&st_rd); destroy_thread(&st_tx); log_message(RL_DEBUG,"%s:Everything is done, goodbye",__FUNCTION__); /* That's all folks! */ // TODO: Report that we're done return EXIT_SUCCESS; }
int main ( int argc, char** argv ) { FILE* pipe; SHAREDBUFFER* shared_buffer; CONFIG* config; char main_process_lifetime[15]; int producer_count = 0; char producer_lifetime[15]; int consumer_count = 0; int child_exit_status = 0; int child_exit_pid; int child_pid; int i = 0; int logfd; char message[150]; char dir[255]; int available_process_count = 10000; strncpy(dir, argv[0], last_index_of(argv[0], '/')); chdir(dir); logfd = log_open_file( NULL ); if ( !logfd ) { printf("Unable to open log file.\n"); return EXIT_FAILURE; } log_event( "--------------------------------" ); log_event( "Main process started." ); // first of all load configuration file config = load_config_file(); if ( !config ) { log_event( "Unable to access configuration." ); return EXIT_FAILURE; } // read values from configuration producer_count = atoi(read_configuration(config, "producer_count", "5")); consumer_count = atoi(read_configuration(config, "consumer_count", "2")); strcpy(producer_lifetime, read_configuration(config, "producer_lifetime", "10")); strcpy(main_process_lifetime, read_configuration(config, "main_process_lifetime", "40")); destroy_config( config ); log_event( "Fetching available process count of system." ); pipe = popen(PROCESS_COUNT_SCRIPT, "r"); if ( pipe ) { fgets(message, 100, pipe); pclose(pipe); available_process_count = atoi(message); } if ( producer_count + consumer_count + 1 > available_process_count ) { log_event( "Requested total process count is more than available process count of system." ); goto SAFE_EXIT; } //initialize shared buffer shared_buffer = create_shared_buffer(); if ( !shared_buffer ) { log_event( "Unable to initialize shared buffer." ); destroy_config( config ); return EXIT_FAILURE; } // create and start producer processes // producer processes run for a specified lifetime ( in seconds ) // which is read from configuration for ( i=0; i<producer_count; ++i) { child_pid = vfork(); if ( child_pid == 0 ) // producer process { execl("producer", "producer", producer_lifetime, NULL); exit(0); } } // start consumer processes // consumer processes run until a SIGKILL signal // there is no specific entry in the requirements that // when a consumer process should end. for ( i=0; i<consumer_count; ++i) { child_pid = vfork(); if ( child_pid == 0 ) // consumer process { execl("consumer", "consumer", NULL); exit(0); } } // start controller process // controller process checks elapsed time // once in every 5 seconds // if total execution time is above a specified time (in seconds) // signals all child processes except itself, to force exit child_pid = vfork(); if ( child_pid == 0 ) //controller process { execl("controller", "controller", main_process_lifetime, NULL); exit(0); } // in order to catch all child processes exits // we need a common wait for all them // here exitting processes is cought with pid and exit status // wait childs to exit while( (child_exit_pid = wait(&child_exit_status)) > 0 ) { sprintf( message, "Process [PID:%d] exitid with status: %d", child_exit_pid, child_exit_status ); log_event( message ); } SAFE_EXIT: log_event( "Main process is being closed." ); // relase allocated data structures to OS destroy_shared_buffer( shared_buffer ); log_close_file( ); return EXIT_SUCCESS; }