/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 #include #include #include #include #include #if !defined(WIN32) && !defined(__MINGW32__) #include #include #include #include #include /****************/ /* 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 -i \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 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 */