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 */ }
/* 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)); }
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; } } }
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); }
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"; }
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; } }
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; }
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; }
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); }
/* 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); }
/* * 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); }
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); }
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); }
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); }
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); }
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); }
/* * 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(©_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); }
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"; }
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); }
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); }
/* * 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); }
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); }