Index: include/pbs_ifl.h =================================================================== --- include/pbs_ifl.h (revision 2) +++ include/pbs_ifl.h (revision 10) @@ -229,9 +229,9 @@ #define ATTR_NODE_ntype "ntype" #define ATTR_NODE_jobs "jobs" #define ATTR_NODE_status "status" +#define ATTR_NODE_comment "comment" - /* various attribute values */ #define CHECKPOINT_UNSPECIFIED "u" @@ -328,7 +328,8 @@ #define PBS_SCHEDULER_SERVICE_PORT 15004 enum batch_op { SET, UNSET, INCR, DECR, - EQ, NE, GE, GT, LE, LT, DFLT + EQ, NE, GE, GT, LE, LT, DFLT, + DECR_BEGIN }; /* Index: include/attribute.h =================================================================== --- include/attribute.h (revision 2) +++ include/attribute.h (revision 10) @@ -284,6 +284,7 @@ #define ATR_ACTION_ALTER 2 #define ATR_ACTION_RECOV 3 #define ATR_ACTION_FREE 4 +#define ATR_ACTION_DEL 5 /* * values for the mode parameter to at_encode(), determines: @@ -410,6 +411,7 @@ extern int acl_check A_((attribute *, char *canidate, int type)); extern char *arst_string A_((char *str, attribute *pattr)); +extern int arst_string_num A_((char *str, attribute *pattr)); extern void attrl_fixlink A_((list_head *svrattrl)); extern void recov_acl A_((attribute *, attribute_def *, char *, char *)); extern int save_acl A_((attribute *, attribute_def *, char *, char *)); @@ -434,6 +436,7 @@ extern int node_ntype A_(( attribute*, void*, int)); extern int node_prop_list A_(( attribute*, void*, int)); extern int node_status_list A_(( attribute*, void*, int)); +extern int node_comment_list A_(( attribute*, void*, int)); /* "type" to pass to acl_check() */ #define ACL_Host 1 Index: include/qmgr_node_public.h =================================================================== --- include/qmgr_node_public.h (revision 2) +++ include/qmgr_node_public.h (revision 10) @@ -94,3 +94,4 @@ ATTR_NODE_properties, ATTR_NODE_ntype, ATTR_NODE_status, +ATTR_NODE_comment, Index: include/pbs_nodes.h =================================================================== --- include/pbs_nodes.h (revision 2) +++ include/pbs_nodes.h (revision 10) @@ -118,13 +118,17 @@ struct prop *nd_last; struct prop *nd_f_st; /* first and last status */ struct prop *nd_l_st; + struct prop *nd_f_cm; /* first and last comment */ + struct prop *nd_l_cm; u_long *nd_addrs; /* IP addresses of host */ struct array_strings *nd_prop; /* array of properities */ struct array_strings *nd_status; + struct array_strings *nd_comment; int nd_stream; /* RPP stream to Mom on host */ enum psit nd_flag; short nd_nprops; /* number of properties */ short nd_nstatus; /* number of status items */ + short nd_ncomment; /* number of comment items */ short nd_nsn; /* number of VPs */ short nd_nsnfree; /* number of VPs free */ short nd_nsnshared; /* number of VPs shared */ @@ -193,6 +197,7 @@ ND_ATR_ntype, ND_ATR_jobs, NODE_ATR_status, + NODE_ATR_comment, ND_ATR_LAST /* WARNING: Must be the highest valued enum */ }; Index: server/node_func.c =================================================================== --- server/node_func.c (revision 2) +++ server/node_func.c (revision 10) @@ -358,10 +358,12 @@ static struct pbsnode *old_address = 0; /*node in question */ static struct prop *old_first = (struct prop *)0xdead; /*node's first prop*/ static struct prop *old_f_st = (struct prop *)0xdead; /*node's first status*/ +static struct prop *old_f_cm = (struct prop *)0xdead; /*node's first comment*/ static short old_state = (short)0xdead; /*node's state */ static short old_ntype = (short)0xdead; /*node's ntype */ static int old_nprops = 0xdead; /*node's nprops */ static int old_nstatus = 0xdead; /*node's nstatus */ +static int old_ncomment = 0xdead; /*node's ncomment */ @@ -386,8 +388,10 @@ old_ntype = pnode->nd_ntype; old_nprops = pnode->nd_nprops; old_nstatus = pnode->nd_nstatus; + old_ncomment = pnode->nd_ncomment; old_first = pnode->nd_first; old_f_st = pnode->nd_f_st; + old_f_cm = pnode->nd_f_cm; return; } /* END save_characteristic() */ @@ -504,6 +508,8 @@ atemp[i].at_val.at_short = pnode->nd_ntype; else if (!strcmp ((padef + i)->at_name, ATTR_NODE_jobs)) atemp[i].at_val.at_jinfo = pnode; + else if (!strcmp ((padef + i)->at_name, ATTR_NODE_comment)) + atemp[i].at_val.at_arst = pnode->nd_comment; else if (!strcmp ((padef + i)->at_name, ATTR_NODE_np)) atemp[i].at_val.at_long = pnode->nd_nsn; else @@ -630,14 +636,18 @@ pnode->nd_order = 0; pnode->nd_prop = (struct array_strings *)0; pnode->nd_status = (struct array_strings *)0; + pnode->nd_comment = (struct array_strings *)0; pnode->nd_psn = NULL; pnode->nd_state = INUSE_UNKNOWN | INUSE_NEEDS_HELLO_PING | INUSE_DOWN; pnode->nd_first = init_prop(pnode->nd_name); pnode->nd_last = pnode->nd_first; pnode->nd_f_st = init_prop(pnode->nd_name); pnode->nd_l_st = pnode->nd_f_st; + pnode->nd_f_cm = init_prop(pnode->nd_name); + pnode->nd_l_cm = pnode->nd_f_cm; pnode->nd_nprops = 0; pnode->nd_nstatus = 0; + pnode->nd_ncomment= 0; pnode->nd_warnbad = 0; for (i = 0;pul[i];i++) Index: server/node_manager.c =================================================================== --- server/node_manager.c (revision 2) +++ server/node_manager.c (revision 10) @@ -461,12 +461,67 @@ np->nd_state &= ~(INUSE_DOWN|INUSE_UNKNOWN|INUSE_NEEDS_HELLO_PING); + /* remove any down comments automatically added */ + /* This is a hack although it does work. + * np->nd_comment = NULL; + */ + if (decode_arst(&temp,NULL,NULL,"down: ")) + { + DBPRT(("is_get_stat: cannot setup prefix for comment list purge\n")); + } + else + { + if (node_comment_list(&temp, np, ATR_ACTION_DEL)) + DBPRT(("is_get_stat: cannot purge auto-down comment list\n")); + } + + return(DIS_SUCCESS); } /* END is_stat_get() */ +/* + * add_node_comment - add a server comment about node + * Simply add a comment to the comment list. + */ +int add_node_comment(struct pbsnode *np, char *caller, char *msg, char *err) + { + attribute temp; + if (np == NULL || caller == NULL || msg == NULL) + return (2); + + if (decode_arst(&temp,NULL,NULL,NULL)) + { + DBPRT(("%s: cannot initialize comment attribute\n", caller)); + return (1); + } + + if (decode_arst(&temp,NULL,NULL,msg)) + { + DBPRT(("%s: cannot add message to comment\n", caller)); + free_arst(&temp); + return(1); + } + + if (node_comment_list(&temp, np, ATR_ACTION_ALTER)) + { + if (err == NULL) + { + DBPRT(("%s: cannot add comment to comment list\n", caller)); + } + else + { + DBPRT(("%s: %s\n", caller, err)); + } + return(1); + } + return 0; + } + + + /* ** Start a standard inter-server message. */ @@ -565,6 +620,7 @@ /* down node and all subnodes */ + add_node_comment(np, __FUNCTION__, "down: connection dropped", NULL); np->nd_state |= INUSE_DOWN; if (stream > 0) @@ -625,6 +681,7 @@ if (np->nd_stream < 0) { np->nd_stream = rpp_open(np->nd_name, pbs_rm_port); + add_node_comment(np, __FUNCTION__, "down: ping failed", NULL); np->nd_state |= INUSE_DOWN; for (sp = np->nd_psn; sp; sp = sp->next) @@ -689,6 +746,7 @@ tdelete((u_long)np->nd_stream, &streams); np->nd_stream = -1; np->nd_state |= INUSE_DOWN; + add_node_comment(np, __FUNCTION__, "down: ping failed", NULL); for (sp = np->nd_psn; sp; sp = sp->next) sp->inuse |= INUSE_DOWN; @@ -749,6 +807,7 @@ if (np->nd_lastupdate < (time_now - chk_len)) { np->nd_state |= INUSE_DOWN; + add_node_comment(np, __FUNCTION__, "down: checkin timeout", NULL); } } /* END for (i = 0) */ @@ -794,6 +853,7 @@ struct sockaddr_in *addr; struct pbsnode *np, *node; struct pbssubn *sp; + attribute temp; if (LOGLEVEL >= 2) { @@ -900,6 +960,16 @@ DBPRT(("%s: IS_HELLO\n",id)) node->nd_state &= ~(INUSE_DOWN|INUSE_UNKNOWN|INUSE_NEEDS_HELLO_PING); + sprintf(log_buffer, "%s: attempting to delete downs from comment list\n", __FUNCTION__); + if (decode_arst(&temp,NULL,NULL,"down: ")) + { + DBPRT(("%s: cannot setup regex for comment list purge\n", __FUNCTION__)); + } + else + { + if (node_comment_list(&temp, node, ATR_ACTION_DEL)) + DBPRT(("%s: cannot purge auto-down comment list\n", __FUNCTION__)); + } for (sp = node->nd_psn; sp; sp = sp->next) sp->inuse &= ~INUSE_DOWN; @@ -959,6 +1029,8 @@ node->nd_state &= ~(INUSE_DOWN|INUSE_BUSY); node->nd_state |= i; + if (node->nd_state | INUSE_DOWN) + add_node_comment(node, __FUNCTION__, "down: update failed", NULL); } break; @@ -1079,6 +1151,7 @@ rpp_close(stream); node->nd_state |= INUSE_DOWN; + add_node_comment(node, __FUNCTION__, "down: DIS write error", NULL); for (sp = node->nd_psn; sp; sp = sp->next) sp->inuse |= INUSE_DOWN; Index: server/req_manager.c =================================================================== --- server/req_manager.c (revision 2) +++ server/req_manager.c (revision 10) @@ -578,6 +578,7 @@ int i; int index; int nstatus = 0; + int ncomment = 0; int nprops = 0; int rc; int updating_props = 0; @@ -779,6 +780,31 @@ pnode->nd_l_st = pdest; pnode->nd_nstatus = nstatus + 1; + /* update comment list based on new comment array */ + free_prop_list(pnode->nd_f_cm); + + plink = &pnode->nd_f_cm; + + if (pnode->nd_comment) + { + ncomment = pnode->nd_comment->as_usedptr; + + for (i = 0;i < ncomment;++i) + { + pdest = init_prop(pnode->nd_comment->as_string[i]); + + *plink = pdest; + plink = &pdest->next; + } + } + + /* now add in name as last comment */ + pdest = init_prop(pnode->nd_name); + *plink = pdest; + pnode->nd_l_cm = pdest; + pnode->nd_ncomment = ncomment + 1; + + /* now update subnodes */ update_subnode(pnode); Index: server/node_attr_def.c =================================================================== --- server/node_attr_def.c (revision 2) +++ server/node_attr_def.c (revision 10) @@ -197,5 +197,18 @@ MGR_ONLY_SET, ATR_TYPE_ARST, PARENT_TYPE_NODE, + }, + +/* NODE_ATR_comment */ + { ATTR_NODE_comment, + decode_arst, + encode_arst, + set_arst, + comp_null, + free_arst, + node_comment_list, + MGR_ONLY_SET, + ATR_TYPE_ARST, + PARENT_TYPE_NODE, } }; Index: lib/Libattr/attr_fn_arst.c =================================================================== --- lib/Libattr/attr_fn_arst.c (revision 2) +++ lib/Libattr/attr_fn_arst.c (revision 10) @@ -416,7 +416,8 @@ * * A=B --> set of strings in A replaced by set of strings in B * A+B --> set of strings in B appended to set of strings in A - * A-B --> any string in B found is A is removed from A + * A-B --> (1) any string in B found is A is removed from A + * A-B --> (2) any string starting with B found in A is removed from A * * Returns: 0 if ok * >0 if error @@ -440,7 +441,12 @@ struct array_strings *pas; struct array_strings *xpasx; void free_arst A_((attribute *)); + size_t len; + char logmsg[1024]; + char *str_begin; + int str_next; + assert(attr && new && (new->at_flags & ATR_VFLAG_SET)); pas = attr->at_val.at_arst; @@ -636,7 +642,36 @@ } break; + case DECR_BEGIN: + /* decrement (remove) all strings beginning with passed + * strings from array + */ + + for (i = 0;i < pas->as_usedptr;i++) + { + /* pas has the passed begin wildcards */ + str_begin = pas->as_string[i]; + str_next = arst_string_num(str_begin, new); + while (str_next != -1) + { + /* compact the string */ + nsize = strlen(xpasx->as_string[str_next]) + 1; + pc = xpasx->as_string[str_next] + nsize; + need = xpasx->as_next - pc; + memcpy(xpasx->as_string[i], pc, (int)need); + xpasx->as_next -= nsize; + for (++i;i < xpasx->as_npointers;i++) + xpasx->as_string[i - 1] = xpasx->as_string[i] - nsize; + xpasx->as_string[i - 1] = NULL; + xpasx->as_usedptr--; + str_next = arst_string_num(str_begin, new); + } + } + + break; + + default: return(PBSE_INTERNAL); @@ -752,4 +787,31 @@ } return ((char *)0); } + + +/* + * arst_string_num - if a string occurs in an arst attribute, return its index + * Search each entry in the value of an arst attribute until a match + * is found and return the index corresponding to its position in the arst. + */ + +int arst_string_num(str, pattr) + char *str; + attribute *pattr; +{ + int i; + size_t len; + struct array_strings *parst; + + if ((pattr->at_type != ATR_TYPE_ARST) || !(pattr->at_flags & ATR_VFLAG_SET)) + return(-1); + + len = strlen(str); + parst = pattr->at_val.at_arst; + for (i = 0; i < parst->as_usedptr; i++) { + if (strncmp(str, parst->as_string[i], len) == 0) + return (i); + } + return(-1); +} Index: lib/Libattr/attr_node_func.c =================================================================== --- lib/Libattr/attr_node_func.c (revision 2) +++ lib/Libattr/attr_node_func.c (revision 10) @@ -909,6 +909,104 @@ return(rc); } /* END node_status_list() */ + + +/* + * node_comment_list - Either derive a "comment list" attribute from the node + * or update node's comment list from attribute's comment list. + */ + +int node_comment_list( + + attribute *new, /*derive comment into this attribute*/ + void *pnode, /*pointer to a pbsnode struct */ + int actmode) /*action mode; "NEW" or "ALTER" */ + + { + int rc = 0; + struct pbsnode *np; + attribute temp; + + np = (struct pbsnode *)pnode; /* because of at_action arg type */ + + switch(actmode) + { + case ATR_ACTION_NEW: + + /* if node has a comment list, then copy array_strings */ + /* into temp to use to setup a copy, otherwise setup empty */ + + if (np->nd_comment != NULL) + { + /* setup temporary attribute with the array_strings */ + /* from the node */ + + temp.at_val.at_arst = np->nd_comment; + temp.at_flags = ATR_VFLAG_SET; + temp.at_type = ATR_TYPE_ARST; + + rc = set_arst(new,&temp,SET); + } + else + { + /* node has no properties, setup empty attribute */ + + new->at_val.at_arst = NULL; + new->at_flags = 0; + new->at_type = ATR_TYPE_ARST; + } + + break; + + case ATR_ACTION_ALTER: + + if (np->nd_comment != NULL) + { + free(np->nd_comment->as_buf); + free(np->nd_comment); + + np->nd_comment = NULL; + } + + /* update node with new attr_strings */ + + np->nd_comment = new->at_val.at_arst; + + new->at_val.at_arst = NULL; + + /* update number of comment items listed in node */ + /* does not include name and subnode property */ + + if (np->nd_comment != NULL) + np->nd_ncomment = np->nd_comment->as_usedptr; + else + np->nd_ncomment = 0; + + break; + + case ATR_ACTION_DEL: + + /* delete a comment if it matches - this is a + * frontend to the appropriate set_arst() function call + * 1st argument is patterns to match, 2nd argument is array + */ + temp.at_val.at_arst = np->nd_comment; + temp.at_flags = ATR_VFLAG_SET; + temp.at_type = ATR_TYPE_ARST; + + rc = set_arst(new, &temp, DECR_BEGIN); + break; + + default: + + rc = PBSE_INTERNAL; + + break; + } /* END switch(actmode) */ + + return(rc); + } /* END node_comment_list() */ + /* END attr_node_func.c */ Index: lib/Libattr/attr_func.c =================================================================== --- lib/Libattr/attr_func.c (revision 12) +++ lib/Libattr/attr_func.c (revision 13) @@ -472,9 +472,11 @@ ++pc; } back = pc; +#if 0 + Why? while (isspace((int)*--back)) /* strip trailing spaces */ *back = '\0'; - +#endif if (*pc) *pc++ = '\0'; /* if not end, terminate this and adv past */