hdf5/test/atomic_writer.c
2024-03-16 19:43:47 -07:00

257 lines
8.5 KiB
C

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the COPYING file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*-------------------------------------------------------------------------
*
* Created: atomic_writer.c
*
* Purpose: This is the "writer" part of the standalone test to check
* atomic read-write operation on a system.
* a) atomic_writer.c--the writer (this file)
* b) atomic_reader.c--the reader
* c) atomic_data--the name of the data file used by writer and reader
*
*-------------------------------------------------------------------------
*/
/***********/
/* Headers */
/***********/
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#if !defined(WIN32) && !defined(__MINGW32__)
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
/****************/
/* Local Macros */
/****************/
#define FILENAME "atomic_data"
/********************/
/* Local Prototypes */
/********************/
static void usage(void);
/*-------------------------------------------------------------------------
* Function: usage
*
* Purpose: To print information about the command line options
*
* Parameters: None
*
* Return: void
*
*-------------------------------------------------------------------------
*/
static void
usage(void)
{
printf("\n");
printf("Usage error!\n");
printf("Usage: atomic_writer -n <number of integers to write> -i <number of iterations for writer>\n");
printf(" Note**The number of integers for option n has to be positive\n");
printf(" Note**The number of integers for option i has to be positive\n");
printf("\n");
} /* usage() */
/*-------------------------------------------------------------------------
* Function: main
*
* Purpose: To write a series of integers to a file for the reader to verify the data.
* A write is atomic if the whole amount written in one operation is not interleaved
* with data from any other process.
* (1) Iterate with i iterations
* (2) Write a series of integers (0 to n-1) to the file with this pattern:
* offset 0: 0000000000000000000000000000000
* offset 1: 111111111111111111111111111111
* offset 2: 22222222222222222222222222222
* offset 3: 3333333333333333333333333333
* ...
* ...
* offset n-1: (n-1)
*
* At the end of the writes, the data in the file will be:
* 01234567........(n-1)
*
* Note:
* (a) The # of integers (via -n option) used by the writer and reader should be the same.
* (b) The data file used by the writer and reader should be the same.
*
* Future enhancement:
* 1) Provide default values for n and i and allow user to run with either 0 or 1 option
* 2) Use HDF library HD<system calls> instead of the system calls
* 3) Handle large sized buffer (gigabytes) if needed
*
* Return: Success: EXIT_SUCCESS
* Failure: EXIT_FAILURE
*
*-------------------------------------------------------------------------
*/
int
main(int argc, char *argv[])
{
int fd = -1; /* file descriptor */
ssize_t bytes_wrote; /* the number of bytes written */
unsigned int *buf = NULL; /* buffer to hold written data */
unsigned int n, u, i; /* local index variable */
int temp; /* temporary variable */
unsigned int iterations = 0; /* the input for "-i" */
unsigned int num = 0; /* the input for "-n" */
int opt = 0; /* option char */
/* Ensure the # of arguments is as expected */
if (argc != 5) {
usage();
exit(EXIT_FAILURE);
} /* end if */
/* Parse command line options */
while ((opt = getopt(argc, argv, "n:i:")) != -1) {
switch (opt) {
case 'n':
if ((temp = atoi(optarg)) < 0) {
usage();
exit(EXIT_FAILURE);
} /* end if */
num = (unsigned int)temp;
break;
case 'i':
if ((temp = atoi(optarg)) < 0) {
usage();
exit(EXIT_FAILURE);
} /* end if */
iterations = (unsigned int)temp;
break;
default:
printf("Invalid option encountered\n");
break;
} /* end switch */
} /* end while */
printf("WRITER: # of integers to write = %u; # of iterations = %d\n", num, iterations);
/* Remove existing data file if needed */
if (remove(FILENAME) < 0) {
if (errno == ENOENT)
printf("WRITER: remove %s--%s\n", FILENAME, strerror(errno));
else {
printf("WRITER: error from remove: %d--%s\n", errno, strerror(errno));
goto error;
} /* end else */
}
else
printf("WRITER: %s is removed\n", FILENAME);
/* Create the data file */
if ((fd = open(FILENAME, O_RDWR | O_TRUNC | O_CREAT, 0664)) < 0) {
printf("WRITER: error from open\n");
goto error;
} /* end if */
/* Allocate buffer for holding data to be written */
if ((buf = (unsigned int *)malloc(num * sizeof(unsigned int))) == NULL) {
printf("WRITER: error from malloc\n");
if (fd >= 0 && close(fd) < 0)
printf("WRITER: error from close\n");
goto error;
} /* end if */
printf("\n");
for (i = 1; i <= iterations; i++) {
printf("WRITER: *****start iteration %u*****\n", i);
/* Write the series of integers to the file */
for (n = 0; n < num; n++) {
size_t seek_pos;
/* Set up data to be written */
for (u = 0; u < num; u++)
buf[u] = n;
seek_pos = n * sizeof(unsigned int);
if (sizeof(off_t) < 8) {
if (seek_pos > INT32_MAX) {
printf("WRITER: seek past range for lseek\n");
goto error;
}
}
else {
if (seek_pos > INT64_MAX) {
printf("WRITER: seek past range for lseek\n");
goto error;
}
}
/* Position the file to the proper location */
if (lseek(fd, (off_t)seek_pos, SEEK_SET) < 0) {
printf("WRITER: error from lseek\n");
goto error;
} /* end if */
/* Write the data */
if ((bytes_wrote = write(fd, buf, ((num - n) * sizeof(unsigned int)))) < 0) {
printf("WRITER: error from write\n");
goto error;
} /* end if */
/* Verify the bytes written is correct */
if (bytes_wrote != (ssize_t)((num - n) * sizeof(unsigned int))) {
printf("WRITER: error from bytes written\n");
goto error;
} /* end if */
} /* end for */
printf("WRITER: *****end iteration %u*****\n\n", i);
} /* end for */
/* Close the file */
if (close(fd) < 0) {
printf("WRITER: error from close\n");
goto error;
} /* end if */
/* Free the buffer */
if (buf)
free(buf);
return EXIT_SUCCESS;
error:
return EXIT_FAILURE;
} /* end main() */
#else /* WIN32 / MINGW32 */
int
main(void)
{
printf("Non-POSIX platform. Exiting.\n");
return EXIT_FAILURE;
} /* end main() */
#endif /* WIN32 / MINGW32 */