We provide this description with the following warning; users wishing to create their own snapshot files should only create SDDS snapshot files. Further, continued support for those users wishing to create their own snapshot files will come in the form of a C header file called burtpublic.h (explained below in section 1). Users who create their own non-SDDS snapshot files do so at their own risk. We provide no support for those users that choose to create their own non-SDDS snapshot files, and further, we reserve the right to change any or all of the syntax/format of non-SDDS snapshot files without any consideration for such users.
burtpublic.h contains all the column and parameter names as well as some other standard values all in the form of #define macros. Users wishing to create their own SDDS snapshot files are best shielded from any changes to these names and standard values by producing these files with a C program and using the #include facility to include burtpublic.h. The intention here is that, although we may change the column and parameter names found in SDDS snapshot files, it is unlikely that we will ever change the #define'd names.
----------------------------------------------------------------------------------------- Public Names Parameter Required / Values Default Values Names Optional ----------------------------------------------------------------------------------------- TIMEHEADERSTRING TimeStamp optional when snapshot was pro 1/1/70 00:00 GMT duced LOGINHEADERSTRING LoginId optional loginid and realworld UNKNOWNLOGINID name of user producing (UNKNOWNREAL snapshot WORLDNAME) EFFUIDHEADERSTRING EffectiveUID optional effective UID of user UNKNOWN producing snapshot GROUPIDHEADERSTRING GroupID optional group ID of user pro UNKNOWN ducing snapshot KEYWORDSHEADERSTRING BurtKeywords optional user supplied keywords empty string COMMENTSHEADERSTRING BurtComments optional user supplied comments empty string TYPEHEADERSTRING SnapType required type of snapshot, ABSOLUTESTRING, RELATIVESTRING, or NOWRITESTRING -----------------------------------------------------------------------------------------Parameter Names are the names of the parameters as they currently (with respect to the creation of this document) appear. These names may change over time. Public Names are the names of the parameters as they appear in burtpublic.h, names that are far less likely to change and users are therefore recommended to use these names instead of the ones found in Parameter Names.
All the parameters are strings and are defined as fixed values that are intended to pertain to the entire snapshot file. Note that all but one of the parameters are optional. The only required parameter is TYPEHEADERSTRING (SnapType). However, when supplying an optional parameter, the user must be very careful to format its value carefully. Examples of how to format each of the parameters correctly appears in the example in section 4.
The values of the parameters KEYWORDSHEADERSTING (BurtKeywords), COMMENTSHEADERSTRING (BurtComments), and TYPEHEADERSTRING (SnapType) are specified directly by the user. The values of the other parameters, TIMEHEADERSTRING (TimeStamp), LOGINHEADERSTRING (LoginID), EFFUIDHEADERSTRING (EffectiveUID), and GROUPIDHEADERSTRING (GroupID) are also supplied by the user, but only after making calls to operating system, i.e., UNIX. This is illustrated by the example in section 4.
-------------------------------------------------------------------------------------------------- Public Names Column SDDS Types Required/ Contents Default Default Names Optional Values Meanings -------------------------------------------------------------------------------------------------- NAME_COL ControlName SDDS_STRING required PV or Device name TYPE_COL ControlType SDDS_STRING required type of entity, PVSTRING or DEVSTRING LINEAGE_COL Lineage SDDS_STRING required lineage of composite devices, for devices only, DEFAULT STRING for pvars NELEM_COL Count SDDS_LONG required number of elements, 1 for devices VAL_COL ValueString SDDS_STRING required value MODE_COL ControlMode SDDS_STRING optional read only tag, DEFAULT restore to IOC DERAULTSTRING, STRING READONLYSTRING, or READONLYNOTI FYSTRING READMSG_COL BackupMsg SDDS_STRING optional device read msg, DEFAULT DEFAULT DEFAULTSTRING for STRING READMSG pvars WRITEMSG_COL RestoreMsg SDDS_STRING optional device write msg, DEFAULT DEFAULT DEFAULTSTRING for STRING WRITEMSG pvars --------------------------------------------------------------------------------------------------Similar to the parameter names, Column Names are the names of the columns as they currently appear in the SDDS snapshot files. These names may change over time. Public Names are the names of the columns as they appear in burtpublic.h, names that are far less likely to change and users are therefore recommended to use these names instead of the ones found in Column Names.
Note that all but three of the columns are required. Additionally, values of certain columns are dictated by values in other columns. For example, NELEM_COL (Count) must be 0 for devices and the columns LINEAGE_COL (Lineage), READMSG_COL (BackupMsg), and WRITEMSG_COL (RestoreMsg) must all be DEFAULT_STRING (currently defined as ``-'' in burtpublic.h) for process variables.
/* for getpwuid() */ #include <pwd.h> /* for time() */ #include <sys/types.h> #include <sys/time.h> /* for geteuid() */ #include <unistd.h> #include <burtpublic.h> #include <SDDS.h>Initially we have the #include files. The first four are necessary for the subsequent UNIX calls we need to make to get information about the user generating the snapshot and the time at which the snapshot was generated. The last two are necessary for BURT and SDDS, respectively.
main() { SDDS_TABLE table; int effective_uid; time_t currtime; struct passwd *pp; char buff[100]; if (!SDDS_InitializeOutput(&table, SDDS_ASCII, 1L, NULL, NULL, "Snapshot")) { fprintf(stderr, "ERROR: unable to initialize table.\n"); exit(1); } /* endif */Above we have named the output file Snapshot. Below we define the snapshot header,i.e., the fixed valued parameters. Recall that BURT requires that only one of the parameters be defined, TYPEHEADERSTRING (SnapType). However, we have defined all for this program. First, we need to make some UNIX calls.
/***************************/ /* */ /* Defining the Parameters */ /* */ /***************************/ /* first, make all the necessary UNIX calls */ if (time(&currtime) == (time_t) -1) { fprintf(stderr, "ERROR: unable to get current time.\n"); exit(1); } /* endif */ effective_uid = geteuid(); if ((pp = getpwuid(effective_uid)) == NULL) { fprintf(stderr, "ERROR: unable to get user information.\n"); exit(1); } /* endif */Above are examples of the UNIX calls necessary identify who is creating the snapshot file and the time at which it is created. Following are the SDDS calls to create each of the fixed valued parameters. Note that the public names of the parameters, i.e., those found in burtpublic.h, are used and that each parameter has been defined as the correct SDDS type. Note also the format of the parameters, particularly the format of TIMEHEADERSTRING (TimeStamp) and LOGINHEADERSTING (LoginID). BURT expects and demands this exact syntax.
/* time stamp */ if (!SDDS_DefineParameter(&table, TIMEHEADERSTRING, NULL, NULL, NULL, NULL, SDDS_STRING, ctime(&currtime)) == -1) { fprintf(stderr, "ERROR: could not define parameter >%s<.\n", TIMEHEADERSTRING); exit(1); } /* endif */ /* loginid (real world name) */ sprintf(buff, "%s (%s)", pp->pw_name, pp->pw_gecos); if (!SDDS_DefineParameter(&table, LOGINHEADERSTING, NULL, NULL, NULL, NULL, SDDS_STRING, buff) == -1) { fprintf(stderr, "ERROR: could not define parameter >%s<.\n", LOGINHEADERSTING); exit(1); } /* endif */ /* effective uid */ /* uid - person who logged in ... effective uid person as */ /* defined by "set-user-ID" (if done at all) */ sprintf(buff, "%d", (int) pp->pw_uid); if (!SDDS_DefineParameter(&table, EFFUIDHEADERSTRING, NULL, NULL, NULL, NULL, SDDS_STRING, buff) == -1) { fprintf(stderr, "ERROR: could not define parameter >%s<.\n", EFFUIDHEADERSTRING); exit(1); } /* endif */ /* group id */ sprintf(buff, "%d", (int) pp->pw_gid); if (!SDDS_DefineParameter(&table, GROUPIDHEADERSTRING, NULL, NULL, NULL, NULL, SDDS_STRING, buff) == -1) { fprintf(stderr, "ERROR: could not define parameter >%s<.\n", GROUPIDHEADERSTRING); exit(1); } /* endif */ /* keywords */ if (!SDDS_DefineParameter(&table, KEYWORDSHEADERSTRING, NULL, NULL, NULL, NULL, SDDS_STRING, "these are keywords") == -1) { fprintf(stderr, "ERROR: could not define parameter >%s<.\n", KEYWORDSHEADERSTRING); exit(1); } /* endif */ /* comments */ if (!SDDS_DefineParameter(&table, COMMENTSHEADERSTRING, NULL, NULL, NULL, NULL, SDDS_STRING, "these are comments") == -1) { fprintf(stderr, "ERROR: could not define parameter >%s<.\n", COMMENTSHEADERSTRING); exit(1); } /* endif */ /* snapshot type, Absolute */ if (!SDDS_DefineParameter(&table, TYPEHEADERSTRING, NULL, NULL, NULL, NULL, SDDS_STRING, ABSOLUTESTRING) == -1) { fprintf(stderr, "ERROR: could not define parameter >%s<.\n", TYPEHEADERSTRING); exit(1); } /* endif */We have chosen to create an Absolute snapshot file by specifying the value ABSOLUTESTRING. We could have just as easily created a Relative or Nowrite snapshot file.
Immediately following is the definition of the columns. Although BURT does not require all the columns, we chose to include all of them. Note that each column has been defined with the correct public name and as the correct SDDS type.
/************************/ /* */ /* Defining the Columns */ /* */ /************************/ if (SDDS_DefineColumn(&table, NAME_COL, NULL, NULL, NULL, NULL, SDDS_STRING, 0) == -1) { fprintf(stderr, "ERROR: could not define column >%s<.\n", NAME_COL); exit(1); } /* endif */ if (SDDS_DefineColumn(&table, TYPE_COL, NULL, NULL, NULL, NULL, SDDS_STRING, 0) == -1) { fprintf(stderr, "ERROR: could not define column >%s<.\n", TYPE_COL); exit(1); } /* endif */ if (SDDS_DefineColumn(&table, LINEAGE_COL, NULL, NULL, NULL, NULL, SDDS_STRING, 0) == -1) { fprintf(stderr, "ERROR: could not define column >%s<.\n", LINEAGE_COL); exit(1); } /* endif */ if (SDDS_DefineColumn(&table, READMSG_COL, NULL, NULL, NULL, NULL, SDDS_STRING, 0) == -1) { fprintf(stderr, "ERROR: could not define column >%s<.\n", READMSG_COL); exit(1); } /* endif */ if (SDDS_DefineColumn(&table, WRITEMSG_COL, NULL, NULL, NULL, NULL, SDDS_STRING, 0) == -1) { fprintf(stderr, "ERROR: could not define column >%s<.\n", WRITEMSG_COL); exit(1); } /* endif */ if (SDDS_DefineColumn(&table, MODE_COL, NULL, NULL, NULL, NULL, SDDS_STRING, 0) == -1) { fprintf(stderr, "ERROR: could not define column >%s<.\n", MODE_COL); exit(1); } /* endif */ if (SDDS_DefineColumn(&table, NELEM_COL, NULL, NULL, NULL, NULL, SDDS_LONG, 0) == -1) { fprintf(stderr, "ERROR: could not define column >%s<.\n", NELEM_COL); exit(1); } /* endif */ if (SDDS_DefineColumn(&table, VAL_COL, NULL, NULL, NULL, NULL, SDDS_STRING, 0) == -1) { fprintf(stderr, "ERROR: could not define column >%s<.\n", VAL_COL); exit(1); } /* endif */
/**********************/ /* */ /* Writing the Header */ /* */ /**********************/ if (!SDDS_WriteLayout(&table)) { fprintf(stderr, "ERROR: could not write header.\n"); exit(1); } /* endif */
/***************************/ /* */ /* Starting the Data Table */ /* */ /***************************/ if (!SDDS_StartTable(&table, 5L)) { fprintf(stderr, "ERROR: unable to start the data table\n"); exit(1); } /* endif */Below we fill the table with data values. This particular table has five entries, two process variables and three devices.
/*******************************/ /* */ /* Filling the Table With Data */ /* */ /*******************************/The first value is a scalar process variable, ``burtgenerator'', with a value of 0.0.
/* row 0: scalar pv, name="burtgenerator" val=0.0 */ if (!SDDS_SetRowValues(&table, (long) (SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE), 0L, NAME_COL, "burtgenerator", TYPE_COL, PVSTRING, LINEAGE_COL, DEFAULTSTRING, READMSG_COL, DEFAULTSTRING, WRITEMSG_COL, DEFAULTSTRING, MODE_COL, DEFAULTSTRING, NELEM_COL, 1L, VAL_COL, "0.0", NULL)) { fprintf(stderr, "ERROR: unable to set row 0\n"); exit(1); } /* endif */The second value is a device, ``burtdevao'', that is tagged Read Only and has a value of 1.0
/* row 1: device, name="burtdevao" val=1.0 mode=RO */ if (!SDDS_SetRowValues(&table, (long) (SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE), 1L, NAME_COL, "burtdevao", TYPE_COL, DEVSTRING, LINEAGE_COL, DEFAULTSTRING, READMSG_COL, DEFAULTREADMSG, WRITEMSG_COL, DEFAULTWRITEMSG, MODE_COL, READONLYSTRING, NELEM_COL, 1L, VAL_COL, "1.0", NULL)) { fprintf(stderr, "ERROR: unable to set row 1\n"); exit(1); } /* endif */The third value is also a device, ``burtdevcalc'', that is tagged Read Only Notify and has a value of 2.0.
/* row 2: device, name="burtdevcalc" val=2.0 mode=RON */ if (!SDDS_SetRowValues(&table, (long) (SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE), 2L, NAME_COL, "burtdevcalc", TYPE_COL, DEVSTRING, LINEAGE_COL, DEFAULTSTRING, READMSG_COL, DEFAULTREADMSG, WRITEMSG_COL, DEFAULTWRITEMSG, MODE_COL, READONLYNOTIFYSTRING, NELEM_COL, 1L, VAL_COL, "2.0", NULL)) { fprintf(stderr, "ERROR: unable to set row 2\n"); exit(1); } /* endif */The fourth value is a device, ``burtdevcalc'', that is part of a composite device called ``burtdevcomp''. Its value is 3.0 and it here we choose to explicitly supply its backup message, ``read''. Although its backup message happens to be the same as the DEFAULTREADMSG, we explicitly assigned the backup message its value to demonstrate how to do so. We could have just as easily chosen any backup message we wanted to.
/* row 3: device, name="burtdevcalc" val=3.0 parent=burtdevcomp */ /* readmsg="read" */ if (!SDDS_SetRowValues(&table, (long) (SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE), 3L, NAME_COL, "burtdevcalc", TYPE_COL, DEVSTRING, LINEAGE_COL, "burtdevcomp", READMSG_COL, "read", WRITEMSG_COL, DEFAULTWRITEMSG, MODE_COL, DEFAULTSTRING, NELEM_COL, 1L, VAL_COL, "3.0", NULL)) { fprintf(stderr, "ERROR: unable to set row 3\n"); exit(1); } /* endif */The fifth value is a vector process variable, ``burtwaveform'', that has six elements. The last two values of the vector are missing. Note when supplying values to a vector where some of the values are missing the user must use NULLSTRING (from burtpublic.h) to specify the missing values.
/* row 4: vector pv, name="burtwaveform" nelem=6 */ /* val=[4.0 4.1 4.2 4.3 4.4 <missing> <missing> ] */ sprintf(buff, "4.0 4.1 4.2 4.3 %s %s", NULLSTRING, NULLSTRING); if (!SDDS_SetRowValues(&table, (long) (SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE), 4L, NAME_COL, "burtwaveform", TYPE_COL, PVSTRING, LINEAGE_COL, DEFAULTSTRING, READMSG_COL, DEFAULTSTRING, WRITEMSG_COL, DEFAULTSTRING, MODE_COL, DEFAULTSTRING, NELEM_COL, 6L, VAL_COL, buff, NULL)) { fprintf(stderr, "ERROR: unable to set row 4\n"); exit(1); } /* endif */
/**************************/ /* */ /* Writing the Data Table */ /* */ /**************************/ if (!SDDS_WriteTable(&table)) { fprintf(stderr, "ERROR: could not write table.\n"); exit(1); } /* endif */
/***********/ /* */ /* Cleanup */ /* */ /***********/ if (!SDDS_Terminate(&table)) { fprintf(stderr, "ERROR: could not terminate SDDS table.\n"); exit(1); } /* endif */ } /* end main() */As mentioned, the previous program without interleaved commentary, its makefile, and the output it generates can all be found in the appendices to this document.
There is one more note of interest which has to do with reading SDDS snapshot files into programs outside the suite of BURT's programs. As mentioned earlier, this document is not intended as an instructional aid for SDDS, however, there is one parameter in the SDDS snapshot files that merits further discussion, TIMEHEADERSTRING (TimeStamp). It has a format all its own and it is occasionally convenient to convert that string value to one of the UNIX conventions of the number of seconds since 00:00:00, January 1, 1970. This is done with the UNIX command strptime() which converts a string representation of time to the number of seconds. It expects, as one of its arguments, a description of the format of the string. This format can also be found in burtpublic.h in the #define'd variable TIMEFORMATSTRING.
Assuming that the value of the parameter has been read into a string pointed at by the variable cp, here is the code convert the string into one of UNIX's internal structures.
/* for strptime() */ #include <time.h> #include <burtpublic.h> main() { char *cp; struct tm tmtime; . . . strptime(cp, TIMEFORMATSTRING, &tmtime); . . . } /* end main() */
Table of Contents Next Chapter