2017-01-27 03:34:12 +08:00
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
|
|
* 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 *
|
2017-04-18 03:32:16 +08:00
|
|
|
* the COPYING file, which can be found at the root of the source code *
|
2021-02-17 22:52:04 +08:00
|
|
|
* distribution tree, or in https://www.hdfgroup.org/licenses. *
|
2017-04-18 03:32:16 +08:00
|
|
|
* If you do not have access to either file, you may request a copy from *
|
|
|
|
* help@hdfgroup.org. *
|
2017-01-27 03:34:12 +08:00
|
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* Created: atomic_writer.c
|
|
|
|
*
|
2019-08-25 03:07:19 +08:00
|
|
|
* Purpose: This is the "writer" part of the standalone test to check
|
2017-01-27 03:34:12 +08:00
|
|
|
* 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 <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.
|
2019-08-25 03:07:19 +08:00
|
|
|
* A write is atomic if the whole amount written in one operation is not interleaved
|
2017-01-27 03:34:12 +08:00
|
|
|
* 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[])
|
|
|
|
{
|
2020-09-30 22:27:10 +08:00
|
|
|
int fd = -1; /* file descriptor */
|
|
|
|
ssize_t bytes_wrote; /* the nubmer 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 */
|
2017-01-27 03:34:12 +08:00
|
|
|
|
|
|
|
/* Ensure the # of arguments is as expected */
|
2020-09-30 22:27:10 +08:00
|
|
|
if (argc != 5) {
|
2017-01-27 03:34:12 +08:00
|
|
|
usage();
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
} /* end if */
|
|
|
|
|
|
|
|
/* Parse command line options */
|
2020-09-30 22:27:10 +08:00
|
|
|
while ((opt = getopt(argc, argv, "n:i:")) != -1) {
|
|
|
|
switch (opt) {
|
2017-01-27 03:34:12 +08:00
|
|
|
case 'n':
|
2020-09-30 22:27:10 +08:00
|
|
|
if ((temp = atoi(optarg)) < 0) {
|
2017-01-27 03:34:12 +08:00
|
|
|
usage();
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
} /* end if */
|
|
|
|
num = (unsigned int)temp;
|
|
|
|
break;
|
|
|
|
case 'i':
|
2020-09-30 22:27:10 +08:00
|
|
|
if ((temp = atoi(optarg)) < 0) {
|
2017-01-27 03:34:12 +08:00
|
|
|
usage();
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
} /* end if */
|
|
|
|
iterations = (unsigned int)temp;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
printf("Invalid option encountered\n");
|
|
|
|
break;
|
|
|
|
} /* end switch */
|
2020-09-30 22:27:10 +08:00
|
|
|
} /* end while */
|
2017-01-27 03:34:12 +08:00
|
|
|
|
|
|
|
printf("WRITER: # of integers to write = %u; # of iterations = %d\n", num, iterations);
|
|
|
|
|
|
|
|
/* Remove existing data file if needed */
|
2020-09-30 22:27:10 +08:00
|
|
|
if (remove(FILENAME) < 0) {
|
|
|
|
if (errno == ENOENT)
|
2017-01-27 03:34:12 +08:00
|
|
|
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 */
|
2020-09-30 22:27:10 +08:00
|
|
|
}
|
|
|
|
else
|
2017-01-27 03:34:12 +08:00
|
|
|
printf("WRITER: %s is removed\n", FILENAME);
|
|
|
|
|
|
|
|
/* Create the data file */
|
2020-09-30 22:27:10 +08:00
|
|
|
if ((fd = open(FILENAME, O_RDWR | O_TRUNC | O_CREAT, 0664)) < 0) {
|
2017-01-27 03:34:12 +08:00
|
|
|
printf("WRITER: error from open\n");
|
|
|
|
goto error;
|
|
|
|
} /* end if */
|
|
|
|
|
|
|
|
/* Allocate buffer for holding data to be written */
|
2020-09-30 22:27:10 +08:00
|
|
|
if ((buf = (unsigned int *)malloc(num * sizeof(unsigned int))) == NULL) {
|
2017-01-27 03:34:12 +08:00
|
|
|
printf("WRITER: error from malloc\n");
|
2020-09-30 22:27:10 +08:00
|
|
|
if (fd >= 0 && close(fd) < 0)
|
2017-01-27 03:34:12 +08:00
|
|
|
printf("WRITER: error from close\n");
|
|
|
|
goto error;
|
|
|
|
} /* end if */
|
|
|
|
|
|
|
|
printf("\n");
|
|
|
|
|
2020-09-30 22:27:10 +08:00
|
|
|
for (i = 1; i <= iterations; i++) {
|
2017-01-27 03:34:12 +08:00
|
|
|
printf("WRITER: *****start iteration %u*****\n", i);
|
|
|
|
|
|
|
|
/* Write the series of integers to the file */
|
2020-09-30 22:27:10 +08:00
|
|
|
for (n = 0; n < num; n++) {
|
2017-01-27 03:34:12 +08:00
|
|
|
|
|
|
|
/* Set up data to be written */
|
2020-09-30 22:27:10 +08:00
|
|
|
for (u = 0; u < num; u++)
|
2017-01-27 03:34:12 +08:00
|
|
|
buf[u] = n;
|
|
|
|
|
|
|
|
/* Position the file to the proper location */
|
2020-09-30 22:27:10 +08:00
|
|
|
if (lseek(fd, (off_t)(n * sizeof(unsigned int)), SEEK_SET) < 0) {
|
2017-01-27 03:34:12 +08:00
|
|
|
printf("WRITER: error from lseek\n");
|
|
|
|
goto error;
|
|
|
|
} /* end if */
|
2019-08-25 03:07:19 +08:00
|
|
|
|
2017-01-27 03:34:12 +08:00
|
|
|
/* Write the data */
|
2020-09-30 22:27:10 +08:00
|
|
|
if ((bytes_wrote = write(fd, buf, ((num - n) * sizeof(unsigned int)))) < 0) {
|
2017-01-27 03:34:12 +08:00
|
|
|
printf("WRITER: error from write\n");
|
|
|
|
goto error;
|
|
|
|
} /* end if */
|
|
|
|
|
|
|
|
/* Verify the bytes written is correct */
|
2020-09-30 22:27:10 +08:00
|
|
|
if (bytes_wrote != (ssize_t)((num - n) * sizeof(unsigned int))) {
|
2017-01-27 03:34:12 +08:00
|
|
|
printf("WRITER: error from bytes written\n");
|
|
|
|
goto error;
|
|
|
|
} /* end if */
|
2020-09-30 22:27:10 +08:00
|
|
|
} /* end for */
|
2017-01-27 03:34:12 +08:00
|
|
|
|
|
|
|
printf("WRITER: *****end iteration %u*****\n\n", i);
|
|
|
|
|
|
|
|
} /* end for */
|
|
|
|
|
|
|
|
/* Close the file */
|
2020-09-30 22:27:10 +08:00
|
|
|
if (close(fd) < 0) {
|
2017-01-27 03:34:12 +08:00
|
|
|
printf("WRITER: error from close\n");
|
|
|
|
goto error;
|
|
|
|
} /* end if */
|
|
|
|
|
|
|
|
/* Free the buffer */
|
2020-09-30 22:27:10 +08:00
|
|
|
if (buf)
|
2017-01-27 03:34:12 +08:00
|
|
|
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 */
|