Skip to content

Commit ce0fe3e

Browse files
committed
tst_multi_redefine.c tests entering define mode multiple times
1 parent f3a6ab1 commit ce0fe3e

File tree

2 files changed

+257
-1
lines changed

2 files changed

+257
-1
lines changed

test/testcases/Makefile.am

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,8 @@ TESTPROGRAMS = file_create_open \
9999
tst_del_attr \
100100
tst_redefine \
101101
tst_grow_header \
102-
tst_varn_var1
102+
tst_varn_var1 \
103+
tst_multi_redefine
103104

104105
M4_SRCS = put_all_kinds.m4 \
105106
erange_fill.m4 \
Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
/*
2+
* Copyright (C) 2025, Northwestern University and Argonne National Laboratory
3+
* See COPYRIGHT notice in top-level directory.
4+
*
5+
*/
6+
7+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
8+
*
9+
* This program tests entering define modes multiple times.
10+
*
11+
* The compile and run commands are given below.
12+
*
13+
* % mpicc -g -o tst_multi_redefine tst_multi_redefine.c -lpnetcdf
14+
*
15+
* % mpiexec -l -n 4 ./tst_multi_redefine testfile.nc
16+
*
17+
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
18+
19+
#include <stdio.h>
20+
#include <stdlib.h>
21+
#include <string.h>
22+
#include <strings.h> /* strcasecmp() */
23+
#include <libgen.h> /* basename() */
24+
#include <unistd.h> /* getopt() */
25+
26+
#include <pnetcdf.h>
27+
28+
#include <testutils.h>
29+
30+
#define NROUNDS 2
31+
#define NY 10
32+
#define NX 10
33+
#define NVARS 2
34+
35+
static int verbose;
36+
37+
static int
38+
tst_fmt(char *filename,
39+
int cmode,
40+
int nRounds,
41+
int len_y,
42+
int len_x)
43+
{
44+
int i, j, k, rank, nprocs, ncid, err, nerrs=0, dimids[3];
45+
MPI_Offset old_hdr_size, new_hdr_size;
46+
MPI_Offset old_hdr_ext, new_hdr_ext;
47+
48+
MPI_Info info=MPI_INFO_NULL;
49+
50+
MPI_Comm comm = MPI_COMM_WORLD;
51+
52+
MPI_Comm_rank(comm, &rank);
53+
MPI_Comm_size(comm, &nprocs);
54+
55+
if (verbose && rank == 0) {
56+
char *fmt;
57+
if (cmode == 0)
58+
fmt = "NC_CLASSIC";
59+
else if (cmode == NC_64BIT_OFFSET)
60+
fmt = "NC_64BIT_OFFSET";
61+
else if (cmode == NC_64BIT_DATA)
62+
fmt = "NC_64BIT_DATA";
63+
printf("\n---- Testing file format %s ----\n", fmt);
64+
}
65+
66+
/* create a new file */
67+
cmode |= NC_CLOBBER;
68+
err = ncmpi_create(comm, filename, cmode, info, &ncid); CHECK_ERROUT
69+
70+
err = ncmpi_def_dim(ncid, "time", NC_UNLIMITED, &dimids[0]); CHECK_ERROUT
71+
err = ncmpi_def_dim(ncid, "Y", len_y, &dimids[1]); CHECK_ERROUT
72+
err = ncmpi_def_dim(ncid, "X", len_x*nprocs, &dimids[2]); CHECK_ERROUT
73+
74+
/* Default v_align of 512 is pretty bad choice, as almost every iteration
75+
* grows the file extension.
76+
*/
77+
// err = ncmpi__enddef(ncid, 0, 4096, 0, 0);
78+
err = ncmpi_enddef(ncid);
79+
CHECK_ERROUT
80+
81+
err = ncmpi_inq_header_size(ncid, &old_hdr_size); CHECK_ERROUT
82+
err = ncmpi_inq_header_extent(ncid, &old_hdr_ext); CHECK_ERROUT
83+
if (verbose && rank == 0)
84+
printf("Newly created file with header size %lld, extension %lld\n",
85+
old_hdr_size, old_hdr_ext);
86+
87+
k = 0;
88+
for (i=0; i<nRounds; i++) {
89+
char str[64];
90+
int *fix_varids, *rec_varids;
91+
92+
fix_varids = (int*) malloc(sizeof(int) * NVARS);
93+
rec_varids = (int*) malloc(sizeof(int) * NVARS);
94+
95+
err = ncmpi_redef(ncid); CHECK_ERROUT
96+
97+
/* add new fix-sized variables */
98+
for (j=0; j<NVARS; j++) {
99+
sprintf(str, "fix_var_%d", k);
100+
err = ncmpi_def_var(ncid, str, NC_DOUBLE, 2, dimids+1, &fix_varids[j]);
101+
CHECK_ERROUT
102+
sprintf(str, "attribute of variable %d", k);
103+
err = ncmpi_put_att_text(ncid, fix_varids[j], "attr", strlen(str), str); CHECK_ERROUT
104+
k++;
105+
}
106+
107+
/* add new record variables */
108+
for (j=0; j<NVARS; j++) {
109+
sprintf(str, "rec_var_%d", k);
110+
err = ncmpi_def_var(ncid, str, NC_DOUBLE, 3, dimids, &rec_varids[j]);
111+
CHECK_ERROUT
112+
sprintf(str, "attribute of variable %d", k);
113+
err = ncmpi_put_att_text(ncid, rec_varids[j], "attr", strlen(str), str); CHECK_ERROUT
114+
k++;
115+
}
116+
117+
err = ncmpi_enddef(ncid); CHECK_ERROUT
118+
err = ncmpi_inq_header_size(ncid, &new_hdr_size); CHECK_ERROUT
119+
err = ncmpi_inq_header_extent(ncid, &new_hdr_ext); CHECK_ERROUT
120+
if (verbose && rank == 0) {
121+
printf("Iternation %d: file header size grows from %lld to %lld\n",
122+
i, old_hdr_size, new_hdr_size);
123+
if (new_hdr_ext > old_hdr_ext)
124+
printf("Iternation %d: file header extension grows from %lld to %lld\n",
125+
i, old_hdr_ext, new_hdr_ext);
126+
}
127+
old_hdr_size = new_hdr_size;
128+
old_hdr_ext = new_hdr_ext;
129+
130+
/* write to new variables */
131+
MPI_Offset start[3], count[3];
132+
start[0] = 0;
133+
start[1] = 0;
134+
start[2] = rank * len_x;
135+
count[0] = 1;
136+
count[1] = len_y;
137+
count[2] = len_x;
138+
139+
/* write to fix-sized variables */
140+
int *int_buf = (int*) malloc(sizeof(int) * count[0] * count[1]);
141+
for (j=0; j<count[0] * count[1]; j++) int_buf[j] = rank + j;
142+
143+
for (j=0; j<NVARS; j++) {
144+
err = ncmpi_put_vara_int_all(ncid, fix_varids[j], start+1, count+1, int_buf);
145+
CHECK_ERROUT
146+
}
147+
free(int_buf);
148+
149+
/* write to record variables */
150+
double *dbl_buf = (double*) malloc(sizeof(double) * count[0] * count[1]);
151+
for (j=0; j<count[0] * count[1]; j++) dbl_buf[j] = rank + j;
152+
153+
for (j=0; j<NVARS; j++) {
154+
err = ncmpi_put_vara_double_all(ncid, rec_varids[j], start, count, dbl_buf);
155+
CHECK_ERROUT
156+
}
157+
free(dbl_buf);
158+
159+
free(fix_varids);
160+
free(rec_varids);
161+
}
162+
163+
err = ncmpi_close(ncid); CHECK_ERROUT
164+
165+
err_out:
166+
if (info != MPI_INFO_NULL) MPI_Info_free(&info);
167+
168+
return nerrs;
169+
}
170+
171+
#define FILE_NAME "testfile.nc"
172+
173+
static void
174+
usage(char *argv0)
175+
{
176+
char *help =
177+
"Usage: %s [OPTIONS]...[filename]\n"
178+
" [-h] Print help\n"
179+
" [-v]: enable verbose output mode (default: no)\n"
180+
" [-n num]: number of rounds entering define mode (default: %d)\n"
181+
" [-y num]: Y dimension size of global array (default: %d)\n"
182+
" [-x num]: X dimension size of local array (default: %d)\n"
183+
" [filename]: output netCDF file name (default: %s)\n";
184+
fprintf(stderr, help, argv0, FILE_NAME, NROUNDS, NY, NX);
185+
}
186+
187+
int main(int argc, char** argv)
188+
{
189+
extern int optind;
190+
extern char *optarg;
191+
char filename[256];
192+
int i, fmt, rank, err, nerrs=0, cmode[3], nRounds, len_y, len_x;
193+
194+
MPI_Init(&argc, &argv);
195+
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
196+
197+
verbose = 0;
198+
nRounds = NROUNDS;
199+
len_y = NY;
200+
len_x = NX;
201+
while ((i = getopt(argc, argv, "hvn:y:x:")) != EOF)
202+
switch(i) {
203+
case 'v': verbose = 1;
204+
break;
205+
case 'n': nRounds = atoi(optarg);
206+
break;
207+
case 'y': len_y = atoi(optarg);
208+
break;
209+
case 'x': len_x = atoi(optarg);
210+
break;
211+
case 'h':
212+
default: if (rank==0) usage(argv[0]);
213+
MPI_Finalize();
214+
return 1;
215+
}
216+
if (argv[optind] == NULL) strcpy(filename, FILE_NAME);
217+
else snprintf(filename, 256, "%s", argv[optind]);
218+
219+
if (rank == 0) {
220+
char *cmd_str = (char*)malloc(strlen(argv[0]) + 256);
221+
sprintf(cmd_str, "*** TESTING C %s for entering define mode ", basename(argv[0]));
222+
printf("%-66s ------ ", cmd_str); fflush(stdout);
223+
free(cmd_str);
224+
}
225+
cmode[0] = 0;
226+
cmode[1] = NC_64BIT_OFFSET;
227+
cmode[2] = NC_64BIT_DATA;
228+
229+
for (fmt=0; fmt<3; fmt++) {
230+
nerrs += tst_fmt(filename, cmode[fmt], nRounds, len_y, len_x);
231+
if (nerrs > 0) goto err_out;
232+
}
233+
234+
/* check if PnetCDF freed all internal malloc */
235+
MPI_Offset malloc_size, sum_size;
236+
err = ncmpi_inq_malloc_size(&malloc_size);
237+
if (err == NC_NOERR) {
238+
MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
239+
if (rank == 0 && sum_size > 0)
240+
printf("heap memory allocated by PnetCDF internally has "OFFFMT" bytes yet to be freed\n",
241+
sum_size);
242+
if (malloc_size > 0) ncmpi_inq_malloc_list();
243+
}
244+
245+
err_out:
246+
MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
247+
if (rank == 0) {
248+
if (nerrs) printf(FAIL_STR,nerrs);
249+
else printf(PASS_STR);
250+
}
251+
252+
MPI_Finalize();
253+
return (nerrs > 0);
254+
}
255+

0 commit comments

Comments
 (0)