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 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; }
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); }
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; }
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); }
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; }