[Top] [Prev] [Next]

4.5 Writing to Multi-Field Vdatas

There are several steps involved in creating general vdatas with more than one field: define the vdata, define the fields of the vdata, and write the vdata to the file. These steps are usually executed within a single program, although it is also possible to define an empty vdata in anticipation of writing data to it at a later time.

4.5.1 Creating Vdatas

Creating an empty vdata involves the following steps:

  1. Open a file.
  2. Initialize the Vdata interface.
  3. Create the new vdata.
  4. Assign a vdata name. (optional)
  5. Assign a vdata class. (optional)
  6. Define the fields.
  7. Initialize fields for writing.
  8. Set the interlace mode.
  9. Dispose of the vdata identifier.
  10. Terminate access to the Vdata interface.
  11. Close the file.

Like the high-level VH interface, the Vdata interface does not retain default settings from one operation to the next or from one file to the next. Each time a vdata is created, its definitions must be explicitly reset.

To create a multi-field vdata, the calling program must contain the following:

C:		file_id = Hopen(filename, file_access_mode, num_dds_block);
		status = Vstart(file_id);
		vdata_id = VSattach(file_id, -1, vdata_access_mode);
		status = VSsetname(vdata_id, vdata_name);
		status = VSsetclass(vdata_id, vdata_class);
		status = VSfdefine(vdata_id, fieldname1, data_type1, order1);
		 . . . . . . . . . .
		status = VSfdefine(vdata_id, fieldnameN, data_typeN, orderN);
		status = VSsetfields(vdata_id, fieldname_list);
		status = VSsetinterlace(vdata_id, interlace_mode);
		status = VSdetach(vdata_id);
		status = Vend(file_id);
		status = Hclose(file_id);
FORTRAN:	file_id = hopen(filename, file_access_mode, num_dds_block)
		status = vfstart(file_id)
		vdata_id = vsfatch(file_id, -1, vdata_access_mode)
		status = vsfsnam(vdata_id, vdata_name)
		status = vsfscls(vdata_id, vdata_class)
		status = vsffdef(vdata_id, fieldname1, data_type1, order1)
		 . . . . . . . . . .
		status = vsffdef(vdata_id, fieldnameN, data_typeN, orderN)
		status = vsfsfld(vdata_id, fieldname_list)
		status = vsfsint(vdata_id, interlace_mode)
		status = vsfdtch(vdata_id)
		status = vfend(file_id)
		status = hclose(file_id)
In the routines that follow, vdata_id is the vdata identifier returned by VSattach.

4.5.1.1 Assigning a Vdata Name and Class: VSsetname and VSsetclass

VSsetname assigns a name to a vdata. If not explicitly named by a call to VSsetname, the name of the vdata is set by default to NULL. A name may be assigned and reassigned at any time after the vdata is created. The parameter vdata_name contains the name to be assigned to the vdata.

VSsetclass assigns a class to a vdata. If VSsetclass is not called, the vdata's class is set by default to NULL. As with the vdata name, the class may be assigned and reassigned any time after the vdata is created. The parameter vdata_class contains the class name to be assigned to the vdata.

VSsetname and VSsetclass return either SUCCEED (or 0) or FAIL (or -1). The parameters for these routines are further defined in Table 4E on page 137.

4.5.1.2 Defining a Field within a Vdata: VSfdefine

VSfdefine defines a field within a newly-created vdata. Each VSfdefine call assigns the name contained in the argument fieldname, the data type contained in the argument data_type, and the order contained in the argument order to one new field. Once data is written to a vdata, the name, data type and order of the field may not be modified or deleted.

The Vdata interface also provides certain predefined fields. A predefined field has a specific name, data type, and order, so there is no need to call VSfdefine to define a predefined field. Some applications may require the use of predefined fields in vdatas. Available predefined fields are discussed in Table 4D.

Note that VSfdefine does not allocate memory for the field, but simply introduces the field. The field definition must be completed by VSsetfields, which is discussed in Section 4.5.1.3 on page 136.

VSfdefine returns either SUCCEED (or 0) or FAIL (or -1). The parameters for VSfdefine are further described in Table 4E on page 137.

TABLE 4D - Predefined Data Types and Field Names for Vdata Fields

Data Type
Coordinate Point Field Names
Normal Component Field Names
x-coordinate
y-coordinate
z-coordinate
x-component
y-component
z-component
float
PX
PY
PZ
NX
NY
NZ
integer
IX
IY
IZ
None
None
None

4.5.1.3 Initializing the Fields for Write Access: VSsetfields

VSsetfields initializes read and write access to the fields in a vdata. It must be called prior to read or write operations. Initializing for read access is discussed in Section 4.6.1 on page 144. For writing, VSsetfields specifies the fields to be written and the order in which they are to be placed.

The parameter fieldname_list is a comma-separated list of the field names, with no white space included. The fields can be either the predefined fields or the fields that have been previously introduced by VSfdefine. VSfdefine allows a user to declare a field, along with its data type and order, but VSsetfields finalizes the definition by allowing the user to select the fields that are to be included in the vdata. Thus, any fields created by VSfdefine that are not in the parameter fieldname_list of VSsetfields will be ignored. This feature was originally intended for interactive-mode users. The combined width of the fields in the parameter fieldname_list is also the length of the record and must be less than MAX_FIELD_SIZE (or 65535). An attempt to create a larger record will cause VSsetfields to return FAIL (or -1).

VSsetfields returns either SUCCEED (or 0) or FAIL (or -1). The parameters for VSsetfields are further defined in Table 4E on page 137.

4.5.1.4 Specifying the Interlace Mode: VSsetinterlace

The Vdata interface supports two types of interlacing: file interlacing and buffer interlacing. File interlacing determines how data is stored in a file and buffer interlacing determines how data is stored in memory. The Vdata interface can write data from a buffer to a file in an interlaced or non-interlaced manner. It can also read data from a file in an interlaced or non-interlaced manner.

The VSread and VSwrite routines set the buffer's interlace mode. The VSwrite routine will be discussed in Section 4.5.2.2 on page 139 and the VSread routine will be discussed in Section 4.6.2 on page 145.

VSsetinterlace sets the file interlacing mode for a vdata. Setting the parameter interlace_mode to FULL_INTERLACE (or 0) fills the vdata by record, whereas specifying NO_INTERLACE (or 1) fills the vdata by field. (See Figure 4d.) For multi-component fields, all components are treated as a single field.

As with file interlacing, the default buffer interlace mode is FULL_INTERLACE because it is more efficient to write complete records than it is to write fields if the file and buffer interlace modes are the same, although both require the same amount of disk space.

In Figure 4d, the illustrated vdata has four fields and three records.

FIGURE 4d - Interlaced and Non-Interlaced Vdata Contents

VSsetinterlace can only be used for operations on new vdatas as the interlacing cannot be changed once the data has been written to a vdata. Records in a fully interlaced vdata can be written record-by-record and, thus, can be appended; however, all records in a non-interlaced vdata must be written at the same time.

VSsetinterlace returns either SUCCEED (or 0) or FAIL (or -1). The parameters for VSsetinterlace are further described in Table 4E.

TABLE 4E - VSsetname, VSsetclass, VSfdefine, VSsetfields, and VSsetinterlace Parameter Lists

Routine Name

[Return Type]

(FORTRAN-77)
Parameter
Parameter Type
Description
C
FORTRAN-77
VSsetname

[int32]

(vsfsnam)
vdata_id
int32
integer
Vdata identifier

vdata_name
char *
character*(*)
Vdata name

VSsetclass

[int32]

(vsfscls)
vdata_id
int32
integer
Vdata identifier

vdata_class
char *
character*(*)
Vdata name

VSfdefine

[intn]

(vsffdef)
vdata_id
int32
integer
Vdata identifier

fieldname
char *
character*(*)
Name of the field to be defined

data_type
int32
integer
Type of the field data

order
int32
integer
Order of the new field

VSsetfields

[intn]

(vsfsfld)
vdata_id
int32
integer
Vdata identifier

fieldname_list
char *
character*(*)
Names of the vdata fields to be accessed

VSsetinterlace

[intn]

(vsfsint)
vdata_id
int32
integer
Vdata identifier

interlace_mode
int32
integer
Interlace mode

4.5.2 Writing Data to Vdatas

This section describes the vdata writing operation (VSwrite), random access to vdata (VSseek), and packing and unpacking mechanisms that allow storing vdata fields of different data types (VSfpack).

Writing to a vdata requires the following steps:

  1. Open a file.
  2. Initialize the Vdata interface.
  3. Initialize fields for writing.
  4. Initiate access to the vdata.
  5. Seek to the target record.
  6. Write the data.
  7. Dispose of the vdata identifier.
  8. Terminate access to the Vdata interface.
  9. Close the file.

These steps correspond to the following sequence of function calls:

C:		file_id = Hopen(filename, file_access_mode, num_dds_block);
		status = Vstart(file_id);
		vdata_id = VSattach(file_id, vdata_ref, vdata_access_mode);
		status = VSsetfields(vdata_id, fieldname_list);
		record_pos = VSseek(vdata_id, record_index);
		num_of_recs = VSwrite(vdata_id, databuf, n_records, interlace_mode);
		status = VSdetach(vdata_id);
		status = Vend(file_id);
		status = Hclose(file_id);
FORTRAN:	file_id = hopen(filename, file_access_mode, num_dds_block)
		status = vfstart(file_id)
		vdata_id = vsfatch(file_id, vdata_ref, vdata_access_mode)
		status = vsfsfld(vdata_id, fieldname_list);
		record_pos = vsfseek(vdata_id, record_index);
		num_of_recs = vsfwrt(vdata_id, databuf, n_records, interlace_mode)
	OR	num_of_recs = vsfwrtc(vdata_id, databuf, n_records, interlace_mode)
	OR	num_of_recs = vsfwrit(vdata_id, databuf, n_records, interlace_mode)
		status = vsfdtch(vdata_id)
		status = vfend(file_id)
		status = hclose(file_id)

4.5.2.1 Resetting the Current Position within Vdatas: VSseek

VSseek provides a mechanism for random access to fully-interlaced vdatas. Random-access for non-interlaced vdatas is not available. The parameter record_index is the position of the record to be written. The position of the first record in a vdata is specified by record_index = 0. Any vdata operation will be performed on this record by default; vdata operations on other records require that VSseek be called first to specify the target record.

Note that VSseek has been designed for the purpose of overwriting data, not appending data. That means VSseek puts the current record pointer at the beginning of the sought record and the subsequent write will overwrite the record. To append data to a vdata, the current record pointer must be put at the end of the last record. Thus, you must seek to the last record then read this record so that the current record pointer will be put at the end of the record. A write operation will now start at the end of the last record in the vdata. Figure 4e illustrates a situation where VSseek can be misused while attempting to append data to the vdata and how VSread is called to correctly place the record pointer at the end of the vdata for appending.

Note that, because the record location numbering starts at 0, the record location and the value of the parameter record_index are off by 1. For example, reading the fourth record in the buffer requires record_index to be set to 3.

FIGURE 4e - Setting the Record Pointer to the End of a Vdata

In this illustration, the vdata to which we plan to append data contains 4 records. Using VSseek to seek to the end of the fourth record by setting the parameter record_index to 4 results in an error condition. Setting the parameter record_index to 3 places the current record pointer at the beginning of the fourth record. We then use VSread to read the contents of the fourth record into a buffer; this moves the current record pointer to the end of the fourth record. The contents of the buffer can then be discarded and a write operation can be called to append data to the end of the vdata.

VSseek returns the sought record location or FAIL (or -1). Its parameters are further defined in Table 4F.

4.5.2.2 Writing to a Vdata: VSwrite

VSwrite writes buffered data to a specified vdata. The parameter databuf is a buffer containing the records to be stored in the vdata. The parameter n_records specifies the number of records to be stored.

Recall that the file interlacing is set by VSsetinterlace when the vdata is created, and the buffer interlacing is specified by the parameter interlace_mode in the call to VSwrite when data is written to the file. The array databuf is assumed to be organized in memory as specified by interlace_mode. Setting interlace_mode to FULL_INTERLACE (or 0) indicates that the array in memory is organized by record, whereas to NO_INTERLACE (or 1) indicates that the array is organized by field. (See Figure 4f.) VSwrite will write interlaced or non-interlaced data to a vdata in a file: interlaced data in the buffer can be written to the vdata in the file as non-interlaced data and vice versa. If the data is to be stored with an interlace mode different from that of the buffer, VSsetinterlace (described in Section 4.5.1.4 on page 136) must be called prior to VSwrite. Multiple write operations can only be used on fully-interlaced vdatas in the file.

FIGURE 4f - Writing Interlaced or Non-interlaced Buffers into Interlaced or Non-interlaced Vdatas

The data in the array databuf is assumed to contain the exact amount of data in the order needed to fill the fields defined in the last call to VSsetfields. Because VSwrite writes the contents of databuf contiguously to the vdata, any "padding" due to record alignment must be removed before attempting to write from databuf to the vdata. For more information on alignment padding see Section 4.5.2.3 on page 141.

It should be remembered that VSwrite writes whole records, not individual fields. If a modification to one field within a previously-written record is needed, the contents of the record must first be preserved by reading it to a buffer with VSread, which will be described in Section 4.6.2 on page 145; the record must then be updated in the buffer and written back to the file with VSwrite.

To store a vdata to the file after being created, either VSsetname, VSsetfields, or VSwrite must be called before VSdetach for the vdata. If VSwrite is not called, the vdata created will be empty.

The FORTRAN-77 version of VSwrite has three routines: vsfwrt is for buffered numeric data, vsfwrtc is for buffered character data and vsfwrit is for generic packed data.

VSwrite returns the total number of records written or FAIL (or -1). Its parameters are further defined in Table 4F.

TABLE 4F - VSseek and VSwrite Parameter Lists

Routine Name

[Return Type]

(FORTRAN-77)
Parameter
Parameter Type
Description
C
FORTRAN-77
VSseek

[int32]

(vsfseek)
vdata_id
int32
integer
Vdata identifier

record_index
int32
integer
Index of the record to seek to

VSwrite

[int32]

(vsfwrt/vsfwrtc/
vsfwrit)
vdata_id
int32
integer
Vdata identifier

databuf
uint8*
<valid numeric data type>(*) / character*(*) / integer
Buffer containing data to be written

n_records
int32
integer
Number of records to be written

interlace_mode
int32
integer
Interlace mode of the buffered data

EXAMPLE 3. Writing a Vdata of Homogeneous Type

This example illustrates the use of VSfdefine/vsffdef, VSsetname/vsfsnam, VSsetclass/vsfscls, VSsetfields/vsfsfld, and VSwrite/vsfwrt to create and write a three-field vdata to the file "General_Vdatas.hdf". Although the fields have data of the same type, they have different orders.

To clarify the illustration, let us assume that the vdata is used to contain the data of some particles collected from an experiment. Each record of the data includes the position of a particle, its weight, and the minimum and maximum temperature the particle can endure. The vdata is named "Solid Particle", contains 10 records, and belongs to a class, named "Particle Data". The fields of the vdata include "Position", "Mass", and "Temperature". The field "Position" has an order of 3 for the x, y, and z values representing the position of a particle. The field "Mass" has an order of 1. The field "Temperature" has an order of 2 for the minimum and maximum temperature. The program creates the vdata, sets its name and class name, defines its fields, and then writes the data to it.

C version

FORTRAN-77 version

4.5.2.3 Packing or Unpacking Field Data: VSfpack

Storing fields of mixed data types is an efficient use of disk space and is useful in applications that use structures. However, while data structures in memory containing fields of variable lengths can contain alignment bytes, field data stored in a vdata cannot include them. This is true for both fully-interlaced and non-interlaced data. Because of this storing limitation, when variable-length field types are used, it is generally not possible to write data directly from a structure in memory into a vdata in a file with a VSwrite call or to read data directly into a buffer from the vdata with a call to VSread. Thus, when writing, VSfpack is used to pack field data into a temporary buffer by removing the padding, or alignment bytes, and when reading, to unpack field data into vdata fields by adding necessary alignment bytes. The syntax for VSfpack is as follows:

C:		status = VSfpack(vdata_id, action, fields_in_buf, buf, buf_size, n_records, fieldname_list, bufptrs);
FORTRAN:	status = vsfcpak(vdata_id, action, fields_in_buf, buf, buf_size, n_records, fieldname_list, bufptrs)
	OR	status = vsfnpak(vdata_id, action, fields_in_buf, buf, buf_size, n_records, fieldname_list, bufptrs)
The process of removing the alignment bytes is called "packing the array." An illustration of this process is provided in Figure 4g. The data provided by the user is stored in the structure in memory. The field values are aligned with padded bytes. VSfpack packs the data into the array in memory after removing the padded bytes. The packed data is then written to the vdata in the file by VSwrite.

FIGURE 4g - Removing Alignment Bytes When Writing Data From a C Structure to a Vdata

The process illustrated in Figure 4g can be read in the reverse direction for "unpacking the array," that is when using VSfpack to fill a structure in memory with vdata field data. In this case, alignment bytes are added to the field data to make the data conform to the specific alignment requirements of the platform.

VSfpack performs both tasks, packing and unpacking, and the parameter action specifies the appropriate action for the routine. Valid values for the parameter action are _HDF_VSPACK (or 0) for packing and _HDF_VSUNPACK (or 1) for unpacking.

The calling program must allocate sufficient space for the buffer buf to hold all packed or unpacked fields. The parameter buf_size specifies the size of the buffer buf and should be at least n_records *( the total size of all fields specified in fields_in_buf).

When VSfpack is called to pack field values into buf, the parameter fields_in_buf must specify all fields of the vdata. This can be accomplished either by listing all of the field names in fields_in_buf or by setting fields_in_buf to NULL in C or to one blank character in FORTRAN-77.

When VSfpack is called to unpack field values, the parameter fields_in_buf may specify a subset of the vdata fields. The parameter fields_in_buf can be set to NULL in C or to one space character in FORTRAN-77 to specify all fields in the vdata.

The parameter fieldname_list specifies the field(s) to be packed or unpacked. The parameter bufptrs provides pointers to the buffers for each field to be packed or unpacked. The calling program is responsible for allocating sufficient space for each field buffer. Significant differences between the C and FORTRAN-77 functionality are described in the following paragraphs.

In C, fieldname_list can list either all of the fields specified by fields_in_buf or a subset of those fields. Only if fields_in_buf specifies all of the vdata fields, then fields_in_buf can be set to NULL to specify all vdata fields. The parameter bufptrs contains an array of pointers to the buffers where field data will be packed or unpacked.

The FORTRAN-77 routines can pack or unpack only one field at a time, so the parameter fieldname_list contains only the name of that field. The parameter bufptrs is the buffer for that field.

The FORTRAN-77 version of VSfpack has two routines: vsfcpak packs or unpacks character data and vsfnpak packs or unpacks numeric data. Refer to the FORTRAN-77 version in Example 4 for a more specific illustration.

VSfpack returns either SUCCEED (or 0) or FAIL (or -1). The parameters for VSfpack are described in Table 4G.

TABLE 4G - VSfpack Parameter List

Routine Name

[Return Type]

(FORTRAN-77)
Parameter
Parameter Type
Description
C
FORTRAN-77
VSfpack

[intn]

(vsfcpak/vsfnpak)
vdata_id
int32
integer
Vdata identifier

action
intn
integer
Action to be performed

fields_in_buf
char *
character*(*)
Fields in the buffer buf to write or read from the vdata

buf
VOIDP
integer
Buffer for the vdata values

buf_size
intn
integer
Buffer size in bytes

n_records
intn
integer
Number of records to pack or unpack

fieldname_lis t
char *
character*(*)
Names of the fields to be packed or unpacked

bufptrs
VOIDP
<valid numeric data type>(*)/
character*(*)
Array of pointers to the field buffers in C and field buffer in FORTRAN-77

EXAMPLE 4. Writing a Multi-field and Mixed-type Vdata with Packing

This example illustrates the use of VSfpack/vsfnpak/vsfcpak and VSwrite/vsfwrit to write a vdata with data of different types. Note that the approach used in Example 3 makes it difficult for the vdata to have mixed-type data.

In this example, the program creates an HDF file, named "Packed_Vdata.hdf", then defines a vdata which is named "Mixed Data Vdata" and belongs to class "General Data Class". The vdata contains four order-1 fields, "Temp", "Height", "Speed", and "Ident" of type float32, int16, float32, and char8, respectively. The program then packs the data in fully interlaced mode into a databuf and writes the packed data to the vdata. Note that, in the C example, a VSfpack call packs all N_RECORDS and a VSwrite call writes out all N_RECORDS records. In the Fortran example, N_RECORDS of each field are packed using separate calls to vsfnpak and vsfcpak; vsfwrit writes packed data to the vdata.

C version

FORTRAN-77 version



[Top] [Prev] [Next]

hdfhelp@ncsa.uiuc.edu
HDF User's Guide - 07/21/98, NCSA HDF Development Group.