Changeset 5bb306cd48a5523c1719766ad6cd61624f997929

Show
Ignore:
Timestamp:
11/08/09 06:49:48 (4 years ago)
Author:
Theo Schlossnagle <jesus@omniti.com>
git-committer:
Theo Schlossnagle <jesus@omniti.com> 1257662988 +0000
git-parent:

[f0555be1474aedabc7e5fefccaadb1bb838098b5]

git-author:
Theo Schlossnagle <jesus@omniti.com> 1257662988 +0000
Message:

make the logging API private and add locking for jlog so that in-flight reopens are safe, refs #215

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • src/noit_console.c

    re491b53 r5bb306c  
    487487static int 
    488488noit_console_logio_write(noit_log_stream_t ls, const void *buf, size_t len) { 
    489   noit_console_closure_t ncct = ls->op_ctx; 
     489  noit_console_closure_t ncct; 
     490  ncct = noit_log_stream_get_ctx(ls); 
    490491  int rv, rlen, mask; 
    491492  if(!ncct) return 0; 
    492   rlen = nc_write(ls->op_ctx, buf, len); 
     493  rlen = nc_write(ncct, buf, len); 
    493494  while((rv = noit_console_continue_sending(ncct, &mask)) == -1 && errno == EINTR); 
    494495  if(rv == -1 && errno == EAGAIN) { 
     
    499500static int 
    500501noit_console_logio_close(noit_log_stream_t ls) { 
    501   ls->op_ctx = NULL
     502  noit_log_stream_set_ctx(ls, NULL)
    502503  return 0; 
    503504} 
  • src/noit_jlog_listener.c

    r1da42f7 r5bb306c  
    228228  if(!ac->service_ctx) { 
    229229    noit_log_stream_t ls; 
    230     const char *logname
     230    const char *logname, *type
    231231    char path[PATH_MAX], subscriber[256], *sub; 
    232232    jcl = ac->service_ctx = noit_jlog_closure_alloc(); 
     
    247247      goto socket_error; 
    248248    } 
    249     if(!ls->type || strcmp(ls->type, "jlog")) { 
     249    type = noit_log_stream_get_type(ls); 
     250    if(!type || strcmp(type, "jlog")) { 
    250251      snprintf(errbuff, sizeof(errbuff), 
    251252               "Log '%s' for log_transit is not a jlog.", logname); 
     
    268269    jcl->subscriber = strdup(subscriber); 
    269270 
    270     strlcpy(path, ls->path, sizeof(path)); 
     271    strlcpy(path, noit_log_stream_get_path(ls), sizeof(path)); 
    271272    sub = strchr(path, '('); 
    272273    if(sub) { 
  • src/noit_livestream_listener.c

    r4a83807 r5bb306c  
    9797static int 
    9898noit_livestream_logio_write(noit_log_stream_t ls, const void *buf, size_t len) { 
    99   noit_livestream_closure_t *jcl = ls->op_ctx
     99  noit_livestream_closure_t *jcl
    100100  struct log_entry *le; 
     101 
     102  jcl = noit_log_stream_get_ctx(ls); 
    101103  if(!jcl) return 0; 
    102104 
     
    121123static int 
    122124noit_livestream_logio_close(noit_log_stream_t ls) { 
    123   noit_livestream_closure_t *jcl = ls->op_ctx; 
     125  noit_livestream_closure_t *jcl; 
     126  jcl = noit_log_stream_get_ctx(ls); 
    124127  if(jcl) noit_livestream_closure_free(jcl); 
    125   ls->op_ctx = NULL
     128  noit_log_stream_set_ctx(ls, NULL)
    126129  return 0; 
    127130} 
  • src/utils/noit_log.c

    rf0555be r5bb306c  
    3939#include <sys/time.h> 
    4040#include <assert.h> 
    41  
     41#if HAVE_ERRNO_H 
     42#include <errno.h> 
     43#endif 
     44#if HAVE_DIRENT_H 
     45#include <dirent.h> 
     46#endif 
     47 
     48#define noit_log_impl 
    4249#include "utils/noit_log.h" 
    4350#include "utils/noit_hash.h" 
    4451#include "jlog/jlog.h" 
     52#include "jlog/jlog_private.h" 
     53 
     54struct _noit_log_stream { 
     55  unsigned enabled:1; 
     56  unsigned debug:1; 
     57  /* Above is exposed... */ 
     58  char *type; 
     59  char *name; 
     60  int mode; 
     61  char *path; 
     62  logops_t *ops; 
     63  void *op_ctx; 
     64  noit_hash_table *config; 
     65  struct _noit_log_stream_outlet_list *outlets; 
     66  pthread_rwlock_t *lock; 
     67}; 
    4568 
    4669static noit_hash_table noit_loggers = NOIT_HASH_EMPTY; 
     
    108131 
    109132static int 
    110 jlog_logio_reopen(noit_log_stream_t ls) { 
    111   char **subs; 
    112   int i; 
    113   /* reopening only has the effect of removing temporary subscriptions */ 
    114   /* (they start with ~ in our hair-brained model */ 
    115  
    116   if(jlog_ctx_list_subscribers(ls->op_ctx, &subs) == -1) { 
    117     noitL(noit_error, "Cannot list subscribers: %s\n", 
    118           jlog_ctx_err_string(ls->op_ctx)); 
    119     return 0; 
    120   } 
    121  
    122   for(i=0;subs[i];i++) 
    123     if(subs[i][0] == '~') 
    124       if(jlog_ctx_remove_subscriber(ls->op_ctx, subs[i]) == -1) 
    125         noitL(noit_error, "Cannot remove subscriber '%s': %s\n", 
    126               subs[i], jlog_ctx_err_string(ls->op_ctx)); 
    127  
    128   jlog_ctx_list_subscribers_dispose(ls->op_ctx, subs); 
    129   return 0; 
    130 
    131 static int 
    132 jlog_logio_open(noit_log_stream_t ls) { 
    133   char path[PATH_MAX], *sub; 
    134   jlog_ctx *log = NULL; 
     133jlog_lspath_to_fspath(noit_log_stream_t ls, char *buff, int len) { 
     134  char *sub; 
    135135  if(!ls->path) return -1; 
    136   strlcpy(path, ls->path, sizeof(path)); 
    137   sub = strchr(path, '('); 
     136  strlcpy(buff, ls->path, len); 
     137  sub = strchr(buff, '('); 
    138138  if(sub) { 
    139139    char *esub = strchr(sub, ')'); 
     
    144144    } 
    145145  } 
     146  return strlen(buff); 
     147} 
     148 
     149/* These next functions arr basically cribbed from jlogctl.c */ 
     150static int 
     151is_datafile(const char *f, u_int32_t *logid) { 
     152  int i; 
     153  u_int32_t l = 0; 
     154  for(i=0; i<8; i++) { 
     155    if((f[i] >= '0' && f[i] <= '9') || 
     156       (f[i] >= 'a' && f[i] <= 'f')) { 
     157      l <<= 4; 
     158      l |= (f[i] < 'a') ? (f[i] - '0') : (f[i] - 'a' + 10); 
     159    } 
     160    else 
     161      return 0; 
     162  } 
     163  if(f[i] != '\0') return 0; 
     164  if(logid) *logid = l; 
     165  return 1; 
     166} 
     167 
     168static int 
     169jlog_logio_cleanse(noit_log_stream_t ls) { 
     170  jlog_ctx *log; 
     171  DIR *d; 
     172  struct dirent de, *entry; 
     173  int cnt = 0; 
     174  char path[PATH_MAX]; 
     175 
     176  log = (jlog_ctx *)ls->op_ctx; 
     177  if(!log) return -1; 
     178  if(jlog_lspath_to_fspath(ls, path, sizeof(path)) <= 0) return -1; 
     179  d = opendir(path); 
     180  if(!d) return -1; 
     181  while(portable_readdir_r(d, &de, &entry) == 0 && entry != NULL) { 
     182    u_int32_t logid; 
     183    if(is_datafile(entry->d_name, &logid)) { 
     184      int rv; 
     185      struct stat st; 
     186      char fullfile[PATH_MAX]; 
     187      char fullidx[PATH_MAX]; 
     188 
     189      snprintf(fullfile, sizeof(fullfile), "%s/%s", path, entry->d_name); 
     190      snprintf(fullidx, sizeof(fullidx), "%s/%s" INDEX_EXT, 
     191               path, entry->d_name); 
     192      while((rv = stat(fullfile, &st)) != 0 && errno == EINTR); 
     193      if(rv == 0) { 
     194        int readers; 
     195        readers = __jlog_pending_readers(log, logid); 
     196        if(readers == 0) { 
     197          unlink(fullfile); 
     198          unlink(fullidx); 
     199        } 
     200      } 
     201    } 
     202  } 
     203  closedir(d); 
     204  return cnt; 
     205} 
     206 
     207static int 
     208jlog_logio_reopen(noit_log_stream_t ls) { 
     209  char **subs; 
     210  int i; 
     211  /* reopening only has the effect of removing temporary subscriptions */ 
     212  /* (they start with ~ in our hair-brained model */ 
     213 
     214  if(ls->lock) pthread_rwlock_wrlock(ls->lock); 
     215  if(jlog_ctx_list_subscribers(ls->op_ctx, &subs) == -1) 
     216    goto bail; 
     217 
     218  for(i=0;subs[i];i++) 
     219    if(subs[i][0] == '~') 
     220      jlog_ctx_remove_subscriber(ls->op_ctx, subs[i]); 
     221 
     222  jlog_ctx_list_subscribers_dispose(ls->op_ctx, subs); 
     223  jlog_logio_cleanse(ls); 
     224 bail: 
     225  if(ls->lock) pthread_rwlock_unlock(ls->lock); 
     226  return 0; 
     227} 
     228static int 
     229jlog_logio_open(noit_log_stream_t ls) { 
     230  char path[PATH_MAX], *sub; 
     231  jlog_ctx *log = NULL; 
     232 
     233  if(jlog_lspath_to_fspath(ls, path, sizeof(path)) <= 0) return -1; 
    146234  log = jlog_new(path); 
    147235  if(!log) return -1; 
     
    181269static int 
    182270jlog_logio_write(noit_log_stream_t ls, const void *buf, size_t len) { 
     271  int rv = -1; 
    183272  if(!ls->op_ctx) return -1; 
    184   if(jlog_ctx_write((jlog_ctx *)ls->op_ctx, buf, len) != 0) 
    185     return -1; 
    186   return len; 
     273  pthread_rwlock_rdlock(ls->lock); 
     274  if(jlog_ctx_write((jlog_ctx *)ls->op_ctx, buf, len) == 0) 
     275    rv = len; 
     276  pthread_rwlock_unlock(ls->lock); 
     277  return rv; 
    187278} 
    188279static int 
     
    196287static size_t 
    197288jlog_logio_size(noit_log_stream_t ls) { 
     289  size_t size; 
    198290  if(!ls->op_ctx) return -1; 
    199   return jlog_raw_size((jlog_ctx *)ls->op_ctx); 
     291  pthread_rwlock_rdlock(ls->lock); 
     292  size = jlog_raw_size((jlog_ctx *)ls->op_ctx); 
     293  pthread_rwlock_unlock(ls->lock); 
     294  return size; 
    200295} 
    201296static logops_t jlog_logio_ops = { 
     
    223318} 
    224319 
     320void * 
     321noit_log_stream_get_ctx(noit_log_stream_t ls) { 
     322  return ls->op_ctx; 
     323} 
     324 
     325void 
     326noit_log_stream_set_ctx(noit_log_stream_t ls, void *nctx) { 
     327  ls->op_ctx = nctx; 
     328} 
     329 
     330const char * 
     331noit_log_stream_get_type(noit_log_stream_t ls) { 
     332  return ls->type; 
     333} 
     334 
     335const char * 
     336noit_log_stream_get_name(noit_log_stream_t ls) { 
     337  return ls->name; 
     338} 
     339 
     340const char * 
     341noit_log_stream_get_path(noit_log_stream_t ls) { 
     342  return ls->path; 
     343} 
     344 
    225345noit_log_stream_t 
    226346noit_log_stream_new_on_fd(const char *name, int fd, noit_hash_table *config) { 
     
    232352  ls->enabled = 1; 
    233353  ls->config = config; 
     354  ls->lock = calloc(1, sizeof(*ls->lock)); 
     355  pthread_rwlock_init(ls->lock, NULL); 
    234356  /* This double strdup of ls->name is needed, look for the next one 
    235357   * for an explanation. 
     
    270392  saved = noit_log_stream_find(name); 
    271393  if(saved) { 
     394    pthread_rwlock_t *lock = saved->lock; 
    272395    memcpy(&tmpbuf, saved, sizeof(*saved)); 
    273396    memcpy(saved, ls, sizeof(*saved)); 
    274397    memcpy(ls, &tmpbuf, sizeof(*saved)); 
     398    saved->lock = lock; 
     399 
     400    ls->lock = NULL; 
    275401    noit_log_stream_free(ls); 
    276402    ls = saved; 
    277403  } 
    278   else 
     404  else { 
    279405    /* We strdup the name *again*.  We'going to kansas city shuffle the 
    280406     * ls later (see memcpy above).  However, if don't strdup, then the 
     
    285411                       strdup(ls->name), strlen(ls->name), ls) == 0) 
    286412      goto freebail; 
    287  
     413    ls->lock = calloc(1, sizeof(*ls->lock)); 
     414    pthread_rwlock_init(ls->lock, NULL); 
     415  } 
    288416  /* This is for things that don't open on paths */ 
    289417  if(ctx) ls->op_ctx = ctx; 
     
    384512      noit_hash_destroy(ls->config, free, free); 
    385513      free(ls->config); 
     514    } 
     515    if(ls->lock) { 
     516      pthread_rwlock_destroy(ls->lock); 
     517      free(ls->lock); 
    386518    } 
    387519    free(ls); 
  • src/utils/noit_log.h

    rf0555be r5bb306c  
    5252} logops_t; 
    5353 
     54#ifdef noit_log_impl 
     55typedef struct _noit_log_stream * noit_log_stream_t; 
     56#else 
    5457typedef struct _noit_log_stream { 
    55   char *type; 
    56   char *name; 
    57   int enabled:1; 
    58   int debug:1; 
    59   int mode; 
    60   char *path; 
    61   logops_t *ops; 
    62   void *op_ctx; 
    63   noit_hash_table *config; 
    64   struct _noit_log_stream_outlet_list *outlets; 
     58  unsigned enabled:1; 
     59  unsigned debug:1; 
     60  /* totally private type, don't even think about it */ 
    6561} * noit_log_stream_t; 
     62#endif 
    6663 
    6764extern noit_log_stream_t noit_stderr; 
     
    7269API_EXPORT(int) noit_log_reopen_all(); 
    7370API_EXPORT(void) noit_register_logops(const char *name, logops_t *ops); 
     71API_EXPORT(void *) noit_log_stream_get_ctx(noit_log_stream_t); 
     72API_EXPORT(void) noit_log_stream_set_ctx(noit_log_stream_t, void *); 
     73API_EXPORT(const char *) noit_log_stream_get_type(noit_log_stream_t); 
     74API_EXPORT(const char *) noit_log_stream_get_name(noit_log_stream_t); 
     75API_EXPORT(const char *) noit_log_stream_get_path(noit_log_stream_t); 
     76 
    7477API_EXPORT(noit_log_stream_t) 
    7578  noit_log_stream_new(const char *, const char *, const char *, 
     
    101104  ; 
    102105 
    103 #define noitLT(ls, t, args...) \ 
    104   if((ls) && (ls)->enabled) noit_log(ls, t, __FILE__, __LINE__, args) 
     106#define noitLT(ls, t, args...) do { \ 
     107  if((ls) && (ls)->enabled) noit_log(ls, t, __FILE__, __LINE__, args); \ 
     108} while(0) 
    105109#define noitL(ls, args...) do { \ 
    106110  if((ls) && (ls)->enabled) { \