int main() { int el, t; struct cfifo f; cfifo_init(&f, sizeof(int), 5); /* Initialization assertions */ assert(f.cap == 5); assert(f.h == 0); assert(f.len == 0); assert(f.sz == sizeof(int)); assert(f.ptr != 0); assert(cfifo_isempty(&f)); assert(!cfifo_isfull(&f)); /* After one push */ el = 1, cfifo_push(&f, &el); assert(f.len == 1); assert(!cfifo_isempty(&f)); assert(!cfifo_isfull(&f)); /* After one pop */ cfifo_pop(&f, &t); assert(el == t); assert(f.len == 0); assert(f.h == 1); assert(cfifo_isempty(&f)); /* Push until full */ el = 1, cfifo_push(&f, &el); el = 2, cfifo_push(&f, &el); el = 3, cfifo_push(&f, &el); el = 4, cfifo_push(&f, &el); el = 5, cfifo_push(&f, &el); assert(cfifo_isfull(&f)); assert(!cfifo_isempty(&f)); /* Push to overwrite head */ el = 6, cfifo_push(&f, &el); assert(cfifo_isfull(&f)); assert(!cfifo_isempty(&f)); /* Pop until empty */ cfifo_pop(&f, &el), assert(el == 2); cfifo_pop(&f, &el), assert(el == 3); cfifo_pop(&f, &el), assert(el == 4); cfifo_pop(&f, &el), assert(el == 5); cfifo_pop(&f, &el), assert(el == 6); assert(cfifo_isempty(&f)); assert(!cfifo_isfull(&f)); cfifo_free(&f); return 0; }
// Responsible for the thread that manages the Task Manager: receiving tasks, // Sending results, requesting new tasks and etc. void task_manager(struct tm_thread_data *d) { int end = 0; // To indicate a true ending. Dead but fine. enum message_type mtype; // Type of received message. int min_results = TM_RESULT_BUFFER_SIZE; // Minimum of results to send at the same time. enum blocking b = NONBLOCKING; // Indicates if should block or not in flushing. int comm_return=0; // Return values from send and read. int flushed_tasks; // Return value from flush_results. int tm_retries; // Count the number of times TM tries to reconnect. int task_wait_max=1; // Current max time of wait in CASE MSG_NO_TASK (sec) int wait; // wait(sec) in CASE MSG_NO_TASK int j_id=0; // Id from journal (if it exists). struct j_entry * entry; // new entry for journal. // Data structure to exchange message between processes. struct byte_array * ba; d->tasks = 0; // Tasks received and not committed. d->alive = 1; // Indicate if it still alive. srand (time(NULL)); if(TM_KEEP_JOURNAL > 0) { j_id = JOURNAL_get_id(d->dia, 'M'); } info("Starting task manager main loop"); while (d->alive) { ba = (struct byte_array *) malloc(sizeof(struct byte_array)); byte_array_init(ba, 100); debug("Sending READY message to JOB_MANAGER"); if(TM_KEEP_JOURNAL > 0) { entry = JOURNAL_new_entry(d->dia, j_id); entry->action = 'R'; gettimeofday(&entry->start, NULL); } comm_return = COMM_send_message(NULL, MSG_READY, socket_manager); if(comm_return < 0) { if(TM_KEEP_JOURNAL > 0) { gettimeofday(&entry->end, NULL); } if(COMM_get_actor_type() == VM_TASK_MANAGER) { error("Dumping VM journal"); vm_dump_journal(d); } error("Problem found sending message to Job Manager"); mtype = MSG_EMPTY; } else { comm_return = COMM_read_message(ba, &mtype, socket_manager); if(TM_KEEP_JOURNAL > 0) { gettimeofday(&entry->end, NULL); if(mtype == MSG_TASK) { debug("Received MSG_TASK of size : %d", (int)ba->len); entry->size = (int)ba->len; } } if(comm_return < 0) { error("Problem found to read message from Job Manager"); mtype = MSG_EMPTY; if(COMM_get_actor_type() == VM_TASK_MANAGER) { error("Dumping VM journal"); vm_dump_journal(d); } } } switch (mtype) { case MSG_TASK: // Received at least one, mark to reuse id if connection problem occurs. if(received_one ==0 ) { received_one = 1; } debug("waiting task buffer to free some space"); sem_wait(&d->sem); pthread_mutex_lock(&d->tlock); cfifo_push(&d->f, &ba); pthread_mutex_unlock(&d->tlock); sem_post(&d->tcount); if(TM_FLUSHER_THREAD > 0) { pthread_mutex_lock(&d->tasks_lock); d->tasks++; pthread_mutex_unlock(&d->tasks_lock); } else { d->tasks++; } break; case MSG_KILL: info("Got a KILL message"); d->alive = 0; end = 1; b = BLOCKING; break; case MSG_EMPTY: COMM_close_connection(socket_manager); tm_retries = TM_CON_RETRIES; if(COMM_connect_to_job_manager(COMM_addr_manager, &tm_retries)!=0) { info("Couldn't reconnect to the Job Manager. Closing Task Manager."); d->alive = 0; } else { info("Reconnected to the Job Manager."); } break; case MSG_NO_TASK: wait = int_rand(1, task_wait_max); debug("No task available, is it still loading? Sleeping for %d seconds", wait); sleep(wait); task_wait_max = task_wait_max * 2; if(task_wait_max > TM_MAX_SLEEP) { task_wait_max = TM_MAX_SLEEP; } break; default: break; } if (d->alive || end) { debug("Trying to flush %d %s...", min_results, b == BLOCKING ? "blocking":"non blocking"); if(TM_FLUSHER_THREAD > 0) { if((d->tasks >= min_results) || (b == BLOCKING)) { pthread_mutex_lock(&d->flusher_d_mutex); d->flusher_min_results = min_results; d->flusher_b = b; sem_post(&d->flusher_r_sem); } } else { if(b == BLOCKING) { min_results = d->tasks; } flushed_tasks = 0; if(d->tasks >= min_results) { flushed_tasks = flush_results(d, min_results, b, j_id); } if(flushed_tasks < 0) { info("Couldn't flush results. Is committer still alive?"); tm_retries = TM_CON_RETRIES; if(COMM_connect_to_committer(&tm_retries)<0) { info("If it is, I just couldn't find it. Closing."); d->alive = 0; } else { info("Reconnected to the committer."); } } else { d->tasks = d->tasks - flushed_tasks; debug("I have sent %d tasks\n", flushed_tasks); } } } } info("Terminating task manager"); byte_array_free(ba); free(ba); }