1 /*
2 Copyright 2011, UCAR/Unidata
3 See COPYRIGHT file for copying and redistribution conditions.
4
5 This is part of netCDF.
6
7 This program tests for a bug discovered with nofill mode that failed
8 only on file systems with block size in a particular range. It fails
9 when invoked with the blksize argument between 2091953 and 2150032,
10 inclusive, and succeeds for other blksizes.
11 */
12
13 #include <config.h>
14 #include <nc_tests.h>
15 #include "err_macros.h"
16 #include <stdio.h>
17 #include <limits.h>
18 #include <stdlib.h>
19 #include <errno.h>
20 #include <netcdf.h>
21
22 #define FILE_NAME "tst_nofill2.nc"
23 #define LON_LEN 240
24 #define LAT_LEN 121
25 #define LVL_LEN 31
26 #define TIME_LEN 1
27 #define NDIMS1 1
28 #define NDIMS4 4
29
30 int
create_file(char * file_name,int fill_mode,size_t * sizehintp)31 create_file(char *file_name, int fill_mode, size_t* sizehintp)
32 {
33 int ncid, time_id, zonal_wnd_id;
34 int dimids[NDIMS4];
35 size_t start[NDIMS4] = {0, 0, 0, 0};
36 size_t count[NDIMS4] = {TIME_LEN, 1, LAT_LEN, LON_LEN};
37 float zonal_wnd[LON_LEN * LAT_LEN * TIME_LEN];
38 size_t default_initialsize = 0;
39 double time[TIME_LEN] = {1.};
40 int i;
41
42 /* Init data. */
43 for(i = 0; i < TIME_LEN * LAT_LEN * LON_LEN; i++)
44 zonal_wnd[i] = 100 + i;
45
46 /* To test bug on filesystem without large block size, we can get
47 * the same effect by providing the desired value as sizehint to
48 * nc__create() instead of calling nc_create() and getting the
49 * block size reported by fstat */
50 if (nc__create(file_name, NC_CLOBBER, default_initialsize, sizehintp, &ncid)) ERR;
51 if (nc_set_fill(ncid, fill_mode, NULL)) ERR;
52
53 /* define dimensions */
54 if (nc_def_dim(ncid, "lon", LON_LEN, &dimids[3])) ERR;
55 if (nc_def_dim(ncid, "lat", LAT_LEN, &dimids[2])) ERR;
56 if (nc_def_dim(ncid, "lvl", LVL_LEN, &dimids[1])) ERR;
57 if (nc_def_dim(ncid, "time", TIME_LEN, &dimids[0])) ERR;
58
59 /* define variables */
60 if (nc_def_var(ncid, "time", NC_DOUBLE, NDIMS1, &dimids[0], &time_id)) ERR;
61 if (nc_def_var(ncid, "zonal_wnd", NC_FLOAT, NDIMS4, dimids, &zonal_wnd_id)) ERR;
62
63 if (nc_enddef (ncid)) ERR;
64 if (nc_put_var_double(ncid, time_id, time)) ERR;
65
66 /* Bug exposed when written in reverse order. */
67 for(i = LVL_LEN - 1; i>=0; i--)
68 {
69 start[1] = i;
70 if (nc_put_vara_float(ncid, zonal_wnd_id, start, count, zonal_wnd)) ERR;
71 }
72 if (nc_close(ncid)) ERR;
73 return 0;
74 }
75
76 int
main(int argc,char ** argv)77 main(int argc, char **argv)
78 {
79 size_t sizehint = (1750000); /* default if not set on command line,
80 * exposes bug. It turns out any
81 * value between 2091953 and 2150032
82 * triggers bug, whereas all other
83 * values work fine. */
84
85 printf("\n*** Testing nofill mode.\n");
86 printf("*** Create file in nofill mode, writing all values...");
87 {
88 #define NUM_TRIES 1
89 int ncid;
90 size_t idx[1] = {0};
91 double data;
92 int i;
93
94 for (i = 0; i < NUM_TRIES; i++)
95 {
96 printf(", trying sizehint of %lu ...", (unsigned long)sizehint);
97 if (create_file(FILE_NAME, NC_NOFILL, &sizehint)) ERR;
98 if (nc_open(FILE_NAME, 0, &ncid)) ERR;
99 if (nc_get_var1(ncid, 0, idx, &data)) ERR;
100 if (!data) ERR;
101 if (nc_close(ncid)) ERR;
102 sizehint += 10000;
103 }
104 }
105 SUMMARIZE_ERR;
106 FINAL_RESULTS;
107 }
108