Changeset 80f47472f0d3f59e9aceccab41a0940edd7946d3

Show
Ignore:
Timestamp:
01/04/12 21:55:54 (2 years ago)
Author:
Theo Schlossnagle <jesus@omniti.com>
git-committer:
Theo Schlossnagle <jesus@omniti.com> 1325714154 -0500
git-parent:

[1a07d8a36938e3fe7306909982a2d3bdb372d002], [70a52b32620458fceed674ce5d4f8e10dd65aad5]

git-author:
Theo Schlossnagle <jesus@omniti.com> 1325714154 -0500
Message:

Merge branch 'shatter'

Files:

Legend:

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

    rc6c11c3 r80f4747  
    488488  /* delete this here */ 
    489489  noit_poller_deschedule(check->checkid); 
     490  CONF_REMOVE(node); 
    490491  xmlUnlinkNode(node); 
    491492  xmlFreeNode(node); 
  • src/noit_conf.c

    rc6c11c3 r80f4747  
    3636#include <unistd.h> 
    3737#include <fcntl.h> 
     38#include <dirent.h> 
    3839#include <errno.h> 
    3940#include <assert.h> 
     
    4647#include "noit_check.h" 
    4748#include "noit_console.h" 
     49#include "noit_xml.h" 
    4850#include "utils/noit_hash.h" 
    4951#include "utils/noit_log.h" 
     
    6365static xmlDocPtr master_config = NULL; 
    6466static int config_include_cnt = -1; 
     67static int backingstore_include_cnt = -1; 
     68 
    6569static struct { 
    6670  xmlNodePtr insertion_point; 
     
    6872  xmlDocPtr doc; 
    6973  xmlNodePtr root; 
    70 } *config_include_nodes = NULL; 
     74} *config_include_nodes = NULL, 
     75  *backingstore_include_nodes = NULL; 
     76 
     77typedef struct noit_xml_userdata { 
     78  char       *name; 
     79  char       *path; 
     80  u_int64_t   dirty_time; 
     81  struct noit_xml_userdata *freelist; 
     82} noit_xml_userdata_t; 
     83 
     84static noit_xml_userdata_t *backingstore_freelist = NULL; 
     85static u_int64_t last_config_flush = 0; 
     86 
     87#define is_stopnode_name(n) ((n) && \ 
     88    (!strcmp((char *)(n), "check") || \ 
     89     !strcmp((char *)(n), "config") || \ 
     90     !strcmp((char *)(n), "filterset"))) 
     91#define is_stopnode(node) ((node) && is_stopnode_name((node)->name)) 
    7192 
    7293static char *root_node_name = NULL; 
     
    81102static u_int32_t __config_coalesce = 0; 
    82103static u_int32_t __config_coalesce_time = 0; 
     104static u_int64_t max_gen_count = 0; 
    83105void noit_conf_coalesce_changes(u_int32_t seconds) { 
    84106  __config_coalesce_time = seconds; 
     
    96118  void *jc_closure; 
    97119}; 
     120 
     121static void 
     122noit_xml_userdata_free(noit_xml_userdata_t *n) { 
     123  if(n->name) free(n->name); 
     124  if(n->path) free(n->path); 
     125} 
     126 
    98127static int 
    99128noit_conf_watch_config_and_journal(eventer_t e, int mask, void *closure, 
     
    239268  config_include_nodes = NULL; 
    240269  config_include_cnt = -1; 
     270 
     271  if(backingstore_include_nodes) { 
     272    int i; 
     273    for(i=0; i<backingstore_include_cnt; i++) { 
     274      if(backingstore_include_nodes[i].doc) { 
     275        xmlNodePtr n; 
     276        for(n=backingstore_include_nodes[i].insertion_point->children; 
     277            n; n = n->next) { 
     278          n->parent = backingstore_include_nodes[i].root; 
     279          n->parent->last = n; 
     280        } 
     281        backingstore_include_nodes[i].insertion_point->children = 
     282          backingstore_include_nodes[i].old_children; 
     283        for(n=backingstore_include_nodes[i].insertion_point->children; 
     284            n; n = n->next) { 
     285          n->parent->last = n; /* sets it to the last child */ 
     286        } 
     287        xmlFreeDoc(backingstore_include_nodes[i].doc); 
     288      } 
     289    } 
     290    free(backingstore_include_nodes); 
     291  } 
     292  backingstore_include_nodes = NULL; 
     293  backingstore_include_cnt = -1; 
    241294} 
    242295void 
     
    272325  } 
    273326} 
     327static u_int64_t 
     328usec_now() { 
     329  u_int64_t usec; 
     330  struct timeval tv; 
     331  gettimeofday(&tv, NULL); 
     332  usec = tv.tv_sec * 1000000UL; 
     333  usec += tv.tv_usec; 
     334  return usec; 
     335} 
     336void 
     337noit_conf_backingstore_remove(noit_conf_section_t vnode) { 
     338  xmlNodePtr node = vnode; 
     339  noit_xml_userdata_t *subctx = node->_private; 
     340  if(subctx) { 
     341    noitL(noit_debug, "marking %s for removal\n", subctx->path); 
     342    if(!backingstore_freelist) backingstore_freelist = subctx; 
     343    else { 
     344      noit_xml_userdata_t *fl = backingstore_freelist; 
     345      while(fl->freelist) fl = fl->freelist; 
     346      fl->freelist = subctx; 
     347    } 
     348    node->_private = NULL; 
     349  } 
     350  /* If we're deleted, we'll mark the parent as dirty */ 
     351  if(node->parent) noit_conf_backingstore_dirty(node->parent); 
     352} 
     353void 
     354noit_conf_backingstore_dirty(noit_conf_section_t vnode) { 
     355  xmlNodePtr node = vnode; 
     356  noit_xml_userdata_t *subctx = node->_private; 
     357  if(subctx) { 
     358    subctx->dirty_time = usec_now(); 
     359    return; 
     360  } 
     361  if(node->parent) noit_conf_backingstore_dirty(node->parent); 
     362} 
     363int 
     364noit_conf_backingstore_write(noit_xml_userdata_t *ctx, noit_boolean skip, 
     365                             xmlAttrPtr attrs, xmlNodePtr node) { 
     366  int failure = 0; 
     367  char newpath[PATH_MAX]; 
     368  xmlNodePtr n; 
     369  snprintf(newpath, sizeof(newpath), "%s/.attrs", ctx->path); 
     370  if(attrs) { 
     371    xmlDocPtr tmpdoc; 
     372    xmlNodePtr tmpnode; 
     373    noitL(noit_debug, " **> %s\n", newpath); 
     374    tmpdoc = xmlNewDoc((xmlChar *)"1.0"); 
     375    tmpnode = xmlNewNode(NULL, ctx->name ? (xmlChar *)ctx->name : (xmlChar *)"stub"); 
     376    xmlDocSetRootElement(tmpdoc, tmpnode); 
     377    tmpnode->properties = attrs; 
     378    failure = noit_xmlSaveToFile(tmpdoc, newpath); 
     379    tmpnode->properties = NULL; 
     380    xmlFreeDoc(tmpdoc); 
     381    if(failure) return -1; 
     382  } 
     383  else if(!skip) { 
     384    unlink(newpath); 
     385  } 
     386  for(n = node; n; n = n->next) { 
     387    int leaf; 
     388    noit_xml_userdata_t *subctx; 
     389    subctx = n->_private; 
     390    leaf = is_stopnode(n); 
     391    if(!subctx) { /* This has never been written out */ 
     392      subctx = calloc(1, sizeof(*subctx)); 
     393      subctx->name = strdup((char *)n->name); 
     394      snprintf(newpath, sizeof(newpath), "%s/%s#%llu", ctx->path, n->name, ++max_gen_count); 
     395      if(leaf) strlcat(newpath, ".xml", sizeof(newpath)); 
     396      subctx->path = strdup(newpath); 
     397      subctx->dirty_time = usec_now(); 
     398      n->_private = subctx; 
     399      noitL(noit_debug, " !!> %s\n", subctx->path); 
     400    } 
     401    if(leaf) { 
     402      xmlDocPtr tmpdoc; 
     403      xmlNodePtr tmpnode; 
     404      if(subctx->dirty_time > last_config_flush) { 
     405        tmpdoc = xmlNewDoc((xmlChar *)"1.0"); 
     406        tmpnode = xmlNewNode(NULL, n->name); 
     407        xmlDocSetRootElement(tmpdoc, tmpnode); 
     408        tmpnode->properties = n->properties; 
     409        tmpnode->children = n->children; 
     410        failure = noit_xmlSaveToFile(tmpdoc, subctx->path); 
     411        tmpnode->properties = NULL; 
     412        tmpnode->children = NULL; 
     413        xmlFreeDoc(tmpdoc); 
     414        noitL(noit_debug, " ==> %s\n", subctx->path); 
     415        if(failure) return -1; 
     416      } 
     417    } 
     418    else { 
     419      noit_boolean skip_attrs; 
     420      skip_attrs = leaf || (subctx->dirty_time <= last_config_flush); 
     421      noitL(noit_debug, " --> %s\n", subctx->path); 
     422      if(noit_conf_backingstore_write(subctx, skip_attrs, skip_attrs ? NULL : n->properties, n->children)) 
     423        return -1; 
     424    } 
     425  } 
     426  return 0; 
     427} 
     428void 
     429noit_conf_shatter_write(xmlDocPtr doc) { 
     430  if(backingstore_freelist) { 
     431    noit_xml_userdata_t *fl, *last; 
     432    for(fl = backingstore_freelist; fl; ) { 
     433      last = fl; 
     434      fl = fl->freelist; 
     435      /* If it is a file, we'll unlink it, otherwise, 
     436       * we need to delete the attributes and the directory. 
     437       */ 
     438      if(unlink(last->path)) { 
     439        char attrpath[PATH_MAX]; 
     440        snprintf(attrpath, sizeof(attrpath), "%s/.attrs", last->path); 
     441        unlink(attrpath); 
     442        if(rmdir(last->path) && errno != ENOENT) { 
     443          /* This shouldn't happen, but if it does we risk 
     444           * leaving a mess. Don't do that. 
     445           */ 
     446          noitL(noit_error, "backingstore mess %s: %s\n", 
     447                last->path, strerror(errno)); 
     448        } 
     449      } 
     450      noit_xml_userdata_free(last); 
     451    } 
     452    backingstore_freelist = NULL; 
     453  } 
     454  if(backingstore_include_nodes) { 
     455    int i; 
     456    for(i=0; i<backingstore_include_cnt; i++) { 
     457      if(backingstore_include_nodes[i].doc) { 
     458        xmlNodePtr n; 
     459        noit_xml_userdata_t *what = backingstore_include_nodes[i].doc->_private; 
     460 
     461        for(n=backingstore_include_nodes[i].insertion_point->children; 
     462            n; n = n->next) { 
     463          n->parent = backingstore_include_nodes[i].root; 
     464          n->parent->last = n; 
     465        } 
     466        backingstore_include_nodes[i].root->children = 
     467          backingstore_include_nodes[i].insertion_point->children; 
     468        backingstore_include_nodes[i].insertion_point->children = 
     469          backingstore_include_nodes[i].old_children; 
     470        for(n=backingstore_include_nodes[i].insertion_point->children; 
     471            n; n = n->next) { 
     472          n->parent->last = n; /* sets it to the last child */ 
     473        } 
     474        noit_conf_backingstore_write(what, noit_false, NULL, backingstore_include_nodes[i].root->children); 
     475      } 
     476    } 
     477    last_config_flush = usec_now(); 
     478  } 
     479} 
     480void 
     481noit_conf_shatter_postwrite(xmlDocPtr doc) { 
     482  if(backingstore_include_nodes) { 
     483    int i; 
     484    for(i=0; i<backingstore_include_cnt; i++) { 
     485      if(backingstore_include_nodes[i].doc) { 
     486        xmlNodePtr n; 
     487        backingstore_include_nodes[i].insertion_point->children = 
     488          backingstore_include_nodes[i].root->children; 
     489        for(n=backingstore_include_nodes[i].insertion_point->children; 
     490            n; n = n->next) { 
     491          n->parent = backingstore_include_nodes[i].insertion_point; 
     492          n->parent->last = n; 
     493        } 
     494      } 
     495    } 
     496  } 
     497} 
     498 
     499int 
     500noit_conf_read_into_node(xmlNodePtr node, const char *path) { 
     501  DIR *dirroot; 
     502  struct dirent *de, *entry; 
     503  char filepath[PATH_MAX]; 
     504  xmlDocPtr doc; 
     505  xmlNodePtr root = NULL; 
     506  xmlAttrPtr a; 
     507  struct stat sb; 
     508  int size, rv; 
     509 
     510  noitL(noit_debug, "read backing store: %s\n", path); 
     511  snprintf(filepath, sizeof(filepath), "%s/.attrs", path); 
     512  while((rv = stat(filepath, &sb)) < 0 && errno == EINTR); 
     513  if(rv == 0) { 
     514    doc = xmlParseFile(filepath); 
     515    if(doc) root = xmlDocGetRootElement(doc); 
     516    if(doc && root) { 
     517      node->properties = root->properties; 
     518      for(a = node->properties; a; a = a->next) { 
     519        a->parent = node; 
     520        a->doc = node->doc; 
     521      } 
     522      root->properties = NULL; 
     523      xmlFreeDoc(doc); 
     524      doc = NULL; 
     525    } 
     526  } 
     527#ifdef _PC_NAME_MAX 
     528  size = pathconf(path, _PC_NAME_MAX); 
     529#endif 
     530  size = MAX(size, PATH_MAX + 128); 
     531  de = alloca(size); 
     532  dirroot = opendir(path); 
     533  if(!dirroot) return -1; 
     534  while(portable_readdir_r(dirroot, de, &entry) == 0 && entry != NULL) { 
     535    noit_xml_userdata_t *udata; 
     536    char name[PATH_MAX]; 
     537    char *sep; 
     538    xmlNodePtr child; 
     539    u_int64_t gen; 
     540 
     541    sep = strchr(entry->d_name, '#'); 
     542    if(!sep) continue; 
     543    snprintf(filepath, sizeof(filepath), "%s/%s", path, entry->d_name); 
     544    while((rv = stat(filepath, &sb)) < 0 && errno == EINTR); 
     545    if(rv == 0) { 
     546      strlcpy(name, entry->d_name, sizeof(name)); 
     547      name[sep - entry->d_name] = '\0'; 
     548      gen = strtoull(sep+1, NULL, 10); 
     549      if(gen > max_gen_count) max_gen_count = gen; 
     550 
     551      if(S_ISDIR(sb.st_mode)) { 
     552        noitL(noit_debug, "<DIR< %s\n", entry->d_name); 
     553        child = xmlNewNode(NULL, (xmlChar *)name); 
     554        noit_conf_read_into_node(child, filepath); 
     555        udata = calloc(1, sizeof(*udata)); 
     556        udata->name = strdup(name); 
     557        udata->path = strdup(filepath); 
     558        child->_private = udata; 
     559        xmlAddChild(node, child); 
     560      } 
     561      else if(S_ISREG(sb.st_mode)) { 
     562        xmlDocPtr cdoc; 
     563        xmlNodePtr cnode = NULL; 
     564        noitL(noit_debug, "<FILE< %s\n", entry->d_name); 
     565        cdoc = xmlParseFile(filepath); 
     566        if(cdoc) { 
     567          cnode = xmlDocGetRootElement(cdoc); 
     568          xmlDocSetRootElement(cdoc, xmlNewNode(NULL, (xmlChar *)"dummy")); 
     569          if(cnode) { 
     570            udata = calloc(1, sizeof(*udata)); 
     571            udata->name = strdup(name); 
     572            udata->path = strdup(filepath); 
     573            cnode->_private = udata; 
     574            xmlAddChild(node, cnode); 
     575          } 
     576          xmlFreeDoc(cdoc); 
     577        } 
     578      } 
     579    } 
     580  } 
     581  closedir(dirroot); 
     582  return 0; 
     583} 
     584 
     585xmlDocPtr 
     586noit_conf_read_backing_store(const char *path) { 
     587  xmlDocPtr doc; 
     588  xmlNodePtr root; 
     589  noit_xml_userdata_t *what; 
     590 
     591  doc = xmlNewDoc((xmlChar *)"1.0"); 
     592  what = calloc(1, sizeof(*what)); 
     593  what->path = strdup(path); 
     594  doc->_private = what; 
     595  root = xmlNewNode(NULL, (xmlChar *)"stub"); 
     596  xmlDocSetRootElement(doc, root); 
     597  noit_conf_read_into_node(root, path); 
     598  return doc; 
     599} 
    274600int 
    275601noit_conf_magic_mix(const char *parentfile, xmlDocPtr doc) { 
     
    280606 
    281607  assert(config_include_cnt == -1); 
    282  
     608  assert(backingstore_include_cnt == -1); 
     609 
     610  backingstore_include_cnt = 0; 
     611  mix_ctxt = xmlXPathNewContext(doc); 
     612  pobj = xmlXPathEval((xmlChar *)"//*[@backingstore]", mix_ctxt); 
     613  if(!pobj) goto includes; 
     614  if(pobj->type != XPATH_NODESET) goto includes; 
     615  if(xmlXPathNodeSetIsEmpty(pobj->nodesetval)) goto includes; 
     616  cnt = xmlXPathNodeSetGetLength(pobj->nodesetval); 
     617  if(cnt > 0) 
     618    backingstore_include_nodes = calloc(cnt, sizeof(*backingstore_include_nodes)); 
     619  for(i=0; i<cnt; i++) { 
     620    char *path, *infile; 
     621    node = xmlXPathNodeSetItem(pobj->nodesetval, i); 
     622    path = (char *)xmlGetProp(node, (xmlChar *)"backingstore"); 
     623    if(!path) continue; 
     624    if(*path == '/') infile = strdup(path); 
     625    else { 
     626      char *cp; 
     627      infile = malloc(PATH_MAX); 
     628      strlcpy(infile, parentfile, PATH_MAX); 
     629      for(cp = infile + strlen(infile) - 1; cp > infile; cp--) { 
     630        if(*cp == '/') { *cp = '\0'; break; } 
     631        else *cp = '\0'; 
     632      } 
     633      strlcat(infile, "/", PATH_MAX); 
     634      strlcat(infile, path, PATH_MAX); 
     635    } 
     636    xmlFree(path); 
     637    backingstore_include_nodes[i].doc = noit_conf_read_backing_store(infile); 
     638    if(backingstore_include_nodes[i].doc) { 
     639      xmlNodePtr n, lchild; 
     640      backingstore_include_nodes[i].insertion_point = node; 
     641      backingstore_include_nodes[i].root = xmlDocGetRootElement(backingstore_include_nodes[i].doc); 
     642      /* for backing store, they are permanently reattached under the backing store. 
     643       * so for any children, we need to glue them into the new parent document. 
     644       */ 
     645      lchild = backingstore_include_nodes[i].root->children; 
     646      while(lchild && lchild->next) lchild = lchild->next; 
     647      if(lchild) { 
     648        lchild->next = node->children; 
     649        if(node->children) node->children->prev = lchild; 
     650      } 
     651      else 
     652        backingstore_include_nodes[i].root->children = node->children; 
     653      for(n=node->children; n; n = n->next) { 
     654        n->parent = backingstore_include_nodes[i].root; /* this gets mapped right back, just for clarity */ 
     655        n->doc = backingstore_include_nodes[i].doc; 
     656      } 
     657      backingstore_include_nodes[i].old_children = NULL; 
     658      node->children = backingstore_include_nodes[i].root->children; 
     659      for(n=node->children; n; n = n->next) { 
     660        n->parent = backingstore_include_nodes[i].insertion_point; 
     661        n->parent->last = n; 
     662      } 
     663    } 
     664    else { 
     665      noitL(noit_error, "Could not load: '%s'\n", infile); 
     666      rv = -1; 
     667    } 
     668    free(infile); 
     669  } 
     670  mix_ctxt = xmlXPathNewContext(doc); 
     671  backingstore_include_cnt = cnt; 
     672  noitL(noit_debug, "Processed %d backing stores.\n", backingstore_include_cnt); 
     673  if(pobj) xmlXPathFreeObject(pobj); 
     674 
     675 includes: 
    283676  config_include_cnt = 0; 
    284   mix_ctxt = xmlXPathNewContext(doc); 
    285677  pobj = xmlXPathEval((xmlChar *)"//include[@file]", mix_ctxt); 
    286678  if(!pobj) goto out; 
     
    8501242  } 
    8511243  noit_conf_kansas_city_shuffle_undo(master_config); 
     1244  noit_conf_shatter_write(master_config); 
    8521245  len = xmlSaveFormatFileTo(out, master_config, "utf8", 1); 
     1246  noit_conf_shatter_postwrite(master_config); 
    8531247  noit_conf_kansas_city_shuffle_redo(master_config); 
    8541248  close(fd); 
     
    9031297  xmlCharEncodingHandlerPtr enc; 
    9041298  struct config_line_vstr *clv; 
     1299  noit_boolean notify_only = noit_false; 
     1300  const char *v; 
    9051301  SETUP_LOG(config, return -1); 
     1302  v = noit_log_stream_get_property(config_log, "notify_only"); 
     1303  if(v && !strcmp(v, "on")) notify_only = noit_true; 
    9061304 
    9071305  /* We know we haven't changed */ 
    9081306  if(last_write_gen == __config_gen) return 0; 
    909  
    9101307  gettimeofday(&__now, NULL); 
     1308 
     1309  if(notify_only) { 
     1310    noitL(config_log, "n\t%lu.%03lu\t%d\t\n", 
     1311          (unsigned long int)__now.tv_sec, 
     1312          (unsigned long int)__now.tv_usec / 1000UL, 0); 
     1313    last_write_gen = __config_gen; 
     1314    return 0; 
     1315  } 
     1316 
    9111317  clv = calloc(1, sizeof(*clv)); 
    9121318  clv->target = CONFIG_B64; 
     
    12151621  if(delete) { 
    12161622    node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, 0); 
     1623    CONF_REMOVE(node); 
    12171624    xmlUnlinkNode(node); 
    12181625    noit_conf_mark_changed(); 
  • src/noit_conf.h

    rc6c11c3 r80f4747  
    133133API_EXPORT(int) noit_conf_log_init_rotate(const char *, noit_boolean); 
    134134 
     135API_EXPORT(void) noit_conf_backingstore_remove(noit_conf_section_t node); 
     136API_EXPORT(void) noit_conf_backingstore_dirty(noit_conf_section_t node); 
     137 
     138#define CONF_REMOVE(n) do { \ 
     139  noit_conf_backingstore_remove(n); \ 
     140} while(0) 
     141 
     142#define CONF_DIRTY(n) do { \ 
     143 noit_conf_backingstore_dirty(n); \ 
     144 noit_conf_mark_changed(); \ 
     145} while(0) 
     146 
    135147#define EXPOSE_CHECKER(name) \ 
    136148  API_EXPORT(pcre *) noit_conf_get_valid_##name##_checker() 
  • src/noit_conf_checks.c

    r022178b r8e9cf57  
    173173    if(val) 
    174174      xmlSetProp(node, (xmlChar *)attrinfo->name, (xmlChar *)val); 
     175    CONF_DIRTY(node); 
    175176    noit_conf_mark_changed(); 
    176177  } 
     
    212213    } 
    213214    else { 
     215      CONF_DIRTY(newnode); 
    214216      noit_conf_mark_changed(); 
    215217      rv = 0; 
     
    586588        for(j=1;j<argc;j++) 
    587589          xmlUnsetProp(node, (xmlChar *)argv[j]); 
     590        CONF_DIRTY(node); 
    588591      } else { 
    589592        nc_printf(ncct, "descheduling %s\n", uuid_conf); 
    590593        noit_poller_deschedule(checkid); 
     594        CONF_REMOVE(node); 
    591595        xmlUnlinkNode(node); 
    592596      } 
     
    904908    xmlNodePtr toremove; 
    905909    toremove = xmlXPathNodeSetItem(pobj->nodesetval, 0); 
     910    CONF_REMOVE(toremove); 
    906911    xmlUnlinkNode(toremove); 
    907912  } 
     
    934939    /* Now we create a child */ 
    935940    xmlNewChild(confignode, NULL, (xmlChar *)name, (xmlChar *)value); 
     941    CONF_DIRTY(confignode); 
    936942  } 
    937943  noit_conf_mark_changed(); 
     
    10061012  if(value) 
    10071013    xmlSetProp(node, (xmlChar *)attrinfo->name, (xmlChar *)value); 
     1014  CONF_DIRTY(node); 
    10081015  noit_conf_mark_changed(); 
    10091016  rv = 0; 
  • src/noit_filters_rest.c

    r637731d r8e9cf57  
    148148  if(!node) goto not_found; 
    149149  if(noit_filter_remove(node) == 0) goto not_found; 
     150  CONF_REMOVE(node); 
    150151  xmlUnlinkNode(node); 
    151152  xmlFreeNode(node); 
  • src/noit_xml.c

    rc30a0fe r8e9cf57  
    3131 */ 
    3232 
     33#include "noit_defines.h" 
    3334#include "noit_xml.h" 
     35#include "utils/noit_log.h" 
     36#include "utils/noit_mkdir.h" 
     37#include <fcntl.h> 
     38#include <unistd.h> 
     39#include <errno.h> 
    3440#include <assert.h> 
    3541 
     
    8591} 
    8692 
     93int 
     94noit_xmlSaveToFile(xmlDocPtr doc, const char *filename) { 
     95  int rv = -1, fd, have_backup = 0, once; 
     96  char tmpfile[PATH_MAX], bakfile[PATH_MAX]; 
     97  xmlOutputBufferPtr out; 
     98  xmlCharEncodingHandlerPtr enc; 
     99 
     100  snprintf(tmpfile, sizeof(tmpfile), "%s.tmp", filename); 
     101  snprintf(bakfile, sizeof(bakfile), "%s.bak", filename); 
     102  once = 1; 
     103 mkbkup: 
     104  if(link(filename, bakfile) == 0) { 
     105    unlink(filename); 
     106    have_backup = 1; 
     107  } 
     108  else if (errno != ENOENT) { 
     109    if(!once) return -1; 
     110    once = 0; 
     111    if(errno == EEXIST) { 
     112      unlink(bakfile); 
     113      goto mkbkup; 
     114    } 
     115    noitL(noit_error, "Cannot create backup for %s: %s\n", 
     116          filename, strerror(errno)); 
     117    return -1; 
     118  } 
     119  else { 
     120    noitL(noit_debug, "link(%s,%s) -> %s\n", filename, bakfile, strerror(errno)); 
     121  } 
     122 
     123 retry: 
     124  fd = open(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0640); 
     125  if(fd < 0) { 
     126    if(!once) return -1; 
     127    once = 0; 
     128    if(errno == ENOENT) { 
     129      if(mkdir_for_file(tmpfile, 0750) == 0) goto retry; 
     130    } 
     131    if(errno == EEXIST) { 
     132      unlink(tmpfile); 
     133      goto retry; 
     134    } 
     135    return -1; 
     136  } 
     137  enc = xmlGetCharEncodingHandler(XML_CHAR_ENCODING_UTF8); 
     138  out = xmlOutputBufferCreateFd(fd, enc); 
     139  assert(out); 
     140  xmlSaveFormatFileTo(out, doc, "utf8", 1); 
     141  close(fd); 
     142  rv = 0; 
     143  if(link(tmpfile, filename)) { 
     144    rv = -1; 
     145    if(link(bakfile, filename) != 0) have_backup = 0; 
     146  } 
     147  unlink(tmpfile); 
     148  if(have_backup) 
     149    unlink(bakfile); 
     150  return rv; 
     151} 
  • src/noit_xml.h

    rea6ba41 r8e9cf57  
    4040  noit_xmlSaveToBuffer(xmlDocPtr doc); 
    4141 
     42API_EXPORT(int) 
     43  noit_xmlSaveToFile(xmlDocPtr doc, const char *filename); 
     44 
    4245#endif 
  • src/stratcon_jlog_streamer.c

    r39120ca r8e9cf57  
    14631463      pthread_mutex_unlock(&noit_ip_by_cn_lock); 
    14641464    } 
     1465    CONF_REMOVE(noit_configs[i]); 
    14651466    xmlUnlinkNode(noit_configs[i]); 
    14661467    xmlFreeNode(noit_configs[i]);