static void *main_alarm_handler(void *ctx) { QALARM *q = (QALARM *)ctx; QUEUE_ITEM *item; pthread_t tid; QTHREAD *qt; while ((item = Get_Queue_Item(q->queue))) { if (!strcmp(item->action, "Terminate")) { /* Send termination signal */ for (qt = q->threads; qt != NULL; qt = qt->next) Add_Queue_Item(qt->queue, "Terminate", NULL, 0); /* Wait for termination */ for (qt = q->threads; qt != NULL; qt = qt->next) pthread_join(qt->tid, NULL); while (q->threads) delete_alarm(q, q->threads->tid); Free_Queue_Item(item); return NULL; } else if (!strcmp(item->action, "Wait")) { /* Wait for termination */ for (qt = q->threads; qt != NULL; qt = qt->next) pthread_join(qt->tid, NULL); while (q->threads) delete_alarm(q, q->threads->tid); Free_Queue_Item(item); return NULL; } else if (!strcmp(item->action, "Destroy")) { if (item->sz != sizeof(pthread_t)) { Free_Queue_Item(item); continue; } pthread_join(*((pthread_t *)(item->data)), NULL); delete_alarm(q, *((pthread_t *)(item->data))); } else { fprintf(stderr, "Unknown action: %s\n", item->action); } Free_Queue_Item(item); } return NULL; }
static void *inner_alarm_handler(void *ctx) { QTHREAD *qt = (QTHREAD *)ctx; time_t starttime; time_t newtime; struct timeval t; QUEUE_ITEM *item; starttime = time(NULL); newtime = qt->timeout; while (time(NULL) - starttime < newtime) { t.tv_sec = newtime < POLLSEC ? newtime : POLLSEC; t.tv_usec = 0; select(0, NULL, NULL, NULL, &t); newtime = qt->timeout - (time(NULL) - starttime); if (!Queue_Empty(qt->queue)) { item = Get_Queue_Item(qt->queue); if (!strcmp(item->action, "Terminate")) { Free_Queue_Item(item); return NULL; } Free_Queue_Item(item); } } qt->cb(qt->data); if (qt->flags & QALARM_RECUR) add_alarm(qt->parent, qt->timeout, qt->cb, qt->data, qt->flags); Add_Queue_Item(qt->parent->queue, "Destroy", &(qt->tid), sizeof(pthread_t)); return NULL; }
int main(int argc, char* argv[]) { if(argc != 4) { usage(); exit(1); } init_env(); init_protocal_buf(); pthread_mutex_init(&lockDownload, NULL); /** init server address **/ struct sockaddr_in servaddr; bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(SERV_PORT); if(inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) { printf("[%s] is not avalid IP address!\n", argv[1]); exit(1); } int sockfd = socket(AF_INET, SOCK_DGRAM, 0); /** check if configure file exists **/ char conf_full[100]; strcpy(conf_full, path); strcat(conf_full, conf_file); if(access(conf_full, 0) == -1) { task_flag = NEW_TASK; printf("cannot access the file %s\n", conf_full); /** init config file, can be expended later for any request **/ init_conf(conf_full); }else { task_flag = OLD_TASK; printf("access the file %s\n", conf_full); //TODO continue to send config_t *conf_hd = confRead(conf_full); sprintf(filename, "%s", confGet(conf_hd, "filename")); load_detail(conf_hd); confDestory(conf_hd); } queue = Initialize_Queue(); //Add_Queue_Item(queue, "", file_name, 0); //Add_Queue_Item(queue, "", file_name, 0); //Add_Queue_Item(queue, "", file_name, 0); cookLive = YES; soldierLive = YES; receiverLive = YES; /** start Cook thread **/ pthread_t cook_fd; pthread_create(&cook_fd, NULL, cook_mission, path); //pthread_join(cook_fd, NULL); /** start Receiver thread **/ pthread_t receiver_id; pthread_create(&receiver_id, NULL, receiver, NULL); //pthread_join(cook_fd, NULL); //pthread_join(receiver_id, NULL); printf("===========================================================\n"); struct synack syn_pack; syn_pack.thread_num = THREAD_LIMITION; syn_pack.file_info.blocksize = BODYLEN; while(clientLive){ soldierLive = YES; taskIndex = 0; taskArray = NULL; filesize = 0; block_num = 0; QUEUE_ITEM *item = NULL; //memset(item, 0, sizeof(QUEUE_ITEM)); while(!item && clientLive == YES){ printf("[Main] main thread check queue\n"); item = Get_Queue_Item(queue); if(item){ printf("[Main] item.filename = %s\n", item->data); strcpy(filename, item->data); printf("[Main] transmitting: %s \n", filename); break; }else{ printf("[Main] Queue empty will check again in 2 seconds...\n"); sleep(2); } } strcpy(syn_pack.file_info.filename, filename); /** count filesize **/ char target_full[100]; strcpy(target_full, path); strcat(target_full, filename); int fd = open(target_full, O_RDONLY); filesize = get_filesize(fd); syn_pack.file_info.filesize = filesize; /** count block_num **/ if(filesize % BODYLEN == 0) syn_pack.file_info.block_num = filesize / BODYLEN; else syn_pack.file_info.block_num = filesize / BODYLEN + 1; block_num = syn_pack.file_info.block_num; /** make taskArray **/ taskArray = (int*)malloc(sizeof(int) * block_num); memset(taskArray, 0, sizeof(int) * block_num); /* count downloaded_block */ if(task_flag == NEW_TASK) { printf("new task\n"); downloaded_block = 0; } else { printf("block_num = %d, thread_num = %d, blocksize = %d, filesize = %d\n", syn_pack.file_info.block_num, syn_pack.thread_num, syn_pack.file_info.blocksize, syn_pack.file_info.filesize); /** count local global downloaded_block **/ downloaded_block = 0; if(downloaded_block == block_num) { printf("download already finished\n"); continue; } task_flag = OLD_TASK; } syn_pack.file_info.downloaded_block = downloaded_block; printf("figure out filesize = %d, block_num = %d, downloaded_block = %d\n", filesize, block_num, downloaded_block); { /**TODO store config info **/ /*config_t *conf_hd = confRead(conf_full); if(conf_hd == NULL) { printf("conf file null, return \n"); return 0; } confSet(conf_hd, "filename", filename); confSet(conf_hd, "filesize", filesize); store_detail(conf_hd); confDestory(conf_hd); */ } /** ask for link with server **/ struct synack synack_pack = get_new_port(syn_pack, sockfd, (struct sockaddr*)(&servaddr), sizeof(servaddr)); printf("receive: thread_num = %d, downloaded_block = %d, block_num = %d\n", synack_pack.thread_num, synack_pack.file_info.downloaded_block, synack_pack.file_info.block_num); //if(synack_pack == NULL){ //printf("main get connection failed, exiting...\n"); //process_end(); //return 0; //} /** create subthreads here **/ task_list = (struct subthread_task *)malloc(sizeof(struct subthread_task) * THREAD_LIMITION); int i; for(i = 0; i < THREAD_LIMITION; i++) { task_list[i].hostname = argv[1]; task_list[i].port = synack_pack.port[i]; task_list[i].thread_no = i + 1; task_list[i].thread_num = THREAD_LIMITION; strcpy(task_list[i].file_info.filename, filename); task_list[i].file_info.filesize= filesize; task_list[i].file_info.block_num = block_num; task_list[i].file_info.blocksize= BODYLEN; pthread_create(&ptid[i], NULL, soldier_mission, &task_list[i]); } signal(SIGINT, process_end); signal(SIGKILL, process_end); /** print the transmit progress **/ do{ sleep(0.1); //int percent = (downloaded_block * 100) / block_num; /** print_process(percent, 100); **/ }while(downloaded_block < block_num); //soldierLive = NO; for(i = 0; i < THREAD_LIMITION; i ++){ pthread_join(ptid[i], NULL); } print_process(100, 100); printf("\ndownload finished, exiting...[please wait and not interrupt or power off]\n"); //int j = 0; //for(; j < block_num; j ++) //printf("%d, ", taskArray[i]); //printf("\n"); free(task_list); free(taskArray); task_list = NULL; taskArray = NULL; } pthread_mutex_destroy(&lockDownload); return 0; }