예제 #1
0
파일: main.c 프로젝트: Moddus/mpi_search
int
main(int argc, char *argv[])
{
    ps_status_t rv = PS_SUCCESS;
    int log_level = LOG_LEVEL_NONE;
    char *search = NULL, *path = NULL;
    size_t search_len = 0;
    int i = 0, c = 0;
    int number_of_procs = 0, own_rank = 0;
    int *slave_nodes = NULL;
    unsigned long chunk_size = DEFAULT_CHUNK_SIZE;
    ps_searcher_t *searcher = NULL;
    ps_search_task_t *task = NULL;
    char *result = NULL;
    size_t result_len = 0, total_result_len = 0, *all_result_len = NULL;
    int search_col = PS_CSV_ALL_COL;

#ifdef TIME_MEASUREMENT
    float total_seconds = 0, total_search_time = 0, total_file_io_time = 0, total_setup_time = 0, total_reduce_time = 0;
    struct timeval time_start, current_time;
    gettimeofday(&time_start, NULL);
    memcpy(&current_time, &time_start, sizeof(struct timeval));
#endif

    out_fd = stdout; /*For Logging*/

    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &number_of_procs);
    MPI_Comm_rank (MPI_COMM_WORLD, &own_rank);

    /*set log level until arguments are passed and processed*/
    set_log_level(log_level);

    if (own_rank == MASTER)
    {
        opterr = 0;
        while ((c = getopt (argc, argv, "hds:f:c:l:")) != -1)
        {
            switch (c)
            {
            case 'd':
                log_level = LOG_LEVEL_DEBUG;
                break;
            case 'f':
                path = optarg;
                break;
            case 's':
                search = optarg;
                search_len = strlen(search);
                break;
            case 'c':
                PS_CHECK_ZERO_GO_ERR( (chunk_size = atol(optarg)), PS_ERROR_WRONG_CHUNK_SIZE);
                break;
            case 'l':
                search_col = atoi(optarg);
                break;
            case 'h':
                break;
            default:
                if (optopt == 's')
                    fprintf (stderr, "Option -%c requires an argument.\n", optopt);
                else if (isprint (optopt))
                    fprintf (stderr, "Unknown option `-%c'.\n", optopt);
                else
                    fprintf (stderr,
                             "Unknown option character `\\x%x'.\n", optopt);

                rv = PS_ERROR_WRONG_ARGUMENTS;
                goto error;
            }
        }
    }

    /*Communicate and set log_level*/
    PS_MPI_CHECK_ERR(MPI_Bcast(&log_level, 1, MPI_INT, MASTER, MPI_COMM_WORLD));
    set_log_level(log_level);

    /*Communicate the token to search for*/
    PS_MPI_CHECK_ERR(MPI_Bcast(&search_len, 1, MPI_UNSIGNED_LONG, MASTER, MPI_COMM_WORLD));
    if (own_rank != MASTER)
    {
        PS_MALLOC(search, sizeof(char) * (search_len + 1));
    }
    PS_MPI_CHECK_ERR(MPI_Bcast(search, search_len + 1, MPI_CHAR, MASTER, MPI_COMM_WORLD));
    log_debug("Process %d: search_len:%u search:%s", own_rank, search_len, search);

#ifdef TIME_MEASUREMENT
    if(own_rank == MASTER)
    {
        update_timestamp_and_total_seconds(&current_time, &total_setup_time);
    }
#endif

    if (own_rank == MASTER)
    {
        log_debug("search = %s, path = %s, chunk_size=%lu", search, path, chunk_size);
        log_debug("sizeof(ps_search_task_t:%lu", sizeof(ps_search_task_t));

        for (i = optind; i < argc; i++)
        {
            log_debug("Non-option argument %s", argv[i]);
        }

        /*-------------------Processing of arguments done!-----------*/
        log_debug("Number of procs:%d", number_of_procs);
        PS_MALLOC( slave_nodes, sizeof(int) * (number_of_procs));
        for (i = 0; i < number_of_procs - 1; i++)
        {
            slave_nodes[i] = i + 1;
        }

        PS_CHECK_GOTO_ERROR( distribute_path_and_search_range(path,
                                                              number_of_procs ,
                                                              slave_nodes,
                                                              chunk_size,
                                                              search_col,
                                                              MPI_COMM_WORLD,
                                                              &task));

        /*Slaves receive path_length and search_task*/

        PS_CHECK_GOTO_ERROR(ps_file_searcher_create(&searcher, search, task));
        PS_CHECK_GOTO_ERROR(ps_file_searcher_search(searcher, &result, &result_len));
        log_debug("Process %d: result_len: %lu", own_rank, result_len);
        PS_CHECK_GOTO_ERROR(ps_file_searcher_free(&searcher));
        PS_MALLOC(all_result_len, sizeof(size_t) * number_of_procs);
    }
    else
    {
        /*Slaves receive path_length and search_task*/
        PS_CHECK_GOTO_ERROR(recv_task(&task, own_rank, MASTER, MPI_COMM_WORLD));

        PS_CHECK_GOTO_ERROR(ps_file_searcher_create(&searcher, search, task));
        PS_CHECK_GOTO_ERROR(ps_file_searcher_search(searcher, &result, &result_len));
        log_debug("Process %d: result_len: %lu", own_rank, result_len);
        PS_CHECK_GOTO_ERROR(ps_file_searcher_free(&searcher));
    }

#ifdef TIME_MEASUREMENT
    if(own_rank == MASTER)
    {
        gettimeofday(&current_time, NULL);
    }
#endif

    PS_MPI_CHECK_ERR(MPI_Gather(&result_len, 1, MPI_UNSIGNED_LONG, all_result_len, 1, MPI_UNSIGNED_LONG, MASTER,
            MPI_COMM_WORLD));

    if(own_rank == MASTER)
    {
        for(i = 0; i < number_of_procs; i++){
            total_result_len += all_result_len[i];
        }
        log_debug("Process %d: total_result_len:%lu", own_rank, total_result_len);
        PS_REALLOC(result, total_result_len);
        for(i = 1; i < number_of_procs; i++){
            PS_MPI_CHECK_ERR(MPI_Recv(result + all_result_len[i - 1], all_result_len[i], MPI_CHAR,
                    i, PS_MPI_TAG_RESULT, MPI_COMM_WORLD, MPI_STATUSES_IGNORE));
            result_len += all_result_len[i];
        }
        write(STDOUT_FILENO, result, result_len);
    }
    else
    {
        PS_MPI_CHECK_ERR(MPI_Send(result, result_len, MPI_CHAR, MASTER, PS_MPI_TAG_RESULT, MPI_COMM_WORLD));
        PS_FREE(search);
    }

    log_debug("Process %d finished", own_rank);

#ifdef TIME_MEASUREMENT
    if(own_rank == MASTER)
    {
        update_timestamp_and_total_seconds(&current_time, &total_reduce_time);
    }
    printf("Process %d: process_search_time: %f, process_file_io_time: %f\n", own_rank
        ,process_search_time, process_file_io_time);

    PS_MPI_CHECK_ERR(MPI_Reduce(&process_search_time, &total_search_time, 1, MPI_FLOAT, MPI_SUM, MASTER,
            MPI_COMM_WORLD));
    PS_MPI_CHECK_ERR(MPI_Reduce(&process_file_io_time , &total_file_io_time, 1, MPI_FLOAT, MPI_SUM, MASTER,
            MPI_COMM_WORLD));

    update_timestamp_and_total_seconds(&time_start, &total_seconds);
    if(own_rank == MASTER)
    {
        printf("Total-Time: %.3fs\n"
                        "\ttotal_setup_time: %.3fs\n"
                        "\ttotal_reduce_time: %.3fs\n"
                        "\taverage-io-time: %.3fs\n"
                        "\taverage-search-time: %.3fs\n"
                        "processes: %d\n"
                        "chunksize: %lu Bytes\n",
                total_seconds, total_setup_time, total_reduce_time,
                total_file_io_time / number_of_procs, total_search_time / number_of_procs,
                number_of_procs, chunk_size);
    }
#endif

    MPI_Finalize();

    PS_FREE(slave_nodes);
    PS_FREE(result);
    PS_FREE(all_result_len);

    return EXIT_SUCCESS;
    /*-----------------ERROR-Handling------------------------------*/
error:
    log_err("Process %d finished with error: %d", own_rank, rv);
    MPI_Finalize();

    if (own_rank != MASTER)
    {
        PS_FREE(search);
    }

    PS_FREE(slave_nodes);
    if(searcher)
    {
        PS_FREE(searcher->task);
    }
    PS_FREE(result);
    PS_FREE(all_result_len);

    return rv;
}
예제 #2
0
파일: sync_src.c 프로젝트: javelinjs/VDD
void *sync_src(void *arg)
{
	sync_thread_arg_t *tmparg = arg;
	int sock_fd = tmparg->sock_fd;
	io_sync_ctrl_block_t *dcp = tmparg->dcp;

	int ret;

	//iterate berkeley db, retrieving each record in turn.
	struct list_head key_head;
	struct hashtable *key_hash;
	DBC *cursorp;
	DBT dbt_key, dbt_data;
	dcp->dbp->cursor(dcp->dbp, NULL, &cursorp, 0);
	memset(&dbt_key, 0, sizeof(DBT));
	memset(&dbt_data, 0, sizeof(DBT));

	pthread_mutex_lock(&(dcp->io_lock));
	key_hash = create_hashtable(10000, hash_from_key_fn, keys_equal_fn);
	INIT_LIST_HEAD(&key_head);
	while ((ret = cursorp->c_get(cursorp, &dbt_key, &dbt_data, DB_NEXT)) == 0) {
		key_list_t *tmp = (key_list_t *)malloc(sizeof(key_list_t));
		memcpy(tmp->key, dbt_key.data, KEY_SIZE);
		list_add_tail(&(tmp->list_node), &key_head);
		if (!hashtable_insert(key_hash, tmp->key, tmp)) {
			perror("hash insert error!");
			return NULL;
		}
	}

	//close
	if (cursorp != NULL)
		cursorp->c_close(cursorp);

	pthread_mutex_unlock(&(dcp->io_lock));

	unsigned int max_packet_size = sizeof(msg_sync_t) + SECTION_SIZE;
	unsigned char *sock_buf = (unsigned char *)malloc(max_packet_size);
	DBT key, data;
	MD5_CTX md5_ctx;
	unsigned char tmp[BLOCK_INDEX_SIZE];
	msg_sync_t msg;
	unsigned int bi, fi = 0;
	off_t off1 = 0, off2 = 0;
	key_list_t *valuep;

	void *buf;
	if (posix_memalign(&buf, 512, SECTION_SIZE) != 0) {
		perror("posix_memalign error");
		return NULL;
	}

	int is_data_end = 0, is_block_end = 1;
	while (!is_data_end) {

		if (recv_task(sock_fd, sock_buf, max_packet_size) <= 0) {
			perror("rece_task error");
			return NULL;
		}

		msg = *((msg_sync_t *)sock_buf);
		unsigned char *sock_data;
		switch (msg.type) {
		//recv section md5 code
		case SYNC_SECTION_MD5:
			if (is_block_end || off2 >= BLOCK_SIZE) {
				perror("wrong section msg");
				return NULL;
			}

			sock_data = sock_buf + sizeof(msg_sync_t);

			//read src section data, and calc md5
			if (lseek(dcp->fd[fi], off1 + off2, SEEK_SET) == (off_t)-1) {
				perror("seek error");
				return NULL;
			}

			if (read(dcp->fd[fi], buf, SECTION_SIZE) != SECTION_SIZE) {
				perror("seek error");
				return NULL;
			}

			MD5Calc(&md5_ctx, (unsigned char *)buf, SECTION_SIZE);
#ifdef _SYNC_SRC_DEBUG__
			unsigned int kk;
			for (kk = 0; kk < 16; ++kk)
				printf("%02X", md5_ctx.digest[kk]);
			printf("\n");
#endif
			off2 += SECTION_SIZE;

			// compare to dest md5
			if (memcmp(md5_ctx.digest, sock_data, 16) == 0) {
				SEND_MSG(0, buf, SYNC_SECTION_SAME, "Can't send msg to client");
			} else {
				SEND_MSG(SECTION_SIZE, buf, SYNC_SECTION_DATA, "Can't send msg to client");
			}

			break;

		case SYNC_BLOCK_KEY:
			sock_data = sock_buf + sizeof(msg_sync_t);
#ifdef _SYNC_SRC_DEBUG__
			printf("%u %u ", msg.size, msg.type);
			int jj;
			for (jj = 0; jj < KEY_SIZE; ++jj) {
				printf("%u ", sock_data[jj]);
			}
			printf("\n");
#endif

			if ((valuep = hashtable_remove(key_hash, sock_data)) != NULL) {
				list_del(&(valuep->list_node));
				free(valuep);
			}

			//get block index by key
			memset(&key, 0, sizeof(DBT));
			key.data = sock_data;
			key.size = KEY_SIZE;

			memset(&data, 0, sizeof(DBT));
			data.data = tmp;
			data.ulen = BLOCK_INDEX_SIZE;
			data.flags = DB_DBT_USERMEM;

			ret = dcp->dbp->get(dcp->dbp, NULL, &key, &data, 0);
			if (ret == DB_NOTFOUND) {
				//reply SYNC_BLOCK_DELETE
				SEND_MSG(0, buf, SYNC_BLOCK_DELETE, "Can't send msg to client");
			} else if (ret) {
				printf("dbp->get error - %d\n", ret);
				perror("dbp->get error");
				return NULL;
			} else {
				//reply SYNC_BLOCK_CONTINUE
				bi = *((unsigned int *)tmp);
				fi = *(unsigned int *)(tmp + 4);
				off1 = bi;
				off1 = off1 * BLOCK_SIZE;
				off2 = 0;
				is_block_end = 0;

				SEND_MSG(0, buf, SYNC_BLOCK_CONTINUE,
					"log_deliver send error -can't send msg to client");
			}

			break;

		case SYNC_BLOCK_END:
			if (off2 != BLOCK_SIZE) {
				perror("wrong section");
				return NULL;
			}
			is_block_end = 1;
			SEND_MSG(0, buf, SYNC_OK, "Can't send msg to client");
			break;

		case SYNC_DATA_END:
			is_data_end = 1;
			break;

		default:
			perror("unknown sync msg code");
			return NULL;
		}
	}

   	//destroy hashtable but not free key and value
    hashtable_destroy(key_hash, 2);

	key_list_t *v;
    while (!list_empty(&key_head)) {
    	v = container_of(key_head.next, key_list_t , list_node);
#ifdef _SYNC_SRC_H__
		int kk;
		for (kk = 0; kk < 8; ++kk) printf("%u ", v->key[kk]);
		printf("\n");
#endif

		memset(&key, 0, sizeof(DBT));
		key.data = v->key;
		key.size = KEY_SIZE;

		memset(&data, 0, sizeof(DBT));
		data.data = tmp;
		data.ulen = BLOCK_INDEX_SIZE;
		data.flags = DB_DBT_USERMEM;

		ret = dcp->dbp->get(dcp->dbp, NULL, &key, &data, 0);
		if (ret == DB_NOTFOUND) {
			//do something here
			//key may be deleted
			list_del(key_head.next);
			continue;
		}

		bi = *(unsigned int *)tmp;
		fi = *(unsigned int *)(tmp + 4);

		//send keys
		SEND_MSG(KEY_SIZE, v->key, SYNC_BLOCK_KEY, "Can't send msg to client");

		//recv reply
		RECV_MSG(SYNC_BLOCK_CONTINUE, "recv key_reply error", "return type error");

		//new block, send section data
		off1 = bi;
		off1 = off1 * BLOCK_SIZE;
		for (off2 = 0; off2 < BLOCK_SIZE; off2 += SECTION_SIZE) {
			if (lseek(dcp->fd[fi], off1 + off2, SEEK_SET) == (off_t)-1) {
				perror("seek error");
				return NULL;
			}

			if (read(dcp->fd[fi], buf, SECTION_SIZE) != SECTION_SIZE) {
				perror("read error");
				return NULL;
			}

			//new block, send section data
			SEND_MSG(SECTION_SIZE, buf, SYNC_SECTION_DATA, "send section data failed");

			RECV_MSG(SYNC_OK, "recv section_reply error", "return type error");
		}

		//new block, send block end
		SEND_MSG(0, buf, SYNC_BLOCK_END, "send block end failed");
		
		RECV_MSG(SYNC_OK, "recv data_end_reply", "return type error");

    	list_del(key_head.next);
    }

	//new block, send data end
	SEND_MSG(0, buf, SYNC_DATA_END, "send data end failed");

	close(sock_fd);
	free(sock_buf);

//EXIT:

	return NULL;
}