1 /*********************************************************************
2  *
3  *  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
4  *  See COPYRIGHT notice in top-level directory.
5  *
6  *********************************************************************/
7 /*  $Id: test_bput.c 2744 2016-12-28 16:25:22Z wkliao $ */
8 
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <libgen.h> /* basename() */
13 #include <assert.h>
14 #include <pnetcdf.h>
15 
16 #include <testutils.h>
17 
18 #define FILE_NAME "testfile.nc"
19 
20 #define ERR if (err!=NC_NOERR) {printf("Error at line %d: err=%d %s\n", __LINE__, err, ncmpi_strerror(err)); nerrs++;}
21 
22 /*----< main() >------------------------------------------------------------*/
main(int argc,char ** argv)23 int main(int argc, char **argv) {
24     int i, j, ncid, dimid[2], varid, err, nerrs=0, rank, nprocs;
25     int req[2], status[2];
26     float  var[4][6];
27     char filename[256];
28     MPI_Offset bufsize,  start[2], count[2], stride[2], imap[2];
29     MPI_Info info;
30 
31     MPI_Init(&argc, &argv);
32     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
33     MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
34 
35 #ifdef DEBUG
36     if (nprocs > 1 && rank == 0)
37         printf("Warning: %s is designed to run on 1 process\n", argv[0]);
38 #endif
39 
40     if (argc > 2) {
41         if (!rank) printf("Usage: %s [filename]\n",argv[0]);
42         MPI_Finalize();
43         return 0;
44     }
45     if (argc == 2) snprintf(filename, 256, "%s", argv[1]);
46     else           strcpy(filename, "testfile.nc");
47 
48     if (rank == 0) {
49         char *cmd_str = (char*)malloc(strlen(argv[0]) + 256);
50         sprintf(cmd_str, "*** TESTING C   %s for bput API ", basename(argv[0]));
51         printf("%-66s ------ ", cmd_str);
52         free(cmd_str);
53     }
54 
55     MPI_Info_create(&info);
56     /* MPI_Info_set(info, "romio_pvfs2_posix_write","enable"); */
57 
58     err = ncmpi_create(MPI_COMM_WORLD, filename, NC_CLOBBER | NC_64BIT_DATA, info, &ncid); ERR
59     MPI_Info_free(&info);
60 
61     /* define a variable of a 6 x 4 integer array in the nc file */
62     err = ncmpi_def_dim(ncid, "Y", 6, &dimid[0]); ERR
63     err = ncmpi_def_dim(ncid, "X", 4, &dimid[1]); ERR
64     err = ncmpi_def_var(ncid, "var", NC_INT64, 2, dimid, &varid); ERR
65     err = ncmpi_enddef(ncid); ERR
66 
67     /* set the contents of the write buffer var, a 4 x 6 float array
68           50, 51, 52, 53, 54, 55,
69           56, 57, 58, 59, 60, 61,
70           62, 63, 64, 65, 66, 67,
71           68, 69, 70, 71, 72, 73
72      */
73     for (j=0; j<4; j++) for (i=0; i<6; i++) var[j][i] = 50.5 + j*6+i;
74 
75     /* bufsize must be max of data type converted before and after */
76     bufsize = 4*6*sizeof(long long);
77     err = ncmpi_buffer_attach(ncid, bufsize); ERR
78 
79     /* write var to the NC variable in the matrix transposed way */
80     count[0]  = 6; count[1]  = 2;
81     stride[0] = 1; stride[1] = 1;
82     imap[0]   = 1; imap[1]   = 6;   /* would be {4, 1} if not transposing */
83 
84     if (rank > 0) /* non-root processes just participate the call */
85         count[0] = count[1] = 0;
86 
87     /* write the first two columns of the NC variable in the matrix transposed way */
88     start[0]  = 0; start[1]  = 0;
89     err = ncmpi_bput_varm_float(ncid, varid, start, count, stride, imap, &var[0][0], &req[0]); ERR
90 
91     /* check if write buffer contents have been altered */
92     for (j=0; j<4; j++)
93         for (i=0; i<6; i++) {
94             if (var[j][i] != 50.5 + j*6+i) {
95                 printf("Error: put buffer[%d][%d]=%f altered, should be %f\n",
96                        j,i,var[j][i],50.5+j*6+i);
97                 nerrs++;
98             }
99         }
100 
101     /* write the second two columns of the NC variable in the matrix transposed way */
102     start[0]  = 0; start[1]  = 2;
103     err = ncmpi_bput_varm_float(ncid, varid, start, count, stride, imap, &var[2][0], &req[1]); ERR
104 
105     /* check if write buffer contents have been altered */
106     for (j=0; j<4; j++)
107         for (i=0; i<6; i++) {
108             if (var[j][i] != 50.5 + j*6+i) {
109                 printf("Error: put buffer[%d][%d]=%f altered, should be %f\n",
110                        j,i,var[j][i],50.5+j*6+i);
111                 nerrs++;
112             }
113         }
114 
115     err = ncmpi_wait_all(ncid, 2, req, status); ERR
116 
117     /* check each bput status */
118     for (i=0; i<2; i++)
119         if (status[i] != NC_NOERR) {
120             printf("Error at line %d: err=%d %s\n", __LINE__, status[i], ncmpi_strerror(err));
121             nerrs++;
122         }
123 
124     err = ncmpi_buffer_detach(ncid); ERR
125 
126     /* the output from command "ncmpidump -v var test.nc" should be:
127            var =
128             50, 56, 62, 68,
129             51, 57, 63, 69,
130             52, 58, 64, 70,
131             53, 59, 65, 71,
132             54, 60, 66, 72,
133             55, 61, 67, 73 ;
134      */
135 
136     /* check if the contents of write buffer have been altered (should not be) */
137     for (j=0; j<4; j++) {
138         for (i=0; i<6; i++) {
139             if (var[j][i] != 50.5+j*6+i) {
140                 /* this error is a pntecdf internal error, if occurs */
141                 printf("Error: put buffer[%d][%d]=%f altered, should be %f\n",
142                        j,i,var[j][i],50.5+j*6+i);
143                 nerrs++;
144                 break;
145             }
146         }
147     }
148     err = ncmpi_close(ncid); ERR
149 
150     /* check if PnetCDF freed all internal malloc */
151     MPI_Offset malloc_size, sum_size;
152     err = ncmpi_inq_malloc_size(&malloc_size);
153     if (err == NC_NOERR) {
154         MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
155         if (rank == 0 && sum_size > 0)
156             printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
157                    sum_size);
158     }
159 
160     MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
161     if (rank == 0) {
162         if (nerrs) printf(FAIL_STR,nerrs);
163         else       printf(PASS_STR);
164     }
165 
166     MPI_Finalize();
167 
168     return nerrs;
169 }
170 
171