示例#1
0
/* this returns cached result */
gfarm_error_t
gfs_stat_cached_internal(const char *path, struct gfs_stat *st)
{
	struct gfarm_hash_entry *entry;
	struct stat_cache_data *data;
	struct timeval now;

	if (stat_cache == NULL) {
		gfarm_error_t e = gfs_stat_cache_init();

		if (e != GFARM_ERR_NO_ERROR)
			return (e);
	}
	gettimeofday(&now, NULL);
	gfs_stat_cache_expire_internal(&now);
	entry = gfarm_hash_lookup(stat_cache, path, strlen(path) + 1);
	if (entry != NULL) {
#ifdef DIRCACHE_DEBUG
		gflog_debug(GFARM_MSG_1000092,
		    "%ld.%06ld: gfs_stat_cached(%s): hit (%d)",
		    (long)now.tv_sec,(long)now.tv_usec, path,stat_cache_count);
#endif
		data = gfarm_hash_entry_data(entry);
		return (gfs_stat_copy(st, &data->st));
	}
#ifdef DIRCACHE_DEBUG
	gflog_debug(GFARM_MSG_1000093,
	    "%ld.%06ld: gfs_stat_cached(%s): miss (%d)",
	    (long)now.tv_sec, (long)now.tv_usec, path, stat_cache_count);
#endif
	return (gfs_stat_caching(path, st));
}
示例#2
0
文件: error.c 项目: krichter722/gfarm
int
gfarm_error_to_errno(const char *error)
{
	struct gfarm_hash_entry *p;
	int i;

	if (gfarm_errlist_hashtab == NULL)
		gfarm_errlist_hashtab_initialize();

	for (i = 0; i < GFARM_ARRAY_LENGTH(gfarm_errno_error_map); i++) {
		if (error == gfarm_errno_error_map[i].gfarm_error)
			return (gfarm_errno_error_map[i].unix_errno);
	}

	/*
	 * The reason why we compare string content rather than string
	 * address here is that strerror(3) may always copy error string
	 * to its internal buffer.
	 *
	 * XXX - If we always use sys_errlist[] rather than strerror(3),
	 *	is it ok to just compare string address?
	 */
	/* XXX - if locale LC_MESSAGES is changed, this may not work. */
	p = gfarm_hash_lookup(gfarm_errlist_hashtab, error, strlen(error) + 1);
	if (p != NULL)
		return (*(int *)gfarm_hash_entry_data(p));

	return (EINVAL); /* last resort, cannot mapped into errno */
}
示例#3
0
static char *
cache_path_info_remove(const char *pathname)
{
	struct gfarm_hash_entry *he;
	int pathlen;
	struct path_info_cache *pic;

	if (!cache_path_info_init())
		return (GFARM_PATH_INFO_CACHE_CANCEL);

	pathlen = strlen(pathname);
	he = gfarm_hash_lookup(cache_table, pathname, pathlen);
	if (he != NULL) {
		pic = gfarm_hash_entry_data(he);
		if (pic != NULL) {
			if (pic->noent == CACHE_SET)
				gfarm_path_info_free(&pic->info);
			if (gfarm_hash_purge(cache_table, pathname, pathlen)) {
				_debug("! remove path_info cache: %s\n",
				       pathname);
				current_cache_num--;
				return (NULL);
			}
		}
	}
	return "cache_path_info_remove: no path_info cache";
}
示例#4
0
文件: gfrep.c 项目: ddk50/gfarm_v2
static gfarm_error_t
create_hostlist_by_domain_and_hash(struct file_info *finfo, char *domain,
	struct gfarm_hash_table *hosthash,
	int *nhostsp, char ***hostsp, int **portsp)
{
	int ninfo, i, j, *ports, nhosts;
	struct gfarm_host_sched_info *infos;
	char **hosts;
	gfarm_error_t e;

	e = schedule_host_domain(finfo->pathname, domain, &ninfo, &infos);
	if (e != GFARM_ERR_NO_ERROR)
		return (e);
	/* sort 'infos' in descending order wrt available capacity */
	qsort(infos, ninfo, sizeof(*infos), compare_available_capacity_r);

	/* eliminate file system nodes that do not have enough space */
	for (i = 0; i < ninfo; ++i)
		/* note that disk_avail is the number of 1K blocks */
		if (infos[i].disk_avail * 1024
		    < gfarm_get_minimum_free_disk_space())
			break;
	nhosts = i;

	/* XXX - abandon CPU load and available capacity */
	GFARM_MALLOC_ARRAY(hosts, nhosts);
	if (hosts == NULL) {
		gfarm_host_sched_info_free(ninfo, infos);
		return (GFARM_ERR_NO_MEMORY);
	}
	GFARM_MALLOC_ARRAY(ports, nhosts);
	if (ports == NULL) {
		free(hosts);
		gfarm_host_sched_info_free(ninfo, infos);
		return (GFARM_ERR_NO_MEMORY);
	}
	for (i = 0, j = 0; i < nhosts; ++i) {
		char *host = infos[i].host;

		if (hosthash == NULL ||
		    gfarm_hash_lookup(hosthash, host, strlen(host) + 1)) {
			hosts[j] = strdup(host);
			ports[j] = infos[i].port;
			if (hosts[j] == NULL) {
				gfarm_strings_free_deeply(j, hosts);
				return (GFARM_ERR_NO_MEMORY);
			}
			++j;
		}
	}
	gfarm_host_sched_info_free(ninfo, infos);
	*hostsp = hosts;
	*portsp = ports;
	*nhostsp = j;

	return (e);
}
示例#5
0
static int
is_host_runnable(struct string_filter *self, const char *host)
{
	struct host_runnable_filter *filter =
	    (struct host_runnable_filter *)self;
	struct gfarm_hash_entry *entry = gfarm_hash_lookup(filter->hosts_state,
	    host, strlen(host) + 1);
	struct search_idle_host_state *h;

	if (entry == NULL) /* never happen, if metadata is consistent */
		return (0);
	h = gfarm_hash_entry_data(entry);
	return ((h->flags & HOST_STATE_FLAG_RUNNABLE) != 0);
}
示例#6
0
/*
 * Return GFARM_ERR_NO_HOST, if there is a replica, but there isn't
 * any host which satisfies the hostname_filter.
 */
static char *
search_idle_by_section_copy_info(struct gfarm_hash_table *hosts_state,
	int ncopies, struct gfarm_file_section_copy_info *copies,
	struct string_filter *hostname_filter,
	int nohosts, char **ohosts)
{
	char *e;
	int i, nhosts;
	struct section_copy_info_array_iterator copy_iterator;
	struct gfarm_hash_entry *entry;
	struct search_idle_host_state *h;

	nhosts = 0;
	for (i = 0; i < ncopies; i++) {
		if ((*hostname_filter->suitable)(hostname_filter,
		    copies[i].hostname))
			nhosts++;
	}
	if (nhosts == 0)
		return (GFARM_ERR_NO_HOST);

	e = search_idle_cyclic(hosts_state, nhosts, hostname_filter,
	    init_section_copy_info_array_iterator(&copy_iterator, copies),
	    nohosts, ohosts);
	if (e == NULL) {
		e = gfarm_fixedstrings_dup(nohosts, ohosts, ohosts);
		if (e == NULL) {
			/* increase the load average of scheduled hosts */
			for (i = 0; i < nohosts; i++) {
				entry = gfarm_hash_lookup(hosts_state,
				    ohosts[i], strlen(ohosts[i]) + 1);
				if (entry == NULL)
					continue; /* shouldn't happen */
				h = gfarm_hash_entry_data(entry);
				h->loadavg += VIRTUAL_LOAD_FOR_SCHEDULED_HOST;
			}
		}
	}
	return (e);
}
示例#7
0
static char *
cache_path_info_get(const char *pathname, struct gfarm_path_info *info)
{
	struct gfarm_hash_entry *he;
	int pathlen;
	struct path_info_cache *pic;
	struct timeval now;

	if (!cache_path_info_init())
		return (GFARM_PATH_INFO_CACHE_CANCEL);

	pathlen = strlen(pathname);
	he = gfarm_hash_lookup(cache_table, pathname, pathlen);
	if (he != NULL) {
		pic = gfarm_hash_entry_data(he);
		if (pic != NULL) {
			/* check term of validity */
			gettimeofday(&now, NULL);
			gfarm_timeval_sub(&now, &pic->time);
			if (gfarm_timeval_cmp(&now, &cache_timeout) >= 0) {
				_debug("! expire path_info cache: %s\n",
				       pathname);
#if 1  /* purge */
				if (pic->noent == CACHE_SET)
					gfarm_path_info_free(&pic->info);
				if (gfarm_hash_purge(cache_table, pathname,
						     strlen(pathname)))
					current_cache_num--;
#endif
				return "expired path_info cache content";
			}
			_debug("! use path_info cache: %s\n", pathname);
			if (pic->noent == CACHE_NOENT) /* NOENT cache */
				return (GFARM_ERR_NO_SUCH_OBJECT);

			return gfarm_path_info_dup(&pic->info, info);
		}
	}
	return "cache_path_info_get: no path_info cache";
}
示例#8
0
文件: conn_hash.c 项目: eterps/pwrake
gfarm_error_t
gfp_conn_hash_lookup(struct gfarm_hash_table **hashtabp, int hashtabsize,
	const char *hostname, int port, const char *username,
	struct gfarm_hash_entry **entry_ret)
{
	gfarm_error_t e;
	struct gfp_conn_hash_id id;
	struct gfarm_hash_entry *entry;

	if (*hashtabp == NULL &&
	    (e = gfp_conn_hash_table_init(hashtabp, hashtabsize)) !=
	    GFARM_ERR_NO_ERROR)
		return (e);

	id.hostname = (char *)hostname; /* UNCONST */
	id.port = port;
	id.username = (char *)username; /* UNCONST */
	entry = gfarm_hash_lookup(*hashtabp, &id, sizeof(id));
	if (entry == NULL)
		return (GFARM_ERR_NO_SUCH_OBJECT);

	*entry_ret = entry;
	return (GFARM_ERR_NO_ERROR);
}
示例#9
0
/*
 * if (op != GFARM_INODE_CREATE), (is_dir) may be -1,
 * and that means "don't care".
 */
char *
lookup_node(struct node *parent, const char *name,
	int len, int is_dir, enum gfarm_node_lookup_op op,
	struct node **np)
{
	struct gfarm_hash_entry *entry;
	int created, already_purged;
	struct node *n;

	if ((parent->flags & NODE_FLAG_IS_DIR) == 0)
		return (GFARM_ERR_NOT_A_DIRECTORY);
	if (len == 0) {
		/* We don't handle GFARM_INODE_MARK for this case */
		if (op == GFARM_INODE_REMOVE)
			return (GFARM_ERR_INVALID_ARGUMENT);
		*np = parent;
		return (NULL);
	} else if (len == 1 && name[0] == '.') {
		/* We don't handle GFARM_INODE_MARK for this case */
		if (op == GFARM_INODE_REMOVE)
			return (GFARM_ERR_INVALID_ARGUMENT);
		*np = parent;
		return (NULL);
	} else if (len == 2 && name[0] == '.' && name[1] == '.') {
		/* We don't handle GFARM_INODE_MARK for this case */
		if (op == GFARM_INODE_REMOVE)
			return (GFARM_ERR_DIRECTORY_NOT_EMPTY);
		*np = parent->parent;
		return (NULL);
	}
	if (len > GFS_MAXNAMLEN)
		len = GFS_MAXNAMLEN;
	if (op == GFARM_INODE_MARK) {
		entry = gfarm_hash_lookup(parent->u.d.children, name, len);
		/* We should not honor the PURGED flag here */
		if (entry != NULL) {
			n = gfarm_hash_entry_data(entry);
			if ((n->flags & NODE_FLAG_IS_DIR) == is_dir) {
				/* abandon the PURGED flag at the mark phase */
				n->flags &= ~NODE_FLAG_PURGED;
				n->flags |= NODE_FLAG_MARKED;
				*np = n;
				return (NULL);
			}
			if (opendir_count > 0) {
				if (is_dir) {
					change_file_node_to_dir(n);
				} else {
					recursive_delayed_purge_nodes(n);
					change_dir_node_to_file(n);
				}
				/* abandon the PURGED flag at the mark phase */
				n->flags &= ~NODE_FLAG_PURGED;
				n->flags |= NODE_FLAG_MARKED;
				*np = n;
				return (NULL);
			}
			recursive_free_nodes(n);
			gfarm_hash_purge(parent->u.d.children, name, len);
		}
		/* do create */
	} else if (op != GFARM_INODE_CREATE) {
		entry = gfarm_hash_lookup(parent->u.d.children, name, len);
		if (entry == NULL)
			return (GFARM_ERR_NO_SUCH_OBJECT);
		n = gfarm_hash_entry_data(entry);
		already_purged = (n->flags & NODE_FLAG_PURGED) != 0;
		if (already_purged || op == GFARM_INODE_REMOVE) {
			if (opendir_count > 0) {
				recursive_delayed_purge_nodes(n);
			} else {
				recursive_free_nodes(n);
				gfarm_hash_purge(parent->u.d.children,
				    name, len);
			}
			if (already_purged)
				return (GFARM_ERR_NO_SUCH_OBJECT);
			*np = NULL;
			return (NULL);
		}
		*np = n;
		return (NULL);
	}

	entry = gfarm_hash_enter(parent->u.d.children, name, len,
#if 0
	    is_dir ? DIR_NODE_SIZE : FILE_NODE_SIZE,
#else
	/*
	 * always allocate DIR_NODE_SIZE
	 * to make it possible to change a file to a dir
	 */
	    DIR_NODE_SIZE,
#endif
	    &created);
	if (entry == NULL)
		return (GFARM_ERR_NO_MEMORY);
	n = gfarm_hash_entry_data(entry);
	if (!created) {
		n->flags &= ~NODE_FLAG_PURGED;
		/* assert(op == GFARM_INODE_CREATE); */
		*np = n;
		return (NULL);
	}
	if (is_dir)
		init_dir_node(n, name, len);
	else
		init_file_node(n, name, len);
	n->parent = parent;
	if (op == GFARM_INODE_MARK)
		n->flags |= NODE_FLAG_MARKED;
	*np = n;
	return (NULL);
}
示例#10
0
文件: gfrep.c 项目: ddk50/gfarm_v2
static gfarm_error_t
create_filelist(char *file, struct gfs_stat *st, void *arg)
{
	struct flist *a = arg;
	int i, j, ncopy, src_ncopy = 0, dst_ncopy = 0;
	char **copy;
	gfarm_error_t e;

	if (!GFARM_S_ISREG(st->st_mode)) {
		if (opt_verbose)
			printf("%s: not a regular file, skipped\n", file);
		return (GFARM_ERR_NO_ERROR);
	}
	e = gfs_replica_list_by_name(file, &ncopy, &copy);
	if (e != GFARM_ERR_NO_ERROR)
		return (e);
	/* if there is no available file replica, display error message */
	if (ncopy == 0 && st->st_size > 0) {
		fprintf(stderr, "%s: no available file repilca\n", file);
		e = GFARM_ERR_NO_ERROR;
		goto free_copy;
	}
	for (i = 0; i < ncopy; ++i) {
		if ((a->src_hosthash == NULL || gfarm_hash_lookup(
			a->src_hosthash, copy[i], strlen(copy[i]) + 1)) &&
		    gfarm_host_is_in_domain(copy[i], a->src_domain)) {
			++src_ncopy;
		}
		if ((a->dst_hosthash == NULL || gfarm_hash_lookup(
			a->dst_hosthash, copy[i], strlen(copy[i]) + 1)) &&
		    gfarm_host_is_in_domain(copy[i], a->dst_domain)) {
			++dst_ncopy;
		}
	}
	/*
	 * if there is no replica in a set of source nodes or there
	 * are already specified number of replicas in a set of
	 * destination nodes, do not add.
	 */
	if (src_ncopy == 0 || dst_ncopy == opt_nrep) {
		e = GFARM_ERR_NO_ERROR;
		goto free_copy;
	}

	/* add source nodes to srchash to count the number of source nodes */
	for (i = 0; i < ncopy; ++i) {
		char *s = copy[i];

		if ((a->src_hosthash == NULL || gfarm_hash_lookup(
			a->src_hosthash, s, strlen(s) + 1)) &&
		    gfarm_host_is_in_domain(s, a->src_domain))
			gfarm_hash_enter(a->srchash, s, strlen(s)+1, 0, NULL);
	}

	/* add a file info to slist */
	for (j = 0; j < opt_nrep - dst_ncopy; ++j) {
		e = gfarm_list_add_file_info(file, st->st_size, ncopy, copy,
			0, &a->slist);
		if (e != GFARM_ERR_NO_ERROR)
			goto free_copy;
	}

	/* add a file info to dlist if too many file replicas exist */
	if (dst_ncopy > opt_nrep) {
		e = gfarm_list_add_file_info(file, st->st_size, ncopy, copy,
			dst_ncopy - opt_nrep, &a->dlist);
	}
 free_copy:
	gfarm_strings_free_deeply(ncopy, copy);

	return (e);
}
示例#11
0
static char *
search_idle(int concurrency, int enough_number,
	struct gfarm_hash_table *hosts_state,
	int nihosts, struct string_filter *ihost_filter,
	struct get_next_iterator *ihost_iterator,
	int *nohostsp, char **ohosts)
{
	char *e, *ihost;
	int i, rv, desired_number = *nohostsp;
	struct search_idle_state s;
	struct gfarm_hash_entry *entry;
	struct search_idle_host_state *h;
	struct search_idle_callback_closure *c;
	struct sockaddr addr;
	struct gfs_client_get_load_state *gls;

	if (nihosts == 0)
		return (GFARM_ERR_NO_HOST);
	s.q = gfarm_eventqueue_alloc();
	if (s.q == NULL)
		return (GFARM_ERR_NO_MEMORY);
	s.available_hosts_number =
	    s.idle_hosts_number = s.semi_idle_hosts_number = 0;
	s.available_hosts = malloc(nihosts * sizeof(*s.available_hosts));
	if (s.available_hosts == NULL) {
		gfarm_eventqueue_free(s.q);
		return (GFARM_ERR_NO_MEMORY);
	}
	s.concurrency = 0;
	for (i = 0; i < nihosts; i++) {
		do {
			ihost = (*ihost_iterator->get_next)(ihost_iterator);
		} while (!(*ihost_filter->suitable)(ihost_filter, ihost));
		entry = gfarm_hash_lookup(hosts_state,
		    ihost, strlen(ihost) + 1);
		if (entry == NULL)
			continue; /* never happen, if metadata is consistent */
		h = gfarm_hash_entry_data(entry);
		if ((h->flags & HOST_STATE_FLAG_LOADAVG_TRIED) != 0) {
			if ((h->flags &
			     (default_search_method ==
			      GFARM_SCHEDULE_SEARCH_BY_LOADAVG ?
			      HOST_STATE_FLAG_LOADAVG_AVAIL :
			      HOST_STATE_FLAG_AUTH_SUCCEED)) != 0)
				search_idle_record_host(&s, h, ihost);
		} else {
			e = gfarm_host_info_address_get(ihost,
			    gfarm_spool_server_port, h->host_info,
			    &addr, NULL);
			if (e != NULL)
				continue;

			/* We limit concurrency here */
			rv = 0;
			while (s.concurrency >= concurrency) {
				rv = gfarm_eventqueue_turn(s.q, NULL);
				/* XXX - how to report this error? */
				if (rv != 0 && rv != EAGAIN && rv != EINTR)
					break;
			}
			if (rv != 0 && rv != EAGAIN && rv != EINTR)
				break;

			c = malloc(sizeof(*c));
			if (c == NULL)
				break;
			c->state = &s;
			c->peer_addr = addr;
			c->ah.host_state = h;
			c->ah.hostname = ihost; /* record return value */
			h->flags |= HOST_STATE_FLAG_LOADAVG_TRIED;
			e = gfs_client_get_load_request_multiplexed(s.q,
			    &c->peer_addr,
			    default_search_method ==
			    GFARM_SCHEDULE_SEARCH_BY_LOADAVG ?
			    search_idle_load_callback :
			    search_idle_load_and_connect_callback,
			    c, &gls);
			if (e != NULL) {
				free(c);
			} else {
				c->protocol_state = gls;
				s.concurrency++;
			}
		}
		if (s.idle_hosts_number >= desired_number ||
		    s.semi_idle_hosts_number >= enough_number)
			break;
	}
	/* XXX - how to report this error? */
	rv = gfarm_eventqueue_loop(s.q, NULL);
	gfarm_eventqueue_free(s.q);
	if (s.available_hosts_number == 0) {
		free(s.available_hosts);
		*nohostsp = 0;
		return (GFARM_ERR_NO_HOST);
	}

	/* sort hosts in the order of load average */
	qsort(s.available_hosts, s.available_hosts_number,
	    sizeof(*s.available_hosts), loadavg_compare);

	for (i = 0; i < s.available_hosts_number && i < desired_number; i++)
		ohosts[i] = s.available_hosts[i].hostname; /* return value */
	*nohostsp = i;
	free(s.available_hosts);

	return (NULL);
}