SDDS ToolKit Programs and Libraries for C and Python
Loading...
Searching...
No Matches
SDDSmpi_output.c File Reference

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.

#include "SDDS.h"
#include "SDDS_internal.h"
#include "mdb_thread.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.
 

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 78 of file SDDSmpi_output.c.

78 {
79 if (!string || SDDS_StringIsBlank(string))
80 return NULL;
81 return string;
82}
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 739 of file SDDSmpi_output.c.

739 {
740 switch (SDDS_type) {
741 case SDDS_SHORT:
742 return MPI_SHORT;
743 case SDDS_USHORT:
744 return MPI_UNSIGNED_SHORT;
745 case SDDS_LONG:
746 /* SDDS_LONG type is actually int32_t */
747 return MPI_INT;
748 case SDDS_ULONG:
749 return MPI_UNSIGNED;
750 case SDDS_LONG64:
751 return MPI_INT64_T;
752 case SDDS_ULONG64:
753 return MPI_UINT64_T;
754 case SDDS_FLOAT:
755 return MPI_FLOAT;
756 case SDDS_DOUBLE:
757 return MPI_DOUBLE;
758 case SDDS_LONGDOUBLE:
759 return MPI_LONG_DOUBLE;
760 case SDDS_STRING:
761 case SDDS_CHARACTER:
762 return MPI_CHAR;
763 default:
764 SDDS_Bomb("Unknown SDDS datatype provided to ConvertSDDS_To_MPI.");
765 return 0;
766 }
767}
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:380
#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 297 of file SDDSmpi_output.c.

297 {
298 char *array = NULL, *tmpstr;
299 char buf[40];
300 array = (char *)malloc(sizeof(char) * 2048);
301 array[0] = 0;
302 sprintf(array, "&array ");
303 strcat(array, SDDS_CreateNamelistField("name", array_definition->name));
304 if ((tmpstr = BlankToNull(array_definition->symbol)))
305 strcat(array, SDDS_CreateNamelistField("symbol", tmpstr));
306 if ((tmpstr = BlankToNull(array_definition->units)))
307 strcat(array, SDDS_CreateNamelistField("units", tmpstr));
308 if ((tmpstr = BlankToNull(array_definition->description)))
309 strcat(array, SDDS_CreateNamelistField("description", tmpstr));
310 if ((tmpstr = BlankToNull(array_definition->format_string)))
311 strcat(array, SDDS_CreateNamelistField("format_string", tmpstr));
312 if ((tmpstr = BlankToNull(array_definition->group_name)))
313 strcat(array, SDDS_CreateNamelistField("group_name", tmpstr));
314 strcat(array, SDDS_CreateNamelistField("type", SDDS_type_name[array_definition->type - 1]));
315 if (array_definition->dimensions != 1) /* 1 is default */
316 {
317 //sprintf(array, "%sdimensions=%" PRId32 ", ", array, array_definition->dimensions);
318 sprintf(buf, "dimensions=%" PRId32 ", ", array_definition->dimensions);
319 strcat(array, buf);
320 }
321 strcat(array, " &end\n");
322 return array;
323}
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 333 of file SDDSmpi_output.c.

333 {
334 char *associate = NULL, *tmpstr;
335 char buf[40];
336 associate = (char *)malloc(sizeof(char) * 2048);
337 associate[0] = 0;
338 sprintf(associate, "&associate ");
339 strcat(associate, SDDS_CreateNamelistField("name", associate_definition->name));
340 if ((tmpstr = BlankToNull(associate_definition->filename)))
341 strcat(associate, SDDS_CreateNamelistField("filename", tmpstr));
342 if ((tmpstr = BlankToNull(associate_definition->contents)))
343 strcat(associate, SDDS_CreateNamelistField("contents", tmpstr));
344 if ((tmpstr = BlankToNull(associate_definition->path)))
345 strcat(associate, SDDS_CreateNamelistField("path", tmpstr));
346 if ((tmpstr = BlankToNull(associate_definition->description)))
347 strcat(associate, SDDS_CreateNamelistField("description", tmpstr));
348 //sprintf(associate, "%ssdds=%" PRId32, associate, associate_definition->sdds);
349 sprintf(buf, "sdds=%" PRId32 " &end\n", associate_definition->sdds);
350 strcat(associate, buf);
351 //strcat(associate, " &end\n");
352 return associate;
353 ;
354}

◆ 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 270 of file SDDSmpi_output.c.

270 {
271 char *col = NULL, *tmpStr;
272 col = (char *)malloc(sizeof(char) * 2048);
273 col[0] = 0;
274 sprintf(col, "&column ");
275 strcat(col, SDDS_CreateNamelistField("name", column_definition->name));
276 if ((tmpStr = BlankToNull(column_definition->symbol)))
277 strcat(col, SDDS_CreateNamelistField("symbol", tmpStr));
278 if ((tmpStr = BlankToNull(column_definition->units)))
279 strcat(col, SDDS_CreateNamelistField("units", tmpStr));
280 if ((tmpStr = BlankToNull(column_definition->description)))
281 strcat(col, SDDS_CreateNamelistField("description", tmpStr));
282 if ((tmpStr = BlankToNull(column_definition->format_string)))
283 strcat(col, SDDS_CreateNamelistField("format_string", tmpStr));
284 strcat(col, SDDS_CreateNamelistField("type", SDDS_type_name[column_definition->type - 1]));
285 strcat(col, " &end\n");
286 return col;
287}

◆ 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 364 of file SDDSmpi_output.c.

364 {
365 char *mode = NULL;
366 char buf[40];
367 if (data_mode->mode > SDDS_NUM_DATA_MODES)
368 return NULL;
369 mode = (char *)malloc(sizeof(char) * 2048);
370 mode[0] = 0;
371 sprintf(mode, "&data ");
372 strcat(mode, SDDS_CreateNamelistField("mode", SDDS_data_mode[data_mode->mode - 1]));
373 if (data_mode->lines_per_row > 1) {
374 //sprintf(mode, "%slines_per_row=%" PRId32 ", ", mode, data_mode->lines_per_row);
375 sprintf(buf, "lines_per_row=%" PRId32 ", ", data_mode->lines_per_row);
376 strcat(mode, buf);
377 }
378 if (data_mode->no_row_counts) {
379 //sprintf(mode, "%sno_row_counts=1, ", mode);
380 strcat(mode, "no_row_counts=1, ");
381 }
382 if (data_mode->column_major) {
383 strcat(mode, "column_major_order=1, ");
384 }
385 strcat(mode, "&end\n");
386 return mode;
387}
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 215 of file SDDSmpi_output.c.

215 {
216 char *desc = NULL;
217 if (!text && !contents)
218 return NULL;
219 desc = (char *)malloc(sizeof(char) * 2048);
220 desc[0] = 0;
221 sprintf(desc, "&description ");
222 if (text)
223 strcat(desc, SDDS_CreateNamelistField("text", text));
224 if (contents)
225 strcat(desc, SDDS_CreateNamelistField("contents", contents));
226 //sprintf(desc, "%s&end\n", desc);
227 desc = strcat(desc, "&end\n");
228 return desc;
229}

◆ 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 164 of file SDDSmpi_output.c.

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

◆ 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 239 of file SDDSmpi_output.c.

239 {
240 char *par, *tmpstr;
241 par = (char *)malloc(sizeof(char) * 2048);
242 par[0] = 0;
243 sprintf(par, "&parameter ");
244 strcat(par, SDDS_CreateNamelistField("name", parameter_definition->name));
245 if ((tmpstr = BlankToNull(parameter_definition->symbol)))
246 strcat(par, SDDS_CreateNamelistField("symbol", tmpstr));
247 if ((tmpstr = BlankToNull(parameter_definition->units)))
248 strcat(par, SDDS_CreateNamelistField("units", tmpstr));
249 if ((tmpstr = BlankToNull(parameter_definition->description)))
250 strcat(par, SDDS_CreateNamelistField("description", tmpstr));
251 if ((tmpstr = BlankToNull(parameter_definition->format_string)))
252 strcat(par, SDDS_CreateNamelistField("format_string", tmpstr));
253 strcat(par, SDDS_CreateNamelistField("type", SDDS_type_name[parameter_definition->type - 1]));
254 /*if ((tmpstr=BlankToNull(parameter_definition->fixed_value)))
255 strcat(par, SDDS_CreateNamelistField("fixed_value", tmpstr)); */
256 if (parameter_definition->fixed_value)
257 strcat(par, SDDS_CreateNamelistField("fixed_value", parameter_definition->fixed_value));
258 strcat(par, "&end\n");
259 return par;
260}

◆ 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 689 of file SDDSmpi_output.c.

689 {
690 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
691 if (text)
692 fprintf(stderr, "Error: %s\n", text);
693 if (mpi_file)
694 MPI_File_close(mpi_file);
695 MPI_Finalize();
696 exit(1);
697}
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:474

◆ 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 1099 of file SDDSmpi_output.c.

1099 {
1100 MPI_DATASET *MPI_dataset;
1101
1102#if MPI_DEBUG
1103 logDebug("SDDS_MPI_DisconnectFile", SDDS_dataset);
1104#endif
1105
1106 MPI_dataset = SDDS_dataset->MPI_dataset;
1107 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_MPI_DisconnectFile"))
1108 return 0;
1109 if (!SDDS_dataset->layout.filename) {
1110 SDDS_SetError("Can't disconnect file. No filename or gzip file. (SDDS_MPI_DisconnectFile)");
1111 return 0;
1112 }
1113 if (SDDS_dataset->layout.disconnected) {
1114 SDDS_SetError("Can't disconnect file. Already disconnected. (SDDS_MPI_DisconnectFile)");
1115 return 0;
1116 }
1117 /* if (SDDS_dataset->page_started && !SDDS_WritePage(SDDS_dataset)) {
1118 SDDS_SetError("Can't disconnect file. Problem updating page. (SDDS_MPI_DisconnectFile)");
1119 return 0;
1120 } */
1121 SDDS_dataset->layout.disconnected = 1;
1122 MPI_File_close(&(MPI_dataset->MPI_file));
1123 return 1;
1124}
void SDDS_SetError(char *error_text)
Records an error message in the SDDS error stack.
Definition SDDS_utils.c:421
int32_t SDDS_CheckDataset(SDDS_DATASET *SDDS_dataset, const char *caller)
Validates the SDDS dataset pointer.
Definition SDDS_utils.c:618

◆ 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 121 of file SDDSmpi_output.c.

121 {
122 unsigned long file_opened = 0; /* Flag to indicate that the file was successfully opened */
123 int mpi_amode = MPI_MODE_RDWR;
124 int mpi_code; /* mpi return code */
125
126 /* Get the MPI rank of this process and the total number of processes */
127 /*if (MPI_SUCCESS != (mpi_code=MPI_Comm_rank(MPI_dataset->comm, &MPI_dataset->myid)))
128 SDDS_MPI_GOTO_ERROR(stderr, "MPI_Comm_rank failed", mpi_code, 1);
129 if (MPI_SUCCESS != (mpi_code=MPI_Comm_size(MPI_dataset->comm, &MPI_dataset->n_processors)))
130 SDDS_MPI_GOTO_ERROR(stderr, "MPI_Comm_size failed", mpi_code, 1); */
131
132 MPI_dataset->fpdeb = NULL;
133
134 if (flags & SDDS_MPI_WRITE_ONLY)
135 mpi_amode = MPI_MODE_CREATE | MPI_MODE_WRONLY;
136 if (flags & SDDS_MPI_READ_ONLY)
137 mpi_amode = MPI_MODE_RDONLY;
138 if (flags & SDDS_MPI_READ_WRITE)
139 mpi_amode = MPI_MODE_CREATE | MPI_MODE_RDWR;
140 if (MPI_SUCCESS != (mpi_code = MPI_File_open(MPI_dataset->comm, filename, mpi_amode, MPI_INFO_NULL, &(MPI_dataset->MPI_file))))
141 SDDS_MPI_GOTO_ERROR(stderr, "MPI_File_open failed", mpi_code, 1);
142 else
143 file_opened = 1;
144 MPI_dataset->n_page = 0;
145 if (mpi_amode & MPI_MODE_WRONLY)
146 MPI_File_set_size(MPI_dataset->MPI_file, 0);
147 if (mpi_amode != MPI_MODE_RDONLY) {
148 if (MPI_SUCCESS != (mpi_code = MPI_File_sync(MPI_dataset->MPI_file)))
149 SDDS_MPI_GOTO_ERROR(stderr, "MPI_File_sync failed", mpi_code, 1);
150 }
151 /*MPI_dataset->file_offset = 0; */
152 return file_opened;
153}
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 94 of file SDDSmpi_output.c.

94 {
95 char mpi_error_str[MPI_MAX_ERROR_STRING];
96 int32_t mpi_error_str_len;
97
98 MPI_Error_string(mpierr, mpi_error_str, &mpi_error_str_len);
99 mdb_thread_lock(&SDDS_mpi_error_lock);
100 SDDS_mpi_error_str_len = mpi_error_str_len;
101 snprintf(SDDS_mpi_error_str, sizeof(SDDS_mpi_error_str), "%s", mpi_error_str);
102 mdb_thread_unlock(&SDDS_mpi_error_lock);
103 if (str)
104 fprintf(fp, "%s: ", str);
105 if (mpi_error_str_len > 0)
106 fprintf(fp, "%s\n", mpi_error_str);
107 if (exit_code)
108 exit(1);
109}

◆ 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 1019 of file SDDSmpi_output.c.

1019 {
1020 MPI_DATASET *MPI_target = SDDS_target->MPI_dataset;
1021
1022 if (!SDDS_CheckDataset(SDDS_source, "SDDS_InitializeCopy"))
1023 return (0);
1024 if (!SDDS_CheckDataset(SDDS_target, "SDDS_InitializeCopy"))
1025 return (0);
1026 /* if (!SDDS_ZeroMemory((void *)SDDS_target, sizeof(SDDS_DATASET))) {
1027 SDDS_SetError("Unable to copy layout--can't zero SDDS_DATASET structure (SDDS_InitializeCopy)");
1028 return(0);
1029 } */
1030 /*has been zeroed in the setup */
1031 SDDS_target->pagecount_offset = NULL;
1032 SDDS_target->mode = SDDS_WRITEMODE;
1033 SDDS_target->layout.popenUsed = 0;
1034 SDDS_target->layout.gzipFile = 0;
1035 SDDS_target->layout.lzmaFile = 0;
1036 if (filename) {
1037 if (!SDDS_CopyString(&SDDS_target->layout.filename, filename)) {
1038 SDDS_SetError("Memory allocation failure (SDDS_InitializeCopy)");
1039 return (0);
1040 }
1041 }
1042 SDDS_target->page_number = SDDS_target->page_started = 0;
1043 if (!SDDS_CopyLayout(SDDS_target, SDDS_source))
1044 return (0);
1045 /* SDDS_target->MPI_dataset = MPI_target; */
1046 SDDS_target->layout.data_mode.column_major = column_major;
1047 if (!SDDS_MPI_File_Open(MPI_target, filename, SDDS_MPI_WRITE_ONLY))
1048 return 0;
1049 SDDS_target->parallel_io = 1;
1050 MPI_target->file_offset = 0;
1051 if (!SDDS_MPI_WriteLayout(SDDS_target))
1052 return 0;
1053 return 1;
1054}
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:922
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 985 of file SDDSmpi_output.c.

985 {
986 MPI_DATASET *MPI_dataset = SDDS_dataset->MPI_dataset;
987
988 if (!SDDS_Parallel_InitializeOutput(SDDS_dataset, description, contents, filename))
989 return 0;
990 if (flags & SDDS_MPI_READ_ONLY) {
991 SDDS_SetError("Wrong flags pass (SDDS_MPI_READ_ONLY) passed to SDDS_MPI_InitializeOutput)!");
992 return 0;
993 }
994 /* SDDS_dataset->MPI_dataset = MPI_dataset; */
995 SDDS_dataset->layout.data_mode.column_major = column_major;
996 if (!SDDS_MPI_File_Open(MPI_dataset, filename, flags)) {
997 SDDS_SetError("Failed in opening file for MPI output!");
998 return 0;
999 }
1000#if MPI_DEBUG
1001 logDebug("SDDS_MPI_InitializeOutput", SDDS_dataset);
1002#endif
1003 return 1;
1004}
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 1136 of file SDDSmpi_output.c.

1136 {
1137 MPI_DATASET *MPI_dataset;
1138
1139#if MPI_DEBUG
1140 logDebug("SDDS_MPI_ReconnectFile", SDDS_dataset);
1141#endif
1142 MPI_dataset = SDDS_dataset->MPI_dataset;
1143 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_MPI_ReconnectFile"))
1144 return 0;
1145 if (!SDDS_dataset->layout.disconnected || !SDDS_dataset->layout.filename) {
1146 SDDS_SetError("Can't reconnect file. Not disconnected or missing filename. (SDDS_MPI_ReconnectFile)");
1147 return 0;
1148 }
1149 if (MPI_File_open(MPI_dataset->comm, SDDS_dataset->layout.filename, MPI_MODE_RDWR, MPI_INFO_NULL, &(MPI_dataset->MPI_file)) != MPI_SUCCESS) {
1150 SDDS_SetError("Can't reconnect file, MPI_File_open failed. (SDDS_MPI_ReconnectFile)");
1151 return 0;
1152 }
1153 MPI_File_get_size(MPI_dataset->MPI_file, &(MPI_dataset->file_offset));
1154 MPI_File_set_view(MPI_dataset->MPI_file, MPI_dataset->file_offset, MPI_BYTE, MPI_BYTE, "native", MPI_INFO_NULL);
1155 /* MPI_dataset->file_offset=0; */
1156 SDDS_dataset->layout.disconnected = 0;
1157 return 1;
1158}

◆ 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 1070 of file SDDSmpi_output.c.

1070 {
1071 MPI_DATASET *MPI_dataset;
1072
1073 if (!SDDS_ZeroMemory((void *)SDDS_dataset, sizeof(SDDS_DATASET)))
1074 SDDS_Bomb("Unable to zero memory for SDDS dataset(SDDS_MPI_Setup)");
1075 if (parallel_io) {
1076 MPI_dataset = malloc(sizeof(*MPI_dataset));
1077 if (!SDDS_ZeroMemory((void *)MPI_dataset, sizeof(MPI_DATASET)))
1078 SDDS_Bomb("Unable to zero memory for MPI_DATASEAT (SDDS_MPI_Setup)");
1079 MPI_dataset->n_processors = n_processors;
1080 MPI_dataset->myid = myid;
1081 MPI_dataset->comm = comm;
1082 MPI_dataset->collective_io = 0;
1083 MPI_dataset->master_read = master_read;
1084 MPI_dataset->fpdeb = NULL;
1085 SDDS_dataset->MPI_dataset = MPI_dataset;
1086 SDDS_dataset->parallel_io = 1;
1087 }
1088}
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 779 of file SDDSmpi_output.c.

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

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

◆ 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 462 of file SDDSmpi_output.c.

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

709 {
710 int32_t result;
711
712#if MPI_DEBUG
713 logDebug("SDDS_MPI_WritePage", SDDS_dataset);
714#endif
715
716 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_WritePage"))
717 return 0;
718 if (!SDDS_dataset->layout.layout_written) {
719 SDDS_SetError("Unable to write page--layout not written (SDDS_WritePage)");
720 return 0;
721 }
722 if (SDDS_dataset->layout.disconnected) {
723 SDDS_SetError("Can't write page--file is disconnected (SDDS_WritePage)");
724 return 0;
725 }
726 result = SDDS_MPI_WriteBinaryPage(SDDS_dataset);
727 return result;
728}
int32_t SDDS_MPI_WriteBinaryPage(SDDS_DATASET *SDDS_dataset)
Write an SDDS binary page using MPI.