OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
ffdds.cc
Go to the documentation of this file.
1 // -*- mode: c++; c-basic-offset:4 -*-
2 
3 // This file is part of ff_handler a FreeForm API handler for the OPeNDAP
4 // DAP2 data server.
5 
6 // Copyright (c) 2005 OPeNDAP, Inc.
7 // Author: James Gallagher <jgallagher@opendap.org>
8 //
9 // This is free software; you can redistribute it and/or modify it under the
10 // terms of the GNU Lesser General Public License as published by the Free
11 // Software Foundation; either version 2.1 of the License, or (at your
12 // option) any later version.
13 //
14 // This software is distributed in the hope that it will be useful, but
15 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 // License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24 // (c) COPYRIGHT URI/MIT 1997-99
25 // Please read the full copyright statement in the file COPYRIGHT.
26 //
27 // Authors: reza (Reza Nekovei)
28 
29 // This file contains functions which read the variables and their description
30 // from a freeform API and build the in-memory DDS. These functions form the
31 // core of the server-side software necessary to extract the DDS from a
32 // FreeForm data file.
33 //
34 // It also contains test code which will print the in-memory DDS to
35 // stdout.
36 //
37 // ReZa 6/20/97
38 
39 #include "config_ff.h"
40 
41 #include <cstdio>
42 #include <cstring>
43 
44 #include <iostream>
45 #include <string>
46 
47 #include <Error.h>
48 #include <InternalErr.h>
49 #include <mime_util.h>
50 #include <util.h>
51 
52 #include "FreeFormCPP.h"
53 
54 #include <DDS.h>
55 
56 #include "FFInt16.h"
57 #include "FFUInt16.h"
58 #include "FFInt32.h"
59 #include "FFUInt32.h"
60 #include "FFFloat32.h"
61 #include "FFFloat64.h"
62 #include "FFByte.h"
63 #include "FFArray.h"
64 #include "FFSequence.h"
65 #include "FFGrid.h"
66 #include "FFStr.h"
67 #include "util_ff.h"
68 
69 #include "FFRequestHandler.h"
70 
71 void ff_read_descriptors(DDS &dds_table, const string &filename)
72 {
73  if (!file_exist(filename.c_str()))
74  throw Error((string) "Could not open file " + path_to_filename(filename) + string("."));
75 
76  // Set dataset name
77  dds_table.set_dataset_name(name_path(filename));
78 
79  FF_STD_ARGS_PTR SetUps = NULL;
80  SetUps = ff_create_std_args();
81  if (!SetUps)
82  throw Error("Insufficient memory");
83 
84  // Set the structure values to create the FreeForm DB
85  SetUps->user.is_stdin_redirected = 0;
86 
87  SetUps->input_file = const_cast<char*>(filename.c_str());
88 
89  // Setting the input format file here causes db_set (called by SetDodsDB)
90  // to not set that field of SetUps. In the original modification for the
91  // RSS-hosted data, the server also called this code in FFArray.cc and
92  // FFSequence. However, in a later version of the handler I moved the
93  // format finding code here and recorded the results in the various
94  // objects (including FFArray, ...). So I think the RSS format-specific
95  // code in those classes is not needed anymore. I'm going to #if 0 #endif
96  // them out and check in the result. 10/30/08 jhrg
98  string iff = find_ancillary_rss_formats(filename);
99  SetUps->input_format_file = const_cast<char*>(iff.c_str());
100  }
101 
102  SetUps->output_file = NULL;
103 
104  DATA_BIN_PTR dbin = NULL;
105  char Msgt[Msgt_size];
106  int error = SetDodsDB(SetUps, &dbin, Msgt);
107  if (error && error < ERR_WARNING_ONLY) {
108  if (dbin)
109  db_destroy(dbin);
110  ff_destroy_std_args(SetUps);
111  string msg = (string) Msgt + " FreeForm error code: ";
112  append_long_to_string((long) error, 10, msg);
113  throw Error(msg);
114  }
115 
116  ff_destroy_std_args(SetUps);
117 
118  // These things are defined here so that they can be freed in the catch(...)
119  // clause below
120  PROCESS_INFO_LIST pinfo_list = NULL;
121  char **var_names_vector = NULL;
122  char **dim_names_vector = NULL;
123  Array *ar = NULL;
124  Sequence *seq = NULL;
125 
126  try {
127 
128  int num_names = 0;
129  error = db_ask(dbin, DBASK_VAR_NAMES, FFF_INPUT | FFF_DATA, &num_names, &var_names_vector);
130  if (error) {
131  string msg = "Could not get variable list from the input file. FreeForm error code: ";
132  append_long_to_string((long) error, 10, msg);
133  throw Error(msg);
134  }
135 
136  error = db_ask(dbin, DBASK_PROCESS_INFO, FFF_INPUT | FFF_DATA, &pinfo_list);
137  if (error) {
138  string msg = "Could not get process info for the input file. FreeForm error code: ";
139  append_long_to_string((long) error, 10, msg);
140  throw Error(msg);
141  }
142 
143  bool newseq = true;
144  bool is_array = true;
145  for (int i = 0; i < num_names; i++) {
146  int num_dim_names = 0;
147 
148  char *cp = NULL;
149 
150  error = db_ask(dbin, DBASK_ARRAY_DIM_NAMES, var_names_vector[i], &num_dim_names, &dim_names_vector);
151  if (error) {
152  string msg = "Could not get array dimension names for variable: ";
153  msg += (string) var_names_vector[i] + ", FreeForm error code: ";
154  append_long_to_string((long) error, 10, msg);
155  throw Error(msg);
156  }
157 
158  if (num_dim_names == 0) // sequence names
159  cp = var_names_vector[i];
160  else {
161  cp = strstr(var_names_vector[i], "::");
162  // If cp is not null, advance past the "::"
163  if (cp)
164  cp += 2;
165  }
166 
167  pinfo_list = dll_first(pinfo_list);
168  PROCESS_INFO_PTR pinfo = ((PROCESS_INFO_PTR) (pinfo_list)->data.u.pi);
169  FORMAT_PTR iformat = PINFO_FORMAT(pinfo);
170  VARIABLE_PTR var = ff_find_variable(cp, iformat);
171 
172  // For some formats Freefrom sends an extra EOL variable at the end of
173  // the list.
174  if (IS_EOL(var)) {
175  memFree(dim_names_vector, "**dim_names_vector");
176  dim_names_vector = NULL;
177  break;
178  }
179 
180  while (!var) { // search formats in the format list for the variable
181  pinfo_list = (pinfo_list)->next;
182  pinfo = ((PROCESS_INFO_PTR) (pinfo_list)->data.u.pi);
183 
184  if (!pinfo) {
185  string msg = "Variable " + (string)cp + " was not found in the format file.";
186  throw Error(msg);
187  }
188 
189  iformat = PINFO_FORMAT(pinfo);
190  var = ff_find_variable(cp, iformat);
191  }
192 
193  string input_format_file = PINFO_ORIGIN(pinfo);
194 
195  BaseType *bt = NULL;
196  switch (FFV_DATA_TYPE(var)) {
197  case FFV_TEXT:
198  bt = new FFStr(cp, filename);
199  static_cast<FFStr&>(*bt).set_length(var->end_pos - var->start_pos + 1);
200  break;
201 
202  case FFV_INT8:
203  bt = new FFByte(cp, filename);
204  break;
205 
206  case FFV_UINT8:
207  bt = new FFByte(cp, filename); // Byte is unsigned.
208  break;
209 
210  case FFV_INT16:
211  bt = new FFInt16(cp, filename);
212  break;
213 
214  case FFV_UINT16:
215  bt = new FFUInt16(cp, filename);
216  break;
217 
218  case FFV_INT32:
219  bt = new FFInt32(cp, filename);
220  break;
221 
222  case FFV_UINT32:
223  bt = new FFUInt32(cp, filename);
224  break;
225 
226  case FFV_INT64:
227  bt = new FFInt32(cp, filename); // Ouch!
228  break;
229 
230  case FFV_UINT64:
231  bt = new FFUInt32(cp, filename);
232  break;
233 
234  case FFV_FLOAT32:
235  bt = new FFFloat32(cp, filename);
236  break;
237 
238  case FFV_FLOAT64:
239  bt = new FFFloat64(cp, filename);
240  break;
241 
242  case FFV_ENOTE:
243  bt = new FFFloat64(cp, filename);
244  break;
245 
246  default:
247  throw InternalErr(__FILE__, __LINE__, "Unknown FreeForm type!");
248  }
249 
250  if (num_dim_names == 0) {
251  if (!seq || newseq) {
252  newseq = false;
253  // The format name cannot contain spaces! 8/12/98 jhrg
254  seq = new FFSequence(iformat->name, filename, input_format_file);
255  }
256  seq->add_var_nocopy(bt);
257  is_array = false;
258  }
259  else {
260  ar = new FFArray(cp, filename, bt, input_format_file);
261  delete bt;
262  newseq = true; // An array terminates the old sequence
263  is_array = true;
264  //} The follow loop was separate from this else clause but the
265  // loop won't run if num_dim_names is not > 0
266 
267  for (int j = 0; j < num_dim_names; j++) {
268  FF_ARRAY_DIM_INFO_PTR array_dim_info = NULL;
269 
270  error = db_ask(dbin, DBASK_ARRAY_DIM_INFO, var_names_vector[i], dim_names_vector[j],
271  &array_dim_info);
272  if (error) {
273  string msg = string("Could not get array dimension info for variable ")
274  + string(var_names_vector[i]) + string(", FreeForm error code: ");
275  append_long_to_string((long) error, 10, msg);
276  throw Error(msg);
277  }
278 
279  int DimSiz = (array_dim_info->end_index - array_dim_info->start_index + 1)
280  / array_dim_info->granularity;
281  ar->append_dim(DimSiz, (string) dim_names_vector[j]);
282 
283  memFree(array_dim_info, "");
284  array_dim_info = NULL;
285  }
286  }
287 
288  memFree(dim_names_vector, "**dim_names_vector");
289  dim_names_vector = NULL;
290 
291  if (is_array)
292  dds_table.add_var_nocopy(ar);
293  else if (newseq)
294  dds_table.add_var_nocopy(seq);
295  } // End of the for num_names.
296 
297  if (!is_array)
298  dds_table.add_var_nocopy(seq);
299  }
300  catch (...) {
301  // Because these are added to the DDS using the nocopy methods,
302  // they should only be deleted when an excpetion is thrown
303  delete seq;
304  delete ar;
305 
306  if (dbin)
307  db_destroy(dbin);
308  if (var_names_vector)
309  memFree(var_names_vector, "**var_names_vector");
310  if (pinfo_list)
311  ff_destroy_process_info_list(pinfo_list);
312  if (dim_names_vector)
313  memFree(dim_names_vector, "**dim_names_vector");
314 
315  throw;
316  }
317 
318  if (dbin)
319  db_destroy(dbin);
320  if (var_names_vector)
321  memFree(var_names_vector, "**var_names_vector");
322  if (pinfo_list)
323  ff_destroy_process_info_list(pinfo_list);
324  if (dim_names_vector)
325  memFree(dim_names_vector, "**dim_names_vector");
326 }
#define DBASK_ARRAY_DIM_INFO
Definition: freeform.h:1350
#define FFV_UINT16
Definition: freeform.h:532
void ff_destroy_process_info_list(PROCESS_INFO_LIST)
char * input_format_file
Definition: freeform.h:874
#define memFree(P, TAG)
Definition: memtrack.h:141
const string find_ancillary_rss_formats(const string &dataset, const string &, const string &)
Find the RSS (Remote Sensing Systems) format file using their naming convention.
Definition: util_ff.cc:550
#define FFV_FLOAT64
Definition: freeform.h:538
#define DBASK_ARRAY_DIM_NAMES
Definition: freeform.h:1349
#define FFF_INPUT
Definition: freeform.h:660
bool file_exist(const char *filename)
Definition: util_ff.cc:532
VARIABLE_PTR ff_find_variable(char *, FORMAT_PTR)
#define FFV_FLOAT32
Definition: freeform.h:537
int SetDodsDB(FF_STD_ARGS_PTR std_args, DATA_BIN_HANDLE dbin_h, char *Msgt)
Given a set of standard arguments (input filenames), allocate a DATA-BIN_HANDLE and return an error c...
Definition: util_ff.cc:402
Definition: FFByte.h:51
Definition: FFStr.h:47
DLL_NODE_PTR dll_first(DLL_NODE_PTR node)
struct struct_ff_std_args::struct_std_args_user user
#define DBASK_PROCESS_INFO
Definition: freeform.h:1343
#define DBASK_VAR_NAMES
Definition: freeform.h:1344
#define FFV_TEXT
Definition: freeform.h:499
virtual void set_length(int len)
Definition: FFStr.h:59
FF_NDX_t end_pos
Definition: freeform.h:1049
const int Msgt_size
Definition: util_ff.h:44
#define NULL
Definition: wcsUtil.h:65
#define FFV_UINT32
Definition: freeform.h:534
#define FFF_DATA
Definition: freeform.h:656
#define FFV_INT16
Definition: freeform.h:531
#define FFV_DATA_TYPE(v)
Definition: freeform.h:818
char * output_file
Definition: freeform.h:877
#define PINFO_FORMAT(pi)
Definition: freeform.h:1394
void ff_destroy_std_args(FF_STD_ARGS_PTR)
#define ERR_WARNING_ONLY
Definition: err.h:130
void db_destroy(DATA_BIN_PTR)
#define IS_EOL(v)
Definition: freeform.h:621
FF_STD_ARGS_PTR ff_create_std_args(void)
void ff_read_descriptors(DDS &dds_table, const string &filename)
Definition: ffdds.cc:71
#define FFV_UINT64
Definition: freeform.h:536
#define FFV_UINT8
Definition: freeform.h:530
int db_ask(DATA_BIN_PTR, int,...)
#define PINFO_ORIGIN(pi)
Definition: freeform.h:1411
#define FFV_INT64
Definition: freeform.h:535
FF_NDX_t start_pos
Definition: freeform.h:1048
struct struct_ff_process_info * PROCESS_INFO_PTR
Definition: freeform.h:1192
#define FFV_ENOTE
Definition: freeform.h:539
static bool get_RSS_format_support()
#define FFV_INT32
Definition: freeform.h:533
#define FFV_INT8
Definition: freeform.h:529