Changeset 8ad126b7390d75e24ecc859efb01570b01bbcdc1

Show
Ignore:
Timestamp:
10/02/09 00:20:36 (5 years ago)
Author:
Theo Schlossnagle <jesus@omniti.com>
git-committer:
Theo Schlossnagle <jesus@omniti.com> 1254442836 +0000
git-parent:

[cec1cb615495ea336dfb3d405ee59926b654fa1f]

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

This is pretty intrusive.

Here we refactor the console initalization in noit_conf_checks to have
the reusable parts pulled into the noit_conf directly so that stratcon
can make use of them. noit_conf_checks is retooled to extend that and
override the 'ls' command to have it's old form and function.

stratcon_jlog_streamer extends the noit_conf console syntax to allow
adding and removing of noits within the 'configure terminal' mode.

# conf t
# noit 10.1.2.3
# noit 10.1.5.5:12345
# no noit 10.1.2.3
# no noit 10.1.5.5:12345

This should not change the operation of noitd's console in any way;
however, the changes were quite substantial, so we should keep an eye
out for collateral breakage.

refs #195

Files:

Legend:

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

    r25fec2c r8ad126b  
    5353static noit_hash_table _tmp_config = NOIT_HASH_EMPTY; 
    5454static xmlDocPtr master_config = NULL; 
     55static char *root_node_name = NULL; 
    5556static char master_config_file[PATH_MAX] = ""; 
    5657static xmlXPathContextPtr xpath_ctxt = NULL; 
     
    174175int noit_conf_load(const char *path) { 
    175176  xmlDocPtr new_config; 
     177  xmlNodePtr root; 
    176178  new_config = xmlParseFile(path); 
    177179  if(new_config) { 
     180    root = xmlDocGetRootElement(new_config); 
     181    if(root_node_name) free(root_node_name); 
     182    root_node_name = strdup((char *)root->name); 
    178183    if(master_config) xmlFreeDoc(master_config); 
    179184    if(xpath_ctxt) xmlXPathFreeContext(xpath_ctxt); 
     
    784789  if(log_configs) free(log_configs); 
    785790} 
     791 
     792static void 
     793conf_t_userdata_free(void *data) { 
     794  noit_conf_t_userdata_t *info = data; 
     795  if(info) { 
     796    if(info->path) free(info->path); 
     797    free(info); 
     798  } 
     799} 
     800 
     801static int 
     802noit_console_state_conf_terminal(noit_console_closure_t ncct, 
     803                                 int argc, char **argv, 
     804                                 noit_console_state_t *state, void *closure) { 
     805  noit_conf_t_userdata_t *info; 
     806  if(argc) { 
     807    nc_printf(ncct, "extra arguments not expected.\n"); 
     808    return -1; 
     809  } 
     810  info = calloc(1, sizeof(*info)); 
     811  info->path = strdup("/"); 
     812  noit_console_userdata_set(ncct, NOIT_CONF_T_USERDATA, info, 
     813                            conf_t_userdata_free); 
     814  noit_console_state_push_state(ncct, state); 
     815  noit_console_state_init(ncct); 
     816  return 0; 
     817} 
     818static int 
     819noit_console_config_section(noit_console_closure_t ncct, 
     820                            int argc, char **argv, 
     821                            noit_console_state_t *state, void *closure) { 
     822  const char *err = "internal error"; 
     823  char *path, xpath[1024]; 
     824  noit_conf_t_userdata_t *info; 
     825  xmlXPathObjectPtr pobj = NULL; 
     826  xmlXPathContextPtr xpath_ctxt = NULL; 
     827  xmlNodePtr node = NULL, newnode; 
     828  vpsized_int delete = (vpsized_int)closure; 
     829 
     830  noit_conf_xml_xpath(NULL, &xpath_ctxt); 
     831  if(argc != 1) { 
     832    nc_printf(ncct, "requires one argument\n"); 
     833    return -1; 
     834  } 
     835  if(strchr(argv[0], '/')) { 
     836    nc_printf(ncct, "invalid section name\n"); 
     837    return -1; 
     838  } 
     839  if(!strcmp(argv[0], "check") || 
     840     !strcmp(argv[0], "noit") || 
     841     !strcmp(argv[0], "filterset") || 
     842     !strcmp(argv[0], "config")) { 
     843    nc_printf(ncct, "%s is reserved.\n", argv[0]); 
     844    return -1; 
     845  } 
     846  info = noit_console_userdata_get(ncct, NOIT_CONF_T_USERDATA); 
     847  if(!strcmp(info->path, "/")) { 
     848    nc_printf(ncct, "manipulation of toplevel section disallowed\n"); 
     849    return -1; 
     850  } 
     851 
     852  if(delete) { 
     853    /* We cannot delete if we have checks */ 
     854    snprintf(xpath, sizeof(xpath), "/%s%s/%s//check", root_node_name, 
     855             info->path, argv[0]); 
     856    pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt); 
     857    if(!pobj || pobj->type != XPATH_NODESET || 
     858       !xmlXPathNodeSetIsEmpty(pobj->nodesetval)) { 
     859      err = "cannot delete section, has checks"; 
     860      goto bad; 
     861    } 
     862    if(pobj) xmlXPathFreeObject(pobj); 
     863  } 
     864 
     865  snprintf(xpath, sizeof(xpath), "/%s%s/%s", root_node_name, 
     866           info->path, argv[0]); 
     867  pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt); 
     868  if(!pobj || pobj->type != XPATH_NODESET) { 
     869    err = "internal error: cannot detect section"; 
     870    goto bad; 
     871  } 
     872  if(!delete && !xmlXPathNodeSetIsEmpty(pobj->nodesetval)) { 
     873    if(xmlXPathNodeSetGetLength(pobj->nodesetval) == 1) { 
     874      node = xmlXPathNodeSetItem(pobj->nodesetval, 0); 
     875      if(info->path) free(info->path); 
     876      info->path = strdup((char *)xmlGetNodePath(node) + 
     877                          1 + strlen(root_node_name)); 
     878      goto cdout; 
     879    } 
     880    err = "cannot create section"; 
     881    goto bad; 
     882  } 
     883  if(delete && xmlXPathNodeSetIsEmpty(pobj->nodesetval)) { 
     884    err = "no such section"; 
     885    goto bad; 
     886  } 
     887  if(delete) { 
     888    node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, 0); 
     889    xmlUnlinkNode(node); 
     890    noit_conf_mark_changed(); 
     891    return 0; 
     892  } 
     893  if(pobj) xmlXPathFreeObject(pobj); 
     894 
     895  path = strcmp(info->path, "/") ? info->path : ""; 
     896  snprintf(xpath, sizeof(xpath), "/%s%s", root_node_name, path); 
     897  pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt); 
     898  if(!pobj || pobj->type != XPATH_NODESET || 
     899     xmlXPathNodeSetGetLength(pobj->nodesetval) != 1) { 
     900    err = "path invalid?"; 
     901    goto bad; 
     902  } 
     903  node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, 0); 
     904  if((newnode = xmlNewChild(node, NULL, (xmlChar *)argv[0], NULL)) != NULL) { 
     905    noit_conf_mark_changed(); 
     906    if(info->path) free(info->path); 
     907    info->path = strdup((char *)xmlGetNodePath(newnode) + 1 + 
     908                        strlen(root_node_name)); 
     909  } 
     910  else { 
     911    err = "failed to create section"; 
     912    goto bad; 
     913  } 
     914 cdout: 
     915  if(pobj) xmlXPathFreeObject(pobj); 
     916  return 0; 
     917 bad: 
     918  if(pobj) xmlXPathFreeObject(pobj); 
     919  nc_printf(ncct, "%s\n", err); 
     920  return -1; 
     921} 
     922 
     923int 
     924noit_console_generic_show(noit_console_closure_t ncct, 
     925                          int argc, char **argv, 
     926                          noit_console_state_t *state, void *closure) { 
     927  int i, cnt, titled = 0, cliplen = 0; 
     928  const char *path = "", *basepath = NULL; 
     929  char xpath[1024]; 
     930  noit_conf_t_userdata_t *info = NULL; 
     931  xmlXPathObjectPtr pobj = NULL; 
     932  xmlXPathContextPtr xpath_ctxt = NULL, current_ctxt; 
     933  xmlDocPtr master_config = NULL; 
     934  xmlNodePtr node = NULL; 
     935 
     936  noit_conf_xml_xpath(&master_config, &xpath_ctxt); 
     937  if(argc > 1) { 
     938    nc_printf(ncct, "too many arguments\n"); 
     939    return -1; 
     940  } 
     941 
     942  info = noit_console_userdata_get(ncct, NOIT_CONF_T_USERDATA); 
     943  if(info) path = basepath = info->path; 
     944  if(!info && argc == 0) { 
     945    nc_printf(ncct, "argument required when not in configuration mode\n"); 
     946    return -1; 
     947  } 
     948 
     949  if(argc == 1) path = argv[0]; 
     950  if(!basepath) basepath = path; 
     951 
     952  /* { / } is a special case */ 
     953  if(!strcmp(basepath, "/")) basepath = ""; 
     954  if(!strcmp(path, "/")) path = ""; 
     955 
     956  if(!master_config) { 
     957    nc_printf(ncct, "no config\n"); 
     958    return -1; 
     959  } 
     960 
     961  /* { / } is the only path that will end with a / 
     962   * in XPath { / / * } means something _entirely different than { / * } 
     963   * Ever notice how it is hard to describe xpath in C comments? 
     964   */ 
     965  /* We don't want to show the root node */ 
     966  cliplen = strlen(root_node_name) + 2; /* /name/ */ 
     967 
     968  /* If we are in configuration mode 
     969   * and we are without an argument or the argument is absolute, 
     970   * clip the current path off */ 
     971  if(info && (argc == 0 || path[0] != '/')) cliplen += strlen(basepath); 
     972  if(!path[0] || path[0] == '/') /* base only, or absolute path requested */ 
     973    snprintf(xpath, sizeof(xpath), "/%s%s/@*", root_node_name, path); 
     974  else 
     975    snprintf(xpath, sizeof(xpath), "/%s%s/%s/@*", root_node_name, 
     976             basepath, path); 
     977 
     978  current_ctxt = xpath_ctxt; 
     979  pobj = xmlXPathEval((xmlChar *)xpath, current_ctxt); 
     980  if(!pobj || pobj->type != XPATH_NODESET) { 
     981    nc_printf(ncct, "no such object\n"); 
     982    goto bad; 
     983  } 
     984  cnt = xmlXPathNodeSetGetLength(pobj->nodesetval); 
     985  titled = 0; 
     986  for(i=0; i<cnt; i++) { 
     987    node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, i); 
     988    if(node->children && node->children == xmlGetLastChild(node) && 
     989      xmlNodeIsText(node->children)) { 
     990      if(!titled++) nc_printf(ncct, "== Section Settings ==\n"); 
     991      nc_printf(ncct, "%s: %s\n", xmlGetNodePath(node) + cliplen, 
     992                xmlXPathCastNodeToString(node->children)); 
     993    } 
     994  } 
     995  xmlXPathFreeObject(pobj); 
     996 
     997  /* _shorten string_ turning last { / @ * } to { / * } */ 
     998  if(!path[0] || path[0] == '/') /* base only, or absolute path requested */ 
     999    snprintf(xpath, sizeof(xpath), "/%s%s/*", root_node_name, path); 
     1000  else 
     1001    snprintf(xpath, sizeof(xpath), "/%s%s/%s/*", 
     1002             root_node_name, basepath, path); 
     1003  pobj = xmlXPathEval((xmlChar *)xpath, current_ctxt); 
     1004  if(!pobj || pobj->type != XPATH_NODESET) { 
     1005    nc_printf(ncct, "no such object\n"); 
     1006    goto bad; 
     1007  } 
     1008  cnt = xmlXPathNodeSetGetLength(pobj->nodesetval); 
     1009  titled = 0; 
     1010  for(i=0; i<cnt; i++) { 
     1011    node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, i); 
     1012    if(!(node->children && node->children == xmlGetLastChild(node) && 
     1013         xmlNodeIsText(node->children))) { 
     1014      if(!titled++) nc_printf(ncct, "== Subsections ==\n"); 
     1015      nc_printf(ncct, "%s\n", xmlGetNodePath(node) + cliplen); 
     1016    } 
     1017  } 
     1018  xmlXPathFreeObject(pobj); 
     1019  return 0; 
     1020 bad: 
     1021  if(pobj) xmlXPathFreeObject(pobj); 
     1022  return -1; 
     1023} 
     1024int 
     1025noit_console_config_cd(noit_console_closure_t ncct, 
     1026                       int argc, char **argv, 
     1027                       noit_console_state_t *state, void *closure) { 
     1028  const char *err = "internal error"; 
     1029  char *path, xpath[1024]; 
     1030  noit_conf_t_userdata_t *info; 
     1031  xmlXPathObjectPtr pobj = NULL; 
     1032  xmlXPathContextPtr xpath_ctxt = NULL, current_ctxt; 
     1033  xmlNodePtr node = NULL; 
     1034  char *dest; 
     1035 
     1036  noit_conf_xml_xpath(NULL, &xpath_ctxt); 
     1037  if(argc != 1 && !closure) { 
     1038    nc_printf(ncct, "requires one argument\n"); 
     1039    return -1; 
     1040  } 
     1041  dest = argc ? argv[0] : (char *)closure; 
     1042  info = noit_console_userdata_get(ncct, NOIT_CONF_T_USERDATA); 
     1043  if(dest[0] == '/') 
     1044    snprintf(xpath, sizeof(xpath), "/%s%s", root_node_name, dest); 
     1045  else { 
     1046    snprintf(xpath, sizeof(xpath), "/%s%s/%s", root_node_name, 
     1047             info->path, dest); 
     1048  } 
     1049  if(xpath[strlen(xpath)-1] == '/') xpath[strlen(xpath)-1] = '\0'; 
     1050 
     1051  current_ctxt = xpath_ctxt; 
     1052  pobj = xmlXPathEval((xmlChar *)xpath, current_ctxt); 
     1053  if(!pobj || pobj->type != XPATH_NODESET || 
     1054     xmlXPathNodeSetIsEmpty(pobj->nodesetval)) { 
     1055    err = "no such section"; 
     1056    goto bad; 
     1057  } 
     1058  if(xmlXPathNodeSetGetLength(pobj->nodesetval) > 1) { 
     1059    err = "ambiguous section"; 
     1060    goto bad; 
     1061  } 
     1062 
     1063  node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, 0); 
     1064  if(!strcmp((char *)node->name, "check") || 
     1065     !strcmp((char *)node->name, "noit") || 
     1066     !strcmp((char *)node->name, "filterset") || 
     1067     !strcmp((char *)node->name, "config")) { 
     1068    err = "reserved word"; 
     1069    goto bad; 
     1070  } 
     1071  path = (char *)xmlGetNodePath(node); 
     1072  if(strlen(path) < strlen(root_node_name) + 1 || 
     1073     strncmp(path + 1, root_node_name, strlen(root_node_name)) || 
     1074     (path[strlen(root_node_name) + 1] != '/' && 
     1075      path[strlen(root_node_name) + 1] != '\0')) { 
     1076    err = "new path outside out tree"; 
     1077    goto bad; 
     1078  } 
     1079  free(info->path); 
     1080  if(!strcmp(path + 1, root_node_name)) 
     1081    info->path = strdup("/"); 
     1082  else 
     1083    info->path = strdup((char *)xmlGetNodePath(node) + 1 + 
     1084                        strlen(root_node_name)); 
     1085  if(pobj) xmlXPathFreeObject(pobj); 
     1086  if(closure) noit_console_state_pop(ncct, argc, argv, NULL, NULL); 
     1087  return 0; 
     1088 bad: 
     1089  if(pobj) xmlXPathFreeObject(pobj); 
     1090  nc_printf(ncct, "%s [%s]\n", err, xpath); 
     1091  return -1; 
     1092} 
     1093 
     1094char * 
     1095conf_t_prompt(EditLine *el) { 
     1096  noit_console_closure_t ncct; 
     1097  noit_conf_t_userdata_t *info; 
     1098  static char *tl = "noit(conf)# "; 
     1099  static char *pfmt = "noit(conf:%s%s)# "; 
     1100  int path_len, max_len; 
     1101 
     1102  el_get(el, EL_USERDATA, (void *)&ncct); 
     1103  if(!ncct) return tl; 
     1104  info = noit_console_userdata_get(ncct, NOIT_CONF_T_USERDATA); 
     1105  if(!info) return tl; 
     1106 
     1107  path_len = strlen(info->path); 
     1108  max_len = sizeof(info->prompt) - (strlen(pfmt) - 4 /* %s%s */) - 1 /* \0 */; 
     1109  if(path_len > max_len) 
     1110    snprintf(info->prompt, sizeof(info->prompt), 
     1111             pfmt, "...", info->path + path_len - max_len + 3 /* ... */); 
     1112  else 
     1113    snprintf(info->prompt, sizeof(info->prompt), pfmt, "", info->path); 
     1114  return info->prompt; 
     1115} 
     1116 
     1117#define NEW_STATE(a) (a) = noit_console_state_alloc() 
     1118#define ADD_CMD(a,cmd,func,ac,ss,c) \ 
     1119  noit_console_state_add_cmd((a), \ 
     1120    NCSCMD(cmd, func, ac, ss, c)) 
     1121#define DELEGATE_CMD(a,cmd,ac,ss) \ 
     1122  noit_console_state_add_cmd((a), \ 
     1123    NCSCMD(cmd, noit_console_state_delegate, ac, ss, NULL)) 
     1124 
     1125void noit_console_conf_init() { 
     1126  noit_console_state_t *tl, *_conf_state, *_conf_t_state, 
     1127                       *_write_state, *_unset_state; 
     1128 
     1129  tl = noit_console_state_initial(); 
     1130 
     1131  /* write <terimal|memory|file> */ 
     1132  NEW_STATE(_write_state); 
     1133  ADD_CMD(_write_state, "terminal", noit_conf_write_terminal, NULL, NULL, NULL); 
     1134  ADD_CMD(_write_state, "file", noit_conf_write_file_console, NULL, NULL, NULL); 
     1135  /* write memory?  It's to a file, but I like router syntax */ 
     1136  ADD_CMD(_write_state, "memory", noit_conf_write_file_console, NULL, NULL, NULL); 
     1137 
     1138  NEW_STATE(_unset_state); 
     1139  ADD_CMD(_unset_state, "section", 
     1140          noit_console_config_section, NULL, NULL, (void *)1); 
     1141 
     1142  NEW_STATE(_conf_t_state);  
     1143  _conf_t_state->console_prompt_function = conf_t_prompt; 
     1144  noit_console_state_add_cmd(_conf_t_state, &console_command_exit); 
     1145 
     1146  ADD_CMD(_conf_t_state, "ls", noit_console_generic_show, NULL, NULL, NULL); 
     1147  ADD_CMD(_conf_t_state, "cd", noit_console_config_cd, NULL, NULL, NULL); 
     1148  ADD_CMD(_conf_t_state, "section", 
     1149          noit_console_config_section, NULL, NULL, (void *)0); 
     1150 
     1151  DELEGATE_CMD(_conf_t_state, "write", 
     1152               noit_console_opt_delegate, _write_state); 
     1153  DELEGATE_CMD(_conf_t_state, "no", noit_console_opt_delegate, _unset_state); 
     1154 
     1155  NEW_STATE(_conf_state); 
     1156  ADD_CMD(_conf_state, "terminal", 
     1157          noit_console_state_conf_terminal, NULL, _conf_t_state, NULL); 
     1158 
     1159  ADD_CMD(tl, "configure", 
     1160          noit_console_state_delegate, noit_console_opt_delegate, 
     1161          _conf_state, NULL); 
     1162  ADD_CMD(tl, "write", 
     1163          noit_console_state_delegate, noit_console_opt_delegate, 
     1164          _write_state, NULL); 
     1165} 
     1166 
  • src/noit_conf.h

    r37daa37 r8ad126b  
    6666API_EXPORT(int) noit_conf_save(const char *path); 
    6767API_EXPORT(char *) noit_conf_config_filename(); 
     68 
     69API_EXPORT(void) noit_console_conf_init(); 
    6870 
    6971API_EXPORT(noit_conf_section_t) 
  • src/noit_conf_checks.c

    r37daa37 r8ad126b  
    5252#include "utils/noit_log.h" 
    5353 
    54 static void register_console_config_commands(); 
     54static void register_console_config_check_commands(); 
    5555 
    5656static struct _valid_attr_t { 
     
    9090static noit_hash_table check_attrs = NOIT_HASH_EMPTY; 
    9191 
    92 void noit_conf_checks_init(const char *toplevel) { 
     92void noit_console_conf_checks_init() { 
    9393  int i; 
    9494  for(i=0;i<sizeof(valid_attrs)/sizeof(*valid_attrs);i++) { 
     
    9797                    &valid_attrs[i]); 
    9898  } 
    99   register_console_config_commands(); 
    100 
    101  
    102 static void 
    103 conf_t_userdata_free(void *data) { 
    104   noit_conf_t_userdata_t *info = data; 
    105   if(info) { 
    106     if(info->path) free(info->path); 
    107     free(info); 
    108   } 
     99  register_console_config_check_commands(); 
    109100} 
    110101 
     
    585576} 
    586577static int 
    587 noit_console_state_conf_terminal(noit_console_closure_t ncct, 
    588                                  int argc, char **argv, 
    589                                  noit_console_state_t *state, void *closure) { 
    590   noit_conf_t_userdata_t *info; 
    591   if(argc) { 
    592     nc_printf(ncct, "extra arguments not expected.\n"); 
    593     return -1; 
    594   } 
    595   info = calloc(1, sizeof(*info)); 
    596   info->path = strdup("/"); 
    597   noit_console_userdata_set(ncct, NOIT_CONF_T_USERDATA, info, 
    598                             conf_t_userdata_free); 
    599   noit_console_state_push_state(ncct, state); 
    600   noit_console_state_init(ncct); 
    601   return 0; 
    602 } 
    603 static int 
    604 noit_console_config_section(noit_console_closure_t ncct, 
    605                             int argc, char **argv, 
    606                             noit_console_state_t *state, void *closure) { 
    607   const char *err = "internal error"; 
    608   char *path, xpath[1024]; 
    609   noit_conf_t_userdata_t *info; 
    610   xmlXPathObjectPtr pobj = NULL; 
    611   xmlXPathContextPtr xpath_ctxt = NULL; 
    612   xmlNodePtr node = NULL, newnode; 
    613   vpsized_int delete = (vpsized_int)closure; 
    614  
    615   noit_conf_xml_xpath(NULL, &xpath_ctxt); 
    616   if(argc != 1) { 
    617     nc_printf(ncct, "requires one argument\n"); 
    618     return -1; 
    619   } 
    620   if(strchr(argv[0], '/')) { 
    621     nc_printf(ncct, "invalid section name\n"); 
    622     return -1; 
    623   } 
    624   if(!strcmp(argv[0], "check")) { 
    625     nc_printf(ncct, "use 'check' to create checks\n"); 
    626     return -1; 
    627   } 
    628   if(!strcmp(argv[0], "filterset")) { 
    629     nc_printf(ncct, "use 'filterset' to create checks\n"); 
    630     return -1; 
    631   } 
    632   if(!strcmp(argv[0], "config")) { 
    633     nc_printf(ncct, "use 'config' to set check config options\n"); 
    634     return -1; 
    635   } 
    636   info = noit_console_userdata_get(ncct, NOIT_CONF_T_USERDATA); 
    637   if(!strcmp(info->path, "/")) { 
    638     nc_printf(ncct, "manipulation of toplevel section disallowed\n"); 
    639     return -1; 
    640   } 
    641  
    642   if(delete) { 
    643     /* We cannot delete if we have checks */ 
    644     snprintf(xpath, sizeof(xpath), "/noit%s/%s//check", info->path, argv[0]); 
    645     pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt); 
    646     if(!pobj || pobj->type != XPATH_NODESET || 
    647        !xmlXPathNodeSetIsEmpty(pobj->nodesetval)) { 
    648       err = "cannot delete section, has checks"; 
    649       goto bad; 
    650     } 
    651     if(pobj) xmlXPathFreeObject(pobj); 
    652   } 
    653  
    654   snprintf(xpath, sizeof(xpath), "/noit%s/%s", info->path, argv[0]); 
    655   pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt); 
    656   if(!pobj || pobj->type != XPATH_NODESET) { 
    657     err = "internal error: cannot detect section"; 
    658     goto bad; 
    659   } 
    660   if(!delete && !xmlXPathNodeSetIsEmpty(pobj->nodesetval)) { 
    661     if(xmlXPathNodeSetGetLength(pobj->nodesetval) == 1) { 
    662       node = xmlXPathNodeSetItem(pobj->nodesetval, 0); 
    663       if(info->path) free(info->path); 
    664       info->path = strdup((char *)xmlGetNodePath(node) + strlen("/noit")); 
    665       goto cdout; 
    666     } 
    667     err = "cannot create section"; 
    668     goto bad; 
    669   } 
    670   if(delete && xmlXPathNodeSetIsEmpty(pobj->nodesetval)) { 
    671     err = "no such section"; 
    672     goto bad; 
    673   } 
    674   if(delete) { 
    675     node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, 0); 
    676     xmlUnlinkNode(node); 
    677     noit_conf_mark_changed(); 
    678     return 0; 
    679   } 
    680   if(pobj) xmlXPathFreeObject(pobj); 
    681  
    682   path = strcmp(info->path, "/") ? info->path : ""; 
    683   snprintf(xpath, sizeof(xpath), "/noit%s", path); 
    684   pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt); 
    685   if(!pobj || pobj->type != XPATH_NODESET || 
    686      xmlXPathNodeSetGetLength(pobj->nodesetval) != 1) { 
    687     err = "path invalid?"; 
    688     goto bad; 
    689   } 
    690   node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, 0); 
    691   if((newnode = xmlNewChild(node, NULL, (xmlChar *)argv[0], NULL)) != NULL) { 
    692     noit_conf_mark_changed(); 
    693     if(info->path) free(info->path); 
    694     info->path = strdup((char *)xmlGetNodePath(newnode) + strlen("/noit")); 
    695   } 
    696   else { 
    697     err = "failed to create section"; 
    698     goto bad; 
    699   } 
    700  cdout: 
    701   if(pobj) xmlXPathFreeObject(pobj); 
    702   return 0; 
    703  bad: 
    704   if(pobj) xmlXPathFreeObject(pobj); 
    705   nc_printf(ncct, "%s\n", err); 
    706   return -1; 
    707 } 
    708  
    709 int 
    710 noit_console_config_cd(noit_console_closure_t ncct, 
    711                        int argc, char **argv, 
    712                        noit_console_state_t *state, void *closure) { 
    713   const char *err = "internal error"; 
    714   char *path, xpath[1024]; 
    715   noit_conf_t_userdata_t *info; 
    716   xmlXPathObjectPtr pobj = NULL; 
    717   xmlXPathContextPtr xpath_ctxt = NULL, current_ctxt; 
    718   xmlNodePtr node = NULL; 
    719   char *dest; 
    720  
    721   noit_conf_xml_xpath(NULL, &xpath_ctxt); 
    722   if(argc != 1 && !closure) { 
    723     nc_printf(ncct, "requires one argument\n"); 
    724     return -1; 
    725   } 
    726   dest = argc ? argv[0] : (char *)closure; 
    727   info = noit_console_userdata_get(ncct, NOIT_CONF_T_USERDATA); 
    728   if(dest[0] == '/') 
    729     snprintf(xpath, sizeof(xpath), "/noit%s", dest); 
    730   else { 
    731     snprintf(xpath, sizeof(xpath), "/noit%s/%s", info->path, dest); 
    732   } 
    733   if(xpath[strlen(xpath)-1] == '/') xpath[strlen(xpath)-1] = '\0'; 
    734  
    735   current_ctxt = xpath_ctxt; 
    736   pobj = xmlXPathEval((xmlChar *)xpath, current_ctxt); 
    737   if(!pobj || pobj->type != XPATH_NODESET || 
    738      xmlXPathNodeSetIsEmpty(pobj->nodesetval)) { 
    739     err = "no such section"; 
    740     goto bad; 
    741   } 
    742   if(xmlXPathNodeSetGetLength(pobj->nodesetval) > 1) { 
    743     err = "ambiguous section"; 
    744     goto bad; 
    745   } 
    746  
    747   node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, 0); 
    748   if(!strcmp((char *)node->name, "check")) { 
    749     err = "can't cd into a check, use 'check' instead"; 
    750     goto bad; 
    751   } 
    752   path = (char *)xmlGetNodePath(node); 
    753   if(strncmp(path, "/noit/", strlen("/noit/")) && strcmp(path, "/noit")) { 
    754     err = "new path outside out tree"; 
    755     goto bad; 
    756   } 
    757   free(info->path); 
    758   if(!strcmp(path, "/noit")) 
    759     info->path = strdup("/"); 
    760   else 
    761     info->path = strdup((char *)xmlGetNodePath(node) + strlen("/noit")); 
    762   if(pobj) xmlXPathFreeObject(pobj); 
    763   if(closure) noit_console_state_pop(ncct, argc, argv, NULL, NULL); 
    764   return 0; 
    765  bad: 
    766   if(pobj) xmlXPathFreeObject(pobj); 
    767   nc_printf(ncct, "%s [%s]\n", err, xpath); 
    768   return -1; 
    769 } 
    770 static int 
    771578noit_console_config_show(noit_console_closure_t ncct, 
    772579                         int argc, char **argv, 
     
    969776    snprintf(info->prompt, sizeof(info->prompt), pfmt, "[", uuid_str, "]"); 
    970777  } 
    971   return info->prompt; 
    972 } 
    973 static char * 
    974 conf_t_prompt(EditLine *el) { 
    975   noit_console_closure_t ncct; 
    976   noit_conf_t_userdata_t *info; 
    977   static char *tl = "noit(conf)# "; 
    978   static char *pfmt = "noit(conf:%s%s)# "; 
    979   int path_len, max_len; 
    980  
    981   el_get(el, EL_USERDATA, (void *)&ncct); 
    982   if(!ncct) return tl; 
    983   info = noit_console_userdata_get(ncct, NOIT_CONF_T_USERDATA); 
    984   if(!info) return tl; 
    985  
    986   path_len = strlen(info->path); 
    987   max_len = sizeof(info->prompt) - (strlen(pfmt) - 4 /* %s%s */) - 1 /* \0 */; 
    988   if(path_len > max_len) 
    989     snprintf(info->prompt, sizeof(info->prompt), 
    990              pfmt, "...", info->path + path_len - max_len + 3 /* ... */); 
    991   else 
    992     snprintf(info->prompt, sizeof(info->prompt), pfmt, "", info->path); 
    993778  return info->prompt; 
    994779} 
     
    13251110 
    13261111static 
    1327 void register_console_config_commands() { 
    1328   cmd_info_t *showcmd, *nocmd; 
    1329   noit_console_state_t *tl, *_conf_state, *_conf_t_state, 
    1330                        *_conf_t_check_state, 
    1331                        *_write_state, *_attr_state, 
    1332                        *_unset_state, *_uattr_state; 
     1112void register_console_config_check_commands() { 
     1113  cmd_info_t *showcmd, *nocmd, *confcmd, *conftcmd, *conftnocmd, *lscmd; 
     1114  noit_console_state_t *tl, *_conf_t_check_state, *_unset_state, 
     1115                       *_attr_state, *_uattr_state; 
    13331116 
    13341117  tl = noit_console_state_initial(); 
    1335  
    1336   /* write <terimal|memory|file> */ 
    1337   NEW_STATE(_write_state); 
    1338   ADD_CMD(_write_state, "terminal", noit_conf_write_terminal, NULL, NULL, NULL); 
    1339   ADD_CMD(_write_state, "file", noit_conf_write_file_console, NULL, NULL, NULL); 
    1340   /* write memory?  It's to a file, but I like router syntax */ 
    1341   ADD_CMD(_write_state, "memory", noit_conf_write_file_console, NULL, NULL, NULL); 
    1342  
     1118  showcmd = noit_console_state_get_cmd(tl, "show"); 
     1119  nocmd = noit_console_state_get_cmd(tl, "no"); 
     1120  confcmd = noit_console_state_get_cmd(tl, "configure"); 
     1121  conftcmd = noit_console_state_get_cmd(confcmd->dstate, "terminal"); 
     1122  conftnocmd = noit_console_state_get_cmd(conftcmd->dstate, "no"); 
     1123  lscmd = noit_console_state_get_cmd(conftcmd->dstate, "ls"); 
     1124  lscmd->func = noit_console_config_show; 
    13431125  /* attribute <attrname> <value> */ 
    13441126  NEW_STATE(_attr_state); 
     
    13501132  noit_console_state_add_check_attrs(_uattr_state, noit_conf_check_unset_attr, 
    13511133                                     "/checks"); 
    1352  
    13531134  NEW_STATE(_unset_state); 
    13541135  DELEGATE_CMD(_unset_state, "attribute", 
    13551136               noit_console_opt_delegate, _uattr_state); 
    1356   ADD_CMD(_unset_state, "section", 
    1357           noit_console_config_section, NULL, NULL, (void *)1); 
    13581137  ADD_CMD(_unset_state, "config", 
    13591138          noit_console_config_unsetconfig, NULL, NULL, NULL); 
    1360   ADD_CMD(_unset_state, "check", 
     1139 
     1140  DELEGATE_CMD(conftnocmd->dstate, "attribute", 
     1141               noit_console_opt_delegate, _uattr_state); 
     1142  ADD_CMD(conftnocmd->dstate, "config", 
     1143          noit_console_config_unsetconfig, NULL, NULL, NULL); 
     1144  ADD_CMD(conftnocmd->dstate, "check", 
    13611145          noit_console_config_nocheck, NULL, NULL, NULL); 
    13621146  
     
    13771161          _conf_t_check_state, ".."); 
    13781162 
    1379   NEW_STATE(_conf_t_state);  
    1380   _conf_t_state->console_prompt_function = conf_t_prompt; 
    1381   noit_console_state_add_cmd(_conf_t_state, &console_command_exit); 
    1382   ADD_CMD(_conf_t_state, "ls", noit_console_config_show, NULL, NULL, NULL); 
    1383   ADD_CMD(_conf_t_state, "cd", noit_console_config_cd, NULL, NULL, NULL); 
    1384   ADD_CMD(_conf_t_state, "config", 
     1163  ADD_CMD(conftcmd->dstate, "config", 
    13851164          noit_console_config_setconfig, NULL, NULL, NULL); 
    1386   ADD_CMD(_conf_t_state, "section", 
    1387           noit_console_config_section, NULL, NULL, (void *)0); 
    1388   ADD_CMD(_conf_t_state, "check", 
     1165  ADD_CMD(conftcmd->dstate, "check", 
    13891166          noit_console_check, noit_console_conf_check_opts, 
    13901167          _conf_t_check_state, NULL); 
    13911168 
    1392   showcmd = noit_console_state_get_cmd(tl, "show"); 
    13931169  ADD_CMD(showcmd->dstate, "check", 
    13941170          noit_console_show_check, noit_console_check_opts, NULL, NULL); 
     
    13971173          noit_console_watch_check, noit_console_check_opts, NULL, (void *)1); 
    13981174 
    1399   nocmd = noit_console_state_get_cmd(tl, "no"); 
    14001175  ADD_CMD(nocmd->dstate, "watch", 
    14011176          noit_console_watch_check, noit_console_check_opts, NULL, (void *)0); 
    14021177 
    1403   DELEGATE_CMD(_conf_t_state, "write", 
    1404                noit_console_opt_delegate, _write_state); 
    1405   DELEGATE_CMD(_conf_t_state, "attribute", 
     1178  DELEGATE_CMD(conftcmd->dstate, "attribute", 
    14061179               noit_console_opt_delegate, _attr_state); 
    1407   DELEGATE_CMD(_conf_t_state, "no", noit_console_opt_delegate, _unset_state); 
    1408  
    1409   NEW_STATE(_conf_state); 
    1410   ADD_CMD(_conf_state, "terminal", 
    1411           noit_console_state_conf_terminal, NULL, _conf_t_state, NULL); 
    1412  
    1413   ADD_CMD(tl, "configure", 
    1414           noit_console_state_delegate, noit_console_opt_delegate, 
    1415           _conf_state, NULL); 
    1416   ADD_CMD(tl, "write", 
    1417           noit_console_state_delegate, noit_console_opt_delegate, 
    1418           _write_state, NULL); 
     1180 
    14191181  ADD_CMD(tl, "reload", noit_conf_checks_reload, NULL, NULL, NULL); 
    14201182} 
  • src/noit_conf_checks.h

    r37daa37 r8ad126b  
    3838#include "noit_console.h" 
    3939 
    40 API_EXPORT(void) noit_conf_checks_init(const char *toplevel); 
     40API_EXPORT(void) noit_console_conf_checks_init(); 
    4141API_EXPORT(int) 
    4242  noit_console_config_cd(noit_console_closure_t ncct, 
  • src/noitd.c

    r75ee62d r8ad126b  
    181181  /* Initialize all of our listeners */ 
    182182  noit_console_init(APPNAME); 
     183  noit_console_conf_init(); 
     184  noit_console_conf_checks_init(); 
    183185  noit_capabilities_listener_init(); 
    184186  noit_jlog_listener_init(); 
     
    226228  /* Next load the configs */ 
    227229  noit_conf_init(APPNAME); 
    228   noit_conf_checks_init(APPNAME); 
    229230  if(noit_conf_load(config_file) == -1) { 
    230231    fprintf(stderr, "Cannot load config: '%s'\n", config_file); 
  • src/stratcon_iep.h

    r88a7178 r8ad126b  
    3838#include "utils/noit_hash.h" 
    3939#include "stratcon_datastore.h" 
     40#include "stratcon_jlog_streamer.h" 
    4041 
    4142#include <sys/types.h> 
     
    4950                              struct sockaddr *remote, void *operand); 
    5051 
     52API_EXPORT(jlog_streamer_ctx_t *) 
     53  stratcon_jlog_streamer_iep_ctx_alloc(void); 
     54 
    5155#endif 
  • src/stratcon_jlog_streamer.c

    r4dd8a48 r8ad126b  
    4040#include "stratcon_datastore.h" 
    4141#include "stratcon_jlog_streamer.h" 
     42#include "stratcon_iep.h" 
    4243 
    4344#include <unistd.h> 
     
    7374nc_print_noit_conn_brief(noit_console_closure_t ncct, 
    7475                          noit_connection_ctx_t *ctx) { 
     76  jlog_streamer_ctx_t *jctx = ctx->consumer_ctx; 
    7577  struct timeval now, diff, session_duration; 
    76   gettimeofday(&now, NULL)
     78  const char *feedtype = "unknown"
    7779  const char *lasttime = "never"; 
    7880  if(ctx->last_connect.tv_sec != 0) { 
     
    8587  } 
    8688  nc_printf(ncct, "%s [%s]:\n\tLast connect: %s\n", ctx->remote_str, 
    87             ctx->timeout_event ? "disconnected" : "connected", lasttime); 
     89            ctx->remote_cn ? "connected" : 
     90                             (ctx->timeout_event ? "disconnected" : 
     91                                                   "connecting"), lasttime); 
     92  switch(ntohl(jctx->jlog_feed_cmd)) { 
     93    case NOIT_JLOG_DATA_FEED: feedtype = "durable/storage"; break; 
     94    case NOIT_JLOG_DATA_TEMP_FEED: feedtype = "transient/iep"; break; 
     95  } 
     96  nc_printf(ncct, "\tJLog event streamer [%s]\n", feedtype); 
     97  gettimeofday(&now, NULL); 
    8898  if(ctx->timeout_event) { 
    89     sub_timeval(now, ctx->timeout_event->whence, &diff); 
    90     nc_printf(ncct, "\tNext attempet in %llu.%06us\n", diff.tv_sec, diff.tv_usec); 
    91   } 
    92   else { 
     99    sub_timeval(ctx->timeout_event->whence, now, &diff); 
     100    nc_printf(ncct, "\tNext attempt in %llu.%06us\n", 
     101              (unsigned long long)diff.tv_sec, (unsigned int) diff.tv_usec); 
     102  } 
     103  else if(ctx->remote_cn) { 
    93104    nc_printf(ncct, "\tRemote CN: '%s'\n", 
    94105              ctx->remote_cn ? ctx->remote_cn : "???"); 
    95106    if(ctx->consumer_callback == stratcon_jlog_recv_handler) { 
    96       jlog_streamer_ctx_t *jctx = ctx->consumer_ctx; 
    97107      struct timeval last; 
    98108      double session_duration_seconds; 
    99       const char *feedtype = "unknown"; 
    100109      const char *state = "unknown"; 
    101110 
    102       switch(ntohl(jctx->jlog_feed_cmd)) { 
    103         case NOIT_JLOG_DATA_FEED: feedtype = "durable/storage"; break; 
    104         case NOIT_JLOG_DATA_TEMP_FEED: feedtype = "transient/iep"; break; 
    105       } 
    106111      switch(jctx->state) { 
    107112        case JLOG_STREAMER_WANT_INITIATE: state = "initiate"; break; 
     
    118123      session_duration_seconds = session_duration.tv_sec + 
    119124                                 (double)session_duration.tv_usec/1000000.0; 
    120       nc_printf(ncct, "\tJLog event streamer [%s]\n\tState: %s\n" 
     125      nc_printf(ncct, "\tState: %s\n" 
    121126                      "\tNext checkpoint: [%08x:%08x]\n" 
    122127                      "\tLast event: %llu.%06us ago\n" 
    123128                      "\tEvents this session: %llu (%0.2f/s)\n" 
    124129                      "\tOctets this session: %llu (%0.2f/s)\n", 
    125                 feedtype, state, 
     130                state, 
    126131                jctx->header.chkpt.log, jctx->header.chkpt.marker, 
    127                 diff.tv_sec, diff.tv_usec, 
     132                (unsigned long long)diff.tv_sec, (unsigned int)diff.tv_usec, 
    128133                jctx->total_events, 
    129134                (double)jctx->total_events/session_duration_seconds, 
     
    743748} 
    744749 
    745 static void 
    746 register_console_streamer_commands() { 
    747   noit_console_state_t *tl; 
    748   cmd_info_t *showcmd; 
    749  
    750   tl = noit_console_state_initial(); 
    751   showcmd = noit_console_state_get_cmd(tl, "show"); 
    752   assert(showcmd && showcmd->dstate); 
    753  
    754   noit_console_state_add_cmd(showcmd->dstate, 
    755     NCSCMD("noits", stratcon_console_show_noits, NULL, NULL, NULL)); 
    756 } 
    757  
    758750static int 
    759751rest_show_noits(noit_http_rest_closure_t *restc, 
     
    794786             (int)ctx->last_connect.tv_usec); 
    795787    xmlSetProp(node, (xmlChar *)"last_connect", (xmlChar *)buff); 
    796     xmlSetProp(node, (xmlChar *)"state", ctx->timeout_event ? 
    797                (xmlChar *)"disconnected" : (xmlChar *)"connected"); 
     788    xmlSetProp(node, (xmlChar *)"state", ctx->remote_cn ? 
     789               (xmlChar *)"connected" : 
     790               (ctx->timeout_event ? (xmlChar *)"disconnected" : 
     791                                    (xmlChar *)"connecting")); 
     792    xmlSetProp(node, (xmlChar *)"remote", (xmlChar *)ctx->remote_str); 
     793    switch(ntohl(jctx->jlog_feed_cmd)) { 
     794      case NOIT_JLOG_DATA_FEED: feedtype = "durable/storage"; break; 
     795      case NOIT_JLOG_DATA_TEMP_FEED: feedtype = "transient/iep"; break; 
     796    } 
     797    xmlSetProp(node, (xmlChar *)"type", (xmlChar *)feedtype); 
    798798    if(ctx->timeout_event) { 
    799       sub_timeval(now, ctx->timeout_event->whence, &diff); 
     799      sub_timeval(ctx->timeout_event->whence, now, &diff); 
    800800      snprintf(buff, sizeof(buff), "%llu.%06d", 
    801801               (long long unsigned)diff.tv_sec, (int)diff.tv_usec); 
    802802      xmlSetProp(node, (xmlChar *)"next_attempt", (xmlChar *)buff); 
    803803    } 
    804     xmlSetProp(node, (xmlChar *)"remote", (xmlChar *)ctx->remote_str); 
    805     if(ctx->remote_cn) 
    806       xmlSetProp(node, (xmlChar *)"remote_cn", (xmlChar *)ctx->remote_cn); 
    807  
    808     switch(ntohl(jctx->jlog_feed_cmd)) { 
    809       case NOIT_JLOG_DATA_FEED: feedtype = "durable/storage"; break; 
    810       case NOIT_JLOG_DATA_TEMP_FEED: feedtype = "transient/iep"; break; 
    811     } 
    812     xmlSetProp(node, (xmlChar *)"type", (xmlChar *)feedtype); 
    813     switch(jctx->state) { 
    814       case JLOG_STREAMER_WANT_INITIATE: state = "initiate"; break; 
    815       case JLOG_STREAMER_WANT_COUNT: state = "waiting for next batch"; break; 
    816       case JLOG_STREAMER_WANT_HEADER: state = "reading header"; break; 
    817       case JLOG_STREAMER_WANT_BODY: state = "reading body"; break; 
    818       case JLOG_STREAMER_IS_ASYNC: state = "asynchronously processing"; break; 
    819       case JLOG_STREAMER_WANT_CHKPT: state = "checkpointing"; break; 
    820     } 
    821     xmlSetProp(node, (xmlChar *)"state", (xmlChar *)state); 
    822     snprintf(buff, sizeof(buff), "%08x:%08x",  
    823              jctx->header.chkpt.log, jctx->header.chkpt.marker); 
    824     xmlSetProp(node, (xmlChar *)"checkpoint", (xmlChar *)buff); 
    825     snprintf(buff, sizeof(buff), "%llu", 
    826              (long long unsigned)jctx->total_events); 
    827     xmlSetProp(node, (xmlChar *)"session_events", (xmlChar *)buff); 
    828     snprintf(buff, sizeof(buff), "%llu", 
    829              (long long unsigned)jctx->total_bytes_read); 
    830     xmlSetProp(node, (xmlChar *)"session_bytes", (xmlChar *)buff); 
    831  
    832     sub_timeval(now, ctx->last_connect, &diff); 
    833     snprintf(buff, sizeof(buff), "%llu.%06d", 
    834              (long long unsigned)diff.tv_sec, (int)diff.tv_usec); 
    835     xmlSetProp(node, (xmlChar *)"session_duration", (xmlChar *)buff); 
    836  
    837     if(jctx->header.tv_sec) { 
    838       last.tv_sec = jctx->header.tv_sec; 
    839       last.tv_usec = jctx->header.tv_usec; 
     804    else if(ctx->remote_cn) { 
     805      if(ctx->remote_cn) 
     806        xmlSetProp(node, (xmlChar *)"remote_cn", (xmlChar *)ctx->remote_cn); 
     807   
     808      switch(jctx->state) { 
     809        case JLOG_STREAMER_WANT_INITIATE: state = "initiate"; break; 
     810        case JLOG_STREAMER_WANT_COUNT: state = "waiting for next batch"; break; 
     811        case JLOG_STREAMER_WANT_HEADER: state = "reading header"; break; 
     812        case JLOG_STREAMER_WANT_BODY: state = "reading body"; break; 
     813        case JLOG_STREAMER_IS_ASYNC: state = "asynchronously processing"; break; 
     814        case JLOG_STREAMER_WANT_CHKPT: state = "checkpointing"; break; 
     815      } 
     816      xmlSetProp(node, (xmlChar *)"state", (xmlChar *)state); 
     817      snprintf(buff, sizeof(buff), "%08x:%08x",  
     818               jctx->header.chkpt.log, jctx->header.chkpt.marker); 
     819      xmlSetProp(node, (xmlChar *)"checkpoint", (xmlChar *)buff); 
     820      snprintf(buff, sizeof(buff), "%llu", 
     821               (unsigned long long)jctx->total_events); 
     822      xmlSetProp(node, (xmlChar *)"session_events", (xmlChar *)buff); 
     823      snprintf(buff, sizeof(buff), "%llu", 
     824               (unsigned long long)jctx->total_bytes_read); 
     825      xmlSetProp(node, (xmlChar *)"session_bytes", (xmlChar *)buff); 
     826   
     827      sub_timeval(now, ctx->last_connect, &diff); 
    840828      snprintf(buff, sizeof(buff), "%llu.%06d", 
    841                (long long unsigned)last.tv_sec, (int)last.tv_usec); 
    842       xmlSetProp(node, (xmlChar *)"last_event", (xmlChar *)buff); 
    843       sub_timeval(now, last, &diff); 
    844       snprintf(buff, sizeof(buff), "%llu.%06d", 
    845                (long long unsigned)diff.tv_sec, (int)diff.tv_usec); 
    846       xmlSetProp(node, (xmlChar *)"last_event_age", (xmlChar *)buff); 
     829               (unsigned long long)diff.tv_sec, (int)diff.tv_usec); 
     830      xmlSetProp(node, (xmlChar *)"session_duration", (xmlChar *)buff); 
     831   
     832      if(jctx->header.tv_sec) { 
     833        last.tv_sec = jctx->header.tv_sec; 
     834        last.tv_usec = jctx->header.tv_usec; 
     835        snprintf(buff, sizeof(buff), "%llu.%06d", 
     836                 (unsigned long long)last.tv_sec, (int)last.tv_usec); 
     837        xmlSetProp(node, (xmlChar *)"last_event", (xmlChar *)buff); 
     838        sub_timeval(now, last, &diff); 
     839        snprintf(buff, sizeof(buff), "%llu.%06d", 
     840                 (unsigned long long)diff.tv_sec, (int)diff.tv_usec); 
     841        xmlSetProp(node, (xmlChar *)"last_event_age", (xmlChar *)buff); 
     842      } 
    847843    } 
    848844 
     
    858854  return 0; 
    859855} 
     856static int 
     857stratcon_add_noit(const char *target, unsigned short port) { 
     858  int cnt; 
     859  char path[256]; 
     860  char port_str[6]; 
     861  noit_conf_section_t *noit_configs, parent; 
     862  xmlNodePtr newnoit; 
     863 
     864  snprintf(path, sizeof(path), 
     865           "//noits//noit[@address=\"%s\" and @port=\"%d\"]", target, port); 
     866  noit_configs = noit_conf_get_sections(NULL, path, &cnt); 
     867  free(noit_configs); 
     868  if(cnt != 0) return 0; 
     869 
     870  parent = noit_conf_get_section(NULL, "//noits"); 
     871  if(!parent) return 0; 
     872  snprintf(port_str, sizeof(port_str), "%d", port); 
     873  newnoit = xmlNewNode(NULL, (xmlChar *)"noit"); 
     874  xmlSetProp(newnoit, (xmlChar *)"address", (xmlChar *)target); 
     875  xmlSetProp(newnoit, (xmlChar *)"port", (xmlChar *)port_str); 
     876  xmlAddChild(parent, newnoit); 
     877  noit_conf_mark_changed(); 
     878  stratcon_streamer_connection(NULL, target, 
     879                               stratcon_jlog_recv_handler, 
     880                               (void *(*)())stratcon_jlog_streamer_datastore_ctx_alloc, 
     881                               NULL, 
     882                               jlog_streamer_ctx_free); 
     883  stratcon_streamer_connection(NULL, target, 
     884                               stratcon_jlog_recv_handler, 
     885                               (void *(*)())stratcon_jlog_streamer_iep_ctx_alloc, 
     886                               NULL, 
     887                               jlog_streamer_ctx_free); 
     888  return 1; 
     889} 
     890static int 
     891stratcon_remove_noit(const char *target, unsigned short port) { 
     892  noit_hash_iter iter = NOIT_HASH_ITER_ZERO; 
     893  uuid_t key_id; 
     894  int klen, n = 0, i, cnt = 0; 
     895  void *vconn; 
     896  noit_connection_ctx_t **ctx; 
     897  noit_conf_section_t *noit_configs; 
     898  char path[256]; 
     899  char remote_str[256]; 
     900 
     901  snprintf(remote_str, sizeof(remote_str), "%s:%d", target, port); 
     902 
     903  snprintf(path, sizeof(path), 
     904           "//noits//noit[@address=\"%s\" and @port=\"%d\"]", target, port); 
     905  noit_configs = noit_conf_get_sections(NULL, path, &cnt); 
     906  for(i=0; i<cnt; i++) { 
     907    xmlUnlinkNode(noit_configs[i]); 
     908    xmlFreeNode(noit_configs[i]); 
     909  } 
     910  free(noit_configs); 
     911  noit_conf_mark_changed(); 
     912 
     913  pthread_mutex_lock(&noits_lock); 
     914  ctx = malloc(sizeof(*ctx) * noits.size); 
     915  while(noit_hash_next(&noits, &iter, (const char **)key_id, &klen, 
     916                       &vconn)) { 
     917    if(!strcmp(((noit_connection_ctx_t *)vconn)->remote_str, remote_str)) { 
     918      ctx[n] = (noit_connection_ctx_t *)vconn; 
     919      noit_atomic_inc32(&ctx[n]->refcnt); 
     920      n++; 
     921    } 
     922  } 
     923  pthread_mutex_unlock(&noits_lock); 
     924  for(i=0; i<n; i++) { 
     925    noit_connection_ctx_dealloc(ctx[i]); /* once for the record */ 
     926    noit_connection_ctx_deref(ctx[i]);   /* once for the aboce inc32 */ 
     927  } 
     928  free(ctx); 
     929  return n; 
     930} 
     931static int 
     932stratcon_console_conf_noits(noit_console_closure_t ncct, 
     933                            int argc, char **argv, 
     934                            noit_console_state_t *dstate, 
     935                            void *closure) { 
     936  char *cp, target[128]; 
     937  unsigned short port = 43191; 
     938  int adding = (int)closure; 
     939  if(argc != 1) 
     940    return -1; 
     941 
     942  cp = strchr(argv[0], ':'); 
     943  if(cp) { 
     944    strlcpy(target, argv[0], MIN(sizeof(target), cp-argv[0]+1)); 
     945    port = atoi(cp+1); 
     946  } 
     947  else strlcpy(target, argv[0], sizeof(target)); 
     948  if(adding) { 
     949    if(stratcon_add_noit(target, port)) { 
     950      nc_printf(ncct, "Added noit at %s:%d\n", target, port); 
     951    } 
     952    else { 
     953      nc_printf(ncct, "Failed to add noit at %s:%d\n", target, port); 
     954    } 
     955  } 
     956  else { 
     957    if(stratcon_remove_noit(target, port)) { 
     958      nc_printf(ncct, "Removed noit at %s:%d\n", target, port); 
     959    } 
     960    else { 
     961      nc_printf(ncct, "Failed to remove noit at %s:%d\n", target, port); 
     962    } 
     963  } 
     964  return 0; 
     965} 
     966 
     967static void 
     968register_console_streamer_commands() { 
     969  noit_console_state_t *tl; 
     970  cmd_info_t *showcmd, *confcmd, *conftcmd, *conftnocmd; 
     971 
     972  tl = noit_console_state_initial(); 
     973  showcmd = noit_console_state_get_cmd(tl, "show"); 
     974  assert(showcmd && showcmd->dstate); 
     975  confcmd = noit_console_state_get_cmd(tl, "configure"); 
     976  conftcmd = noit_console_state_get_cmd(confcmd->dstate, "terminal"); 
     977  conftnocmd = noit_console_state_get_cmd(conftcmd->dstate, "no"); 
     978 
     979  noit_console_state_add_cmd(conftcmd->dstate, 
     980    NCSCMD("noit", stratcon_console_conf_noits, NULL, NULL, (void *)1)); 
     981  noit_console_state_add_cmd(conftnocmd->dstate, 
     982    NCSCMD("noit", stratcon_console_conf_noits, NULL, NULL, (void *)0)); 
     983 
     984  noit_console_state_add_cmd(showcmd->dstate, 
     985    NCSCMD("noits", stratcon_console_show_noits, NULL, NULL, NULL)); 
     986} 
     987 
     988 
    860989void 
    861990stratcon_jlog_streamer_init(const char *toplevel) { 
     
    8751004  ) == 0); 
    8761005} 
     1006 
  • src/stratcond.c

    r8504a3b r8ad126b  
    172172 
    173173  noit_console_init(APPNAME); 
     174  noit_console_conf_init(); 
    174175  noit_http_rest_init(); 
    175176  stratcon_realtime_http_init(APPNAME);