Beispiel #1
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);
		
}
Beispiel #2
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";
}
Beispiel #3
0
void
gfp_conn_hash_purge(struct gfarm_hash_table *hashtab,
	struct gfarm_hash_entry *entry)
{
	void *key = gfarm_hash_entry_key(entry);
	int keylen = gfarm_hash_entry_key_length(entry);
	struct gfp_conn_hash_id *idp = key;
	struct gfp_conn_hash_id id = *idp;

	gfarm_hash_purge(hashtab, key, keylen);
	free(id.hostname);
	free(id.username);
}
Beispiel #4
0
void
gfs_stat_cache_clear(void)
{
	struct stat_cache_data *p, *q;
	struct gfarm_hash_entry *entry;

	for (p = stat_cache_list_head.next; p != &stat_cache_list_head; p = q) {
		q = p->next;
		gfs_stat_free(&p->st);

		entry = p->entry;
		gfarm_hash_purge(stat_cache, gfarm_hash_entry_key(entry),
		    gfarm_hash_entry_key_length(entry));
	}
	stat_cache_list_head.next = stat_cache_list_head.prev =
	    &stat_cache_list_head;
	stat_cache_count = 0;
}
Beispiel #5
0
gfarm_error_t
gfp_conn_hash_enter(struct gfarm_hash_table **hashtabp, int hashtabsize,
	size_t entrysize,
	const char *hostname, int port, const char *username,
	struct gfarm_hash_entry **entry_ret, int *created_ret)
{
	gfarm_error_t e;
	struct gfp_conn_hash_id id, *idp;
	struct gfarm_hash_entry *entry;
	int created;

	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_enter(*hashtabp, &id, sizeof(id), entrysize,
	    &created);
	if (entry == NULL)
		return (GFARM_ERR_NO_MEMORY);

	if (created) {
		idp = gfarm_hash_entry_key(entry);
		idp->hostname = strdup(hostname);
		idp->username = strdup(username);
		if (idp->hostname == NULL || idp->username == NULL) {
			if (idp->hostname != NULL)
				free(idp->hostname);
			if (idp->username != NULL)
				free(idp->username);
			idp->hostname = (char *)hostname; /* UNCONST */
			idp->username = (char *)username; /* UNCONST */
			gfarm_hash_purge(*hashtabp, &id, sizeof(id));
			return (GFARM_ERR_NO_MEMORY);
		}
	}

	*entry_ret = entry;
	*created_ret = created;
	return (GFARM_ERR_NO_ERROR);
}
Beispiel #6
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";
}
Beispiel #7
0
static void
gfs_stat_cache_expire_internal(const struct timeval *nowp)
{
	struct stat_cache_data *p, *q;
	struct gfarm_hash_entry *entry;

	for (p = stat_cache_list_head.next; p != &stat_cache_list_head; p = q) {
		/* assumes monotonic time */
		if (gfarm_timeval_cmp(&p->expiration, nowp) > 0)
			break;

		q = p->next;
		gfs_stat_free(&p->st);

		entry = p->entry;
		gfarm_hash_purge(stat_cache, gfarm_hash_entry_key(entry),
		    gfarm_hash_entry_key_length(entry));
		--stat_cache_count;
	}
	stat_cache_list_head.next = p;
	p->prev = &stat_cache_list_head;
}
Beispiel #8
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);
}