[torquedev] new node attribute: "note"
Marcus R. Epperson
mrepper at sandia.gov
Tue Jan 30 22:12:18 MST 2007
Garrick Staples wrote:
> On Wed, Jan 24, 2007 at 10:15:06AM -0700, Marcus R. Epperson alleged:
>> On 01/24/2007 12:17 AM, Garrick Staples wrote:
>>> One question, where are the notes stored on disk? I only flipped the
>>> patch real quick, but didn't see it.
>> Hmm, good point. This attribute probably should survive a server restart.
>> :) I'll look into that.
>>
>> How does /var/spool/torque/server_priv/note_attr sound?
>
> Should probably have "node" in the name. node_note?
Sounds good. How does this look? (attached)
As for Ake's comment, this implementation does not keep a note history with timestamps, but you can get that from the server_logs. It is just like offline state in this regard.
01/28/2007 23:37:36;0004;PBS_Server;node;node1;attributes set: at request of root at node1
01/28/2007 23:37:36;0004;PBS_Server;node;node1;attributes set: note = memory failure: DIMM3
-Marcus
-------------- next part --------------
diff -Naurp --exclude torque.spec --exclude cscope.out --exclude '*.swp' torque-2.2.0-snap.200701181022.orig/src/cmds/pbsnodes.c torque-2.2.0-snap.200701181022/src/cmds/pbsnodes.c
--- torque-2.2.0-snap.200701181022.orig/src/cmds/pbsnodes.c 2006-11-28 13:41:49.000000000 -0700
+++ torque-2.2.0-snap.200701181022/src/cmds/pbsnodes.c 2007-01-29 00:12:15.000000000 -0700
@@ -122,6 +122,7 @@
#define ALLI 5
#define PURGE 6
#define DIAG 7
+#define NOTE 8
int quiet = 0;
@@ -143,6 +144,48 @@ mbool_t DisplayXML = FALSE;
/*
+ * set_note - set the note attribute for a node
+ *
+ */
+static int set_note(
+ int con,
+ char *name,
+ char *msg
+)
+{
+ char *errmsg;
+ struct attropl new;
+ int rc;
+
+ new.name = ATTR_NODE_note;
+ new.resource = NULL;
+ new.value = msg;
+ new.op = SET;
+ new.next = NULL;
+
+ rc = pbs_manager(
+ con,
+ MGR_CMD_SET,
+ MGR_OBJ_NODE,
+ name,
+ &new,
+ NULL);
+
+ if (rc && !quiet)
+ {
+ fprintf(stderr,"Error setting note attribute for node %s - ", name);
+
+ if ((errmsg = pbs_geterrmsg(con)) != NULL)
+ fprintf(stderr,"%s\n", errmsg);
+ else
+ fprintf(stderr,"error: %d\n", pbs_errno);
+ }
+
+ return rc;
+}
+
+
+/*
* cmp_node_name - compare two node names, allow the second to match the
* first if the same up to a dot ('.') in the second; i.e.
* "foo" == "foo.bar"
@@ -366,6 +409,9 @@ int main(
char **pa;
struct batch_status *pbstat;
int flag = ALLI;
+ char *note;
+ int note_flag = 0;
+ int len = 0;
/* get default server, may be changed by -s option */
@@ -374,7 +420,7 @@ int main(
if (def_server == NULL)
def_server = "";
- while ((i = getopt(argc,argv,"acdlopqrs:x-:")) != EOF)
+ while ((i = getopt(argc,argv,"acdlopqrs:x-:n:")) != EOF)
{
switch(i)
{
@@ -440,6 +486,40 @@ int main(
break;
+ case 'n':
+
+ note_flag = 1;
+
+ /* preserve any previous option other than the default,
+ * to allow -n to be combined with -o, -c, etc
+ */
+ if ( flag == ALLI )
+ flag = NOTE;
+
+ note = strdup(optarg);
+
+ if ( note != NULL )
+ {
+ /* -n n is the same as -n "" -- it clears the note */
+ if ( !strcmp(note,"n") )
+ {
+ *note = '\0';
+ }
+
+ len = strlen(note);
+ }
+
+ if ( len > MAX_NOTE )
+ {
+ fprintf(stderr,"\nWarning: note will be truncated at %d characters (was %d)\n\n",
+ MAX_NOTE,len);
+
+ /* this is enforced on the server side too */
+ note[MAX_NOTE] = '\0';
+ }
+
+ break;
+
case '-':
if ((optarg != NULL) && !strcmp(optarg,"version"))
@@ -467,7 +547,7 @@ int main(
{
if (!quiet)
{
- fprintf(stderr,"usage:\t%s [-{c|d|o|p|r}][-s server] [-q] node node ...\n",
+ fprintf(stderr,"usage:\t%s [-{c|d|o|p|r}][-s server] [-n \"note\"] [-q] node node ...\n",
argv[0]);
fprintf(stderr,"\t%s -l [-s server] [-q]\n",
@@ -546,6 +626,16 @@ int main(
}
} /* END if ((flag == ALLI) || (flag == DOWN) || (flag == LIST) || (flag == DIAG)) */
+
+ if ( note_flag )
+ {
+ /* set the note attrib string on specified nodes */
+ for (pa = argv + optind;*pa;pa++)
+ {
+ set_note(con,*pa,note);
+ }
+ }
+
switch (flag)
{
case DIAG:
diff -Naurp --exclude torque.spec --exclude cscope.out --exclude '*.swp' torque-2.2.0-snap.200701181022.orig/src/include/attribute.h torque-2.2.0-snap.200701181022/src/include/attribute.h
--- torque-2.2.0-snap.200701181022.orig/src/include/attribute.h 2006-10-19 17:10:09.000000000 -0600
+++ torque-2.2.0-snap.200701181022/src/include/attribute.h 2007-01-29 00:33:17.000000000 -0700
@@ -435,6 +435,8 @@ extern int node_np_action A_(( att
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_note A_(( attribute*, void*, int));
+extern int set_note_str A_((attribute *attr,attribute *new, enum batch_op));
/* Token manipulation functions */
diff -Naurp --exclude torque.spec --exclude cscope.out --exclude '*.swp' torque-2.2.0-snap.200701181022.orig/src/include/pbs_ifl.h torque-2.2.0-snap.200701181022/src/include/pbs_ifl.h
--- torque-2.2.0-snap.200701181022.orig/src/include/pbs_ifl.h 2007-01-09 19:49:00.000000000 -0700
+++ torque-2.2.0-snap.200701181022/src/include/pbs_ifl.h 2007-01-28 23:02:12.000000000 -0700
@@ -105,6 +105,10 @@
#endif /* __STDC__ */
+/* Macros used to convert a #define'd value to a string literal */
+#define STR(x) #x
+#define TEXT(x) "" STR(x) ""
+
/* Attribute Names used by user commands */
#define ATTR_a "Execution_Time"
@@ -262,6 +266,7 @@
#define ATTR_NODE_ntype "ntype"
#define ATTR_NODE_jobs "jobs"
#define ATTR_NODE_status "status"
+#define ATTR_NODE_note "note"
@@ -333,6 +338,7 @@
#ifndef MAXNAMLEN
#define MAXNAMLEN 255
#endif
+#define MAX_NOTE 1024 /* max node note length */
#define PBS_MAXUSER 16 /* max user name length */
#define PBS_MAXGRPN 16 /* max group name length */
diff -Naurp --exclude torque.spec --exclude cscope.out --exclude '*.swp' torque-2.2.0-snap.200701181022.orig/src/include/pbs_nodes.h torque-2.2.0-snap.200701181022/src/include/pbs_nodes.h
--- torque-2.2.0-snap.200701181022.orig/src/include/pbs_nodes.h 2006-10-19 17:10:09.000000000 -0600
+++ torque-2.2.0-snap.200701181022/src/include/pbs_nodes.h 2007-01-28 17:07:57.000000000 -0700
@@ -123,6 +123,7 @@ struct pbsnode {
u_long *nd_addrs; /* IP addresses of host */
struct array_strings *nd_prop; /* array of properities */
struct array_strings *nd_status;
+ char *nd_note; /* note set by administrator */
int nd_stream; /* RPP stream to Mom on host */
enum psit nd_flag;
short nd_nprops; /* number of properties */
@@ -195,6 +196,7 @@ int tlist(tree *,char *,int);
#define WRITENODE_STATE 0x1 /*associated w/ offline*/
#define WRITE_NEW_NODESFILE 0x2 /*changed: deleted,ntype,or properties*/
+#define WRITENODE_NOTE 0x4 /*associated w/ note*/
/*
* Although at the present time a struct pbssnode doesn't have an array of
@@ -216,6 +218,7 @@ enum nodeattr {
ND_ATR_ntype,
ND_ATR_jobs,
NODE_ATR_status,
+ NODE_ATR_note,
ND_ATR_LAST }; /* WARNING: Must be the highest valued enum */
diff -Naurp --exclude torque.spec --exclude cscope.out --exclude '*.swp' torque-2.2.0-snap.200701181022.orig/src/include/qmgr_node_public.h torque-2.2.0-snap.200701181022/src/include/qmgr_node_public.h
--- torque-2.2.0-snap.200701181022.orig/src/include/qmgr_node_public.h 2006-06-19 18:23:29.000000000 -0600
+++ torque-2.2.0-snap.200701181022/src/include/qmgr_node_public.h 2007-01-26 16:15:53.000000000 -0700
@@ -95,3 +95,4 @@ ATTR_NODE_properties,
ATTR_NODE_np,
ATTR_NODE_ntype,
ATTR_NODE_status,
+ATTR_NODE_note,
diff -Naurp --exclude torque.spec --exclude cscope.out --exclude '*.swp' torque-2.2.0-snap.200701181022.orig/src/include/server_limits.h torque-2.2.0-snap.200701181022/src/include/server_limits.h
--- torque-2.2.0-snap.200701181022.orig/src/include/server_limits.h 2006-08-09 18:27:27.000000000 -0600
+++ torque-2.2.0-snap.200701181022/src/include/server_limits.h 2007-01-26 19:55:06.000000000 -0700
@@ -124,6 +124,7 @@
#define PBS_TRACKING "tracking"
#define NODE_DESCRIP "nodes"
#define NODE_STATUS "node_status"
+#define NODE_NOTE "node_note"
#define PBS_NET_MAX_CONNECTIONS 1024 /* increased from 256 */
diff -Naurp --exclude torque.spec --exclude cscope.out --exclude '*.swp' torque-2.2.0-snap.200701181022.orig/src/lib/Libattr/attr_node_func.c torque-2.2.0-snap.200701181022/src/lib/Libattr/attr_node_func.c
--- torque-2.2.0-snap.200701181022.orig/src/lib/Libattr/attr_node_func.c 2006-10-19 17:10:15.000000000 -0600
+++ torque-2.2.0-snap.200701181022/src/lib/Libattr/attr_node_func.c 2007-01-29 09:27:47.000000000 -0700
@@ -96,6 +96,10 @@
#include "job.h"
#include "pbs_nodes.h"
#include "pbs_error.h"
+#include "log.h"
+#if SYSLOG
+#include <syslog.h>
+#endif
extern int LOGLEVEL;
@@ -1052,6 +1056,109 @@ int node_status_list(
return(rc);
} /* END node_status_list() */
-/* END attr_node_func.c */
+/*
+ * node_note - Either derive a note attribute from the node
+ * or update node's note from attribute's list.
+ */
+int node_note(
+
+ attribute *new, /*derive status 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 note, then copy string into temp */
+ /* to use to setup a copy, otherwise setup empty */
+
+ if (np->nd_note != NULL)
+ {
+ /* setup temporary attribute with the string from the node */
+
+ temp.at_val.at_str = np->nd_note;
+ temp.at_flags = ATR_VFLAG_SET;
+ temp.at_type = ATR_TYPE_STR;
+
+ rc = set_note_str(new,&temp,SET);
+ }
+ else
+ {
+ /* node has no properties, setup empty attribute */
+
+ new->at_val.at_str = NULL;
+ new->at_flags = 0;
+ new->at_type = ATR_TYPE_STR;
+ }
+
+ break;
+ case ATR_ACTION_ALTER:
+
+ if (np->nd_note != NULL)
+ {
+ free(np->nd_note);
+
+ np->nd_note = NULL;
+ }
+
+ /* update node with new string */
+
+ np->nd_note = new->at_val.at_str;
+
+ new->at_val.at_str = NULL;
+
+ break;
+
+ default:
+
+ rc = PBSE_INTERNAL;
+
+ break;
+ } /* END switch(actmode) */
+
+ return(rc);
+ } /* END node_note() */
+
+
+
+/* essentially a set_str() wrapper that does MAX_NOTE enforcement */
+int set_note_str(attr, new, op)
+ struct attribute *attr;
+ struct attribute *new;
+ enum batch_op op;
+ {
+ static char id[] = "set_note_str";
+ size_t nsize;
+
+ assert( attr && new && new->at_val.at_str && (new->at_flags & ATR_VFLAG_SET));
+ nsize = strlen(new->at_val.at_str); /* length of new note */
+
+ if (nsize > MAX_NOTE)
+ {
+ sprintf(log_buffer,"Warning: Client attempted to set note with len (%d) > MAX_NOTE (%d)",
+ nsize,
+ MAX_NOTE);
+
+ log_record(
+ PBSEVENT_SECURITY,
+ PBS_EVENTCLASS_REQUEST,
+ id,
+ log_buffer);
+
+ new->at_val.at_str[MAX_NOTE] = '\0';
+ }
+
+ return set_str(attr,new,op);
+ } /* END set_note_str() */
+
+/* END attr_node_func.c */
diff -Naurp --exclude torque.spec --exclude cscope.out --exclude '*.swp' torque-2.2.0-snap.200701181022.orig/src/server/node_attr_def.c torque-2.2.0-snap.200701181022/src/server/node_attr_def.c
--- torque-2.2.0-snap.200701181022.orig/src/server/node_attr_def.c 2006-10-19 17:10:34.000000000 -0600
+++ torque-2.2.0-snap.200701181022/src/server/node_attr_def.c 2007-01-29 00:36:45.000000000 -0700
@@ -195,5 +195,19 @@ attribute_def node_attr_def[] = {
MGR_ONLY_SET,
ATR_TYPE_ARST,
PARENT_TYPE_NODE,
- }
+ },
+
+/* NODE_ATR_note */
+ { ATTR_NODE_note, /* "note" */
+ decode_str,
+ encode_str,
+ set_note_str,
+ comp_str,
+ free_str,
+ node_note,
+ NO_USER_SET,
+ ATR_TYPE_STR,
+ PARENT_TYPE_NODE,
+ },
+
};
diff -Naurp --exclude torque.spec --exclude cscope.out --exclude '*.swp' torque-2.2.0-snap.200701181022.orig/src/server/node_func.c torque-2.2.0-snap.200701181022/src/server/node_func.c
--- torque-2.2.0-snap.200701181022.orig/src/server/node_func.c 2006-10-19 17:10:29.000000000 -0600
+++ torque-2.2.0-snap.200701181022/src/server/node_func.c 2007-01-28 22:51:40.000000000 -0700
@@ -136,6 +136,7 @@ extern int svr_clnodes;
extern char *path_nodes_new;
extern char *path_nodes;
extern char *path_nodestate;
+extern char *path_nodenote;
extern int LOGLEVEL;
extern attribute_def node_attr_def[]; /* node attributes defs */
@@ -430,6 +431,7 @@ static short old_state = (short)0xdead;
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 char *old_note = NULL; /*node's note */
@@ -457,6 +459,18 @@ void save_characteristic(
old_first = pnode->nd_first;
old_f_st = pnode->nd_f_st;
+ /* if there was a previous note stored here, free it first */
+ if (old_note != NULL)
+ {
+ free(old_note);
+ old_note = NULL;
+ }
+
+ if (pnode->nd_note != NULL)
+ {
+ old_note = strdup(pnode->nd_note);
+ }
+
return;
} /* END save_characteristic() */
@@ -546,6 +560,18 @@ int chk_characteristic(
if ((old_nprops != pnode->nd_nprops) || (old_first != pnode->nd_first))
*pneed_todo |= WRITE_NEW_NODESFILE;
+ if (pnode->nd_note != old_note) /* not both NULL or with the same address */
+ {
+ if (pnode->nd_note == NULL || old_note == NULL)
+ {
+ *pneed_todo |= WRITENODE_NOTE; /*node's note changed*/
+ }
+ else if (strcmp(pnode->nd_note,old_note))
+ {
+ *pneed_todo |= WRITENODE_NOTE; /*node's note changed*/
+ }
+ }
+
old_address = NULL;
return(0);
@@ -603,6 +629,8 @@ int status_nodeattrib(
atemp[i].at_val.at_jinfo = pnode;
else if (!strcmp ((padef + i)->at_name, ATTR_NODE_np))
atemp[i].at_val.at_long = pnode->nd_nsn;
+ else if (!strcmp ((padef + i)->at_name, ATTR_NODE_note))
+ atemp[i].at_val.at_str = pnode->nd_note;
else
{
/*we don't ever expect this*/
@@ -729,6 +757,7 @@ static void initialize_pbsnode(
pnode->nd_order = 0;
pnode->nd_prop = NULL;
pnode->nd_status = NULL;
+ pnode->nd_note = NULL;
pnode->nd_psn = NULL;
pnode->nd_state = INUSE_NEEDS_HELLO_PING | INUSE_DOWN;
pnode->nd_first = init_prop(pnode->nd_name);
@@ -1446,6 +1475,7 @@ int setup_nodes(void)
FILE *nin;
char line[256];
+ char note[MAX_NOTE+1];
char *nodename;
char propstr[256];
char *token;
@@ -1689,6 +1719,44 @@ int setup_nodes(void)
fclose(nin);
}
+ /* initialize note attributes */
+ nin = fopen(path_nodenote,"r");
+
+ if (nin != NULL)
+ {
+
+ while (fscanf(nin,"%s %" TEXT(MAX_NOTE) "[^\n]",
+ line,
+ note) == 2)
+ {
+ for (i = 0;i < svr_totnodes;i++)
+ {
+ np = pbsndmast[i];
+
+ if (strcmp(np->nd_name,line) == 0)
+ {
+ np->nd_note = strdup(note);
+
+ if ( np->nd_note == NULL )
+ {
+ sprintf(log_buffer,"couldn't allocate space for note (node = %s)",
+ np->nd_name);
+
+ log_record(
+ PBSEVENT_SCHED,
+ PBS_EVENTCLASS_REQUEST,
+ id,
+ log_buffer);
+ }
+
+ break;
+ }
+ }
+ }
+
+ fclose(nin);
+ }
+
/* SUCCESS */
return(0);
diff -Naurp --exclude torque.spec --exclude cscope.out --exclude '*.swp' torque-2.2.0-snap.200701181022.orig/src/server/node_manager.c torque-2.2.0-snap.200701181022/src/server/node_manager.c
--- torque-2.2.0-snap.200701181022.orig/src/server/node_manager.c 2006-12-21 16:28:26.000000000 -0700
+++ torque-2.2.0-snap.200701181022/src/server/node_manager.c 2007-01-28 18:44:37.000000000 -0700
@@ -136,6 +136,7 @@ static int svr_numcfgnodes = 0;
static int exclusive; /* node allocation type */
static FILE *nstatef = NULL;
+static FILE *nnotef = NULL;
static int num_addrnote_tasks = 0; /* number of outstanding send_cluster_addrs tasks */
extern int server_init_type;
@@ -148,6 +149,7 @@ extern char *path_home;
extern char *path_nodes;
extern char *path_nodes_new;
extern char *path_nodestate;
+extern char *path_nodenote;
extern unsigned int pbs_mom_port;
extern char server_name[];
@@ -2101,6 +2103,72 @@ void write_node_state()
+/* Create a new node_note file, overwriting the previous one.
+ *
+ * The note file could get up to:
+ * (# of nodes) * (2 + MAX_NODE_NAME + MAX_NOTE) bytes in size
+ */
+void write_node_note()
+
+ {
+ struct pbsnode *np;
+ static char *fmt = "%s %s\n";
+ int i;
+
+ if (LOGLEVEL >= 5)
+ DBPRT(("write_node_note: entered\n"))
+
+ if (nnotef != NULL)
+ {
+ fseek(nnotef,0L,SEEK_SET); /* rewind and clear */
+
+ if (ftruncate(fileno(nnotef),(off_t)0) != 0)
+ {
+ log_err(errno,"write_node_note","could not truncate file");
+
+ return;
+ }
+ }
+ else
+ {
+ /* need to open for first time, temporary-move to pbsd_init */
+
+ if ((nnotef = fopen(path_nodenote,"w+")) == NULL)
+ {
+ log_err(
+ errno,
+ "write_node_note",
+ "could not open file");
+
+ return;
+ }
+ }
+
+ for (i = 0;i < svr_totnodes;i++)
+ {
+ np = pbsndmast[i];
+
+ if (np->nd_state & INUSE_DELETED)
+ continue;
+
+ if (np->nd_note != NULL && np->nd_note != '\0')
+ {
+ fprintf(nnotef,fmt,
+ np->nd_name,
+ np->nd_note);
+ }
+ } /* END for (i) */
+
+ if (fflush(nnotef) != 0)
+ {
+ log_err(errno,"write_node_note","failed saving node note to disk");
+ }
+
+ return;
+ } /* END write_node_note() */
+
+
+
/*
* free_prop - free list of prop structures created by proplist()
diff -Naurp --exclude torque.spec --exclude cscope.out --exclude '*.swp' torque-2.2.0-snap.200701181022.orig/src/server/pbsd_init.c torque-2.2.0-snap.200701181022/src/server/pbsd_init.c
--- torque-2.2.0-snap.200701181022.orig/src/server/pbsd_init.c 2006-11-07 18:34:41.000000000 -0700
+++ torque-2.2.0-snap.200701181022/src/server/pbsd_init.c 2007-01-28 18:08:31.000000000 -0700
@@ -176,6 +176,7 @@ extern char *path_track;
extern char *path_nodes;
extern char *path_nodes_new;
extern char *path_nodestate;
+extern char *path_nodenote;
extern char *path_resources;
extern int queue_rank;
@@ -425,6 +426,7 @@ int pbsd_init(
path_nodes = build_path(path_priv, NODE_DESCRIP, NULL);
path_nodes_new = build_path(path_priv, NODE_DESCRIP, new_tag);
path_nodestate = build_path(path_priv, NODE_STATUS, NULL);
+ path_nodenote = build_path(path_priv, NODE_NOTE, NULL);
path_resources = build_path(path_home, PBS_RESOURCES, NULL);
init_resc_defs(path_resources);
diff -Naurp --exclude torque.spec --exclude cscope.out --exclude '*.swp' torque-2.2.0-snap.200701181022.orig/src/server/pbsd_main.c torque-2.2.0-snap.200701181022/src/server/pbsd_main.c
--- torque-2.2.0-snap.200701181022.orig/src/server/pbsd_main.c 2007-01-17 16:17:39.000000000 -0700
+++ torque-2.2.0-snap.200701181022/src/server/pbsd_main.c 2007-01-26 19:57:04.000000000 -0700
@@ -168,6 +168,7 @@ char *path_track;
char *path_nodes;
char *path_nodes_new;
char *path_nodestate;
+char *path_nodenote;
char *path_resources;
extern char *msg_daemonname;
extern int pbs_errno;
diff -Naurp --exclude torque.spec --exclude cscope.out --exclude '*.swp' torque-2.2.0-snap.200701181022.orig/src/server/req_manager.c torque-2.2.0-snap.200701181022/src/server/req_manager.c
--- torque-2.2.0-snap.200701181022.orig/src/server/req_manager.c 2006-12-15 14:28:39.000000000 -0700
+++ torque-2.2.0-snap.200701181022/src/server/req_manager.c 2007-01-28 23:39:01.000000000 -0700
@@ -1634,6 +1634,15 @@ void mgr_node_set(
need_todo &= ~(WRITENODE_STATE);
}
+ if (need_todo & WRITENODE_NOTE)
+ {
+ /*some nodes have new "note"s*/
+
+ write_node_note( );
+
+ need_todo &= ~(WRITENODE_NOTE);
+ }
+
if (need_todo & WRITE_NEW_NODESFILE)
{
/*create/delete/prop/ntype change*/
More information about the torquedev
mailing list