diff options
Diffstat (limited to 'xlators/performance/stat-prefetch/src')
-rw-r--r-- | xlators/performance/stat-prefetch/src/Makefile.am | 11 | ||||
-rw-r--r-- | xlators/performance/stat-prefetch/src/stat-prefetch.c | 508 | ||||
-rw-r--r-- | xlators/performance/stat-prefetch/src/stat-prefetch.h | 32 |
3 files changed, 551 insertions, 0 deletions
diff --git a/xlators/performance/stat-prefetch/src/Makefile.am b/xlators/performance/stat-prefetch/src/Makefile.am new file mode 100644 index 00000000000..e52f2df48fd --- /dev/null +++ b/xlators/performance/stat-prefetch/src/Makefile.am @@ -0,0 +1,11 @@ +xlator_PROGRAMS = stat-prefetch.so +xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/performance + +stat_prefetch_so_SOURCES = stat-prefetch.c +noinst_HEADERS = stat-prefetch.h + +AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -Wall \ + -I$(top_srcdir)/libglusterfs/src -shared -nostartfiles + +CLEANFILES = + diff --git a/xlators/performance/stat-prefetch/src/stat-prefetch.c b/xlators/performance/stat-prefetch/src/stat-prefetch.c new file mode 100644 index 00000000000..f2a78f676f9 --- /dev/null +++ b/xlators/performance/stat-prefetch/src/stat-prefetch.c @@ -0,0 +1,508 @@ +/* + Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "glusterfs.h" +#include "stat-prefetch.h" +#include "dict.h" +#include "xlator.h" +#include <sys/time.h> + +struct sp_cache { + struct sp_cache *next; + struct sp_cache *prev; + pid_t pid; + long long tv_time; + char *dirname; + dir_entry_t entries; + int32_t count; + pthread_mutex_t lock; +}; + +static void +stat_prefetch_cache_flush (struct sp_cache *cache, int32_t force) +{ + struct sp_cache *trav; + struct timeval tv; + long long tv_time; + + gettimeofday (&tv, NULL); + tv_time = (tv.tv_usec + (tv.tv_sec * 1000000)); + + pthread_mutex_lock (&cache->lock); + + trav = cache->next; + while (trav != cache) { + struct sp_cache *next = trav->next; + { + if (tv_time > trav->tv_time || force) { + gf_log ("stat-prefetch", + GF_LOG_DEBUG, + "flush on: %s", + trav->dirname); + dir_entry_t *entries; + + trav->prev->next = trav->next; + trav->next->prev = trav->prev; + + entries = trav->entries.next; + + while (entries) { + dir_entry_t *nextentry = entries->next; + { + free (entries->name); + free (entries); + } + entries = nextentry; + } + free (trav->dirname); + free (trav); + } + } + trav = next; + } + + pthread_mutex_unlock (&cache->lock); +} + +static int32_t +stat_prefetch_cache_fill (struct sp_cache *cache, + pid_t pid, + char *dirname, + dir_entry_t *entries) +{ + struct sp_cache *trav; + struct timeval tv; + + pthread_mutex_unlock (&cache->lock); + trav = cache->next; + while (trav != cache) { + // if (trav->pid == pid && !strcmp (trav->dirname, dirname)) { + if (!strcmp (trav->dirname, dirname)) { + break; + } + trav = trav->next; + } + + if (trav == cache) { + trav = CALLOC (1, sizeof (*trav)); + ERR_ABORT (trav); + trav->pid = pid; + trav->dirname = dirname; + + trav->prev = cache->prev; + trav->next = cache; + trav->next->prev = trav; + trav->prev->next = trav; + } else { + free (dirname); + } + + while (trav->entries.next) { + dir_entry_t *tmp = trav->entries.next; + + trav->entries.next = trav->entries.next->next; + free (tmp->name); + free (tmp); + } + trav->entries.next = entries->next; + entries->next = NULL; + + gettimeofday (&tv, NULL); + trav->tv_time = (tv.tv_usec + (tv.tv_sec * 1000000)) + cache->tv_time; + + pthread_mutex_unlock (&cache->lock); + return 0; +} + +static int32_t +stat_prefetch_cache_lookup (struct sp_cache *cache, + pid_t pid, + const char *path, + struct stat *buf) +{ + struct sp_cache *trav; + char *dirname = strdup (path); + char *filename = strrchr (dirname, '/'); + dir_entry_t *entries; + dir_entry_t *prev = NULL; + + *filename = '\0'; + filename ++; + + pthread_mutex_lock (&cache->lock); + trav = cache->next; + while (trav != cache) { + // if ((trav->pid == pid) && !strcmp (dirname, trav->dirname)) + if (!strcmp (dirname, trav->dirname)) + break; + trav = trav->next; + } + if (trav == cache) { + free (dirname); + pthread_mutex_unlock (&cache->lock); + return -1; + } + + entries = trav->entries.next; + prev = &trav->entries; + while (entries) { + if (!strcmp (entries->name, filename)) + break; + prev = entries; + entries = entries->next; + } + if (!entries) { + free (dirname); + pthread_mutex_unlock (&cache->lock); + return -1; + } + + *buf = entries->buf; + prev->next = entries->next; + free (entries->name); + free (entries); + free (dirname); + + pthread_mutex_unlock (&cache->lock); + + return 0; +} + + +int32_t +stat_prefetch_readdir_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + dir_entry_t *entries, + int32_t count) +{ + char *path = frame->local; + pid_t pid = frame->root->pid; + frame->local = NULL; + + STACK_UNWIND (frame, op_ret, op_errno, entries, count); + + if (op_ret == 0) + stat_prefetch_cache_fill (this->private, + pid, + path, + entries); + else + free (path); + + return 0; +} + +int32_t +stat_prefetch_readdir (call_frame_t *frame, + xlator_t *this, + const char *path) +{ + stat_prefetch_cache_flush (this->private, 0); + + frame->local = strdup (path); + STACK_WIND (frame, + stat_prefetch_readdir_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->readdir, + path); + return 0; +} + + +int32_t +stat_prefetch_getattr_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct stat *buf) +{ + STACK_UNWIND (frame, op_ret, op_errno, buf); + return 0; +} + +int32_t +stat_prefetch_getattr (call_frame_t *frame, + struct xlator *this, + const char *path) +{ + struct stat buf; + pid_t pid = frame->root->pid; + stat_prefetch_cache_flush (this->private, 0); + + if (stat_prefetch_cache_lookup (this->private, + pid, + path, + &buf) == 0) { + STACK_UNWIND (frame, 0, 0, &buf); + return 0; + } + + STACK_WIND (frame, + stat_prefetch_getattr_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->getattr, + path); + + return 0; +} + + +int32_t +stat_prefetch_unlink_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno) +{ + STACK_UNWIND (frame, op_ret, op_errno); + return 0; +} + +int32_t +stat_prefetch_unlink (call_frame_t *frame, + struct xlator *this, + const char *path) +{ + stat_prefetch_cache_flush (this->private, 1); + + STACK_WIND (frame, + stat_prefetch_unlink_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->unlink, + path); + + return 0; +} + + +int32_t +stat_prefetch_chmod_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct stat *buf) +{ + STACK_UNWIND (frame, op_ret, op_errno, buf); + return 0; +} + +int32_t +stat_prefetch_chmod (call_frame_t *frame, + struct xlator *this, + const char *path, + mode_t mode) +{ + stat_prefetch_cache_flush (this->private, 1); + + STACK_WIND (frame, + stat_prefetch_chmod_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->chmod, + path, + mode); + + return 0; +} + + +int32_t +stat_prefetch_chown_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct stat *buf) +{ + STACK_UNWIND (frame, op_ret, op_errno, buf); + return 0; +} + +int32_t +stat_prefetch_chown (call_frame_t *frame, + struct xlator *this, + const char *path, + uid_t uid, + gid_t gid) +{ + stat_prefetch_cache_flush (this->private, 1); + + STACK_WIND (frame, + stat_prefetch_chown_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->chown, + path, + uid, + gid); + + return 0; +} + + +int32_t +stat_prefetch_utimes_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct stat *buf) +{ + STACK_UNWIND (frame, op_ret, op_errno, buf); + return 0; +} + +int32_t +stat_prefetch_utimes (call_frame_t *frame, + struct xlator *this, + const char *path, + struct timespec *tvp) +{ + stat_prefetch_cache_flush (this->private, 1); + + STACK_WIND (frame, + stat_prefetch_utimes_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->utimes, + path, + tvp); + + return 0; +} + + +int32_t +stat_prefetch_truncate_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct stat *buf) +{ + STACK_UNWIND (frame, op_ret, op_errno, buf); + return 0; +} + +int32_t +stat_prefetch_truncate (call_frame_t *frame, + struct xlator *this, + const char *path, + off_t offset) +{ + stat_prefetch_cache_flush (this->private, 1); + + STACK_WIND (frame, + stat_prefetch_truncate_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->truncate, + path, + offset); + + return 0; +} + + +int32_t +stat_prefetch_rename_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno) +{ + STACK_UNWIND (frame, op_ret, op_errno); + return 0; +} + +int32_t +stat_prefetch_rename (call_frame_t *frame, + struct xlator *this, + const char *oldpath, + const char *newpath) +{ + stat_prefetch_cache_flush (this->private, 1); + + STACK_WIND (frame, + stat_prefetch_rename_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->rename, + oldpath, + newpath); + + return 0; +} + +int32_t +init (struct xlator *this) +{ + struct sp_cache *cache; + dict_t *options = this->options; + + if (!this->children || this->children->next) { + gf_log ("stat-prefetch", + GF_LOG_ERROR, + "FATAL: translator %s does not have exactly one child node", + this->name); + return -1; + } + + cache = (void *) CALLOC (1, sizeof (*cache)); + ERR_ABORT (cache); + cache->next = cache->prev = cache; + + cache->tv_time = 1 * 1000000; + + if (dict_get (options, "cache-seconds")) { + cache->tv_time = (data_to_int64 (dict_get (options, "cache-seconds")) * + 1000000); + } + + pthread_mutex_init (&cache->lock, NULL); + + this->private = cache; + return 0; +} + +void +fini (struct xlator *this) +{ + return; +} + + +struct xlator_fops fops = { + .getattr = stat_prefetch_getattr, + .readdir = stat_prefetch_readdir, + .unlink = stat_prefetch_unlink, + .chmod = stat_prefetch_chmod, + .chown = stat_prefetch_chown, + .rename = stat_prefetch_rename, + .utimes = stat_prefetch_utimes, + .truncate = stat_prefetch_truncate, +}; + +struct xlator_mops mops = { +}; diff --git a/xlators/performance/stat-prefetch/src/stat-prefetch.h b/xlators/performance/stat-prefetch/src/stat-prefetch.h new file mode 100644 index 00000000000..7d9645a2a81 --- /dev/null +++ b/xlators/performance/stat-prefetch/src/stat-prefetch.h @@ -0,0 +1,32 @@ +/* + Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _STAT_PREFETCH_H_ +#define _STAT_PREFETCH_H_ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <sys/time.h> +#include "xlator.h" + +#endif /* _STAT_PREFETCH_H_ */ |