bes Updated for version 3.20.10
BESStreamResponseHandler.cc
1// BESStreamResponseHandler.cc
2
3// This file is part of bes, A C++ back-end server implementation framework
4// for the OPeNDAP Data Access Protocol.
5
6// Copyright (c) 2004-2009 University Corporation for Atmospheric Research
7// Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
8//
9// This library is free software; you can redistribute it and/or
10// modify it under the terms of the GNU Lesser General Public
11// License as published by the Free Software Foundatiion; either
12// version 2.1 of the License, or (at your option) any later version.
13//
14// This library is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17// Lesser General Public 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 University Corporation for Atmospheric Research at
24// 3080 Center Green Drive, Boulder, CO 80301
25
26// (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005
27// Please read the full copyright statement in the file COPYRIGHT_UCAR.
28//
29// Authors:
30// pwest Patrick West <pwest@ucar.edu>
31// jgarcia Jose Garcia <jgarcia@ucar.edu>
32
33#include <unistd.h>
34
35#include <cerrno>
36#include <iostream>
37#include <fstream>
38#include <string>
39#include <cstring>
40
41using std::ifstream;
42using std::ios;
43using std::endl;
44using std::string;
45using std::ostream;
46
47#include "BESStreamResponseHandler.h"
48#include "BESRequestHandlerList.h"
49#include "BESForbiddenError.h"
50#include "BESNotFoundError.h"
51#include "BESInternalError.h"
52#include "BESDataNames.h"
53#include "BESContainer.h"
54#include "BESDataHandlerInterface.h"
55
56#define BES_STREAM_BUFFER_SIZE 4096
57
58BESStreamResponseHandler::BESStreamResponseHandler(const string &name) :
60{
61}
62
63BESStreamResponseHandler::~BESStreamResponseHandler()
64{
65}
66
67extern volatile int bes_timeout; // defined in BESInterface. jhrg 1/24/17
68
80{
81 d_response_object = 0;
82
83 // Hack. We put this here because the bes timeout period should not
84 // include the time it takes to send data for a file transfer response.
85 //
86 // An alternative would be to implement a BESTransmitter for the "get stream"
87 // operation and have that run from the call to BESInterface::transmist_data().
88 // pcw talks about that below.
89 // jhrg 1/24/17
90 if (bes_timeout != 0) {
91 bes_timeout = 0;
92 alarm(bes_timeout);
93 }
94
95 // What if there is a special way to stream back a data file?
96 // Should we pass this off to the request handlers and put
97 // this code into a different class for reuse? For now
98 // just keep it here. pcw 10/11/06
99
100 // I thought about putting this in the transmit method below
101 // but decided that this is like executing a non-buffered
102 // request, so kept it here. Plus the idea expressed above
103 // led me to leave the code in the execute method.
104 // pcw 10/11/06
105 if (dhi.containers.size() != 1) {
106 string err = (string) "Unable to stream file: " + "no container specified";
107 throw BESInternalError(err, __FILE__, __LINE__);
108 }
109
110 dhi.first_container();
111 BESContainer *container = dhi.container;
112 string filename = container->access();
113 if (filename.empty()) {
114 string err = (string) "Unable to stream file: " + "filename not specified";
115 throw BESInternalError(err, __FILE__, __LINE__);
116 }
117
118 int bytes = 0;
119 ifstream os;
120 os.open(filename.c_str(), ios::in);
121 int myerrno = errno;
122 if (!os) {
123 string serr = (string) "Unable to stream file because it cannot be opened. file: '" + filename + "' msg: ";
124 char *err = strerror(myerrno);
125 if (err)
126 serr += err;
127 else
128 serr += "Unknown error";
129
130 // ENOENT means that the node wasn't found.
131 // On some systems a file that doesn't exist returns ENOTDIR because: w.f.t?
132 // Otherwise, access is being denied for some other reason
133 if (myerrno == ENOENT || myerrno == ENOTDIR) {
134 // On some systems a file that doesn't exist returns ENOTDIR because: w.f.t?
135 throw BESNotFoundError(serr, __FILE__, __LINE__);
136 }
137 // Not a 404? Then we'll go with the forbidden fruit theory...
138 throw BESForbiddenError(serr, __FILE__, __LINE__);
139 }
140
141 int nbytes;
142 char block[BES_STREAM_BUFFER_SIZE];
143 os.read(block, sizeof block);
144 nbytes = os.gcount();
145 while (nbytes) {
146 bytes += nbytes;
147 dhi.get_output_stream().write((char*) block, nbytes);
148
149 os.read(block, sizeof block);
150 nbytes = os.gcount();
151 }
152
153 os.close();
154}
155
164{
165 // The Data is transmitted when it is read, dumped to stdout, so there is nothing
166 // to transmit here.
167}
168
175void BESStreamResponseHandler::dump(ostream &strm) const
176{
177 strm << BESIndent::LMarg << "BESStreamResponseHandler::dump - (" << (void *) this << ")" << endl;
178 BESIndent::Indent();
180 BESIndent::UnIndent();
181}
182
184BESStreamResponseHandler::BESStreamResponseBuilder(const string &name)
185{
186 return new BESStreamResponseHandler(name);
187}
188
A container is something that holds data. E.G., a netcdf file or a database entry.
Definition: BESContainer.h:65
virtual std::string access()=0
returns the true name of this container
Structure storing information used by the BES to handle the request.
void first_container()
set the container pointer to the first container in the containers list
BESContainer * container
pointer to current container in this interface
error thrown if the BES is not allowed to access the resource requested
exception thrown if internal error encountered
error thrown if the resource requested cannot be found
handler object that knows how to create a specific response object
virtual void dump(std::ostream &strm) const
dumps information about this object
virtual void dump(std::ostream &strm) const
dumps information about this object
virtual void transmit(BESTransmitter *transmitter, BESDataHandlerInterface &r)
transmit the file, streaming it back to the client
virtual void execute(BESDataHandlerInterface &r)
executes the command 'get file <filename>;' by streaming the specified file