예제 #1
0
int path_disk_size_info_get_r(const char *path, int64_t max_secs, struct path_disk_size_info **state) {
	int64_t start_time = time(0);
	int result = 0;

	if(!*state) {
		/* if state is null, there is no state, and path is the root of the measurement. */
		*state = calloc(1, sizeof(struct path_disk_size_info));
	}

	struct path_disk_size_info *s = *state;     /* shortcut for *state, so we do not need to type (*state)->... */

	/* if no current_dirs, we begin a new measurement. */
	if(!s->current_dirs) {
		s->complete_measurement = 0;

		struct DIR_with_name *here = malloc(sizeof(struct DIR_with_name));

		if((here->dir = opendir(path))) {
			here->name = xxstrdup(path);
			s->current_dirs = list_create(0);
			s->size_so_far  = 0;
			s->count_so_far = 1;                     /* count the root directory */
			list_push_tail(s->current_dirs, here);
		} else {
			debug(D_DEBUG, "error reading disk usage on directory: %s.\n", path);
			s->size_so_far  = -1;
			s->count_so_far = -1;
			s->complete_measurement = 1;
			result       = -1;
			goto timeout;
		}
	}

	struct DIR_with_name *tail;
	while((tail = list_peek_tail(s->current_dirs))) {
		struct dirent *entry;
		struct stat   file_info;
		while((entry = readdir(tail->dir))) {
			if( strcmp(".", entry->d_name) == 0 || strcmp("..", entry->d_name) == 0)
				continue;

			char composed_path[PATH_MAX];
			if(entry->d_name[0] == '/') {
				strncpy(composed_path, entry->d_name, PATH_MAX);
			} else {
				snprintf(composed_path, PATH_MAX, "%s/%s", tail->name, entry->d_name);
			}

			if(lstat(composed_path, &file_info) < 0) {
				if(errno == ENOENT) {
					/* our DIR structure is stale, and a file went away. We simply do nothing. */
				} else {
					debug(D_DEBUG, "error reading disk usage on '%s'.\n", path);
					result = -1;
				}
				continue;
			}

			s->count_so_far++;
			if(S_ISREG(file_info.st_mode)) {
				s->size_so_far += file_info.st_size;
			} else if(S_ISDIR(file_info.st_mode)) {
				struct DIR_with_name *branch = malloc(sizeof(struct DIR_with_name));
				if((branch->dir = opendir(composed_path))) {
					/* future while we'll read from the branch */
					branch->name = xxstrdup(composed_path);
					list_push_head(s->current_dirs, branch);
				} else {
					free(branch);
					result = -1;
					continue;
				}
			} else if(S_ISLNK(file_info.st_mode)) {
				/* do nothing, avoiding infinite loops. */
			}

			if(max_secs > -1) {
				if( time(0) - start_time >= max_secs ) {
					goto timeout;
				}
			}
		}

		/* we are done reading a complete directory, and we go to the next in the queue */
		tail = list_pop_tail(s->current_dirs);
		closedir(tail->dir);
		free(tail->name);
		free(tail);
	}

	list_delete(s->current_dirs);
	s->current_dirs = NULL;       /* signal that a new measurement is needed, if state structure is reused. */
	s->complete_measurement = 1;

timeout:
	if(s->complete_measurement) {
		/* if a complete measurement has been done, then update
		 * for the found value */
		s->last_byte_size_complete  = s->size_so_far;
		s->last_file_count_complete = s->count_so_far;
	}
	else {
		/* else, we hit a timeout. measurement reported is conservative, from
		 * what we knew, and know so far. */

		s->last_byte_size_complete  = MAX(s->last_byte_size_complete, s->size_so_far);
		s->last_file_count_complete = MAX(s->last_file_count_complete, s->count_so_far);
	}

	return result;
}
int main(int argc, char *argv[])
{
	struct work_queue *q;
	int port = WORK_QUEUE_DEFAULT_PORT;

	if(argc != 4) {
		printf("Usage: work_queue_workload_simulator <workload_spec> <logfile> <proj_name> \n");
		exit(1);
	}

	struct list *specs = get_workload_specs(argv[1]);
	if(!specs) {
		printf("Failed to load a non-empty workload specification.\n");
		exit(1);
	}

	created_files = list_create(); 
	if(!created_files) {
		printf("Failed to allocate memory for a list to store created files.\n");
		exit(1);
	}

	// open log file
	logfile = fopen(argv[2], "a");
	if(!logfile) {
		printf("Couldn't open logfile %s: %s\n", argv[2], strerror(errno));
		exit(1);
	}

	q = work_queue_create(port);
	if(!q) {
		printf("couldn't listen on port %d: %s\n", port, strerror(errno));
		goto fail;
		exit(1);
	}

	printf("listening on port %d...\n", work_queue_port(q));

	// specifying the right modes
	work_queue_specify_master_mode(q, WORK_QUEUE_MASTER_MODE_CATALOG);
	work_queue_specify_name(q, argv[3]);
	work_queue_specify_estimate_capacity_on(q, 1); // report capacity on

	int time_elapsed = 0; // in seconds 
	int series_id = 0;
	time_t start_time = time(0);
	log_work_queue_status(q);
	while(1) {
		struct task_series *ts = (struct task_series *)list_peek_tail(specs);
		if(!ts) {
			while(!work_queue_empty(q)) { // wait until all tasks to finish
				wait_for_task(q, 5);
			}
			break;
		} else {
			time_elapsed = time(0) - start_time;
			int time_until_next_submit = ts->submit_time - time_elapsed;
			if(time_until_next_submit <=0) {
				list_pop_tail(specs);
				printf("time elapsed: %d seconds\n", time_elapsed);
				if(!submit_task_series(q, ts, series_id)) {
					// failed to submit tasks
					fprintf(stderr, "Failed to submit tasks.\n");
					goto fail;
				}
				free(ts);
				series_id++;
			} else {
				time_t stoptime = start_time + ts->submit_time;
				while(!work_queue_empty(q)) {
					int timeout = stoptime - time(0);
					if(timeout > 0) {
						wait_for_task(q, timeout);
					} else {
						break;
					}
				}
				time_t current_time = time(0);
				if(current_time < stoptime) {
					sleep(stoptime - current_time);
				}
			}
		}
	}

	printf("all tasks complete!\n");
	work_queue_delete(q);
	remove_created_files();
	fclose(logfile);

	return 0;

fail:
	remove_created_files();
	fclose(logfile);
	exit(1);
}