예제 #1
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 */
}
예제 #2
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));
}
예제 #3
0
파일: gfs_dir.c 프로젝트: krichter722/gfarm
static void
sweep_nodes(struct node *n)
{
	struct gfarm_hash_iterator i;
	struct gfarm_hash_entry *child;

	/* assert((n->flags & NODE_FLAG_IS_DIR) != 0); */

	/*
	 * We don't have to honor the PURGED flag here,
	 * because the mark phase overrides the flag.
	 */

	for (gfarm_hash_iterator_begin(n->u.d.children, &i);
	    (child = gfarm_hash_iterator_access(&i)) != NULL;
	    gfarm_hash_iterator_next(&i)) {
		struct node *c = gfarm_hash_entry_data(child);

		if ((c->flags & NODE_FLAG_MARKED) == 0) {
			if (opendir_count > 0) {
				recursive_delayed_purge_nodes(c);
			} else {
				recursive_free_nodes(c);
				gfarm_hash_iterator_purge(&i);
			}
		} else {
			if ((c->flags & NODE_FLAG_IS_DIR) != 0)
				sweep_nodes(c);
			else if (opendir_count == 0 && c->u.d.children != NULL)
				recursive_free_children(c);
			c->flags &= ~NODE_FLAG_MARKED;
		}
	}
}
예제 #4
0
static gfarm_error_t
gfs_stat_cache_enter_internal(const char *path, const struct gfs_stat *st,
	const struct timeval *nowp)
{
	gfarm_error_t e;
	struct gfarm_hash_entry *entry;
	struct stat_cache_data *data;
	int created;

	if (stat_cache == NULL) {
		if ((e = gfs_stat_cache_init()) != GFARM_ERR_NO_ERROR)
			return (e);
	}
	gfs_stat_cache_expire_internal(nowp);

	if (stat_cache_count >= gfarm_attr_cache_limit) {
		/* remove the head of the list (i.e. oldest entry) */
		data = stat_cache_list_head.next;
		data->prev->next = data->next;
		data->next->prev = data->prev;
		gfs_stat_free(&data->st);
		entry = data->entry;
		gfarm_hash_purge(stat_cache, gfarm_hash_entry_key(entry),
		    gfarm_hash_entry_key_length(entry));
		--stat_cache_count;
	}

	entry = gfarm_hash_enter(stat_cache, path, strlen(path) + 1,
	    sizeof(*data), &created);
	if (entry == NULL)
		return (GFARM_ERR_NO_MEMORY);

	data = gfarm_hash_entry_data(entry);
	if (created) {
		++stat_cache_count;
		data->entry = entry;
	} else {
		/* remove from the list, to move this to the end of the list */
		data->prev->next = data->next;
		data->next->prev = data->prev;

		gfs_stat_free(&data->st);
	}
	e = gfs_stat_copy(&data->st, st);
	if (e != GFARM_ERR_NO_ERROR) {
		gfarm_hash_purge(stat_cache, gfarm_hash_entry_key(entry),
		    gfarm_hash_entry_key_length(entry));
		--stat_cache_count;
		return (e);
	}
	data->expiration = *nowp;
	gfarm_timeval_add(&data->expiration, &stat_cache_lifespan);
	/* add to the end of the cache list, i.e. assumes monotonic time */
	data->next = &stat_cache_list_head;
	data->prev = stat_cache_list_head.prev;
	stat_cache_list_head.prev->next = data;
	stat_cache_list_head.prev = data;
	return (GFARM_ERR_NO_ERROR);
		
}
예제 #5
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";
}
예제 #6
0
파일: error.c 프로젝트: krichter722/gfarm
void
gfarm_errlist_hashtab_initialize(void)
{
	int i, created;
	struct gfarm_hash_entry *p;

	gfarm_errlist_hashtab = gfarm_hash_table_alloc(ERRLIST_HASHTAB_SIZE,
	    gfarm_hash_default, gfarm_hash_key_equal_default);
	if (gfarm_errlist_hashtab == NULL) {
		fprintf(stderr, "gfarm_errlist_hashtab_initialize(): "
			"no memory\n");
		exit(1);
	}
	for (i = 1; IN_ERRNO(i); i++) {
		if (STRERROR(i) == NULL)
			continue;
		p = gfarm_hash_enter(gfarm_errlist_hashtab,
			STRERROR(i), strlen(STRERROR(i)) + 1,
			sizeof(int), &created);
		if (p == NULL) {
			fprintf(stderr, "gfarm_errlist_hashtab_initialize(): "
				"no memory for errno %d\n", i);
			exit(1);
		}
		if (created)
			*(int *)gfarm_hash_entry_data(p) = i;
	}
}
예제 #7
0
static void
cache_path_info_free()
{
	struct gfarm_hash_iterator iterator;
	struct gfarm_hash_entry *he;
	struct path_info_cache *pic;
#ifdef DEBUG
	char *key;
	char path[PATH_MAX];
#endif
	gfarm_hash_iterator_begin(cache_table, &iterator);
	while (1) {
		he = gfarm_hash_iterator_access(&iterator);
		if (he == NULL)
		        break;
		pic = gfarm_hash_entry_data(he);
#ifdef DEBUG
		key = gfarm_hash_entry_key(he);
		memset(path, 0, PATH_MAX);
		memcpy(path, key, gfarm_hash_entry_key_length(he));
		_debug("! free path_info cache: %d: %s\n", pic->noent, path);
#endif
		if (pic->noent == CACHE_SET)
			gfarm_path_info_free(&pic->info);
		gfarm_hash_iterator_next(&iterator);
	}
	/* ?? gfarm_hash_iterator_purge(&iterator); */

	gfarm_hash_table_free(cache_table);
	prepare_cache_table = 0;
}
예제 #8
0
파일: gfs_dir.c 프로젝트: krichter722/gfarm
static void
recursive_free_children(struct node *n)
{
	struct gfarm_hash_iterator i;
	struct gfarm_hash_entry *child;

	for (gfarm_hash_iterator_begin(n->u.d.children, &i);
	    (child = gfarm_hash_iterator_access(&i)) != NULL;
	    gfarm_hash_iterator_next(&i)) {
		recursive_free_nodes(gfarm_hash_entry_data(child));
	}
	gfarm_hash_table_free(n->u.d.children);
	n->u.d.children = NULL;
}
예제 #9
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);
}
예제 #10
0
파일: conn_cache.c 프로젝트: ddk50/gfarm_v2
/* convert from uncached connection to cached */
static inline gfarm_error_t
gfp_uncached_connection_into_cache(struct gfp_conn_cache *cache,
	struct gfp_cached_connection *connection,
	void  (*func)(struct gfarm_lru_cache *, struct gfarm_lru_entry *))

{
	gfarm_error_t e;
	struct gfarm_hash_entry *entry;
	int created;
	static const char diag[] = "gfp_uncached_connection_enter_cache";

	if (GFP_IS_CACHED_CONNECTION(connection)) {
		gflog_fatal(GFARM_MSG_1000057,
		    "gfp_uncached_connection_enter_cache(%s): "
		    "programming error", cache->type_name);
	}

	gfarm_mutex_lock(&cache->mutex, diag, diag_what);
	e = gfp_conn_hash_id_enter_noalloc(&cache->hashtab, cache->table_size,
	    sizeof(connection), &connection->id, &entry, &created);
	if (e != GFARM_ERR_NO_ERROR) {
		gfarm_mutex_unlock(&cache->mutex, diag, diag_what);

		gflog_debug(GFARM_MSG_1001088,
			"insertion to connection hash (%s)(%d) failed: %s",
			gfp_cached_connection_hostname(connection),
			gfp_cached_connection_port(connection),
			gfarm_error_string(e));
		return (e);
	}
	if (!created) {
		gfarm_mutex_unlock(&cache->mutex, diag, diag_what);

		gflog_debug(GFARM_MSG_1001089,
			"insertion to connection hash (%s)(%d) failed: %s",
			gfp_cached_connection_hostname(connection),
			gfp_cached_connection_port(connection),
			gfarm_error_string(GFARM_ERR_ALREADY_EXISTS));
		return (GFARM_ERR_ALREADY_EXISTS);
	}

	func(&cache->lru_list, &connection->lru_entry);

	*(struct gfp_cached_connection **)gfarm_hash_entry_data(entry)
	    = connection;
	connection->hash_entry = entry;

	gfarm_mutex_unlock(&cache->mutex, diag, diag_what);
	return (GFARM_ERR_NO_ERROR);
}
예제 #11
0
파일: conn_cache.c 프로젝트: ddk50/gfarm_v2
/*
 * this function frees all cached connections, including in-use ones.
 *
 * potential problems:
 * - connections which are currently in-use are freed too.
 * - connections which are uncached are NOT freed.
 *   i.e. the followings are all NOT freed:
 *	- connections which have never cached,
 *      - connections which had been once cached but currently uncached
 *	  (since their network connections were dead)
 */
void
gfp_cached_connection_terminate(struct gfp_conn_cache *cache)
{
	struct gfarm_hash_iterator it;
	struct gfarm_hash_entry *entry;
	struct gfp_cached_connection *connection;
	static const char diag[] = "gfp_cached_connection_terminate";

	gfarm_mutex_lock(&cache->mutex, diag, diag_what);
	if (cache->hashtab == NULL) {
		gfarm_mutex_unlock(&cache->mutex, diag, diag_what);
		return;
	}
	gfarm_mutex_unlock(&cache->mutex, diag, diag_what);

	/*
	 * clear all free connections.
	 * to makes cache->lru_list.free_cached_entries 0.
	 */
	gfp_cached_connection_gc_all(cache);

	gfarm_mutex_lock(&cache->mutex, diag, diag_what);

	/* clear all in-use connections too.  XXX really necessary?  */
	for (gfarm_hash_iterator_begin(cache->hashtab, &it);
	     !gfarm_hash_iterator_is_end(&it);) {
		entry = gfarm_hash_iterator_access(&it);
		connection = *(struct gfp_cached_connection **)
		    gfarm_hash_entry_data(entry);

		gfarm_lru_cache_purge_entry(&connection->lru_entry);

		gfp_conn_hash_iterator_purge(&it);

		gfarm_mutex_unlock(&cache->mutex, diag, diag_what);
		(*cache->dispose_connection)(connection->connection_data);
		gfarm_mutex_lock(&cache->mutex, diag, diag_what);

		/* restart from the top, because maybe changed by others */
		gfarm_hash_iterator_begin(cache->hashtab, &it);
	}

	/* free hash table */
	gfarm_hash_table_free(cache->hashtab);
	cache->hashtab = NULL;

	gfarm_mutex_unlock(&cache->mutex, diag, diag_what);
}
예제 #12
0
static char *
cache_path_info_put(const char *pathname, struct gfarm_path_info *info)
{
	struct gfarm_hash_entry *he;
	int pathlen;
	int created;
	struct path_info_cache *pic;

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

	if (current_cache_num >= hash_size)
		cache_path_info_free();  /* clear all cache */

	pathlen = strlen(pathname);
	
	/* set cache */
	he = gfarm_hash_enter(cache_table, pathname, pathlen,
			      sizeof(struct path_info_cache), &created);
	if (he == NULL) {
		_debug("! cache_path_info_put: no memory\n");
		return (GFARM_ERR_NO_MEMORY);
	}
	pic = gfarm_hash_entry_data(he);
	_debug("! put path_info cache: %s\n", pathname);
	if (created)  /* new cache */
		current_cache_num++;
	else if (pic->noent == CACHE_SET)  /* have path_info */
		gfarm_path_info_free(&pic->info);

	if (info == NULL) {  /* set NOENT */
		pic->noent = CACHE_NOENT;
		_debug("! -> set NOENT: %s\n", pathname);
	}
	else {
#ifdef DEBUG
		if (pic->noent == CACHE_NOENT) {
			_debug("! -> update cache from NOENT: %s\n", pathname);
		}
#endif
		(void)gfarm_path_info_dup(info, &pic->info);
		pic->noent = CACHE_SET;
	}
	/* current time */
	gettimeofday(&pic->time, NULL);

	return (NULL);
}
예제 #13
0
static char *
hosts_for_program(char *program,
	int *n_all_hostsp, struct gfarm_host_info **all_hostsp,
	struct gfarm_hash_table **hosts_statep, int *n_runnable_hostsp)
{
	char *e;
	int n_all_hosts, n_runnable_hosts;
	struct gfarm_host_info *all_hosts;
	struct gfarm_hash_table *hosts_state;
	struct gfarm_hash_table *arch_set;
	struct gfarm_hash_iterator it;
	struct gfarm_hash_entry *entry;
	struct search_idle_host_state *h;

	e = alloc_hosts_state(&n_all_hosts, &all_hosts, &hosts_state);
	if (e == NULL) {
		e = program_arch_set(program, &arch_set);
		if (e == NULL) {
			n_runnable_hosts = 0;
			for (gfarm_hash_iterator_begin(hosts_state, &it);
			    !gfarm_hash_iterator_is_end(&it);
			    gfarm_hash_iterator_next(&it)) {
				entry = gfarm_hash_iterator_access(&it);
				h = gfarm_hash_entry_data(entry);
				if (IS_IN_ARCH_SET(h->host_info->architecture,
				    arch_set)) {
					h->flags |= HOST_STATE_FLAG_RUNNABLE;
					++n_runnable_hosts;
				}
			}
			free_arch_set(arch_set);
			if (n_runnable_hosts > 0) {
				*n_all_hostsp = n_all_hosts;
				*all_hostsp = all_hosts;
				*hosts_statep = hosts_state;
				*n_runnable_hostsp = n_runnable_hosts;
				return (NULL);
			}
			e = "there is no host which can run the program";
		}
		free_hosts_state(n_all_hosts, all_hosts, hosts_state);
	}
	return (e);
}
예제 #14
0
static char *
alloc_hosts_state(int *n_all_hostsp, struct gfarm_host_info **all_hostsp,
	struct gfarm_hash_table **hosts_statep)
{
	char *e;
	int i, created, n_all_hosts;
	struct gfarm_host_info *all_hosts;
	struct gfarm_hash_table *hosts_state;
	struct gfarm_hash_entry *entry;
	struct search_idle_host_state *h;

	e = gfarm_host_info_get_all(&n_all_hosts, &all_hosts);
	if (e != NULL)
		return (e);
	if (n_all_hosts == 0) {
		gfarm_host_info_free_all(n_all_hosts, all_hosts);
		return (GFARM_ERR_NO_HOST);
	}
	hosts_state = gfarm_hash_table_alloc(HOSTS_HASHTAB_SIZE,
	    gfarm_hash_casefold, gfarm_hash_key_equal_casefold);
	if (hosts_state == NULL) {
		gfarm_host_info_free_all(n_all_hosts, all_hosts);
		return (GFARM_ERR_NO_MEMORY);
	}
	for (i = 0; i < n_all_hosts; i++) {
		entry = gfarm_hash_enter(hosts_state,
		    all_hosts[i].hostname, strlen(all_hosts[i].hostname) + 1,
		    sizeof(struct search_idle_host_state), &created);
		if (entry == NULL) {
			free_hosts_state(n_all_hosts, all_hosts, hosts_state);
			return (GFARM_ERR_NO_MEMORY);
		}
		/* `created' must be always true. */
		h = gfarm_hash_entry_data(entry);
		h->host_info = &all_hosts[i];
		h->flags = 0;
	}
	*n_all_hostsp = n_all_hosts;
	*all_hostsp = all_hosts;
	*hosts_statep = hosts_state;
	return (NULL);			
}
예제 #15
0
파일: gfs_dir.c 프로젝트: krichter722/gfarm
static void
for_each_node(struct node *n, void (*f)(void *, struct node *), void *cookie)
{
#if 0
	if ((n->flags & NODE_FLAG_IS_DIR) != 0)
#else
	if (n->u.d.children != NULL)
#endif
	{
		struct gfarm_hash_iterator i;
		struct gfarm_hash_entry *child;

		for (gfarm_hash_iterator_begin(n->u.d.children, &i);
		    (child = gfarm_hash_iterator_access(&i)) != NULL;
		    gfarm_hash_iterator_next(&i)) {
			for_each_node(gfarm_hash_entry_data(child), f, cookie);
		}
	}
	(*f)(cookie, n);
}
예제 #16
0
파일: gfs_dir.c 프로젝트: krichter722/gfarm
char *
gfs_readdir(GFS_Dir dir, struct gfs_dirent **entry)
{
	struct gfarm_hash_entry *he;
	struct node *n;

	if (dir->index == 0) {
		n = dir->dir;
		dir->buffer.d_namlen = 1;
		dir->buffer.d_name[0] = '.';
		dir->index++;
	} else if (dir->index == 1) {
		n = dir->dir->parent;
		dir->buffer.d_namlen = 2;
		dir->buffer.d_name[0] = dir->buffer.d_name[1] = '.';
		dir->index++;
	} else {
		for (;;) {
			he = gfarm_hash_iterator_access(&dir->iterator);
			if (he == NULL) {
				*entry = NULL;
				return (NULL);
			}
			n = gfarm_hash_entry_data(he);
			gfarm_hash_iterator_next(&dir->iterator);
			dir->index++;
			if ((n->flags & NODE_FLAG_PURGED) == 0)
				break;
		}
		dir->buffer.d_namlen = gfarm_hash_entry_key_length(he);
		memcpy(dir->buffer.d_name, gfarm_hash_entry_key(he),
		    dir->buffer.d_namlen);
	}
	dir->buffer.d_name[dir->buffer.d_namlen] = '\0';
	dir->buffer.d_type = (n->flags & NODE_FLAG_IS_DIR) ?
	    GFS_DT_DIR : GFS_DT_REG;
	dir->buffer.d_reclen = 0x100; /* XXX */
	dir->buffer.d_fileno = INUMBER(n);
	*entry = &dir->buffer;
	return (NULL);
}
예제 #17
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);
}
예제 #18
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";
}
예제 #19
0
gfarm_error_t
gfs_stat_cache_purge(const char *path)
{
	struct gfarm_hash_iterator it;
	struct gfarm_hash_entry *entry;
	struct stat_cache_data *data;

	if (stat_cache == NULL) /* there is nothing to purge */
		return (GFARM_ERR_NO_ERROR);

	gfs_stat_cache_expire();
	if (!gfarm_hash_iterator_lookup(stat_cache, path, strlen(path)+1, &it))
		return (GFARM_ERR_NO_SUCH_FILE_OR_DIRECTORY);
	entry = gfarm_hash_iterator_access(&it);
	assert(entry != NULL);
	data = gfarm_hash_entry_data(entry);
	data->prev->next = data->next;
	data->next->prev = data->prev;
	gfs_stat_free(&data->st);
	gfarm_hash_iterator_purge(&it);
	--stat_cache_count;
	return (GFARM_ERR_NO_ERROR);
}
예제 #20
0
파일: conn_cache.c 프로젝트: ddk50/gfarm_v2
gfarm_error_t
gfp_cached_connection_acquire(struct gfp_conn_cache *cache,
	const char *canonical_hostname, int port, const char *user,
	struct gfp_cached_connection **connectionp, int *createdp)
{
	gfarm_error_t e;
	struct gfarm_hash_entry *entry;
	struct gfp_cached_connection *connection;
	struct gfp_conn_hash_id *idp, *kidp;
	static const char diag[] = "gfp_cached_connection_acquire";

	gfarm_mutex_lock(&cache->mutex, diag, diag_what);
	e = gfp_conn_hash_enter_noalloc(&cache->hashtab, cache->table_size,
	    sizeof(connection), canonical_hostname, port, user,
	    &entry, createdp);
	if (e != GFARM_ERR_NO_ERROR) {
		gfarm_mutex_unlock(&cache->mutex, diag, diag_what);
		gflog_debug(GFARM_MSG_1001090,
			"insertion to connection hash (%s)(%d) failed: %s",
			canonical_hostname, port,
			gfarm_error_string(e));
		return (e);
	}
	if (!*createdp) {
		connection = *(struct gfp_cached_connection **)
		    gfarm_hash_entry_data(entry);
		gfarm_lru_cache_addref_entry(&cache->lru_list,
		    &connection->lru_entry);
	} else {
		GFARM_MALLOC(connection);
		if (connection == NULL) {
			gfp_conn_hash_purge(cache->hashtab, entry);
			gfarm_mutex_unlock(&cache->mutex, diag, diag_what);
			gflog_debug(GFARM_MSG_1001091,
				"allocation of 'connection' failed: %s",
				gfarm_error_string(GFARM_ERR_NO_MEMORY));
			return (GFARM_ERR_NO_MEMORY);
		}

		idp = &connection->id;
		idp->hostname = strdup(canonical_hostname);
		idp->port = port;
		idp->username = strdup(user);
		if (idp->hostname == NULL || idp->username == NULL) {
			e = GFARM_ERR_NO_MEMORY;
			gflog_debug(GFARM_MSG_1002566,
			    "gfp_cached_connection_acquire (%s)(%d)"
			    " failed: %s",
			    canonical_hostname, port,
			    gfarm_error_string(e));
			free(idp->hostname);
			free(idp->username);
			free(connection);
			gfp_conn_hash_purge(cache->hashtab, entry);
			gfarm_mutex_unlock(&cache->mutex, diag, diag_what);
			return (e);
		}
		kidp = (struct gfp_conn_hash_id *)gfarm_hash_entry_key(entry);
		kidp->hostname = idp->hostname;
		kidp->username = idp->username;

		gfarm_lru_cache_add_entry(&cache->lru_list,
		    &connection->lru_entry);

		*(struct gfp_cached_connection **)gfarm_hash_entry_data(entry)
		    = connection;
		connection->hash_entry = entry;
		connection->connection_data = NULL;
		connection->dispose_connection_data = NULL;
		GFSP_CONN_INIT(connection)
	}
	gfarm_mutex_unlock(&cache->mutex, diag, diag_what);
	*connectionp = connection;
	return (GFARM_ERR_NO_ERROR);
}
예제 #21
0
파일: gfs_dir.c 프로젝트: krichter722/gfarm
/*
 * 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);
}
예제 #22
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);
}