The DODS API defines a connection-less protocol in which a server keeps no information for a client in between data requests. This is in contrast to most data access APIs, which maintain state information about the files or datasets that a user program currently has open. To simulate an API's connection, the client library for that API must create a virtual connection using information about the data set it has read from the server. That is, the client library must maintain the illusion of a connection (state) for each open data object (typically a file) even though no such connection actually exists.
DODS provides the Connect class to make this a simple process. This class contains a variety of information about a dataset and its location on the internet, including the dataset's URL. Most of the information necessary to fake a connection is contained here.
Data access APIs differ widely however, and it is usually necessary to add some information to the Connect class to make a workable virtual connection. This information can be stored in the subclassed Connect. The API's "open" call must be completely recoded so that the DAS and DDS objects, as well as any other information, are requested from the dataset server and stored locally in whatever form is most convenient.
Figure 3.2 shows the sub-class of Connect used to store information extracted from the DAS and DDS objects (for the NetCDF library), and used to simulate the storage of information in the original API.7
class NCConnect: public Connect {
private:
int _ncid;
int _nvars;
int _ndims;
String _dim_name[MAX_NC_DIMS];
int _dim_size[MAX_NC_DIMS];
int _das_loc[MAX_NC_VARS];
void init_list(int i);
void parse_array_dims();
void parse_grid_dims();
public:
NCConnect(const String &name, const int mode);
~NCConnect();
int &ncid();
int ndims();
int nvars();
int dim_size(const int dimid);
const String &dim_name(const int dimid);
int das_loc(const int varid);
void parse_das_loc();
void parse_dims();
};
The private data added to the Connect object with this class is as follows:
_ncid_nvars_ndims_dim_name[MAX_NC_DIMS]_dim_size[MAX_NC_DIMS]_das_loc[MAX_NC_VARS]This additional data allows the client library to emulate most of the NetCDF query functions properly and locally.
Now look at the recoded open call of the NetCDFlibrary in figure 3.2. The new function has exactly the same type as the original implementation; it takes the same number and type of arguments and returns the same type. The first operation performed by the new open call is to create a Connect object (actually an NCConnect object) using the arguments passed to the open call.
After the open call creates the new NCConnect object, it makes
sure that the user is not trying to open the remote dataset for
writing and, if they are not, reads the DAS and DDS
from the dataset. Once read, the DAS and DDS objects
are parsed using NCConnect's member functions
parse_das_loc and parse_dims. These two member
functions, along with the additional state variables in
NCConnect, effectively create the virtual connection.
Subsequent calls to the client library for information about the
variables (e.g., their size, names, etc.) will be answered using
information stored in the symbol table in the NCConnect
object.
int
ncopen(const char *path, int cmode)
{
int id;
NCConnect *c = new NCConnect(path);
if(cmode != NC_NOWRITE) {
delete c;
return(-1);
}
c->request_das();
c->request_dds();
c->parse_das_loc();
c->parse_dims();
return(conns.add_connect(c)) ;
}
The code above checks to see whether the user is trying to open a connection for writing. Since DODS is a read-only protocol, this attempt must fail.