source: XIOS/dev/dev_ym/XIOS_SERVICES/extern/src_netcdf4/nc4dim.c @ 2325

Last change on this file since 2325 was 409, checked in by ymipsl, 12 years ago

Add improved nectdf internal library src

YM

  • Property svn:eol-style set to native
File size: 10.4 KB
Line 
1/*
2
3This file is part of netcdf-4, a netCDF-like interface for HDF5, or a
4HDF5 backend for netCDF, depending on your point of view.
5
6This file handles the nc4 dimension functions.
7
8Copyright 2003-5, University Corporation for Atmospheric Research. See
9the COPYRIGHT file for copying and redistribution conditions.
10
11$Id: nc4dim.c,v 1.41 2010/05/25 17:54:23 dmh Exp $
12*/
13
14#include "nc4internal.h"
15
16#ifdef USE_PNETCDF
17#include <pnetcdf.h>
18#endif
19
20/* Netcdf-4 files might have more than one unlimited dimension, but
21   return the first one anyway. */
22/* Note that this code is inconsistent with nc_inq */
23int 
24NC4_inq_unlimdim(int ncid, int *unlimdimidp)
25{
26   NC_FILE_INFO_T *nc;
27   NC_GRP_INFO_T *grp, *g;
28   NC_HDF5_FILE_INFO_T *h5;
29   NC_DIM_INFO_T *dim;
30   int found = 0;
31   int retval;
32 
33   LOG((2, "called nc_inq_unlimdim"));
34
35   if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
36      return retval;
37
38#ifdef USE_PNETCDF
39   /* Take care of files created/opened with parallel-netcdf library. */
40   if (nc->pnetcdf_file)
41      return ncmpi_inq_unlimdim(nc->int_ncid, unlimdimidp);
42#endif /* USE_PNETCDF */
43
44   /* Take care of netcdf-3 files. */
45   assert(h5);
46
47   /* According to netcdf-3 manual, return -1 if there is no unlimited
48      dimension. */
49   *unlimdimidp = -1;
50   for (g = grp; g && !found; g = g->parent)
51   {
52      for (dim = g->dim; dim; dim = dim->next)
53      {
54         if (dim->unlimited)
55         {
56            *unlimdimidp = dim->dimid;
57            found++;
58            break;
59         }
60      }
61   }
62
63   return NC_NOERR;
64}
65
66/* Dimensions are defined in attributes attached to the appropriate
67   group in the data file. */
68int
69NC4_def_dim(int ncid, const char *name, size_t len, int *idp)
70{
71   NC_FILE_INFO_T *nc;
72   NC_GRP_INFO_T *grp;
73   NC_HDF5_FILE_INFO_T *h5;
74   NC_DIM_INFO_T *dim;
75   char norm_name[NC_MAX_NAME + 1];
76   int retval = NC_NOERR;
77
78   LOG((2, "nc_def_dim: ncid 0x%x name %s len %d", ncid, name, 
79        (int)len));
80
81   /* Find our global metadata structure. */
82   if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
83      return retval;
84   
85#ifdef USE_PNETCDF
86   /* Take care of files created/opened with parallel-netcdf library. */
87   if (nc->pnetcdf_file)
88      return ncmpi_def_dim(nc->int_ncid, name, len, idp);
89#endif /* USE_PNETCDF */
90
91   /* Take care of netcdf-3 files. */
92   assert(h5);
93
94   assert(h5 && nc && grp);
95
96   /* If the file is read-only, return an error. */
97   if (h5->no_write)
98     return NC_EPERM;
99
100   /* Check some stuff if strict nc3 rules are in effect. */
101   if (h5->cmode & NC_CLASSIC_MODEL)
102   {
103      /* Only one limited dimenson for strict nc3. */
104      if (len == NC_UNLIMITED)
105         for (dim = grp->dim; dim; dim = dim->next)
106            if (dim->unlimited)
107               return NC_EUNLIMIT;
108
109      /* Must be in define mode for stict nc3. */
110      if (!(h5->flags & NC_INDEF))
111         return NC_ENOTINDEFINE;
112   }   
113
114   /* If it's not in define mode, enter define mode. */
115   if (!(h5->flags & NC_INDEF))
116      if ((retval = nc_redef(ncid)))
117         return retval;
118
119   /* Make sure this is a valid netcdf name. */
120   if ((retval = nc4_check_name(name, norm_name)))
121      return retval;
122
123   /* For classic model: dim length has to fit in a 32-bit unsigned
124    * int, as permitted for 64-bit offset format. */
125   if (h5->cmode & NC_CLASSIC_MODEL)
126      if(len > X_UINT_MAX) /* Backward compat */
127         return NC_EDIMSIZE;
128
129   /* Make sure the name is not already in use. */
130   for (dim = grp->dim; dim; dim = dim->next)
131      if (!strncmp(dim->name, norm_name, NC_MAX_NAME))
132         return NC_ENAMEINUSE;
133
134   /* Add a dimension to the list. The ID must come from the file
135    * information, since dimids are visible in more than one group. */
136   nc4_dim_list_add(&grp->dim);
137   grp->dim->dimid = grp->file->nc4_info->next_dimid++;
138
139   /* Initialize the metadata for this dimension. */
140   if (!(grp->dim->name = malloc((strlen(norm_name) + 1) * sizeof(char))))
141      return NC_ENOMEM;
142   strcpy(grp->dim->name, norm_name);
143   grp->dim->len = len;
144   grp->dim->dirty++;
145   if (len == NC_UNLIMITED)
146      grp->dim->unlimited++;
147
148   /* Pass back the dimid. */
149   if (idp)
150      *idp = grp->dim->dimid;
151
152   return retval;
153}
154
155/* Given dim name, find its id. */
156int
157NC4_inq_dimid(int ncid, const char *name, int *idp)
158{
159   NC_FILE_INFO_T *nc;
160   NC_GRP_INFO_T *grp, *g;
161   NC_HDF5_FILE_INFO_T *h5;
162   NC_DIM_INFO_T *dim;
163   char norm_name[NC_MAX_NAME + 1];
164   int finished = 0;
165   int retval;
166
167   LOG((2, "nc_inq_dimid: ncid 0x%x name %s", ncid, name));
168
169   /* Find metadata for this file. */
170   if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
171      return retval;
172
173#ifdef USE_PNETCDF
174   /* Take care of files created/opened with parallel-netcdf library. */
175   if (nc->pnetcdf_file)
176      return ncmpi_inq_dimid(nc->int_ncid, name, idp);
177#endif /* USE_PNETCDF */
178
179   /* Handle netcdf-3 files. */
180   assert(h5);
181
182   assert(nc && grp);
183
184   /* Normalize name. */
185   if ((retval = nc4_normalize_name(name, norm_name)))
186      return retval;
187
188   /* Go through each dim and check for a name match. */
189   for (g = grp; g && !finished; g = g->parent)
190      for (dim = g->dim; dim; dim = dim->next)
191         if (!strncmp(dim->name, norm_name, NC_MAX_NAME))
192         {
193            if (idp)
194               *idp = dim->dimid;
195            return NC_NOERR;
196         }
197
198   return NC_EBADDIM;
199}
200
201/* Find out name and len of a dim. For an unlimited dimension, the
202   length is the largest lenght so far written. If the name of lenp
203   pointers are NULL, they will be ignored. */
204int
205NC4_inq_dim(int ncid, int dimid, char *name, size_t *lenp)
206{
207   NC_FILE_INFO_T *nc;
208   NC_HDF5_FILE_INFO_T *h5;
209   NC_GRP_INFO_T *grp, *dim_grp;
210   NC_DIM_INFO_T *dim;
211   int ret = NC_NOERR;
212
213   LOG((2, "nc_inq_dim: ncid 0x%x dimid %d", ncid, dimid));
214
215   /* Find our global metadata structure. */
216   if ((ret = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
217      return ret;
218   
219#ifdef USE_PNETCDF
220   /* Take care of files created/opened with parallel-netcdf library. */
221   if (nc->pnetcdf_file)
222   {
223      MPI_Offset mpi_len;
224      if ((ret = ncmpi_inq_dim(nc->int_ncid, dimid, name, &mpi_len)))
225         return ret;
226      if (lenp)
227         *lenp = mpi_len;
228   }
229#endif /* USE_PNETCDF */
230
231   /* Take care of netcdf-3 files. */
232   assert(h5);
233   
234   assert(nc && grp);
235
236   /* Find the dimension and its home group. */
237   if ((ret = nc4_find_dim(grp, dimid, &dim, &dim_grp)))
238      return ret;
239   assert(dim);
240
241   /* Return the dimension name, if the caller wants it. */
242   if (name && dim->name) 
243      strcpy(name, dim->name);     
244   
245   /* Return the dimension length, if the caller wants it. */
246   if (lenp)
247   {
248      if (dim->unlimited)
249      {
250         /* Since this is an unlimited dimension, go to the file
251            and see how many records there are. Take the max number
252            of records from all the vars that share this
253            dimension. */
254         *lenp = 0;
255         if ((ret = nc4_find_dim_len(dim_grp, dimid, &lenp)))
256            return ret;
257      }
258      else
259      {
260         if (dim->too_long)
261         {
262            ret = NC_EDIMSIZE;
263            *lenp = NC_MAX_UINT;
264         }
265         else
266            *lenp = dim->len;
267      }
268   }
269
270   return ret;
271}
272
273/* Rename a dimension, for those who like to prevaricate. */
274int
275NC4_rename_dim(int ncid, int dimid, const char *name)
276{
277   NC_FILE_INFO_T *nc;
278   NC_GRP_INFO_T *grp;
279   NC_HDF5_FILE_INFO_T *h5;
280   NC_DIM_INFO_T *dim;
281   char norm_name[NC_MAX_NAME + 1];
282   int retval;
283
284   if (!name)
285      return NC_EINVAL;
286
287   LOG((2, "nc_rename_dim: ncid 0x%x dimid %d name %s", ncid, 
288        dimid, name));
289
290   /* Find info for this file and group, and set pointer to each. */
291   if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))     
292      return retval;
293   assert(nc);
294   
295#ifdef USE_PNETCDF
296   /* Take care of files created/opened with parallel-netcdf library. */
297   if (nc->pnetcdf_file)
298      return ncmpi_rename_dim(nc->int_ncid, dimid, name);
299#endif /* USE_PNETCDF */
300
301   /* Handle netcdf-3 cases. */
302   assert(h5);
303   assert(h5 && grp);
304
305   /* Trying to write to a read-only file? No way, Jose! */
306   if (h5->no_write)
307      return NC_EPERM;
308
309   /* Make sure this is a valid netcdf name. */
310   if ((retval = nc4_check_name(name, norm_name)))
311      return retval;
312
313   /* Make sure the new name is not already in use in this group. */
314   for (dim = grp->dim; dim; dim = dim->next)
315      if (!strncmp(dim->name, norm_name, NC_MAX_NAME))
316         return NC_ENAMEINUSE;
317
318   /* Find the dim. */
319   for (dim = grp->dim; dim; dim = dim->next)
320      if (dim->dimid == dimid)
321         break;
322   if (!dim)
323      return NC_EBADDIM;
324
325   /* If not in define mode, switch to it, unless the new name is
326    * shorter. (This is in accordance with the v3 interface.) */
327/*    if (!(h5->flags & NC_INDEF) && strlen(name) > strlen(dim->name)) */
328/*    { */
329/*       if (h5->cmode & NC_CLASSIC_MODEL) */
330/*       return NC_ENOTINDEFINE; */
331/*       if ((retval = nc_redef(ncid))) */
332/*       return retval; */
333/*    } */
334
335   /* Save the old name, we'll need it to rename this object when we
336    * sync to HDF5 file. But if there already is an old_name saved,
337    * just stick with what we've got, since the user might be renaming
338    * the crap out of this thing, without ever syncing with the
339    * file. When the sync does take place, we only need the original
340    * name of the dim, not any of the intermediate ones. If the user
341    * could just make up his mind, we could all get on to writing some
342    * data... */
343   if (!dim->old_name)
344   {
345      if (!(dim->old_name = malloc((strlen(dim->name) + 1) * sizeof(char))))
346         return NC_ENOMEM;
347      strcpy(dim->old_name, dim->name);
348   }
349
350   /* Give the dimension its new name in metadata. UTF8 normalization
351    * has been done. */
352   free(dim->name);
353   if (!(dim->name = malloc((strlen(norm_name) + 1) * sizeof(char))))
354      return NC_ENOMEM;
355   strcpy(dim->name, norm_name);
356
357   return NC_NOERR;
358}
359
360/* Returns an array of unlimited dimension ids.The user can get the
361   number of unlimited dimensions by first calling this with NULL for
362   the second pointer.
363*/
364int 
365NC4_inq_unlimdims(int ncid, int *nunlimdimsp, int *unlimdimidsp) 
366{
367  NC_DIM_INFO_T *dim;
368  NC_GRP_INFO_T *grp;
369  NC_FILE_INFO_T *nc;
370  NC_HDF5_FILE_INFO_T *h5;
371  int num_unlim = 0;
372  int retval;
373
374  LOG((2, "nc_inq_unlimdims: ncid 0x%x", ncid));
375
376   /* Find info for this file and group, and set pointer to each. */
377   if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
378      return retval;
379
380   /* Get our dim info. */
381   assert(h5);
382   {
383      for (dim=grp->dim; dim; dim=dim->next)
384      {
385         if (dim->unlimited)
386         {
387            if (unlimdimidsp)
388               unlimdimidsp[num_unlim] = dim->dimid;
389            num_unlim++;
390         }
391      }
392   }
393
394   /* Give the number if the user wants it. */
395   if (nunlimdimsp)
396      *nunlimdimsp = num_unlim;
397
398   return NC_NOERR;
399}
400
401
Note: See TracBrowser for help on using the repository browser.