1 /*
2  *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
3  *  See COPYRIGHT notice in top-level directory.
4  *
5  *  $Id: one_record.c 2744 2016-12-28 16:25:22Z wkliao $
6  */
7 
8 /*
9  * This program tests the special case of ONLY one record variable is defined
10  * and the record size is not aligned with the 4-byte boundary. As defined in
11  * CDF-1 and CDF-2 format specifications:
12  *    "A special case: Where there is exactly one record variable, we drop the
13  *    requirement that each record be four-byte aligned, so in this case there
14  *    is no record padding."
15  *
16  */
17 
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <libgen.h> /* basename() */
22 #include <pnetcdf.h>
23 
24 #include <testutils.h>
25 
26 #define ERRCODE 2
27 #define ERR if (err != NC_NOERR) {printf("Error at line %d: err=%d %s\n", __LINE__, err, ncmpi_strerror(err));}
28 
29 #define STR_LEN 19
30 #define NUM_VALS 2
31 
32 /*----< main() >------------------------------------------------------------*/
main(int argc,char ** argv)33 int main(int argc, char **argv)
34 {
35     char filename[256];
36     int i, err, nerrs=0, rank, nprocs, cmode;
37     int ncid, dimids[2], varid;
38     char data[NUM_VALS][STR_LEN + 1], data_in[NUM_VALS*STR_LEN];
39     MPI_Offset start[2];
40     MPI_Offset count[2];
41 
42     MPI_Init(&argc, &argv);
43     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
44     MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
45 
46     if (argc > 2) {
47         if (!rank) printf("Usage: %s [filename]\n",argv[0]);
48         MPI_Finalize();
49         return 0;
50     }
51     if (argc == 2) snprintf(filename, 256, "%s", argv[1]);
52     else           strcpy(filename, "testfile.nc");
53 
54     if (rank == 0) {
55         char *cmd_str = (char*)malloc(strlen(argv[0]) + 256);
56         sprintf(cmd_str, "*** TESTING C   %s for only one record variable ", basename(argv[0]));
57         printf("%-66s ------ ", cmd_str); fflush(stdout);
58         free(cmd_str);
59     }
60 
61     strcpy(data[0], "2005-04-11_12:00:00"); /* 19 bytes not a multiply of 4 */
62     strcpy(data[1], "2005-04-11_13:00:00");
63 
64     cmode = NC_CLOBBER;
65     err  = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid); ERR
66 
67     err = ncmpi_def_dim(ncid, "time", NC_UNLIMITED, dimids); ERR
68     err = ncmpi_def_dim(ncid, "text_dim", STR_LEN, &dimids[1]); ERR
69 
70     /* create ONLY one record variable of type NC_CHAR and make sure each
71      * record is of size not aligned with 4-byte boundary.
72      */
73     err = ncmpi_def_var(ncid, "text_var", NC_CHAR, 2, dimids, &varid); ERR
74     err = ncmpi_enddef(ncid); ERR
75 
76     /* Write some records of var data. */
77     count[0] = 1;
78     count[1] = STR_LEN;
79     start[0] = 0;
80     start[1] = 0;
81     for (i=0; i<NUM_VALS; i++) {
82         err = ncmpi_put_vara_text_all(ncid, varid, start, count, data[start[0]]);
83         ERR
84         start[0]++;
85     }
86 
87     /* read the entire data back */
88     err = ncmpi_get_var_text_all(ncid, varid, data_in); ERR
89 
90     /* check the contents */
91     for (i=0; i<NUM_VALS; i++)
92       if (strncmp(data[i], data_in+i*STR_LEN, STR_LEN)) {
93           printf("Error: expecting %s but got %s\n", data[i],data_in+i*STR_LEN);
94           nerrs++;
95       }
96 
97     err = ncmpi_close(ncid);
98     ERR
99 
100     /* check if PnetCDF freed all internal malloc */
101     MPI_Offset malloc_size, sum_size;
102     err = ncmpi_inq_malloc_size(&malloc_size);
103     if (err == NC_NOERR) {
104         MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
105         if (rank == 0 && sum_size > 0)
106             printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
107                    sum_size);
108     }
109 
110     MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
111     if (rank == 0) {
112         if (nerrs) printf(FAIL_STR,nerrs);
113         else       printf(PASS_STR);
114     }
115 
116     MPI_Finalize();
117 
118     return nerrs;
119 }
120 
121