SDDSlib
Loading...
Searching...
No Matches
SDDSmpi_output.c File Reference

MPI-based Parallel I/O Functions for SDDS Datasets. More...

#include "SDDS.h"
#include "stdio.h"

Go to the source code of this file.

Functions

char * BlankToNull (char *string)
 Converts a blank string to NULL.
 
void SDDS_MPI_GOTO_ERROR (FILE *fp, char *str, int32_t mpierr, int32_t exit_code)
 Handles MPI errors by printing an error message and optionally exiting.
 
int32_t SDDS_MPI_File_Open (MPI_DATASET *MPI_dataset, char *filename, unsigned long flags)
 Opens an MPI file with the specified flags.
 
char * SDDS_CreateNamelistField (char *name, char *value)
 Creates a namelist field string from a name and value.
 
char * SDDS_CreateDescription (char *text, char *contents)
 Creates a description block for the SDDS layout.
 
char * SDDS_CreateParameterDefinition (PARAMETER_DEFINITION *parameter_definition)
 Creates a parameter definition block for the SDDS layout.
 
char * SDDS_CreateColumnDefinition (COLUMN_DEFINITION *column_definition)
 Creates a column definition block for the SDDS layout.
 
char * SDDS_CreateArrayDefinition (ARRAY_DEFINITION *array_definition)
 Creates an array definition block for the SDDS layout.
 
char * SDDS_CreateAssociateDefinition (ASSOCIATE_DEFINITION *associate_definition)
 Creates an associate definition block for the SDDS layout.
 
char * SDDS_CreateDataMode (DATA_MODE *data_mode)
 Creates a data mode block for the SDDS layout.
 
int32_t SDDS_MPI_WriteAsciiString (SDDS_DATASET *SDDS_dataset, char *string)
 Writes an ASCII string to the SDDS dataset using MPI.
 
int32_t SDDS_MPI_WriteLayout (SDDS_DATASET *SDDS_dataset)
 Writes the layout of the SDDS dataset to the MPI file.
 
void SDDS_MPI_BOMB (char *text, MPI_File *mpi_file)
 Terminates the program after handling errors and cleaning up MPI resources.
 
int32_t SDDS_MPI_WritePage (SDDS_DATASET *SDDS_dataset)
 Writes a page of data to the MPI file associated with the SDDS dataset.
 
MPI_Datatype Convert_SDDStype_To_MPItype (int32_t SDDS_type)
 Converts an SDDS data type to the corresponding MPI data type.
 
int32_t SDDS_MPI_Terminate (SDDS_DATASET *SDDS_dataset)
 Terminates the SDDS dataset by freeing all allocated resources and closing MPI files.
 
int32_t SDDS_MPI_InitializeOutput (SDDS_DATASET *SDDS_dataset, char *description, char *contents, char *filename, unsigned long flags, short column_major)
 Initializes the SDDS dataset for MPI output.
 
int32_t SDDS_MPI_InitializeCopy (SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, char *filename, short column_major)
 Initializes a copy of an SDDS dataset for MPI output.
 
void SDDS_MPI_Setup (SDDS_DATASET *SDDS_dataset, int32_t parallel_io, int32_t n_processors, int32_t myid, MPI_Comm comm, short master_read)
 Sets up the SDDS dataset for MPI operations.
 
int32_t SDDS_MPI_DisconnectFile (SDDS_DATASET *SDDS_dataset)
 Disconnects the MPI file associated with the SDDS dataset.
 
int32_t SDDS_MPI_ReconnectFile (SDDS_DATASET *SDDS_dataset)
 Reconnects the MPI file associated with the SDDS dataset.
 

Variables

int32_t SDDS_mpi_error_str_len
 
char SDDS_mpi_error_str [MPI_MAX_ERROR_STRING]
 
char * SDDS_MPI_FILE_TYPE [2] = {"external32", "native"}
 
static int32_t terminateMode = 0
 

Detailed Description

MPI-based Parallel I/O Functions for SDDS Datasets.

This file implements a suite of functions to facilitate parallel input/output operations for SDDS (Self Describing Data Set) datasets using MPI (Message Passing Interface). It includes functionalities for initializing MPI output, writing dataset layouts and data pages, handling errors, terminating datasets, and managing MPI file connections.

License
This file is distributed under the terms of the Software License Agreement found in the file LICENSE included with this distribution.
Authors
H. Shang M. Borland R. Soliday

Definition in file SDDSmpi_output.c.

Function Documentation

◆ BlankToNull()

char * BlankToNull ( char * string)

Converts a blank string to NULL.

This function checks if the input string is NULL or consists only of whitespace characters. If so, it returns NULL; otherwise, it returns the original string.

Parameters
stringThe input string to check.
Returns
NULL if the string is NULL or blank, otherwise returns the original string.

Definition at line 77 of file SDDSmpi_output.c.

77 {
78 if (!string || SDDS_StringIsBlank(string))
79 return NULL;
80 return string;
81}
int32_t SDDS_StringIsBlank(char *s)
Checks if a string is blank (contains only whitespace characters).

◆ Convert_SDDStype_To_MPItype()

MPI_Datatype Convert_SDDStype_To_MPItype ( int32_t SDDS_type)

Converts an SDDS data type to the corresponding MPI data type.

This function maps custom SDDS data types to their equivalent MPI data types using a switch statement. If an unknown SDDS data type is provided, the function calls SDDS_Bomb to handle the error.

Parameters
SDDS_typeThe SDDS data type to convert.
Returns
The corresponding MPI_Datatype.

Definition at line 731 of file SDDSmpi_output.c.

731 {
732 switch (SDDS_type) {
733 case SDDS_SHORT:
734 return MPI_SHORT;
735 case SDDS_USHORT:
736 return MPI_UNSIGNED_SHORT;
737 case SDDS_LONG:
738 /* SDDS_LONG type is actually int32_t */
739 return MPI_INT;
740 case SDDS_ULONG:
741 return MPI_UNSIGNED;
742 case SDDS_LONG64:
743 return MPI_INT64_T;
744 case SDDS_ULONG64:
745 return MPI_UINT64_T;
746 case SDDS_FLOAT:
747 return MPI_FLOAT;
748 case SDDS_DOUBLE:
749 return MPI_DOUBLE;
750 case SDDS_LONGDOUBLE:
751 return MPI_LONG_DOUBLE;
752 case SDDS_STRING:
753 case SDDS_CHARACTER:
754 return MPI_CHAR;
755 default:
756 SDDS_Bomb("Unknown SDDS datatype provided to ConvertSDDS_To_MPI.");
757 return 0;
758 }
759}
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342
#define SDDS_ULONG
Identifier for the unsigned 32-bit integer data type.
Definition SDDStypes.h:67
#define SDDS_FLOAT
Identifier for the float data type.
Definition SDDStypes.h:43
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_ULONG64
Identifier for the unsigned 64-bit integer data type.
Definition SDDStypes.h:55
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
Definition SDDStypes.h:61
#define SDDS_SHORT
Identifier for the signed short integer data type.
Definition SDDStypes.h:73
#define SDDS_CHARACTER
Identifier for the character data type.
Definition SDDStypes.h:91
#define SDDS_USHORT
Identifier for the unsigned short integer data type.
Definition SDDStypes.h:79
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
#define SDDS_LONGDOUBLE
Identifier for the long double data type.
Definition SDDStypes.h:31
#define SDDS_LONG64
Identifier for the signed 64-bit integer data type.
Definition SDDStypes.h:49

◆ SDDS_CreateArrayDefinition()

char * SDDS_CreateArrayDefinition ( ARRAY_DEFINITION * array_definition)

Creates an array definition block for the SDDS layout.

This function allocates and constructs an array definition block based on the provided ARRAY_DEFINITION structure. It includes fields such as name, symbol, units, description, format_string, group_name, type, dimensions, and ends the block.

Parameters
array_definitionPointer to the ARRAY_DEFINITION structure.
Returns
A newly allocated string containing the array definition block.

Definition at line 289 of file SDDSmpi_output.c.

289 {
290 char *array = NULL, *tmpstr;
291 char buf[40];
292 array = (char *)malloc(sizeof(char) * 2048);
293 array[0] = 0;
294 sprintf(array, "&array ");
295 strcat(array, SDDS_CreateNamelistField("name", array_definition->name));
296 if ((tmpstr = BlankToNull(array_definition->symbol)))
297 strcat(array, SDDS_CreateNamelistField("symbol", tmpstr));
298 if ((tmpstr = BlankToNull(array_definition->units)))
299 strcat(array, SDDS_CreateNamelistField("units", tmpstr));
300 if ((tmpstr = BlankToNull(array_definition->description)))
301 strcat(array, SDDS_CreateNamelistField("description", tmpstr));
302 if ((tmpstr = BlankToNull(array_definition->format_string)))
303 strcat(array, SDDS_CreateNamelistField("format_string", tmpstr));
304 if ((tmpstr = BlankToNull(array_definition->group_name)))
305 strcat(array, SDDS_CreateNamelistField("group_name", tmpstr));
306 strcat(array, SDDS_CreateNamelistField("type", SDDS_type_name[array_definition->type - 1]));
307 if (array_definition->dimensions != 1) /* 1 is default */
308 {
309 //sprintf(array, "%sdimensions=%" PRId32 ", ", array, array_definition->dimensions);
310 sprintf(buf, "dimensions=%" PRId32 ", ", array_definition->dimensions);
311 strcat(array, buf);
312 }
313 strcat(array, " &end\n");
314 return array;
315}
char * SDDS_type_name[SDDS_NUM_TYPES]
Array of supported data type names.
Definition SDDS_data.c:43
char * BlankToNull(char *string)
Converts a blank string to NULL.
char * SDDS_CreateNamelistField(char *name, char *value)
Creates a namelist field string from a name and value.

◆ SDDS_CreateAssociateDefinition()

char * SDDS_CreateAssociateDefinition ( ASSOCIATE_DEFINITION * associate_definition)

Creates an associate definition block for the SDDS layout.

This function allocates and constructs an associate definition block based on the provided ASSOCIATE_DEFINITION structure. It includes fields such as name, filename, contents, path, description, and the associated SDDS index.

Parameters
associate_definitionPointer to the ASSOCIATE_DEFINITION structure.
Returns
A newly allocated string containing the associate definition block.

Definition at line 325 of file SDDSmpi_output.c.

325 {
326 char *associate = NULL, *tmpstr;
327 char buf[40];
328 associate = (char *)malloc(sizeof(char) * 2048);
329 associate[0] = 0;
330 sprintf(associate, "&associate ");
331 strcat(associate, SDDS_CreateNamelistField("name", associate_definition->name));
332 if ((tmpstr = BlankToNull(associate_definition->filename)))
333 strcat(associate, SDDS_CreateNamelistField("filename", tmpstr));
334 if ((tmpstr = BlankToNull(associate_definition->contents)))
335 strcat(associate, SDDS_CreateNamelistField("contents", tmpstr));
336 if ((tmpstr = BlankToNull(associate_definition->path)))
337 strcat(associate, SDDS_CreateNamelistField("path", tmpstr));
338 if ((tmpstr = BlankToNull(associate_definition->description)))
339 strcat(associate, SDDS_CreateNamelistField("description", tmpstr));
340 //sprintf(associate, "%ssdds=%" PRId32, associate, associate_definition->sdds);
341 sprintf(buf, "sdds=%" PRId32 " &end\n", associate_definition->sdds);
342 strcat(associate, buf);
343 //strcat(associate, " &end\n");
344 return associate;
345 ;
346}

◆ SDDS_CreateColumnDefinition()

char * SDDS_CreateColumnDefinition ( COLUMN_DEFINITION * column_definition)

Creates a column definition block for the SDDS layout.

This function allocates and constructs a column definition block based on the provided COLUMN_DEFINITION structure. It includes fields such as name, symbol, units, description, format_string, type, and ends the block.

Parameters
column_definitionPointer to the COLUMN_DEFINITION structure.
Returns
A newly allocated string containing the column definition block.

Definition at line 262 of file SDDSmpi_output.c.

262 {
263 char *col = NULL, *tmpStr;
264 col = (char *)malloc(sizeof(char) * 2048);
265 col[0] = 0;
266 sprintf(col, "&column ");
267 strcat(col, SDDS_CreateNamelistField("name", column_definition->name));
268 if ((tmpStr = BlankToNull(column_definition->symbol)))
269 strcat(col, SDDS_CreateNamelistField("symbol", tmpStr));
270 if ((tmpStr = BlankToNull(column_definition->units)))
271 strcat(col, SDDS_CreateNamelistField("units", tmpStr));
272 if ((tmpStr = BlankToNull(column_definition->description)))
273 strcat(col, SDDS_CreateNamelistField("description", tmpStr));
274 if ((tmpStr = BlankToNull(column_definition->format_string)))
275 strcat(col, SDDS_CreateNamelistField("format_string", tmpStr));
276 strcat(col, SDDS_CreateNamelistField("type", SDDS_type_name[column_definition->type - 1]));
277 strcat(col, " &end\n");
278 return col;
279}

◆ SDDS_CreateDataMode()

char * SDDS_CreateDataMode ( DATA_MODE * data_mode)

Creates a data mode block for the SDDS layout.

This function allocates and constructs a data mode block based on the provided DATA_MODE structure. It includes fields such as mode, lines_per_row, no_row_counts, column_major_order, and ends the block.

Parameters
data_modePointer to the DATA_MODE structure.
Returns
A newly allocated string containing the data mode block, or NULL if the mode is invalid.

Definition at line 356 of file SDDSmpi_output.c.

356 {
357 char *mode = NULL;
358 char buf[40];
359 if (data_mode->mode > SDDS_NUM_DATA_MODES)
360 return NULL;
361 mode = (char *)malloc(sizeof(char) * 2048);
362 mode[0] = 0;
363 sprintf(mode, "&data ");
364 strcat(mode, SDDS_CreateNamelistField("mode", SDDS_data_mode[data_mode->mode - 1]));
365 if (data_mode->lines_per_row > 1) {
366 //sprintf(mode, "%slines_per_row=%" PRId32 ", ", mode, data_mode->lines_per_row);
367 sprintf(buf, "lines_per_row=%" PRId32 ", ", data_mode->lines_per_row);
368 strcat(mode, buf);
369 }
370 if (data_mode->no_row_counts) {
371 //sprintf(mode, "%sno_row_counts=1, ", mode);
372 strcat(mode, "no_row_counts=1, ");
373 }
374 if (data_mode->column_major) {
375 strcat(mode, "column_major_order=1, ");
376 }
377 strcat(mode, "&end\n");
378 return mode;
379}
char * SDDS_data_mode[SDDS_NUM_DATA_MODES]
Array of supported data modes.
Definition SDDS_data.c:33

◆ SDDS_CreateDescription()

char * SDDS_CreateDescription ( char * text,
char * contents )

Creates a description block for the SDDS layout.

This function allocates and constructs a description block containing the provided text and contents. It formats the description in the SDDS namelist format.

Parameters
textThe descriptive text.
contentsThe contents of the description.
Returns
A newly allocated string containing the description block, or NULL if both text and contents are NULL.

Definition at line 207 of file SDDSmpi_output.c.

207 {
208 char *desc = NULL;
209 if (!text && !contents)
210 return NULL;
211 desc = (char *)malloc(sizeof(char) * 2048);
212 desc[0] = 0;
213 sprintf(desc, "&description ");
214 if (text)
215 strcat(desc, SDDS_CreateNamelistField("text", text));
216 if (contents)
217 strcat(desc, SDDS_CreateNamelistField("contents", contents));
218 //sprintf(desc, "%s&end\n", desc);
219 desc = strcat(desc, "&end\n");
220 return desc;
221}

◆ SDDS_CreateNamelistField()

char * SDDS_CreateNamelistField ( char * name,
char * value )

Creates a namelist field string from a name and value.

This function allocates and constructs a string representing a namelist field in the format name=value or name="value" depending on the content of the value. It handles escaping of double quotes within the value and ensures proper formatting based on the presence of special characters.

Parameters
nameThe name of the field.
valueThe value of the field.
Returns
A newly allocated string containing the namelist field, or NULL if the name is NULL or empty.

sprintf(contents, "%s%s=%s, ", contents, name, value);

Definition at line 156 of file SDDSmpi_output.c.

156 {
157 char *contents;
158 char *buffer = NULL, *bPtr, *vPtr, buf2[2048];
159
160 contents = NULL;
161 if (!name)
162 return NULL;
163 if (!value || !strlen(name))
164 return NULL;
165 contents = (char *)malloc(sizeof(char) * 2048);
166 contents[0] = 0;
167 if (!strlen(value))
168 sprintf(contents, "%s=\"\", ", name);
169 else {
170 if (strchr(value, '"')) {
171 if (!(buffer = SDDS_Malloc(sizeof(*buffer) * 2 * strlen(value))))
172 return 0;
173 vPtr = value;
174 bPtr = buffer;
175 while (*vPtr) {
176 if (*vPtr == '"')
177 *bPtr++ = '\\';
178 *bPtr++ = *vPtr++;
179 }
180 *bPtr = 0;
181 value = buffer;
182 }
183 if (strpbrk(value, " ,*$\t\n\b")) {
184 //sprintf(contents, "%s%s=\"%s\", ", contents, name, value);
185 sprintf(buf2, "%s=\"%s\", ", name, value);
186 contents = strcat(contents, buf2);
187 } else {
188 ///sprintf(contents, "%s%s=%s, ", contents, name, value);
189 sprintf(buf2, "%s=%s, ", name, value);
190 contents = strcat(contents, buf2);
191 }
192 if (buffer)
193 free(buffer);
194 }
195 return contents;
196}
void * SDDS_Malloc(size_t size)
Allocates memory of a specified size.
Definition SDDS_utils.c:639

◆ SDDS_CreateParameterDefinition()

char * SDDS_CreateParameterDefinition ( PARAMETER_DEFINITION * parameter_definition)

Creates a parameter definition block for the SDDS layout.

This function allocates and constructs a parameter definition block based on the provided PARAMETER_DEFINITION structure. It includes fields such as name, symbol, units, description, format_string, type, and fixed_value.

Parameters
parameter_definitionPointer to the PARAMETER_DEFINITION structure.
Returns
A newly allocated string containing the parameter definition block.

Definition at line 231 of file SDDSmpi_output.c.

231 {
232 char *par, *tmpstr;
233 par = (char *)malloc(sizeof(char) * 2048);
234 par[0] = 0;
235 sprintf(par, "&parameter ");
236 strcat(par, SDDS_CreateNamelistField("name", parameter_definition->name));
237 if ((tmpstr = BlankToNull(parameter_definition->symbol)))
238 strcat(par, SDDS_CreateNamelistField("symbol", tmpstr));
239 if ((tmpstr = BlankToNull(parameter_definition->units)))
240 strcat(par, SDDS_CreateNamelistField("units", tmpstr));
241 if ((tmpstr = BlankToNull(parameter_definition->description)))
242 strcat(par, SDDS_CreateNamelistField("description", tmpstr));
243 if ((tmpstr = BlankToNull(parameter_definition->format_string)))
244 strcat(par, SDDS_CreateNamelistField("format_string", tmpstr));
245 strcat(par, SDDS_CreateNamelistField("type", SDDS_type_name[parameter_definition->type - 1]));
246 /*if ((tmpstr=BlankToNull(parameter_definition->fixed_value)))
247 strcat(par, SDDS_CreateNamelistField("fixed_value", tmpstr)); */
248 if (parameter_definition->fixed_value)
249 strcat(par, SDDS_CreateNamelistField("fixed_value", parameter_definition->fixed_value));
250 strcat(par, "&end\n");
251 return par;
252}

◆ SDDS_MPI_BOMB()

void SDDS_MPI_BOMB ( char * text,
MPI_File * mpi_file )

Terminates the program after handling errors and cleaning up MPI resources.

This function prints all accumulated SDDS errors to stderr using SDDS_PrintErrors. If a custom error message (text) is provided, it is printed to stderr. If an MPI file pointer (mpi_file) is provided, the MPI file is closed. Finally, the MPI environment is finalized, and the program exits with a status of 1.

Parameters
textA custom error message to display. Can be NULL.
mpi_filePointer to an MPI_File to be closed. Can be NULL.

Definition at line 681 of file SDDSmpi_output.c.

681 {
682 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
683 if (text)
684 fprintf(stderr, "Error: %s\n", text);
685 if (mpi_file)
686 MPI_File_close(mpi_file);
687 MPI_Finalize();
688 exit(1);
689}
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:432

◆ SDDS_MPI_DisconnectFile()

int32_t SDDS_MPI_DisconnectFile ( SDDS_DATASET * SDDS_dataset)

Disconnects the MPI file associated with the SDDS dataset.

This function checks the validity of the dataset and ensures that the file is connected and has a valid filename. It then closes the MPI file and marks the dataset as disconnected.

Parameters
SDDS_datasetPointer to the SDDS_DATASET structure whose file is to be disconnected.
Returns
1 if the file was successfully disconnected, 0 otherwise.

Definition at line 1089 of file SDDSmpi_output.c.

1089 {
1090 MPI_DATASET *MPI_dataset;
1091
1092#if MPI_DEBUG
1093 logDebug("SDDS_MPI_DisconnectFile", SDDS_dataset);
1094#endif
1095
1096 MPI_dataset = SDDS_dataset->MPI_dataset;
1097 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_MPI_DisconnectFile"))
1098 return 0;
1099 if (!SDDS_dataset->layout.filename) {
1100 SDDS_SetError("Can't disconnect file. No filename or gzip file. (SDDS_MPI_DisconnectFile)");
1101 return 0;
1102 }
1103 if (SDDS_dataset->layout.disconnected) {
1104 SDDS_SetError("Can't disconnect file. Already disconnected. (SDDS_MPI_DisconnectFile)");
1105 return 0;
1106 }
1107 /* if (SDDS_dataset->page_started && !SDDS_WritePage(SDDS_dataset)) {
1108 SDDS_SetError("Can't disconnect file. Problem updating page. (SDDS_MPI_DisconnectFile)");
1109 return 0;
1110 } */
1111 SDDS_dataset->layout.disconnected = 1;
1112 MPI_File_close(&(MPI_dataset->MPI_file));
1113 return 1;
1114}
void SDDS_SetError(char *error_text)
Records an error message in the SDDS error stack.
Definition SDDS_utils.c:379
int32_t SDDS_CheckDataset(SDDS_DATASET *SDDS_dataset, const char *caller)
Validates the SDDS dataset pointer.
Definition SDDS_utils.c:552

◆ SDDS_MPI_File_Open()

int32_t SDDS_MPI_File_Open ( MPI_DATASET * MPI_dataset,
char * filename,
unsigned long flags )

Opens an MPI file with the specified flags.

This function opens an MPI file using the given filename and flags, setting the appropriate MPI file mode based on the flags. It also initializes the MPI dataset's debug file pointer and other related fields. If the file is successfully opened, it returns 1; otherwise, it handles the error and may exit the program.

Parameters
MPI_datasetPointer to the MPI_DATASET structure to initialize.
filenameThe name of the file to open.
flagsFlags indicating the mode in which to open the file (e.g., read-only, write-only, read-write).
Returns
1 if the file was successfully opened, 0 otherwise.

Definition at line 113 of file SDDSmpi_output.c.

113 {
114 unsigned long file_opened = 0; /* Flag to indicate that the file was successfully opened */
115 int mpi_amode = MPI_MODE_RDWR;
116 int mpi_code; /* mpi return code */
117
118 /* Get the MPI rank of this process and the total number of processes */
119 /*if (MPI_SUCCESS != (mpi_code=MPI_Comm_rank(MPI_dataset->comm, &MPI_dataset->myid)))
120 SDDS_MPI_GOTO_ERROR(stderr, "MPI_Comm_rank failed", mpi_code, 1);
121 if (MPI_SUCCESS != (mpi_code=MPI_Comm_size(MPI_dataset->comm, &MPI_dataset->n_processors)))
122 SDDS_MPI_GOTO_ERROR(stderr, "MPI_Comm_size failed", mpi_code, 1); */
123
124 MPI_dataset->fpdeb = NULL;
125
126 if (flags & SDDS_MPI_WRITE_ONLY)
127 mpi_amode = MPI_MODE_CREATE | MPI_MODE_WRONLY;
128 if (flags & SDDS_MPI_READ_ONLY)
129 mpi_amode = MPI_MODE_RDONLY;
130 if (flags & SDDS_MPI_READ_WRITE)
131 mpi_amode = MPI_MODE_CREATE | MPI_MODE_RDWR;
132 if (MPI_SUCCESS != (mpi_code = MPI_File_open(MPI_dataset->comm, filename, mpi_amode, MPI_INFO_NULL, &(MPI_dataset->MPI_file))))
133 SDDS_MPI_GOTO_ERROR(stderr, "MPI_File_open failed", mpi_code, 1);
134 else
135 file_opened = 1;
136 MPI_dataset->n_page = 0;
137 if (mpi_amode & MPI_MODE_WRONLY)
138 MPI_File_set_size(MPI_dataset->MPI_file, 0);
139 if (mpi_amode != MPI_MODE_RDONLY) {
140 if (MPI_SUCCESS != (mpi_code = MPI_File_sync(MPI_dataset->MPI_file)))
141 SDDS_MPI_GOTO_ERROR(stderr, "MPI_File_sync failed", mpi_code, 1);
142 }
143 /*MPI_dataset->file_offset = 0; */
144 return file_opened;
145}
void SDDS_MPI_GOTO_ERROR(FILE *fp, char *str, int32_t mpierr, int32_t exit_code)
Handles MPI errors by printing an error message and optionally exiting.

◆ SDDS_MPI_GOTO_ERROR()

void SDDS_MPI_GOTO_ERROR ( FILE * fp,
char * str,
int32_t mpierr,
int32_t exit_code )

Handles MPI errors by printing an error message and optionally exiting.

Retrieves the MPI error string corresponding to the given error code. If a string is provided, it prints the string followed by the MPI error message to the specified file pointer. If exit_code is non-zero, the program exits with a status of 1.

Parameters
fpFile pointer to write the error message to.
strCustom error message to prefix to the MPI error string. Can be NULL.
mpierrThe MPI error code.
exit_codeIf non-zero, the function will terminate the program.

Definition at line 93 of file SDDSmpi_output.c.

93 {
94 MPI_Error_string(mpierr, SDDS_mpi_error_str, &SDDS_mpi_error_str_len);
95 if (str)
96 fprintf(fp, "%s: ", str);
97 if (SDDS_mpi_error_str_len > 0)
98 fprintf(fp, "%s\n", SDDS_mpi_error_str);
99 if (exit_code)
100 exit(1);
101}

◆ SDDS_MPI_InitializeCopy()

int32_t SDDS_MPI_InitializeCopy ( SDDS_DATASET * SDDS_target,
SDDS_DATASET * SDDS_source,
char * filename,
short column_major )

Initializes a copy of an SDDS dataset for MPI output.

This function creates a new SDDS dataset (SDDS_target) by copying the layout from an existing dataset (SDDS_source). It sets up the target dataset for MPI output, opens the specified file, and writes the layout to the file. The function also sets the data mode to column-major if specified.

Parameters
SDDS_targetPointer to the target SDDS_DATASET structure to initialize.
SDDS_sourcePointer to the source SDDS_DATASET structure to copy from.
filenameThe name of the file to initialize for output.
column_majorIf non-zero, data will be written in column-major order.
Returns
1 if the copy and initialization were successful, 0 otherwise.

Definition at line 1009 of file SDDSmpi_output.c.

1009 {
1010 MPI_DATASET *MPI_target = SDDS_target->MPI_dataset;
1011
1012 if (!SDDS_CheckDataset(SDDS_source, "SDDS_InitializeCopy"))
1013 return (0);
1014 if (!SDDS_CheckDataset(SDDS_target, "SDDS_InitializeCopy"))
1015 return (0);
1016 /* if (!SDDS_ZeroMemory((void *)SDDS_target, sizeof(SDDS_DATASET))) {
1017 SDDS_SetError("Unable to copy layout--can't zero SDDS_DATASET structure (SDDS_InitializeCopy)");
1018 return(0);
1019 } */
1020 /*has been zeroed in the setup */
1021 SDDS_target->pagecount_offset = NULL;
1022 SDDS_target->mode = SDDS_WRITEMODE;
1023 SDDS_target->layout.popenUsed = 0;
1024 SDDS_target->layout.gzipFile = 0;
1025 SDDS_target->layout.lzmaFile = 0;
1026 if (filename) {
1027 if (!SDDS_CopyString(&SDDS_target->layout.filename, filename)) {
1028 SDDS_SetError("Memory allocation failure (SDDS_InitializeCopy)");
1029 return (0);
1030 }
1031 }
1032 SDDS_target->page_number = SDDS_target->page_started = 0;
1033 if (!SDDS_CopyLayout(SDDS_target, SDDS_source))
1034 return (0);
1035 /* SDDS_target->MPI_dataset = MPI_target; */
1036 SDDS_target->layout.data_mode.column_major = column_major;
1037 if (!SDDS_MPI_File_Open(MPI_target, filename, SDDS_MPI_WRITE_ONLY))
1038 return 0;
1039 SDDS_target->parallel_io = 1;
1040 MPI_target->file_offset = 0;
1041 if (!SDDS_MPI_WriteLayout(SDDS_target))
1042 return 0;
1043 return 1;
1044}
int32_t SDDS_CopyLayout(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
Definition SDDS_copy.c:222
int32_t SDDS_CopyString(char **target, const char *source)
Copies a source string to a target string with memory allocation.
Definition SDDS_utils.c:856
int32_t SDDS_MPI_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the layout of the SDDS dataset to the MPI file.
int32_t SDDS_MPI_File_Open(MPI_DATASET *MPI_dataset, char *filename, unsigned long flags)
Opens an MPI file with the specified flags.

◆ SDDS_MPI_InitializeOutput()

int32_t SDDS_MPI_InitializeOutput ( SDDS_DATASET * SDDS_dataset,
char * description,
char * contents,
char * filename,
unsigned long flags,
short column_major )

Initializes the SDDS dataset for MPI output.

This function sets up the SDDS dataset for parallel output using MPI. It initializes the dataset with the provided description, contents, and filename, sets the column major order if specified, and opens the MPI file for writing. It also logs the initialization if MPI debugging is enabled.

Parameters
SDDS_datasetPointer to the SDDS_DATASET structure to initialize.
descriptionA description of the dataset.
contentsAdditional contents for the dataset description.
filenameThe name of the file to initialize for output.
flagsFlags indicating the mode in which to open the file (e.g., read-only, write-only, read-write).
column_majorIf non-zero, data will be written in column-major order.
Returns
1 if initialization was successful, 0 otherwise.

Definition at line 975 of file SDDSmpi_output.c.

975 {
976 MPI_DATASET *MPI_dataset = SDDS_dataset->MPI_dataset;
977
978 if (!SDDS_Parallel_InitializeOutput(SDDS_dataset, description, contents, filename))
979 return 0;
980 if (flags & SDDS_MPI_READ_ONLY) {
981 SDDS_SetError("Wrong flags pass (SDDS_MPI_READ_ONLY) passed to SDDS_MPI_InitializeOutput)!");
982 return 0;
983 }
984 /* SDDS_dataset->MPI_dataset = MPI_dataset; */
985 SDDS_dataset->layout.data_mode.column_major = column_major;
986 if (!SDDS_MPI_File_Open(MPI_dataset, filename, flags)) {
987 SDDS_SetError("Failed in opening file for MPI output!");
988 return 0;
989 }
990#if MPI_DEBUG
991 logDebug("SDDS_MPI_InitializeOutput", SDDS_dataset);
992#endif
993 return 1;
994}
int32_t SDDS_Parallel_InitializeOutput(SDDS_DATASET *SDDS_dataset, const char *description, const char *contents, const char *filename)
Initializes the SDDS output dataset for parallel processing.

◆ SDDS_MPI_ReconnectFile()

int32_t SDDS_MPI_ReconnectFile ( SDDS_DATASET * SDDS_dataset)

Reconnects the MPI file associated with the SDDS dataset.

This function checks the validity of the dataset and ensures that the file is currently disconnected and has a valid filename. It then reopens the MPI file in read-write mode, updates the file view, and marks the dataset as connected.

Parameters
SDDS_datasetPointer to the SDDS_DATASET structure whose file is to be reconnected.
Returns
1 if the file was successfully reconnected, 0 otherwise.

Definition at line 1126 of file SDDSmpi_output.c.

1126 {
1127 MPI_DATASET *MPI_dataset;
1128
1129#if MPI_DEBUG
1130 logDebug("SDDS_MPI_ReconnectFile", SDDS_dataset);
1131#endif
1132 MPI_dataset = SDDS_dataset->MPI_dataset;
1133 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_MPI_ReconnectFile"))
1134 return 0;
1135 if (!SDDS_dataset->layout.disconnected || !SDDS_dataset->layout.filename) {
1136 SDDS_SetError("Can't reconnect file. Not disconnected or missing filename. (SDDS_MPI_ReconnectFile)");
1137 return 0;
1138 }
1139 if (MPI_File_open(MPI_dataset->comm, SDDS_dataset->layout.filename, MPI_MODE_RDWR, MPI_INFO_NULL, &(MPI_dataset->MPI_file)) != MPI_SUCCESS) {
1140 SDDS_SetError("Can't reconnect file, MPI_File_open failed. (SDDS_MPI_ReconnectFile)");
1141 return 0;
1142 }
1143 MPI_File_get_size(MPI_dataset->MPI_file, &(MPI_dataset->file_offset));
1144 MPI_File_set_view(MPI_dataset->MPI_file, MPI_dataset->file_offset, MPI_BYTE, MPI_BYTE, "native", MPI_INFO_NULL);
1145 /* MPI_dataset->file_offset=0; */
1146 SDDS_dataset->layout.disconnected = 0;
1147 return 1;
1148}

◆ SDDS_MPI_Setup()

void SDDS_MPI_Setup ( SDDS_DATASET * SDDS_dataset,
int32_t parallel_io,
int32_t n_processors,
int32_t myid,
MPI_Comm comm,
short master_read )

Sets up the SDDS dataset for MPI operations.

This function initializes the SDDS_DATASET structure for MPI-based parallel I/O. It zeroes out the dataset, allocates and initializes the MPI_DATASET structure if parallel I/O is enabled, and sets MPI-related fields such as the number of processors, process ID, and MPI communicator.

Parameters
SDDS_datasetPointer to the SDDS_DATASET structure to set up.
parallel_ioIf non-zero, the dataset will be set up for parallel I/O using MPI.
n_processorsThe total number of MPI processes.
myidThe MPI process ID of the current process.
commThe MPI communicator to use for I/O operations.
master_readIf non-zero, the master process will handle read operations.

Definition at line 1060 of file SDDSmpi_output.c.

1060 {
1061 MPI_DATASET *MPI_dataset;
1062
1063 if (!SDDS_ZeroMemory((void *)SDDS_dataset, sizeof(SDDS_DATASET)))
1064 SDDS_Bomb("Unable to zero memory for SDDS dataset(SDDS_MPI_Setup)");
1065 if (parallel_io) {
1066 MPI_dataset = malloc(sizeof(*MPI_dataset));
1067 if (!SDDS_ZeroMemory((void *)MPI_dataset, sizeof(MPI_DATASET)))
1068 SDDS_Bomb("Unable to zero memory for MPI_DATASEAT (SDDS_MPI_Setup)");
1069 MPI_dataset->n_processors = n_processors;
1070 MPI_dataset->myid = myid;
1071 MPI_dataset->comm = comm;
1072 MPI_dataset->collective_io = 0;
1073 MPI_dataset->master_read = master_read;
1074 MPI_dataset->fpdeb = NULL;
1075 SDDS_dataset->MPI_dataset = MPI_dataset;
1076 SDDS_dataset->parallel_io = 1;
1077 }
1078}
int32_t SDDS_ZeroMemory(void *mem, int64_t n_bytes)
Sets a block of memory to zero.

◆ SDDS_MPI_Terminate()

int32_t SDDS_MPI_Terminate ( SDDS_DATASET * SDDS_dataset)

Terminates the SDDS dataset by freeing all allocated resources and closing MPI files.

This function performs comprehensive cleanup of the SDDS_DATASET structure, freeing all dynamically allocated memory associated with parameters, arrays, columns, and associates. It also closes the MPI file, finalizes MPI, and resets the dataset's layout and data structures.

Parameters
SDDS_datasetPointer to the SDDS_DATASET structure to terminate.
Returns
1 if termination was successful, 0 otherwise.

Definition at line 771 of file SDDSmpi_output.c.

771 {
772 MPI_DATASET *MPI_dataset;
773 SDDS_LAYOUT *layout;
774 char **ptr;
775 int32_t i, j;
776
777#if MPI_DEBUG
778 logDebug("SDDS_MPI_Terminate", SDDS_dataset);
779#endif
780
781 MPI_dataset = SDDS_dataset->MPI_dataset;
782 layout = &(SDDS_dataset->original_layout);
783 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_Terminate"))
784 return (0);
785 if (SDDS_dataset->pagecount_offset)
786 free(SDDS_dataset->pagecount_offset);
787 if (SDDS_dataset->row_flag)
788 free(SDDS_dataset->row_flag);
789 if (SDDS_dataset->column_order)
790 free(SDDS_dataset->column_order);
791 if (SDDS_dataset->column_flag)
792 free(SDDS_dataset->column_flag);
793 if (SDDS_dataset->fBuffer.buffer)
794 free(SDDS_dataset->fBuffer.buffer);
795 if (SDDS_dataset->titleBuffer.buffer)
796 free(SDDS_dataset->titleBuffer.buffer);
797 if (SDDS_dataset->parameter) {
798 for (i = 0; i < layout->n_parameters; i++) {
799 if (layout->parameter_definition[i].type == SDDS_STRING && *(char **)(SDDS_dataset->parameter[i]))
800 free(*(char **)(SDDS_dataset->parameter[i]));
801 if (SDDS_dataset->parameter[i])
802 free(SDDS_dataset->parameter[i]);
803 }
804 free(SDDS_dataset->parameter);
805 }
806 if (SDDS_dataset->array) {
807 for (i = 0; i < layout->n_arrays; i++) {
808 if (layout->array_definition[i].type == SDDS_STRING && !(terminateMode & TERMINATE_DONT_FREE_ARRAY_STRINGS)) {
809 for (j = 0; j < SDDS_dataset->array[i].elements; j++)
810 if (((char **)SDDS_dataset->array[i].data)[j])
811 free(((char **)SDDS_dataset->array[i].data)[j]);
812 }
813 /*
814 if (SDDS_dataset->array[i].definition->type==SDDS_STRING &&
815 !(terminateMode&TERMINATE_DONT_FREE_ARRAY_STRINGS)) {
816 for (j=0; j<SDDS_dataset->array[i].elements; j++)
817 if (((char**)SDDS_dataset->array[i].data)[j])
818 free(((char**)SDDS_dataset->array[i].data)[j]);
819 }
820 */
821 if (SDDS_dataset->array[i].data)
822 free(SDDS_dataset->array[i].data);
823 /* should free the subpointers too, but it would be a lot of trouble for little benefit: */
824 if (SDDS_dataset->array[i].pointer && SDDS_dataset->array[i].definition->dimensions != 1)
825 free(SDDS_dataset->array[i].pointer);
826 if (SDDS_dataset->array[i].dimension)
827 free(SDDS_dataset->array[i].dimension);
828 /* don't touch this--it's done below */
829 if (SDDS_dataset->array[i].definition && SDDS_dataset->array[i].definition->name) {
830 if (SDDS_dataset->array[i].definition->name != layout->array_definition[i].name)
831 SDDS_FreeArrayDefinition(SDDS_dataset->array[i].definition);
832 }
833 SDDS_dataset->array[i].definition = NULL;
834 }
835 free(SDDS_dataset->array);
836 }
837 if (SDDS_dataset->data) {
838 for (i = 0; i < layout->n_columns; i++)
839 if (SDDS_dataset->data[i]) {
840 if (layout->column_definition[i].type == SDDS_STRING && !(terminateMode & TERMINATE_DONT_FREE_TABLE_STRINGS)) {
841 ptr = (char **)SDDS_dataset->data[i];
842 for (j = 0; j < SDDS_dataset->n_rows_allocated; j++, ptr++)
843 if (*ptr)
844 free(*ptr);
845 }
846 free(SDDS_dataset->data[i]);
847 }
848 free(SDDS_dataset->data);
849 }
850 if (layout->description)
851 free(layout->description);
852 if (layout->contents == (&SDDS_dataset->layout)->contents)
853 (&SDDS_dataset->layout)->contents = NULL;
854 if (layout->contents)
855 free(layout->contents);
856 if (layout->filename)
857 free(layout->filename);
858 if (layout->column_definition) {
859 for (i = 0; i < layout->n_columns; i++) {
860 if (layout->column_index[i])
861 free(layout->column_index[i]);
862 if (layout->column_definition[i].name)
863 free(layout->column_definition[i].name);
864 if (layout->column_definition[i].symbol)
865 free(layout->column_definition[i].symbol);
866 if (layout->column_definition[i].units)
867 free(layout->column_definition[i].units);
868 if (layout->column_definition[i].description)
869 free(layout->column_definition[i].description);
870 if (layout->column_definition[i].format_string)
871 free(layout->column_definition[i].format_string);
872 }
873 free(layout->column_definition);
874 free(layout->column_index);
875 }
876 if (layout->parameter_definition) {
877 for (i = 0; i < layout->n_parameters; i++) {
878 if (layout->parameter_index[i])
879 free(layout->parameter_index[i]);
880 if (layout->parameter_definition[i].name)
881 free(layout->parameter_definition[i].name);
882 if (layout->parameter_definition[i].symbol)
883 free(layout->parameter_definition[i].symbol);
884 if (layout->parameter_definition[i].units)
885 free(layout->parameter_definition[i].units);
886 if (layout->parameter_definition[i].description)
887 free(layout->parameter_definition[i].description);
888 if (layout->parameter_definition[i].format_string)
889 free(layout->parameter_definition[i].format_string);
890 if (layout->parameter_definition[i].fixed_value)
891 free(layout->parameter_definition[i].fixed_value);
892 }
893 free(layout->parameter_definition);
894 free(layout->parameter_index);
895 }
896 if (layout->array_definition) {
897 for (i = 0; i < layout->n_arrays; i++) {
898 if (layout->array_index[i])
899 free(layout->array_index[i]);
900 if (layout->array_definition[i].name)
901 free(layout->array_definition[i].name);
902 if (layout->array_definition[i].symbol)
903 free(layout->array_definition[i].symbol);
904 if (layout->array_definition[i].units)
905 free(layout->array_definition[i].units);
906 if (layout->array_definition[i].description)
907 free(layout->array_definition[i].description);
908 if (layout->array_definition[i].format_string)
909 free(layout->array_definition[i].format_string);
910 if (layout->array_definition[i].group_name)
911 free(layout->array_definition[i].group_name);
912 }
913 free(layout->array_definition);
914 free(layout->array_index);
915 }
916 if (layout->associate_definition) {
917 for (i = 0; i < layout->n_associates; i++) {
918 if (layout->associate_definition[i].name)
919 free(layout->associate_definition[i].name);
920 if (layout->associate_definition[i].filename)
921 free(layout->associate_definition[i].filename);
922 if (layout->associate_definition[i].path)
923 free(layout->associate_definition[i].path);
924 if (layout->associate_definition[i].description)
925 free(layout->associate_definition[i].description);
926 if (layout->associate_definition[i].contents)
927 free(layout->associate_definition[i].contents);
928 }
929 free(layout->associate_definition);
930 }
931 SDDS_ZeroMemory(&SDDS_dataset->original_layout, sizeof(SDDS_LAYOUT));
932 layout = &SDDS_dataset->layout;
933 if (layout->contents)
934 free(layout->contents);
935 if (layout->column_definition)
936 free(layout->column_definition);
937 if (layout->array_definition)
938 free(layout->array_definition);
939 if (layout->associate_definition)
940 free(layout->associate_definition);
941 if (layout->parameter_definition)
942 free(layout->parameter_definition);
943 if (layout->column_index)
944 free(layout->column_index);
945 if (layout->parameter_index)
946 free(layout->parameter_index);
947 if (layout->array_index)
948 free(layout->array_index);
949 SDDS_ZeroMemory(&SDDS_dataset->layout, sizeof(SDDS_LAYOUT));
950 SDDS_ZeroMemory(SDDS_dataset, sizeof(SDDS_DATASET));
951#if DEBUG
952 fprintf(stderr, "done\n");
953#endif
954 MPI_File_close(&(MPI_dataset->MPI_file));
955 free(MPI_dataset);
956 MPI_dataset = NULL;
957 return (1);
958}
int32_t SDDS_FreeArrayDefinition(ARRAY_DEFINITION *source)
Frees memory allocated for an array definition.

◆ SDDS_MPI_WriteAsciiString()

int32_t SDDS_MPI_WriteAsciiString ( SDDS_DATASET * SDDS_dataset,
char * string )

Writes an ASCII string to the SDDS dataset using MPI.

This function writes the provided string to the SDDS dataset's MPI file. It handles buffering to optimize writes and manages buffer overflows by writing buffer contents to the file when necessary. Returns 1 on success, 0 on failure.

Parameters
SDDS_datasetPointer to the SDDS_DATASET structure.
stringThe ASCII string to write.
Returns
1 if the string was successfully written, 0 otherwise.

Definition at line 390 of file SDDSmpi_output.c.

390 {
391 SDDS_FILEBUFFER *fBuffer;
392 MPI_DATASET *MPI_dataset = SDDS_dataset->MPI_dataset;
393 int32_t mpi_code;
394 size_t targetSize;
395
396 fBuffer = &(SDDS_dataset->fBuffer);
397 targetSize = strlen(string) * sizeof(char);
398
399 if (!fBuffer->bufferSize) {
400 if ((mpi_code = MPI_File_write(MPI_dataset->MPI_file, string, targetSize, MPI_CHAR, MPI_STATUS_IGNORE)) != MPI_SUCCESS) {
401 SDDS_MPI_GOTO_ERROR(stderr, "SDDS_MPI_WriteBufferedWrite(MPI_File_write_at failed)", mpi_code, 0);
402 return 0;
403 }
404 return 1;
405 }
406 if ((fBuffer->bytesLeft -= targetSize) >= 0) {
407 memcpy((char *)fBuffer->data, (char *)string, targetSize);
408 fBuffer->data += targetSize;
409 return 1;
410 } else {
411 int32_t lastLeft;
412 /* add back what was subtracted in test above.
413 * lastLeft is the number of bytes left in the buffer before doing anything
414 * and also the number of bytes from the users data that get copied into the buffer.
415 */
416 lastLeft = (fBuffer->bytesLeft += targetSize);
417 /* copy part of the data into the buffer and write the buffer out */
418 memcpy((char *)fBuffer->data, (char *)string, (size_t)fBuffer->bytesLeft);
419 if ((mpi_code = MPI_File_write(MPI_dataset->MPI_file, fBuffer->buffer, (int)(fBuffer->bufferSize), MPI_CHAR, MPI_STATUS_IGNORE)) != MPI_SUCCESS) {
420 SDDS_MPI_GOTO_ERROR(stderr, "SDDS_MPI_WriteBufferedWrite(MPI_File_write_at failed)", mpi_code, 0);
421 return 0;
422 }
423
424 /* reset the data pointer and the bytesLeft value.
425 * also, determine if the remaining data is too large for the buffer.
426 * if so, just write it out.
427 */
428 fBuffer->data = fBuffer->buffer;
429 if ((targetSize -= lastLeft) > (fBuffer->bytesLeft = fBuffer->bufferSize)) {
430 if ((mpi_code = MPI_File_write_at(MPI_dataset->MPI_file, (MPI_Offset)(MPI_dataset->file_offset), string + lastLeft, targetSize, MPI_BYTE, MPI_STATUS_IGNORE)) != MPI_SUCCESS) {
431 SDDS_MPI_GOTO_ERROR(stderr, "SDDS_MPI_WriteBufferedWrite(MPI_File_write_at failed)", mpi_code, 0);
432 return 0;
433 }
434 return 1;
435 }
436 /* copy remaining data into the buffer.
437 * could do this with a recursive call, but this is more efficient.
438 */
439 memcpy((char *)fBuffer->data, (char *)string + lastLeft, targetSize);
440 fBuffer->data += targetSize;
441 fBuffer->bytesLeft -= targetSize;
442 return 1;
443 }
444}

◆ SDDS_MPI_WriteLayout()

int32_t SDDS_MPI_WriteLayout ( SDDS_DATASET * SDDS_dataset)

Writes the layout of the SDDS dataset to the MPI file.

This function writes the SDDS dataset layout information to the associated MPI file. It sets the file view, checks and saves the dataset, determines the byte order, allocates and manages the write buffer, and writes various layout components including description, parameters, arrays, columns, associates, and data mode. It ensures proper synchronization and handles errors appropriately. Only the MPI process with rank 0 performs the actual write operations.

Parameters
SDDS_datasetPointer to the SDDS_DATASET structure.
Returns
1 if the layout was successfully written, 0 otherwise.

Definition at line 454 of file SDDSmpi_output.c.

454 {
455 MPI_DATASET *MPI_dataset;
456 SDDS_LAYOUT *layout;
457 char buf[2048], *field = NULL;
458 int32_t i, data_mode;
459 char *outputEndianess = NULL;
460 SDDS_FILEBUFFER *fBuffer = NULL;
461
462#if MPI_DEBUG
463 logDebug("SDDS_MPI_WriteLayout", SDDS_dataset);
464#endif
465
466 MPI_dataset = SDDS_dataset->MPI_dataset;
467 MPI_File_set_view(MPI_dataset->MPI_file, 0, MPI_CHAR, MPI_CHAR, "native", MPI_INFO_NULL);
468 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_WriteLayout"))
469 return 0;
470 if (!SDDS_SaveLayout(SDDS_dataset))
471 return 0;
472 layout = &SDDS_dataset->layout;
473 if (SDDS_dataset->layout.disconnected) {
474 SDDS_SetError("Can't write layout--file is disconnected (SDDS_MPI_WriteLayout)");
475 return 0;
476 }
477 MPI_dataset->file_offset = 0;
478 if (layout->layout_written) {
479 SDDS_SetError("Can't write layout--already written to file (SDDS_MPI_WriteLayout)");
480 return 0;
481 }
482
483 if ((outputEndianess = getenv("SDDS_OUTPUT_ENDIANESS"))) {
484 if (strncmp(outputEndianess, "big", 3) == 0)
485 layout->byteOrderDeclared = SDDS_BIGENDIAN;
486 else if (strncmp(outputEndianess, "little", 6) == 0)
487 layout->byteOrderDeclared = SDDS_LITTLEENDIAN;
488 }
489
490 if (!layout->byteOrderDeclared)
491 layout->byteOrderDeclared = SDDS_IsBigEndianMachine() ? SDDS_BIGENDIAN : SDDS_LITTLEENDIAN;
492
493 fBuffer = &(SDDS_dataset->fBuffer);
494 /* write out the layout data */
495 if (MPI_dataset->myid == 0) {
496 if (!fBuffer->buffer) {
497 fBuffer->bufferSize = SDDS_SetDefaultWriteBufferSize(-1);
498 if (!(fBuffer->buffer = fBuffer->data = SDDS_Malloc(sizeof(char) * (fBuffer->bufferSize + 1)))) {
499 SDDS_SetError("Unable to do buffered read--allocation failure (SDDS_MPI_WriteLayout)");
500 return 0;
501 }
502 fBuffer->bytesLeft = fBuffer->bufferSize;
503 fBuffer->data[0] = 0;
504 }
505 }
506 layout->version = 1;
507 for (i = 0; i < layout->n_parameters; i++) {
508 if ((layout->parameter_definition[i].type == SDDS_ULONG) || (layout->parameter_definition[i].type == SDDS_USHORT)) {
509 layout->version = 2;
510 break;
511 }
512 }
513 for (i = 0; i < layout->n_arrays; i++) {
514 if ((layout->array_definition[i].type == SDDS_ULONG) || (layout->array_definition[i].type == SDDS_USHORT)) {
515 layout->version = 2;
516 break;
517 }
518 }
519 for (i = 0; i < layout->n_columns; i++) {
520 if ((layout->column_definition[i].type == SDDS_ULONG) || (layout->column_definition[i].type == SDDS_USHORT)) {
521 layout->version = 2;
522 break;
523 }
524 }
525 if ((layout->data_mode.column_major) && (layout->data_mode.mode == SDDS_BINARY)) {
526 layout->version = 3;
527 }
528 for (i = 0; i < layout->n_parameters; i++) {
529 if (layout->parameter_definition[i].type == SDDS_LONGDOUBLE) {
530 layout->version = 4;
531 break;
532 }
533 }
534 for (i = 0; i < layout->n_arrays; i++) {
535 if (layout->array_definition[i].type == SDDS_LONGDOUBLE) {
536 layout->version = 4;
537 break;
538 }
539 }
540 for (i = 0; i < layout->n_columns; i++) {
541 if (layout->column_definition[i].type == SDDS_LONGDOUBLE) {
542 layout->version = 4;
543 break;
544 }
545 }
546 if ((LDBL_DIG != 18) && (layout->version == 4)) {
547 SDDS_SetError("Operating system does not support 80bit float variables used by SDDS_LONGDOUBLE (SDDS_MPI_WriteLayout)");
548 return 0;
549 }
550 for (i = 0; i < layout->n_parameters; i++) {
551 if ((layout->parameter_definition[i].type == SDDS_ULONG64) || (layout->parameter_definition[i].type == SDDS_LONG64)) {
552 layout->version = 5;
553 break;
554 }
555 }
556 for (i = 0; i < layout->n_arrays; i++) {
557 if ((layout->array_definition[i].type == SDDS_ULONG64) || (layout->array_definition[i].type == SDDS_LONG64)) {
558 layout->version = 5;
559 break;
560 }
561 }
562 for (i = 0; i < layout->n_columns; i++) {
563 if ((layout->column_definition[i].type == SDDS_ULONG64) || (layout->column_definition[i].type == SDDS_LONG64)) {
564 layout->version = 5;
565 break;
566 }
567 }
568 // force layout version 5 because the row and column indexes are now 64bit long integers
569 //layout->version = 5;
570 sprintf(buf, "SDDS%" PRId32 "\n", layout->version);
571
572 MPI_dataset->file_offset += strlen(buf) * sizeof(char);
573 data_mode = SDDS_dataset->layout.data_mode.mode;
574 if (MPI_dataset->myid == 0 && !SDDS_MPI_WriteAsciiString(SDDS_dataset, buf)) {
575 fprintf(stderr, "SDDS_MPI_WriteLayout(error1): Unable to write layout.\n");
576 return 0;
577 }
578 if (data_mode == SDDS_BINARY) {
579 if (layout->byteOrderDeclared == SDDS_BIGENDIAN)
580 sprintf(buf, "!# big-endian\n");
581 else
582 sprintf(buf, "!# little-endian\n");
583 if (MPI_dataset->myid == 0 && !SDDS_MPI_WriteAsciiString(SDDS_dataset, buf)) {
584 fprintf(stderr, "SDDS_MPI_WriteLayout(error1): Unable to write layout.\n");
585 return 0;
586 }
587 MPI_dataset->file_offset += strlen(buf) * sizeof(char);
588 }
589 if (SDDS_dataset->layout.data_mode.fixed_row_count) {
590 sprintf(buf, "!# fixed-rowcount\n");
591 if (MPI_dataset->myid == 0 && !SDDS_MPI_WriteAsciiString(SDDS_dataset, buf)) {
592 fprintf(stderr, "SDDS_MPI_WriteLayout(error1): Unable to write layout.\n");
593 return 0;
594 }
595 MPI_dataset->file_offset += strlen(buf) * sizeof(char);
596 }
597 field = NULL;
598 if ((field = SDDS_CreateDescription(layout->description, layout->contents)) != NULL) {
599 if (MPI_dataset->myid == 0 && !SDDS_MPI_WriteAsciiString(SDDS_dataset, field)) {
600 fprintf(stderr, "SDDS_MPI_WriteLayout(error1): Unable to write layout.\n");
601 return 0;
602 }
603 MPI_dataset->file_offset += strlen(field) * sizeof(char);
604 free(field);
605 field = NULL;
606 }
607
608 for (i = 0; i < layout->n_parameters; i++) {
609 field = SDDS_CreateParameterDefinition(layout->parameter_definition + i);
610 if (MPI_dataset->myid == 0 && !SDDS_MPI_WriteAsciiString(SDDS_dataset, field)) {
611 fprintf(stderr, "SDDS_MPI_WriteLayout(error1): Unable to write layout.\n");
612 return 0;
613 }
614 MPI_dataset->file_offset += strlen(field) * sizeof(char);
615 free(field);
616 field = NULL;
617 }
618 for (i = 0; i < layout->n_arrays; i++) {
619 field = SDDS_CreateArrayDefinition(layout->array_definition + i);
620 if (MPI_dataset->myid == 0 && !SDDS_MPI_WriteAsciiString(SDDS_dataset, field)) {
621 fprintf(stderr, "SDDS_MPI_WriteLayout(error1): Unable to write layout.\n");
622 return 0;
623 }
624 MPI_dataset->file_offset += strlen(field) * sizeof(char);
625 free(field);
626 field = NULL;
627 }
628 for (i = 0; i < layout->n_columns; i++) {
629 field = SDDS_CreateColumnDefinition(layout->column_definition + i);
630 if (MPI_dataset->myid == 0 && !SDDS_MPI_WriteAsciiString(SDDS_dataset, field)) {
631 fprintf(stderr, "SDDS_MPI_WriteLayout(error1): Unable to write layout.\n");
632 return 0;
633 }
634 MPI_dataset->file_offset += strlen(field) * sizeof(char);
635 free(field);
636 field = NULL;
637 }
638
639#if RW_ASSOCIATES != 0
640 for (i = 0; i < layout->n_associates; i++) {
641 field = SDDS_CreateAssociateDefinition(layout->associate_definition + i);
642 if (MPI_dataset->myid == 0 && !SDDS_MPI_WriteAsciiString(SDDS_dataset, field)) {
643 fprintf(stderr, "SDDS_MPI_WriteLayout(error1): Unable to write layout.\n");
644 return 0;
645 }
646 MPI_dataset->file_offset += strlen(field) * sizeof(char);
647 free(field);
648 field = NULL;
649 }
650#endif
651 if ((field = SDDS_CreateDataMode(&layout->data_mode)) != NULL) {
652 if (MPI_dataset->myid == 0 && !SDDS_MPI_WriteAsciiString(SDDS_dataset, field)) {
653 fprintf(stderr, "SDDS_MPI_WriteLayout(error1): Unable to write layout.\n");
654 return 0;
655 }
656 MPI_dataset->file_offset += strlen(field) * sizeof(char);
657 free(field);
658 field = NULL;
659 }
660 MPI_dataset->column_offset = SDDS_MPI_Get_Column_Size(SDDS_dataset);
661 layout->layout_written = 1;
662 if (MPI_dataset->myid == 0) {
663 if (!SDDS_MPI_FlushBuffer(SDDS_dataset))
664 return 0;
665 }
666 SDDS_dataset->original_layout.version = layout->version;
667 return (1);
668}
int32_t SDDS_MPI_FlushBuffer(SDDS_DATASET *SDDS_dataset)
Flush the buffer by writing any remaining data to the MPI file.
int32_t SDDS_SetDefaultWriteBufferSize(int32_t newSize)
Set the default write buffer size for SDDS.
MPI_Offset SDDS_MPI_Get_Column_Size(SDDS_DATASET *SDDS_dataset)
Get the total size of all columns in an SDDS dataset.
int32_t SDDS_SaveLayout(SDDS_DATASET *SDDS_dataset)
Definition SDDS_copy.c:615
int32_t SDDS_IsBigEndianMachine()
Determines whether the current machine uses big-endian byte ordering.
int32_t SDDS_MPI_WriteAsciiString(SDDS_DATASET *SDDS_dataset, char *string)
Writes an ASCII string to the SDDS dataset using MPI.
char * SDDS_CreateDataMode(DATA_MODE *data_mode)
Creates a data mode block for the SDDS layout.
char * SDDS_CreateParameterDefinition(PARAMETER_DEFINITION *parameter_definition)
Creates a parameter definition block for the SDDS layout.
char * SDDS_CreateDescription(char *text, char *contents)
Creates a description block for the SDDS layout.
char * SDDS_CreateColumnDefinition(COLUMN_DEFINITION *column_definition)
Creates a column definition block for the SDDS layout.
char * SDDS_CreateAssociateDefinition(ASSOCIATE_DEFINITION *associate_definition)
Creates an associate definition block for the SDDS layout.
char * SDDS_CreateArrayDefinition(ARRAY_DEFINITION *array_definition)
Creates an array definition block for the SDDS layout.

◆ SDDS_MPI_WritePage()

int32_t SDDS_MPI_WritePage ( SDDS_DATASET * SDDS_dataset)

Writes a page of data to the MPI file associated with the SDDS dataset.

This function checks the validity of the dataset and ensures that the layout has been written and that the file is connected. If these conditions are met, it proceeds to write a binary page using SDDS_MPI_WriteBinaryPage.

Parameters
SDDS_datasetPointer to the SDDS_DATASET structure containing the dataset information.
Returns
1 if the page was successfully written, 0 otherwise.

Definition at line 701 of file SDDSmpi_output.c.

701 {
702 int32_t result;
703
704#if MPI_DEBUG
705 logDebug("SDDS_MPI_WritePage", SDDS_dataset);
706#endif
707
708 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_WritePage"))
709 return 0;
710 if (!SDDS_dataset->layout.layout_written) {
711 SDDS_SetError("Unable to write page--layout not written (SDDS_WritePage)");
712 return 0;
713 }
714 if (SDDS_dataset->layout.disconnected) {
715 SDDS_SetError("Can't write page--file is disconnected (SDDS_WritePage)");
716 return 0;
717 }
718 result = SDDS_MPI_WriteBinaryPage(SDDS_dataset);
719 return result;
720}
int32_t SDDS_MPI_WriteBinaryPage(SDDS_DATASET *SDDS_dataset)
Write an SDDS binary page using MPI.

Variable Documentation

◆ SDDS_mpi_error_str

char SDDS_mpi_error_str[MPI_MAX_ERROR_STRING]

Definition at line 28 of file SDDSmpi_output.c.

◆ SDDS_mpi_error_str_len

int32_t SDDS_mpi_error_str_len

Definition at line 27 of file SDDSmpi_output.c.

◆ SDDS_MPI_FILE_TYPE

char* SDDS_MPI_FILE_TYPE[2] = {"external32", "native"}

Definition at line 30 of file SDDSmpi_output.c.

30{"external32", "native"};

◆ terminateMode

int32_t terminateMode = 0
static

Definition at line 32 of file SDDSmpi_output.c.