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_ */  | 
