Diff for /embedaddon/lighttpd/src/stat_cache.c between versions 1.1.1.1 and 1.1.1.3

version 1.1.1.1, 2013/10/14 10:32:48 version 1.1.1.3, 2016/11/02 10:35:00
Line 1 Line 1
   #include "first.h"
   
 #include "log.h"  #include "log.h"
 #include "stat_cache.h"  #include "stat_cache.h"
 #include "fdevent.h"  #include "fdevent.h"
Line 18 Line 20
 # include <attr/attributes.h>  # include <attr/attributes.h>
 #endif  #endif
   
   #ifdef HAVE_SYS_EXTATTR_H
   # include <sys/extattr.h>
   #endif
   
 #ifdef HAVE_FAM_H  #ifdef HAVE_FAM_H
 # include <fam.h>  # include <fam.h>
 #endif  #endif
Line 69 Line 75
 #ifdef HAVE_FAM_H  #ifdef HAVE_FAM_H
 typedef struct {  typedef struct {
         FAMRequest *req;          FAMRequest *req;
         FAMConnection *fc;  
   
         buffer *name;          buffer *name;
   
Line 102  static fake_keys ctrl; Line 107  static fake_keys ctrl;
 #endif  #endif
   
 stat_cache *stat_cache_init(void) {  stat_cache *stat_cache_init(void) {
        stat_cache *fc = NULL;        stat_cache *sc = NULL;
   
        fc = calloc(1, sizeof(*fc));        sc = calloc(1, sizeof(*sc));
         force_assert(NULL != sc);
   
        fc->dir_name = buffer_init();        sc->dir_name = buffer_init();
        fc->hash_key = buffer_init();        sc->hash_key = buffer_init();
 
 #ifdef HAVE_FAM_H  #ifdef HAVE_FAM_H
        fc->fam = calloc(1, sizeof(*fc->fam));        sc->fam_fcce_ndx = -1;
 #endif  #endif
   
 #ifdef DEBUG_STAT_CACHE  #ifdef DEBUG_STAT_CACHE
         ctrl.size = 0;          ctrl.size = 0;
 #endif  #endif
   
        return fc;        return sc;
 }  }
   
 static stat_cache_entry * stat_cache_entry_init(void) {  static stat_cache_entry * stat_cache_entry_init(void) {
         stat_cache_entry *sce = NULL;          stat_cache_entry *sce = NULL;
   
         sce = calloc(1, sizeof(*sce));          sce = calloc(1, sizeof(*sce));
           force_assert(NULL != sce);
   
         sce->name = buffer_init();          sce->name = buffer_init();
         sce->etag = buffer_init();          sce->etag = buffer_init();
Line 147  static fam_dir_entry * fam_dir_entry_init(void) { Line 155  static fam_dir_entry * fam_dir_entry_init(void) {
         fam_dir_entry *fam_dir = NULL;          fam_dir_entry *fam_dir = NULL;
   
         fam_dir = calloc(1, sizeof(*fam_dir));          fam_dir = calloc(1, sizeof(*fam_dir));
           force_assert(NULL != fam_dir);
   
         fam_dir->name = buffer_init();          fam_dir->name = buffer_init();
   
         return fam_dir;          return fam_dir;
 }  }
   
static void fam_dir_entry_free(void *data) {static void fam_dir_entry_free(FAMConnection *fc, void *data) {
         fam_dir_entry *fam_dir = data;          fam_dir_entry *fam_dir = data;
   
         if (!fam_dir) return;          if (!fam_dir) return;
   
        FAMCancelMonitor(fam_dir->fc, fam_dir->req);        FAMCancelMonitor(fc, fam_dir->req);
   
         buffer_free(fam_dir->name);          buffer_free(fam_dir->name);
         free(fam_dir->req);          free(fam_dir->req);
Line 177  void stat_cache_free(stat_cache *sc) { Line 186  void stat_cache_free(stat_cache *sc) {
                 stat_cache_entry_free(node->data);                  stat_cache_entry_free(node->data);
                 sc->files = splaytree_delete(sc->files, node->key);                  sc->files = splaytree_delete(sc->files, node->key);
   
                assert(osize - 1 == splaytree_size(sc->files));                force_assert(osize - 1 == splaytree_size(sc->files));
         }          }
   
         buffer_free(sc->dir_name);          buffer_free(sc->dir_name);
Line 190  void stat_cache_free(stat_cache *sc) { Line 199  void stat_cache_free(stat_cache *sc) {
   
                 osize = sc->dirs->size;                  osize = sc->dirs->size;
   
                fam_dir_entry_free(node->data);                fam_dir_entry_free(&sc->fam, node->data);
                 sc->dirs = splaytree_delete(sc->dirs, node->key);                  sc->dirs = splaytree_delete(sc->dirs, node->key);
   
                 if (osize == 1) {                  if (osize == 1) {
                        assert(NULL == sc->dirs);                        force_assert(NULL == sc->dirs);
                 } else {                  } else {
                        assert(osize == (sc->dirs->size + 1));                        force_assert(osize == (sc->dirs->size + 1));
                 }                  }
         }          }
   
        if (sc->fam) {        if (-1 != sc->fam_fcce_ndx) {
                FAMClose(sc->fam);                /* fd events already gone */
                free(sc->fam);                sc->fam_fcce_ndx = -1;
 
                 FAMClose(&sc->fam);
         }          }
 #endif  #endif
         free(sc);          free(sc);
 }  }
   
#ifdef HAVE_XATTR#if defined(HAVE_XATTR)
static int stat_cache_attr_get(buffer *buf, char *name) {static int stat_cache_attr_get(buffer *buf, char *name, char *xattrname) {
         int attrlen;          int attrlen;
         int ret;          int ret;
   
        attrlen = 1024;        buffer_string_prepare_copy(buf, 1023);
        buffer_prepare_copy(buf, attrlen);        attrlen = buf->size - 1;
        attrlen--;        if(0 == (ret = attr_get(name, xattrname, buf->ptr, &attrlen, 0))) {
        if(0 == (ret = attr_get(name, "Content-Type", buf->ptr, &attrlen, 0))) {                buffer_commit(buf, attrlen);
         }
         return ret;
 }
 #elif defined(HAVE_EXTATTR)
 static int stat_cache_attr_get(buffer *buf, char *name, char *xattrname) {
         ssize_t attrlen;
 
         buffer_string_prepare_copy(buf, 1023);
 
         if (-1 != (attrlen = extattr_get_file(name, EXTATTR_NAMESPACE_USER, xattrname, buf->ptr, buf->size - 1))) {
                 buf->used = attrlen + 1;                  buf->used = attrlen + 1;
                 buf->ptr[attrlen] = '\0';                  buf->ptr[attrlen] = '\0';
                   return 0;
         }          }
        return ret;        return -1;
 }  }
 #endif  #endif
   
Line 232  static uint32_t hashme(buffer *str) { Line 254  static uint32_t hashme(buffer *str) {
                 hash = ((hash << 5) + hash) + *s;                  hash = ((hash << 5) + hash) + *s;
         }          }
   
        hash &= ~(1 << 31); /* strip the highest bit */        hash &= ~(((uint32_t)1) << 31); /* strip the highest bit */
   
         return hash;          return hash;
 }  }
Line 246  handler_t stat_cache_handle_fdevent(server *srv, void  Line 268  handler_t stat_cache_handle_fdevent(server *srv, void 
         UNUSED(_fce);          UNUSED(_fce);
         /* */          /* */
   
        if ((revent & FDEVENT_IN) &&        if (revent & FDEVENT_IN) {
            sc->fam) {                events = FAMPending(&sc->fam);
   
                 events = FAMPending(sc->fam);  
   
                 for (i = 0; i < events; i++) {                  for (i = 0; i < events; i++) {
                         FAMEvent fe;                          FAMEvent fe;
                         fam_dir_entry *fam_dir;                          fam_dir_entry *fam_dir;
                         splay_tree *node;                          splay_tree *node;
                         int ndx, j;                          int ndx, j;
   
                        FAMNextEvent(sc->fam, &fe);                        FAMNextEvent(&sc->fam, &fe);
   
                         /* handle event */                          /* handle event */
   
Line 277  handler_t stat_cache_handle_fdevent(server *srv, void  Line 297  handler_t stat_cache_handle_fdevent(server *srv, void 
   
                                 for (j = 0; j < 2; j++) {                                  for (j = 0; j < 2; j++) {
                                         buffer_copy_string(sc->hash_key, fe.filename);                                          buffer_copy_string(sc->hash_key, fe.filename);
                                        buffer_append_long(sc->hash_key, j);                                        buffer_append_int(sc->hash_key, j);
   
                                         ndx = hashme(sc->hash_key);                                          ndx = hashme(sc->hash_key);
   
Line 287  handler_t stat_cache_handle_fdevent(server *srv, void  Line 307  handler_t stat_cache_handle_fdevent(server *srv, void 
                                         if (node && (node->key == ndx)) {                                          if (node && (node->key == ndx)) {
                                                 int osize = splaytree_size(sc->dirs);                                                  int osize = splaytree_size(sc->dirs);
   
                                                fam_dir_entry_free(node->data);                                                fam_dir_entry_free(&sc->fam, node->data);
                                                 sc->dirs = splaytree_delete(sc->dirs, ndx);                                                  sc->dirs = splaytree_delete(sc->dirs, ndx);
   
                                                assert(osize - 1 == splaytree_size(sc->dirs));                                                force_assert(osize - 1 == splaytree_size(sc->dirs));
                                         }                                          }
                                 }                                  }
                                 break;                                  break;
Line 302  handler_t stat_cache_handle_fdevent(server *srv, void  Line 322  handler_t stat_cache_handle_fdevent(server *srv, void 
   
         if (revent & FDEVENT_HUP) {          if (revent & FDEVENT_HUP) {
                 /* fam closed the connection */                  /* fam closed the connection */
                srv->stat_cache->fam_fcce_ndx = -1;                fdevent_event_del(srv->ev, &(sc->fam_fcce_ndx), FAMCONNECTION_GETFD(&sc->fam));
                 fdevent_unregister(srv->ev, FAMCONNECTION_GETFD(&sc->fam));
   
                fdevent_event_del(srv->ev, &(sc->fam_fcce_ndx), FAMCONNECTION_GETFD(sc->fam));                FAMClose(&sc->fam);
                fdevent_unregister(srv->ev, FAMCONNECTION_GETFD(sc->fam)); 
 
                FAMClose(sc->fam); 
                free(sc->fam); 
 
                sc->fam = NULL; 
         }          }
   
         return HANDLER_GO_ON;          return HANDLER_GO_ON;
Line 319  handler_t stat_cache_handle_fdevent(server *srv, void  Line 334  handler_t stat_cache_handle_fdevent(server *srv, void 
 static int buffer_copy_dirname(buffer *dst, buffer *file) {  static int buffer_copy_dirname(buffer *dst, buffer *file) {
         size_t i;          size_t i;
   
        if (buffer_is_empty(file)) return -1;        if (buffer_string_is_empty(file)) return -1;
   
        for (i = file->used - 1; i+1 > 0; i--) {        for (i = buffer_string_length(file); i > 0; i--) {
                 if (file->ptr[i] == '/') {                  if (file->ptr[i] == '/') {
                         buffer_copy_string_len(dst, file->ptr, i);                          buffer_copy_string_len(dst, file->ptr, i);
                         return 0;                          return 0;
Line 359  handler_t stat_cache_get_entry(server *srv, connection Line 374  handler_t stat_cache_get_entry(server *srv, connection
 #ifdef HAVE_FAM_H  #ifdef HAVE_FAM_H
         fam_dir_entry *fam_dir = NULL;          fam_dir_entry *fam_dir = NULL;
         int dir_ndx = -1;          int dir_ndx = -1;
         splay_tree *dir_node = NULL;  
 #endif  #endif
         stat_cache_entry *sce = NULL;          stat_cache_entry *sce = NULL;
         stat_cache *sc;          stat_cache *sc;
Line 372  handler_t stat_cache_get_entry(server *srv, connection Line 386  handler_t stat_cache_get_entry(server *srv, connection
 #endif  #endif
   
         int file_ndx;          int file_ndx;
         splay_tree *file_node = NULL;  
   
         *ret_sce = NULL;          *ret_sce = NULL;
   
Line 382  handler_t stat_cache_get_entry(server *srv, connection Line 395  handler_t stat_cache_get_entry(server *srv, connection
   
         sc = srv->stat_cache;          sc = srv->stat_cache;
   
        buffer_copy_string_buffer(sc->hash_key, name);        buffer_copy_buffer(sc->hash_key, name);
        buffer_append_long(sc->hash_key, con->conf.follow_symlink);        buffer_append_int(sc->hash_key, con->conf.follow_symlink);
   
         file_ndx = hashme(sc->hash_key);          file_ndx = hashme(sc->hash_key);
         sc->files = splaytree_splay(sc->files, file_ndx);          sc->files = splaytree_splay(sc->files, file_ndx);
Line 397  handler_t stat_cache_get_entry(server *srv, connection Line 410  handler_t stat_cache_get_entry(server *srv, connection
         if (sc->files && (sc->files->key == file_ndx)) {          if (sc->files && (sc->files->key == file_ndx)) {
 #ifdef DEBUG_STAT_CACHE  #ifdef DEBUG_STAT_CACHE
                 /* it was in the cache */                  /* it was in the cache */
                assert(i < ctrl.used);                force_assert(i < ctrl.used);
 #endif  #endif
   
                 /* we have seen this file already and                  /* we have seen this file already and
                  * don't stat() it again in the same second */                   * don't stat() it again in the same second */
   
                file_node = sc->files;                sce = sc->files->data;
   
                 sce = file_node->data;  
   
                 /* check if the name is the same, we might have a collision */                  /* check if the name is the same, we might have a collision */
   
                 if (buffer_is_equal(name, sce->name)) {                  if (buffer_is_equal(name, sce->name)) {
                         if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_SIMPLE) {                          if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_SIMPLE) {
                                if (sce->stat_ts == srv->cur_ts) {                                if (sce->stat_ts == srv->cur_ts && con->conf.follow_symlink) {
                                         *ret_sce = sce;                                          *ret_sce = sce;
                                         return HANDLER_GO_ON;                                          return HANDLER_GO_ON;
                                 }                                  }
                         }                          }
                 } else {                  } else {
                        /* oops, a collision,                        /* collision, forget about the entry */
                         *                        sce = NULL;
                         * file_node is used by the FAM check below to see if we know this file 
                         * and if we can save a stat(). 
                         * 
                         * BUT, the sce is not reset here as the entry into the cache is ok, we 
                         * it is just not pointing to our requested file. 
                         * 
                         *  */ 
 
                        file_node = NULL; 
                 }                  }
         } else {          } else {
 #ifdef DEBUG_STAT_CACHE  #ifdef DEBUG_STAT_CACHE
Line 435  handler_t stat_cache_get_entry(server *srv, connection Line 437  handler_t stat_cache_get_entry(server *srv, connection
                         log_error_write(srv, __FILE__, __LINE__, "xSB",                          log_error_write(srv, __FILE__, __LINE__, "xSB",
                                 file_ndx, "was already inserted but not found in cache, ", name);                                  file_ndx, "was already inserted but not found in cache, ", name);
                 }                  }
                assert(i == ctrl.used);                force_assert(i == ctrl.used);
 #endif  #endif
         }          }
   
Line 448  handler_t stat_cache_get_entry(server *srv, connection Line 450  handler_t stat_cache_get_entry(server *srv, connection
                         return HANDLER_ERROR;                          return HANDLER_ERROR;
                 }                  }
   
                buffer_copy_string_buffer(sc->hash_key, sc->dir_name);                buffer_copy_buffer(sc->hash_key, sc->dir_name);
                buffer_append_long(sc->hash_key, con->conf.follow_symlink);                buffer_append_int(sc->hash_key, con->conf.follow_symlink);
   
                 dir_ndx = hashme(sc->hash_key);                  dir_ndx = hashme(sc->hash_key);
   
                 sc->dirs = splaytree_splay(sc->dirs, dir_ndx);                  sc->dirs = splaytree_splay(sc->dirs, dir_ndx);
   
                if (sc->dirs && (sc->dirs->key == dir_ndx)) {                if ((NULL != sc->dirs) && (sc->dirs->key == dir_ndx)) {
                        dir_node = sc->dirs;                        fam_dir = sc->dirs->data;
                } 
   
                if (dir_node && file_node) {                        /* check whether we got a collision */
                        /* we found a file */                        if (buffer_is_equal(sc->dir_name, fam_dir->name)) {
                                 /* test whether a found file cache entry is still ok */
                                 if ((NULL != sce) && (fam_dir->version == sce->dir_version)) {
                                         /* the stat()-cache entry is still ok */
   
                        sce = file_node->data;                                        *ret_sce = sce;
                        fam_dir = dir_node->data;                                        return HANDLER_GO_ON;
                                }
                        if (fam_dir->version == sce->dir_version) {                        } else {
                                /* the stat()-cache entry is still ok */                                /* hash collision, forget about the entry */
                                fam_dir = NULL;
                                *ret_sce = sce; 
                                return HANDLER_GO_ON; 
                         }                          }
                 }                  }
         }          }
Line 488  handler_t stat_cache_get_entry(server *srv, connection Line 490  handler_t stat_cache_get_entry(server *srv, connection
   
         if (S_ISREG(st.st_mode)) {          if (S_ISREG(st.st_mode)) {
                 /* fix broken stat/open for symlinks to reg files with appended slash on freebsd,osx */                  /* fix broken stat/open for symlinks to reg files with appended slash on freebsd,osx */
                if (name->ptr[name->used-2] == '/') {                if (name->ptr[buffer_string_length(name) - 1] == '/') {
                         errno = ENOTDIR;                          errno = ENOTDIR;
                         return HANDLER_ERROR;                          return HANDLER_ERROR;
                 }                  }
Line 501  handler_t stat_cache_get_entry(server *srv, connection Line 503  handler_t stat_cache_get_entry(server *srv, connection
         }          }
   
         if (NULL == sce) {          if (NULL == sce) {
 #ifdef DEBUG_STAT_CACHE  
                 int osize = splaytree_size(sc->files);  
 #endif  
   
                 sce = stat_cache_entry_init();                  sce = stat_cache_entry_init();
                buffer_copy_string_buffer(sce->name, name);                buffer_copy_buffer(sce->name, name);
   
                sc->files = splaytree_insert(sc->files, file_ndx, sce);                /* already splayed file_ndx */
#ifdef DEBUG_STAT_CACHE                if ((NULL != sc->files) && (sc->files->key == file_ndx)) {
                if (ctrl.size == 0) {                        /* hash collision: replace old entry */
                        ctrl.size = 16;                        stat_cache_entry_free(sc->files->data);
                        ctrl.used = 0;                        sc->files->data = sce;
                        ctrl.ptr = malloc(ctrl.size * sizeof(*ctrl.ptr));                } else {
                } else if (ctrl.size == ctrl.used) {                        int osize = splaytree_size(sc->files);
                        ctrl.size += 16; 
                        ctrl.ptr = realloc(ctrl.ptr, ctrl.size * sizeof(*ctrl.ptr)); 
                } 
   
                ctrl.ptr[ctrl.used++] = file_ndx;                        sc->files = splaytree_insert(sc->files, file_ndx, sce);
                         force_assert(osize + 1 == splaytree_size(sc->files));
   
                assert(sc->files);#ifdef DEBUG_STAT_CACHE
                assert(sc->files->data == sce);                        if (ctrl.size == 0) {
                assert(osize + 1 == splaytree_size(sc->files));                                ctrl.size = 16;
                                 ctrl.used = 0;
                                 ctrl.ptr = malloc(ctrl.size * sizeof(*ctrl.ptr));
                                 force_assert(NULL != ctrl.ptr);
                         } else if (ctrl.size == ctrl.used) {
                                 ctrl.size += 16;
                                 ctrl.ptr = realloc(ctrl.ptr, ctrl.size * sizeof(*ctrl.ptr));
                                 force_assert(NULL != ctrl.ptr);
                         }
 
                         ctrl.ptr[ctrl.used++] = file_ndx;
 #endif  #endif
                   }
                   force_assert(sc->files);
                   force_assert(sc->files->data == sce);
         }          }
   
         sce->st = st;          sce->st = st;
Line 560  handler_t stat_cache_get_entry(server *srv, connection Line 570  handler_t stat_cache_get_entry(server *srv, connection
                  * we assume "/" can not be symlink, so                   * we assume "/" can not be symlink, so
                  * skip the symlink stuff if our path is /                   * skip the symlink stuff if our path is /
                  **/                   **/
                else if ((name->used > 2)) {                else if (buffer_string_length(name) > 1) {
                         buffer *dname;                          buffer *dname;
                         char *s_cur;                          char *s_cur;
   
                         dname = buffer_init();                          dname = buffer_init();
                        buffer_copy_string_buffer(dname, name);                        buffer_copy_buffer(dname, name);
   
                        while ((s_cur = strrchr(dname->ptr,'/'))) {                        while ((s_cur = strrchr(dname->ptr, '/'))) {
                                *s_cur = '\0';                                buffer_string_set_length(dname, s_cur - dname->ptr);
                                dname->used = s_cur - dname->ptr + 1; 
                                 if (dname->ptr == s_cur) {                                  if (dname->ptr == s_cur) {
 #ifdef DEBUG_STAT_CACHE  #ifdef DEBUG_STAT_CACHE
                                         log_error_write(srv, __FILE__, __LINE__, "s", "reached /");                                          log_error_write(srv, __FILE__, __LINE__, "s", "reached /");
Line 597  handler_t stat_cache_get_entry(server *srv, connection Line 606  handler_t stat_cache_get_entry(server *srv, connection
         if (S_ISREG(st.st_mode)) {          if (S_ISREG(st.st_mode)) {
                 /* determine mimetype */                  /* determine mimetype */
                 buffer_reset(sce->content_type);                  buffer_reset(sce->content_type);
#ifdef HAVE_XATTR#if defined(HAVE_XATTR) || defined(HAVE_EXTATTR)
                 if (con->conf.use_xattr) {                  if (con->conf.use_xattr) {
                        stat_cache_attr_get(sce->content_type, name->ptr);                        stat_cache_attr_get(sce->content_type, name->ptr, srv->srvconf.xattr_name->ptr);
                 }                  }
 #endif  #endif
                 /* xattr did not set a content-type. ask the config */                  /* xattr did not set a content-type. ask the config */
                if (buffer_is_empty(sce->content_type)) {                if (buffer_string_is_empty(sce->content_type)) {
                         size_t namelen = buffer_string_length(name);
 
                         for (k = 0; k < con->conf.mimetypes->used; k++) {                          for (k = 0; k < con->conf.mimetypes->used; k++) {
                                 data_string *ds = (data_string *)con->conf.mimetypes->data[k];                                  data_string *ds = (data_string *)con->conf.mimetypes->data[k];
                                 buffer *type = ds->key;                                  buffer *type = ds->key;
                                   size_t typelen = buffer_string_length(type);
   
                                if (type->used == 0) continue;                                if (buffer_is_empty(type)) continue;
   
                                 /* check if the right side is the same */                                  /* check if the right side is the same */
                                if (type->used > name->used) continue;                                if (typelen > namelen) continue;
   
                                if (0 == strncasecmp(name->ptr + name->used - type->used, type->ptr, type->used - 1)) {                                if (0 == strncasecmp(name->ptr + namelen - typelen, type->ptr, typelen)) {
                                        buffer_copy_string_buffer(sce->content_type, ds->value);                                        buffer_copy_buffer(sce->content_type, ds->value);
                                         break;                                          break;
                                 }                                  }
                         }                          }
Line 625  handler_t stat_cache_get_entry(server *srv, connection Line 637  handler_t stat_cache_get_entry(server *srv, connection
         }          }
   
 #ifdef HAVE_FAM_H  #ifdef HAVE_FAM_H
        if (sc->fam &&        if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM) {
            (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM)) { 
                 /* is this directory already registered ? */                  /* is this directory already registered ? */
                if (!dir_node) {                if (NULL == fam_dir) {
                         fam_dir = fam_dir_entry_init();                          fam_dir = fam_dir_entry_init();
                         fam_dir->fc = sc->fam;  
   
                        buffer_copy_string_buffer(fam_dir->name, sc->dir_name);                        buffer_copy_buffer(fam_dir->name, sc->dir_name);
   
                         fam_dir->version = 1;                          fam_dir->version = 1;
   
                         fam_dir->req = calloc(1, sizeof(FAMRequest));                          fam_dir->req = calloc(1, sizeof(FAMRequest));
                           force_assert(NULL != fam_dir);
   
                        if (0 != FAMMonitorDirectory(sc->fam, fam_dir->name->ptr,                        if (0 != FAMMonitorDirectory(&sc->fam, fam_dir->name->ptr,
                                                      fam_dir->req, fam_dir)) {                                                       fam_dir->req, fam_dir)) {
   
                                 log_error_write(srv, __FILE__, __LINE__, "sbsbs",                                  log_error_write(srv, __FILE__, __LINE__, "sbsbs",
Line 647  handler_t stat_cache_get_entry(server *srv, connection Line 658  handler_t stat_cache_get_entry(server *srv, connection
                                                 "file:", name,                                                  "file:", name,
                                                 FamErrlist[FAMErrno]);                                                  FamErrlist[FAMErrno]);
   
                                fam_dir_entry_free(fam_dir);                                fam_dir_entry_free(&sc->fam, fam_dir);
                                 fam_dir = NULL;
                         } else {                          } else {
                                int osize = 0;                                int osize = splaytree_size(sc->dirs);
   
                                if (sc->dirs) {                                /* already splayed dir_ndx */
                                        osize = sc->dirs->size;                                if ((NULL != sc->dirs) && (sc->dirs->key == dir_ndx)) {
                                         /* hash collision: replace old entry */
                                         fam_dir_entry_free(&sc->fam, sc->dirs->data);
                                         sc->dirs->data = fam_dir;
                                 } else {
                                         sc->dirs = splaytree_insert(sc->dirs, dir_ndx, fam_dir);
                                         force_assert(osize == (splaytree_size(sc->dirs) - 1));
                                 }                                  }
   
                                sc->dirs = splaytree_insert(sc->dirs, dir_ndx, fam_dir);                                force_assert(sc->dirs);
                                assert(sc->dirs);                                force_assert(sc->dirs->data == fam_dir);
                                assert(sc->dirs->data == fam_dir); 
                                assert(osize == (sc->dirs->size - 1)); 
                         }                          }
                 } else {  
                         fam_dir = dir_node->data;  
                 }                  }
   
                 /* bind the fam_fc to the stat() cache entry */                  /* bind the fam_fc to the stat() cache entry */
   
                 if (fam_dir) {                  if (fam_dir) {
                         sce->dir_version = fam_dir->version;                          sce->dir_version = fam_dir->version;
                         sce->dir_ndx     = dir_ndx;  
                 }                  }
         }          }
 #endif  #endif
Line 678  handler_t stat_cache_get_entry(server *srv, connection Line 691  handler_t stat_cache_get_entry(server *srv, connection
         return HANDLER_GO_ON;          return HANDLER_GO_ON;
 }  }
   
   int stat_cache_open_rdonly_fstat (server *srv, connection *con, buffer *name, struct stat *st) {
           /*(Note: O_NOFOLLOW affects only the final path segment, the target file,
            * not any intermediate symlinks along the path)*/
           #ifndef O_BINARY
           #define O_BINARY 0
           #endif
           #ifndef O_LARGEFILE
           #define O_LARGEFILE 0
           #endif
           #ifndef O_NOCTTY
           #define O_NOCTTY 0
           #endif
           #ifndef O_NONBLOCK
           #define O_NONBLOCK 0
           #endif
           #ifndef O_NOFOLLOW
           #define O_NOFOLLOW 0
           #endif
           const int oflags = O_BINARY | O_LARGEFILE | O_NOCTTY | O_NONBLOCK
                            | (con->conf.follow_symlink ? 0 : O_NOFOLLOW);
           const int fd = open(name->ptr, O_RDONLY | oflags);
           if (fd >= 0) {
                   if (0 == fstat(fd, st)) {
                           return fd;
                   } else {
                           close(fd);
                   }
           }
           UNUSED(srv); /*(might log_error_write(srv, ...) in the future)*/
           return -1;
   }
   
 /**  /**
  * remove stat() from cache which havn't been stat()ed for   * remove stat() from cache which havn't been stat()ed for
  * more than 10 seconds   * more than 10 seconds
Line 713  int stat_cache_trigger_cleanup(server *srv) { Line 758  int stat_cache_trigger_cleanup(server *srv) {
   
         if (!sc->files) return 0;          if (!sc->files) return 0;
   
        keys = calloc(1, sizeof(size_t) * sc->files->size);        keys = calloc(1, sizeof(int) * sc->files->size);
         force_assert(NULL != keys);
   
         stat_cache_tag_old_entries(srv, sc->files, keys, &max_ndx);          stat_cache_tag_old_entries(srv, sc->files, keys, &max_ndx);
   
Line 742  int stat_cache_trigger_cleanup(server *srv) { Line 788  int stat_cache_trigger_cleanup(server *srv) {
                                 }                                  }
                         }                          }
   
                        assert(osize - 1 == splaytree_size(sc->files));                        force_assert(osize - 1 == splaytree_size(sc->files));
 #endif  #endif
                 }                  }
         }          }

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.3


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>