Skip to main content
U.S. flag

An official website of the United States government

Official websites use .gov
A .gov website belongs to an official government organization in the United States.

Secure .gov websites use HTTPS
A lock ( ) or https:// means you’ve safely connected to the .gov website. Share sensitive information only on official, secure websites.

NML_SET Class

NMLSET Class

Introduction

The NML Set class is a class intended to make it easier to write applications to monitor or interact with multiple NML buffers especially when the number of such buffers is not fixed or known when the application starts. It is designed to work with the NML Configuration Server.

Notation

I like lots of examples.

     Commands users are expected to enter at a command prompt will look like this.  
     Computer program generated example output will look like this.  
Text files listed in line look like this.  

Examples

It is convenient for testing to have a set of applications where the buffer name, process name and configuration file can be set from the command line. I do not expect most applications to be built this way but it allows us to experiment with a number of different scenarios without recompiling anything. To run the demonstrations you need four programs nmlcfgsvr which should have been built along with the RCS library and two programs just for testing: nml_test_write, nml_test_nmlset. The source for the three test programs includes: nml_test_nmlset.cc, nml_test_write.cc, nml_test_format.hh, nml_test_format_n.cc, and nml_test_format_n_codegen_protos.hh. (nml_test_format_n.cc, and nml_test_format_n_codegen_protos.hh were autogenerated from nml_test_format.hh using the NML Code Generator. They should be in the src/test directory of the expanded RCS library source archive or you can download them from the last set of links.

Compiling the test programs:

Exactly how you compile them depends on your operating system, compiler and how directories are laid out. This worked for me:

g++ -Ircslib_install_dir/include -Ircslib-2004.6/src/test  rcslib-2004.6/src/test/nml_test_write.cc rcslib-2004.6/src/test/nml_test_format_n.cc -Lrcslib_install_dir/lib -lrcs -o nml_test_write  g++ -Ircslib_install_dir/include -Ircslib-2004.6/src/test  rcslib-2004.6/src/test/nml_test_nmlset.cc rcslib-2004.6/src/test/nml_test_format_n.cc -Lrcslib_install_dir/lib -lrcs -o nml_test_nmlset  

rcslib_install_dir is unique to my system. Generally that needs to be replaced in all commands with something appropriate to your system, or you could use a symbolic link to make that work.

The programs should also be built if "make check" were run.

Running some demonstrations:

The examples work as follows: Two instances of the nmlcfgsvr are launched. The nml_test_nmlset application begins monitoring those servers for a set of buffers to be created. Multiple instances of nml_test_write are launched each creating a new buffer and repeatedly writing to it. The nml_test_nmlset will repeatedly print some cryptic information indicating how many buffers have been created and the current data in each one.

Start the nmlcfgsvr:

rcslib_install_dir/bin/nmlcfgsvr &  

Start another nmlcfgsvr connecte to port 50000:

rcslib_install_dir/bin/nmlcfgsvr --port 50000 &  

Start the nml_test_nmlset application:

./nml_test_nmlset b1\;b2 ntns nmlcfgsvr:\;nmlcfgsvr::50000   

The three command line arguments are passed to the NMLSET constructor. The first argument is a semicolon delimited list of buffer names, the second argument is a process name, which currently has no impact, and the third argument is a semicolon seperated list of nmlcfgsvrs. The semicolons need to be escaped with a backslash to prevent the shell from breaking the command there.

The nml_test_nmlset application will poll both the nmlcfgsvr's wait 2 seconds and then try again. It prints a cycle count, giving the number of times it has done this and a line of astericks to seperate the output in each cycle. At the beginning there is no other output because there are no buffers created matching the nmlset criteria.

Start several instances of nml_test_write to create different buffers. These could be launched from different terminals or just backgrounded in one terminal. You would probably want to take notice of the the change in the nml_test_nmlset programs output as each program is started or killed and experiment with killing and starting them in different orders.

./nml_test_write b1 ntw nmlcfgsvr: 199 -1 & ./nml_test_write b2 ntw nmlcfgsvr: 198 -1 & ./nml_test_write b1 ntw nmlcfgsvr::50000  197 -1 & ./nml_test_write b2 ntw nmlcfgsvr::50000  196 -1 & env NMLCFGSVR_DOMAIN=d2 ./nml_test_write b1 ntw nmlcfgsvr: 195 -1 & env NMLCFGSVR_DOMAIN=d2 ./nml_test_write b2 ntw nmlcfgsvr: 194 -1 & env NMLCFGSVR_DOMAIN=d2 ./nml_test_write b1 ntw nmlcfgsvr::50000  193 -1 & env NMLCFGSVR_DOMAIN=d2 ./nml_test_write b2 ntw nmlcfgsvr::50000  192 -1 & env NMLCFGSVR_DOMAIN=~newnmldomain~ ./nml_test_write b1 ntw nmlcfgsvr: 191 -1 & env NMLCFGSVR_DOMAIN=~newnmldomain~ ./nml_test_write b2 ntw nmlcfgsvr: 190 -1 & env NMLCFGSVR_DOMAIN=~newnmldomain~ ./nml_test_write b1 ntw nmlcfgsvr::50000  189 -1 & env NMLCFGSVR_DOMAIN=~newnmldomain~ ./nml_test_write b2 ntw nmlcfgsvr::50000  188 -1 & env NMLCFGSVR_DOMAIN=~newnmldomain~ ./nml_test_write b1 ntw nmlcfgsvr: 187 -1 & env NMLCFGSVR_DOMAIN=~newnmldomain~ ./nml_test_write b2 ntw nmlcfgsvr: 186 -1 & env NMLCFGSVR_DOMAIN=~newnmldomain~ ./nml_test_write b1 ntw nmlcfgsvr::50000  185 -1 & env NMLCFGSVR_DOMAIN=~newnmldomain~ ./nml_test_write b2 ntw nmlcfgsvr::50000  184 -1 &  

The first argument to nml_test_write is the buffer name, the second is the process name, the third is the NML configuration file name or nmlcfgsvr pseudo file name, the fourth is an integer that the lastvar variable of the test message will be set to make it easy to identify which instance of nml_test_write wrote which message being displayed by the nml_test_nmlset application, and the fifth argument is the repeat count with -1 indicating that nml_test_write should repeat forever. The env command is used to run another command in a modified environment. The environment variable NMLCFGSVR_DOMAIN allows multiple independant buffers with the same name to be created on the same nmlcfgsvr. The value of "~newnmldomain~" has special significance in that it means a new unique domain name is used for each process. Once all of these processes are running there should be sixteen independant NML buffers created. Eight will be named b1 and eight will be named b2. Four of the eight that are named b1 will be registered with the nmlcfgsvr that is bound to default port and four will be registered to the nmlcfgsvr bound to port 5000. Within each set of four the buffers are distinguished only by their domain which was set using the environment variable NMLCFGSVR_DOMAIN.

Looking at the status of one of the nmlcfgsvr's might make things clearer.

telnet localhost 50000  
Trying 127.0.0.1... Connected to localhost.localdomain (127.0.0.1). Escape character is '^]'.  
list    
BEGIN_LIST B       b1      SHMEM   192.168.1.68     9728    0       0       2       *      1504838656      TCP=37841 bsem=1504838657  packed confirm_write nmlcfgsvr=192.168.1.68:50000 B       b2      SHMEM   192.168.1.68     9728    0       0       3       *      1504838658      TCP=37842 bsem=1504838659  packed confirm_write nmlcfgsvr=192.168.1.68:50000 B       b1      SHMEM   192.168.1.68     9728    0       0       4       *      1504838660      TCP=37845 bsem=1504838661  packed confirm_write nmlcfgsvr=192.168.1.68:50000 domain=d2 B       b2      SHMEM   192.168.1.68     9728    0       0       5       *      1504838662      TCP=37846 bsem=1504838663  packed confirm_write nmlcfgsvr=192.168.1.68:50000 domain=d2 B       b1      SHMEM   192.168.1.68     9728    0       0       6       *      1504838664      TCP=37865 bsem=1504838665  packed confirm_write nmlcfgsvr=192.168.1.68:50000 domain=nd.1.ryf.jyo81.tn5.VClyf1.frTIb1.jKg2. B       b2      SHMEM   192.168.1.68     9728    0       0       7       *      1504838666      TCP=37866 bsem=1504838667  packed confirm_write nmlcfgsvr=192.168.1.68:50000 domain=nd.2.zCf.jyo81.tn5.VClyf1.frTIb1.ZzC2. B       b1      SHMEM   192.168.1.68     9728    0       0       8       *      1504838668      TCP=37867 bsem=1504838669  packed confirm_write nmlcfgsvr=192.168.1.68:50000 domain=nd.3.HGf.jyo81.tn5.VClyf1.frTIb1.VnM2. B       b2      SHMEM   192.168.1.68     9728    0       0       9       *      1504838670      TCP=37869 bsem=1504838671  packed confirm_write nmlcfgsvr=192.168.1.68:50000 domain=nd.4.XOf.jyo81.tn5.VClyf1.frTIb1.9ou3. #END_LIST 
         (press [CTRL]-D )  
Connection closed by foreign host.  

This is the output from only one of the nmlcfgsvr's which is why there are only eight buffers rather than sixteen. Each of the four b1 buffers has a different TCP port, Shared memory key, buffer number and domain. ( Unfortunately the domain is at the end of the line and depending on browser font settings and screen resolution/paper size have likely scrolled of the right side of the screen/page.)

For reference here is the source code for the nml_test_nmlset application:

#include "rcs.hh"// Required for all RCS library applications. #include "nmlset.hh"// Declare the NMLSET,NMLDOMAINSET and NMLDOMAINSET_MEMBER classes.  #include "nml_test_format.hh"// Specific message classes for these examples.  // Standard C/C++ headers #include  #include  #include    // Setup Control-C signal handler for quitting this application. static void (*old_sigint_handler)(int) =0; static bool sigint_occured=false;  static void sigint_handler(int sig) {   if(old_sigint_handler && old_sigint_handler != SIG_IGN &&      old_sigint_handler != SIG_DFL)     {       (*old_sigint_handler)(sig);     }   sigint_occured=true; }    int main(int argc, const char **argv) {   // Parse/handle  the command line arguments.   if(argc < 4)     {       fprintf(stderr,"nml_test_nmlset usage: bufferlist procname cfgsvrlist [buffersneeded] [maxcycles]\n");       exit(1);     }   int bufsneeded = -1;   if(argc >= 5)     {       bufsneeded = strtol(argv[4],0,0);       printf("bufsneeded=%d\n",bufsneeded);     }   int maxcycles = -1;   if(argc >= 6)     {       maxcycles = strtol(argv[5],0,0);       printf("maxcycles=%d\n",maxcycles);     }   int bufsread = 0;   int cycles = 0;   bool error_occured=false;      // Create an NMLSET class object that will be used to   // monitor all buffers in the ; delimited list in argv[1] on   // nmlcfgsvr's listed in the ; delimeted list in argv[3],   // pass argv[2] as our ProcessName.   NMLSET s(nml_test_format,argv[1],argv[2],argv[3]);   printf("NMLSET s(nml_test_format,argv[1]=%s,argv[2]=%s,argv[3]=%s);\n",  argv[1],argv[2],argv[3]);    int *lastnum = 0;   if(bufsneeded > 0)     {       lastnum = new int[bufsneeded];     }   for(int k = 0; k < bufsneeded; k++)     {       lastnum[k] = 0;     }    // Setup the signal handler so we can gracefully quit when   // someone presses Control-C.   old_sigint_handler = signal(SIGINT,sigint_handler);      while(!sigint_occured)     {       cycles++;       if(maxcycles > 0 && cycles > maxcycles) {   break; }       printf("cycles=%d\n",cycles);       printf("\n**********************************************************\n");        // Check all of the configuration servers to see if there are new       // buffers that match our criteria. If a server won't respond after       // 1.0 seconds go on to the next one or return if it is the last one.       s.update_set(1.0);       printf("s..update_set(1.0);\n");        // NMLSETS are divided into NMLDOMAINSETS, there could be an       // infinite number, so we run though the list, by calling s.get_first_domainset() and then s.get_next_domainset() until it returns NULL.       NMLDOMAINSET *nd = s.get_first_domainset();       printf("NMLDOMAINSET *nd = s.get_first_domainset();\nnd=%p\n",      (void*)nd);       while(nd) {   printf("nd->getdomainname() = %s\n",nd->getdomainname());   printf("nd->cfgsvrname() = %s\n",nd->getcfgsvrname());      // Each NMLDOMAINSET has a fixed randomly accessible list of    // members. The member id's correspond to the position of the   // buffer name in the bufferlist passed when the top level NMLSET   // object was created.   for(int i=0; i <= nd->get_max_member_id(); i++)     {       NMLDOMAINSET_MEMBER *nm = nd->get_member(i);       printf("NMLDOMAINSET_MEMBER *nm = nd->get_member(i=%d);\nnm=%p\n",i,nm);        if(nm) {   if(nm->cms && nm->cms->BufferName)     {       printf("nm->cms->BufferName=%s\n",nm->cms->BufferName);     }   NMLTYPE t;    // NMLDOMAINSET_MEMBER is publically derived from NML   // so we can do anything with nm that we could do    // with an NML *, including read, write, peek, get_address()   // etc.   t = nm->peek();   if(t < 0)     {       error_occured=true;     }   printf("nm->peek() returned %d\n",t);   if(t == TEST_MESSAGE_TYPE)     {       TEST_MESSAGE *tm = (TEST_MESSAGE *) nm->get_address();       printf("TEST_MESSAGE *tm = (TEST_MESSAGE *) nm->get_address();\ntm=%p\n",(void *)tm);       printf("tm->i = %d, tm->lastvar=%d\n",tm->i,tm->lastvar);       int j=0;       if(tm->lastvar > 0 && bufsneeded > 0) {   for(j =0; j < bufsread; j++)     {       printf("j=%d,lastnum[j]=%d,bufsread=%d\n",      j,lastnum[j],bufsread);       if(lastnum[j] == tm->lastvar) {   break; }     }   printf("j=%d,lastnum[j]=%d,bufsread=%d\n",  j,lastnum[j],bufsread);   if(lastnum[j] == 0 && j == bufsread)     {       printf("new buffer found. -- bufsread=%d, j=%d,lastnum[j]=%d,tm->lastvar=%d\n",      bufsread,j,lastnum[j],tm->lastvar);       lastnum[j] = tm->lastvar;       bufsread++;       if(bufsread >= bufsneeded) {   break; }     } }     }   else     {       // Deleting an NMLDOMAINSET_MEMBER removes it from       // its parent NMLDOMAINSET.       printf("delete nm;\n");       delete nm;     } }     }   if(bufsneeded > 0 && bufsread >= bufsneeded)     {       break;     }   nd = s.get_next_domainset();   printf("NMLDOMAINSET *nd = s.get_next_domainset();\nnd=%p\n",  (void*)nd); }       if(bufsneeded > 0 && bufsread >= bufsneeded) {   break; }       printf("esleep(2.5);\n");       fflush(stdout);       esleep(2.5);     }    // clean up the signal handler.   signal(SIGINT,old_sigint_handler);     // Set the return value so we can use this program in test scripts.   if(error_occured)     {       exit(2);     }   if(cycles > maxcycles && maxcycles > 0)     {       exit(3);     }   exit(0); }  

The program is somewhat more verbose than an example should be due to its dual use as an implementation testing program. The key points to notice are that:

  • An NMLSET object named s is created when the program is first started using the command line arguments and a pointer to the nml_test_format function which is declared in nml_test_format.hh and allows this particular NMLSET object and the NMLDOMAINSET and NMLDOMAINSET_MEMBER objects that will later be obtained from it to decode and encode messages specific to this example.
  • Each cycle s.update_set() is called. Only during this call can the possible NMLDOMAINSET and NMLDOMAINSET_MEMBER objects than can be obtained from this set change.
  • After calling s.update_set(), a list of NMLDOMAINSET objects is obtained by first calling s.get_first_domainset() and then calling s.get_next_domainset() until an NULL pointer is returned.
  • Each NMLDOMAINSET stores a list of NML connection objects within a single domain.
  • Each of these NML connection objects is obtained by calling nd->get_member(). The returned pointer is of type NMLDOMAINSET_MEMBER *.
  • Since NMLDOMAINSET_MEMBER is publically derived from NML it can be used just any other NML object could be used as described in The NML Programmer's Guide (C++ Version). Except that programmer's should be aware that it should not be dereferenced after the NMLDOMAINSET it was obtained from is deleted, or the NMLSET from which that was obtained is deleted.

The following is a portion of the output from the nml_test_nmlset application:

cycles=33  ********************************************************** s..update_set(1.0); NMLDOMAINSET *nd = s.get_first_domainset(); nd=0x9fbc208 nd->getdomainname() =  nd->cfgsvrname() =  NMLDOMAINSET_MEMBER *nm = nd->get_member(i=0); nm=0x9fb77d0 nm->cms->BufferName=b1 nm->peek() returned 101 TEST_MESSAGE *tm = (TEST_MESSAGE *) nm->get_address(); tm=0x9fb9948 tm->i = 53, tm->lastvar=199 NMLDOMAINSET_MEMBER *nm = nd->get_member(i=1); nm=0x9fbc2a8 nm->cms->BufferName=b2 nm->peek() returned 101 TEST_MESSAGE *tm = (TEST_MESSAGE *) nm->get_address(); tm=0x9fbe420 tm->i = 52, tm->lastvar=198 NMLDOMAINSET *nd = s.get_next_domainset(); nd=0x9fc5668 nd->getdomainname() = d2 nd->cfgsvrname() =  NMLDOMAINSET_MEMBER *nm = nd->get_member(i=0); nm=0x9fc0c98 nm->cms->BufferName=b1 nm->peek() returned 101 TEST_MESSAGE *tm = (TEST_MESSAGE *) nm->get_address(); tm=0x9fc2e10 tm->i = 47, tm->lastvar=195 NMLDOMAINSET_MEMBER *nm = nd->get_member(i=1); nm=0x9fd3620 nm->cms->BufferName=b2 nm->peek() returned 101 TEST_MESSAGE *tm = (TEST_MESSAGE *) nm->get_address(); tm=0x9fd5780 tm->i = 44, tm->lastvar=194 NMLDOMAINSET *nd = s.get_next_domainset(); nd=0x9fca0d0 nd->getdomainname() =  nd->cfgsvrname() = :50000 NMLDOMAINSET_MEMBER *nm = nd->get_member(i=0); nm=0x9fc5700 nm->cms->BufferName=b1 nm->peek() returned 101 TEST_MESSAGE *tm = (TEST_MESSAGE *) nm->get_address(); tm=0x9fc7878 tm->i = 46, tm->lastvar=197 NMLDOMAINSET_MEMBER *nm = nd->get_member(i=1); nm=0x9fca170 nm->cms->BufferName=b2 nm->peek() returned 101 TEST_MESSAGE *tm = (TEST_MESSAGE *) nm->get_address(); tm=0x9fcc2e8 tm->i = 47, tm->lastvar=196 NMLDOMAINSET *nd = s.get_next_domainset(); nd=0x9fd3530 nd->getdomainname() = nd.1.kH1.jyo81.d4a.VClyf1.WHgIb1.Xju1. nd->cfgsvrname() =  NMLDOMAINSET_MEMBER *nm = nd->get_member(i=0); nm=0x9fceb60 nm->cms->BufferName=b1 nm->peek() returned 101 TEST_MESSAGE *tm = (TEST_MESSAGE *) nm->get_address(); tm=0x9fd0cd8 tm->i = 46, tm->lastvar=187 NMLDOMAINSET_MEMBER *nm = nd->get_member(i=1); nm=(nil) NMLDOMAINSET *nd = s.get_next_domainset(); nd=0x9fdc9c0 nd->getdomainname() = d2 nd->cfgsvrname() = :50000 NMLDOMAINSET_MEMBER *nm = nd->get_member(i=0); nm=0x9fd7ff0 nm->cms->BufferName=b1 nm->peek() returned 101 TEST_MESSAGE *tm = (TEST_MESSAGE *) nm->get_address(); tm=0x9fda168 tm->i = 46, tm->lastvar=193 NMLDOMAINSET_MEMBER *nm = nd->get_member(i=1); nm=0x9fdca58 nm->cms->BufferName=b2 nm->peek() returned 101 TEST_MESSAGE *tm = (TEST_MESSAGE *) nm->get_address(); tm=0x9fdebd0 tm->i = 46, tm->lastvar=192 NMLDOMAINSET *nd = s.get_next_domainset(); nd=0x9fe5e10 nd->getdomainname() = nd.3.Kq2.jyo81.d4a.VClyf1.ZHgIb1.6ZE. nd->cfgsvrname() =  NMLDOMAINSET_MEMBER *nm = nd->get_member(i=0); nm=0x9fe1440 nm->cms->BufferName=b1 nm->peek() returned 101 TEST_MESSAGE *tm = (TEST_MESSAGE *) nm->get_address(); tm=0x9fe35b8 tm->i = 44, tm->lastvar=191 NMLDOMAINSET_MEMBER *nm = nd->get_member(i=1); nm=(nil) NMLDOMAINSET *nd = s.get_next_domainset(); nd=0x9fea8c0 nd->getdomainname() = nd.2.Cm2.jyo81.d4a.VClyf1.ZHgIb1.Fdk. nd->cfgsvrname() =  NMLDOMAINSET_MEMBER *nm = nd->get_member(i=0); nm=(nil) NMLDOMAINSET_MEMBER *nm = nd->get_member(i=1); nm=0x9fe5f28 nm->cms->BufferName=b2 nm->peek() returned 101 TEST_MESSAGE *tm = (TEST_MESSAGE *) nm->get_address(); tm=0x9fe8088 tm->i = 44, tm->lastvar=190 NMLDOMAINSET *nd = s.get_next_domainset(); nd=0x9fef368 nd->getdomainname() = nd.1.me2.jyo81.tn5.VClyf1.YHgIb1.KNJ3. nd->cfgsvrname() = :50000 NMLDOMAINSET_MEMBER *nm = nd->get_member(i=0); nm=0x9fea9b0 nm->cms->BufferName=b1 nm->peek() returned 101 TEST_MESSAGE *tm = (TEST_MESSAGE *) nm->get_address(); tm=0x9fecb10 tm->i = 44, tm->lastvar=185 NMLDOMAINSET_MEMBER *nm = nd->get_member(i=1); nm=(nil) NMLDOMAINSET *nd = s.get_next_domainset(); nd=0x9ff3e10 nd->getdomainname() = nd.2.ui2.jyo81.tn5.VClyf1.ZHgIb1.Fo6. nd->cfgsvrname() = :50000 NMLDOMAINSET_MEMBER *nm = nd->get_member(i=0); nm=(nil) NMLDOMAINSET_MEMBER *nm = nd->get_member(i=1); nm=0x9fef458 nm->cms->BufferName=b2 nm->peek() returned 101 TEST_MESSAGE *tm = (TEST_MESSAGE *) nm->get_address(); tm=0x9ff15b8 tm->i = 44, tm->lastvar=184 NMLDOMAINSET *nd = s.get_next_domainset(); nd=0x9ff88b8 nd->getdomainname() = nd.4.8D2.jyo81.d4a.VClyf1.ZHgIb1.qL91. nd->cfgsvrname() =  NMLDOMAINSET_MEMBER *nm = nd->get_member(i=0); nm=(nil) NMLDOMAINSET_MEMBER *nm = nd->get_member(i=1); nm=0x9ff3f00 nm->cms->BufferName=b2 nm->peek() returned 101 TEST_MESSAGE *tm = (TEST_MESSAGE *) nm->get_address(); tm=0x9ff6060 tm->i = 44, tm->lastvar=186 NMLDOMAINSET *nd = s.get_next_domainset(); nd=0x9ffd368 nd->getdomainname() = nd.4.0z2.jyo81.tn5.VClyf1.ZHgIb1.wHX. nd->cfgsvrname() = :50000 NMLDOMAINSET_MEMBER *nm = nd->get_member(i=0); nm=0x9ff89d0 nm->cms->BufferName=b1 nm->peek() returned 101 TEST_MESSAGE *tm = (TEST_MESSAGE *) nm->get_address(); tm=0x9ffab30 tm->i = 44, tm->lastvar=189 NMLDOMAINSET_MEMBER *nm = nd->get_member(i=1); nm=(nil) NMLDOMAINSET *nd = s.get_next_domainset(); nd=0xa001e18 nd->getdomainname() = nd.3.Su2.jyo81.tn5.VClyf1.ZHgIb1.PbN. nd->cfgsvrname() = :50000 NMLDOMAINSET_MEMBER *nm = nd->get_member(i=0); nm=(nil) NMLDOMAINSET_MEMBER *nm = nd->get_member(i=1); nm=0x9ffd480 nm->cms->BufferName=b2 nm->peek() returned 101 TEST_MESSAGE *tm = (TEST_MESSAGE *) nm->get_address(); tm=0x9fff5e0 tm->i = 44, tm->lastvar=188 NMLDOMAINSET *nd = s.get_next_domainset(); nd=(nil) esleep(2.5); cycles=34  **********************************************************  

Notes concerning the above output:

  • There were twelve NMLDOMAINSET objects returned in the single cycle overwhich output was obtained.
  • Four of them had both a b1 and a b2, four had only a b1 and four had only a b2.
  • Seperate NMLDOMAINSET objets were returned with the same domainname when they corresponded to different cfgsvrs.
  • The connection to a b2 buffer was always retrieved with nd->get_member(1) even when there was no b1 buffer and nd->get_member(0) had therefore returned NULL.
  • The nmlcfgsvr names do not include the common "nmlcfgsvr:" prefix.

API Reference

NMLSET

NMLSET is the main class from which objects of type NMLDOMAINSET and NMLDOMAINSET_MEMBER are obtained.

From "nmlset.hh":

class NMLSET { public:   NMLSET(NML_FORMAT_PTR f_ptr,   const char *buflist,   const char *procname,   const char *cfglist);   ~NMLSET();    class NMLDOMAINSET  *get_first_domainset();   class NMLDOMAINSET  *get_next_domainset();   void update_set(double _timeout);  // Other private functions and data members skipped. // . . .  };  

The constructor takes four arguments. The format function is used with all of the NML channels created through this NMLSET. If the channels need different format functions, pass NULL for this argument and use NML::prefix_format_function() to set the format function on each NMLDOMAINSET_MEMBER obtained later. The buflist is a semicolon delimited list of buffer names. The procname is the name of the calling process it is passed to the each nmlcfgsvr and could be used if the nmlcfgsvr needed to be configured to handle this process differently or more likely just to improve diagnostics output, but is typically ignored. The cfglist is a semicolon delimited list of nmlcfgsvrs see NML Configuration Server:Pseudo File Name Syntax. update_set() queries the nmlcfgsvrs for new domains or additional buffers from the list in the existing domains. The timout is passed to each attempt to query so since multiple queries occur over the update_set the time update_set takes to return could be longer than the timeout. A timeout of -1.0 can be used if the queries should never timeout. The functions get_first_domainset and get_next_domainset should be used to iterrate through the list of NMLDOMAINSETs. If the NMLSET object is deleted, pointers to NMLDOMAINSET and NMLDOMAINSET_MEMBERS optained through it should no longer be accessed as they will be deleted as well.

NMLDOMAINSET

NMLDOMAINSET class is used to store the is of NML connections obtained within a single domain.

From "nmlset.hh":

class NMLDOMAINSET { public:   ~NMLDOMAINSET();    class NMLDOMAINSET_MEMBER  *get_member(int id);   const char *getdomainname() const;   const char *getcfgsvrname() const;   int get_max_member_id() const;   // Private members and functions skipped. // . . . };  

get_member() returns the NMLDOMAINSET_MEMBER associated with a given NML connection. It should not be accessed after the NMLDOMAINSET object is deleted. The id should be between 0 and get_max_member_id. NULL will be returned by get_member if no valid NML connection could be obtained for this buffer in the current domain. get_max_member_id always returns an integer one less than the number of buffers in the list passed to the NMLSET constructor. getdomainname returns the domain name associated with this object. The getcfgsvrname() returns the portion of the nmlcfgsvr's pseudo file name after the "nmlcfgsvr:" prefix.


Last Modified: July 12,2004

If you have questions or comments regarding this page please contact Will Shackleford at shackle [at] cme.nist.gov (shackle[at]cme[dot]nist[dot]gov)

Created July 16, 2014, Updated June 2, 2021