1 /*
2   Copyright 2004-2006, UCAR/Unidata
3   See COPYRIGHT file for copying and redistribution conditions.
4 
5   This is part of netCDF.
6 
7   This program also takes a long time to run - it writes some data in
8   a very large file, and then reads it all back to be sure it's
9   correct.
10 
11   This program is an add-on test to check very large 64-bit offset
12   files (8 GB, so make sure you have the disk space!).
13 
14   Ed Hartnett, Ward Fisher
15 */
16 
17 #include <config.h>
18 #include <nc_tests.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <netcdf.h>
22 
23 #define FILE_NAME "large_files.nc"
24 #define NUMRECS 2
25 #define I_LEN 4106
26 #define J_LEN 1023
27 #define K_LEN 1023
28 #define N_LEN 2
29 
30 static void
check_err(const int stat,const int line,const char * file)31 check_err(const int stat, const int line, const char *file) {
32     if (stat != NC_NOERR) {
33 	   (void) fprintf(stderr, "line %d of %s: %s\n", line, file, nc_strerror(stat));
34         exit(1);
35     }
36 }
37 
38 int
main(int argc,char ** argv)39 main(int argc, char **argv) {
40 
41    int  stat;			/* return status */
42    char file_name[NC_MAX_NAME + 1];
43    int  ncid;			/* netCDF id */
44    int rec, i, j;
45    int x[] = {42, 21};
46 
47    /* dimension ids */
48    int rec_dim;
49    int i_dim;
50    int j_dim;
51    int k_dim;
52    int n_dim;
53 
54    /* dimension lengths */
55    size_t rec_len = NC_UNLIMITED;
56    size_t i_len = I_LEN;
57    size_t j_len = J_LEN;
58    size_t k_len = K_LEN;
59    size_t n_len = N_LEN;
60 
61    /* variable ids */
62    int var1_id;
63    int x_id;
64 
65    /* rank (number of dimensions) for each variable */
66 #  define RANK_var1 3
67 #  define RANK_x 2
68 
69    /* variable shapes */
70    int var1_dims[RANK_var1];
71    int x_dims[RANK_x];
72 
73     printf("\n*** Testing large files, slowly.\n");
74 
75     sprintf(file_name, "%s/%s", TEMP_LARGE, FILE_NAME);
76     printf("*** Creating large file %s...", file_name);
77 
78    /* enter define mode */
79    stat = nc_create(file_name, NC_CLOBBER|NC_64BIT_OFFSET, &ncid);
80    check_err(stat,__LINE__,__FILE__);
81 
82    /* define dimensions */
83    stat = nc_def_dim(ncid, "rec", rec_len, &rec_dim);
84    check_err(stat,__LINE__,__FILE__);
85    stat = nc_def_dim(ncid, "i", i_len, &i_dim);
86    check_err(stat,__LINE__,__FILE__);
87    stat = nc_def_dim(ncid, "j", j_len, &j_dim);
88    check_err(stat,__LINE__,__FILE__);
89    stat = nc_def_dim(ncid, "k", k_len, &k_dim);
90    check_err(stat,__LINE__,__FILE__);
91    stat = nc_def_dim(ncid, "n", n_len, &n_dim);
92    check_err(stat,__LINE__,__FILE__);
93 
94    /* define variables */
95 
96    x_dims[0] = rec_dim;
97    x_dims[1] = n_dim;
98    stat = nc_def_var(ncid, "x", NC_INT, RANK_x, x_dims, &x_id);
99    check_err(stat,__LINE__,__FILE__);
100 
101    var1_dims[0] = rec_dim;
102    var1_dims[1] = i_dim;
103    var1_dims[2] = j_dim;
104    /*var1_dims[3] = k_dim;*/
105    stat = nc_def_var(ncid, "var1", NC_FLOAT, RANK_var1, var1_dims, &var1_id);
106    check_err(stat,__LINE__,__FILE__);
107 
108    /* don't initialize variables with fill values */
109    stat = nc_set_fill(ncid, NC_NOFILL, 0);
110    check_err(stat,__LINE__,__FILE__);
111 
112    /* leave define mode */
113    stat = nc_enddef (ncid);
114    check_err(stat,__LINE__,__FILE__);
115 
116    {			/* store var1 */
117      /*static float var1[J_LEN];*/
118      static float *var1 = NULL;
119      var1 = malloc(sizeof(float)*J_LEN);
120      if(!var1) {
121        printf("Malloc failed.  This may happen on systems with < 4GB. THIS TEST DID NOT PASS, but is returning 0.\n");
122        return 0;
123      }
124      static size_t var1_start[RANK_var1] = {0, 0, 0};
125      static size_t var1_count[RANK_var1] = {1, 1, J_LEN};
126      static size_t x_start[RANK_x] = {0, 0};
127      static size_t x_count[RANK_x] = {1, N_LEN};
128      for(rec=0; rec<NUMRECS; rec++) {
129        var1_start[0] = rec;
130        x_start[0] = rec;
131        for(i=0; i<I_LEN; i++) {
132          for(j=0; j<J_LEN; j++) {
133            var1[j] = (float)(j + (rec+1) * i);
134          }
135          var1_start[1] = i;
136          stat = nc_put_vara_float(ncid, var1_id, var1_start, var1_count, var1);
137          check_err(stat,__LINE__,__FILE__);
138        }
139        x[0] += rec; x[1] += rec;
140        stat = nc_put_vara_int(ncid, x_id, x_start, x_count, x);
141        check_err(stat,__LINE__,__FILE__);
142      }
143      free(var1);
144    }
145 
146    stat = nc_close(ncid);
147    check_err(stat,__LINE__,__FILE__);
148 
149    printf("ok\n");
150    printf("*** Reading large file %s...", file_name);
151 
152    stat = nc_open(file_name, NC_NOWRITE, &ncid);
153    check_err(stat,__LINE__,__FILE__);
154 
155    {			/* read var1 */
156 
157      /*static float avar1[J_LEN];*/
158      static float *avar1 = NULL;
159      avar1 = (float*)malloc(sizeof(float)*J_LEN);
160      static size_t avar1_start[RANK_var1] = {0, 0, 0};
161      static size_t avar1_count[RANK_var1] = {1, 1, J_LEN};
162      static size_t ax_start[RANK_x] = {0, 0};
163      static size_t ax_count[RANK_x] = {1, N_LEN};
164      for(rec=0; rec<NUMRECS; rec++) {
165        avar1_start[0] = rec;
166        ax_start[0] = rec;
167        for(i=0; i<I_LEN; i++) {
168          avar1_start[1] = i;
169          stat = nc_get_vara_float(ncid, var1_id, avar1_start, avar1_count, avar1);
170          check_err(stat,__LINE__,__FILE__);
171          for(j=0; j<J_LEN; j++)
172          {
173            if (avar1[j] != (float)(j + (rec + 1) * i)) {
174              printf("Error on read, var1[%d, %d, %d] = %g wrong, "
175                     "should be %g !\n", rec, i, j, avar1[j], (float) (j + (rec + 1)* i));
176              return 1;
177            }
178          }
179        }
180        nc_get_vara_int(ncid, x_id, ax_start, ax_count, x);
181        if(x[0] != (42 + rec) || x[1] != (21+rec)) {
182          printf("Error on read, x[] = %d, %d\n", x[0], x[1]);
183          return 1;
184        }
185      }
186      free(avar1);
187    }
188    stat = nc_close(ncid);
189    check_err(stat,__LINE__,__FILE__);
190 
191    printf("ok\n");
192    printf("*** Tests successful!\n");
193 
194    /* Delete the file. */
195    (void) remove(file_name);
196 
197    return 0;
198 }
199