Skip to content

Commit

Permalink
TEMPORARY: test version of the response buffer management in qhttp
Browse files Browse the repository at this point in the history
  • Loading branch information
iagaponenko committed Jan 18, 2024
1 parent b3fdc96 commit afd37f2
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 17 deletions.
48 changes: 32 additions & 16 deletions src/qhttp/Response.cc
Original file line number Diff line number Diff line change
Expand Up @@ -142,27 +142,39 @@ void Response::send(std::string const& content, std::string const& contentType)
headers["Content-Type"] = contentType;
headers["Content-Length"] = std::to_string(content.length());

std::ostream responseStream(&_responsebuf);
responseStream << _headers() << "\r\n" << content;
_responseBuf = _headers() + "\r\n" + content;
_write();
}

void Response::sendFile(fs::path const& path) {
auto const fileSize = fs::file_size(path);
auto ct = contentTypesByExtension.find(path.extension().string());
headers["Content-Type"] = (ct != contentTypesByExtension.end()) ? ct->second : "text/plain";
headers["Content-Length"] = std::to_string(fs::file_size(path));
headers["Content-Length"] = std::to_string(fileSize);

// Try to open the file for streaming input. Throw if we hit a snag; exception expected to be caught by
// Try to open the file. Throw if we hit a snag; exception expected to be caught by
// top-level handler in Server::_dispatchRequest().
fs::ifstream responseFile(path);
fs::ifstream responseFile(path, ios::binary);
if (!responseFile) {
LOGLS_ERROR(_log, logger(_server) << logger(_socket) << "open failed for " << path << ": "
<< std::strerror(errno));
throw(boost::system::system_error(errno, boost::system::generic_category()));
}

std::ostream responseStream(&_responsebuf);
responseStream << _headers() << "\r\n" << responseFile.rdbuf();
_responseBuf = _headers() + "\r\n";
string::size_type const newCapacity = _responseBuf.size() + fileSize;
_responseBuf.reserve(newCapacity);
if (_responseBuf.capacity() != newCapacity) {
LOGLS_ERROR(_log, logger(_server) << logger(_socket) << "buffer resize failed for " << path
<< ": current_capacity=" << _responseBuf.capacity()
<< " new_capacity=" << newCapacity);
throw(boost::system::system_error(errno, boost::system::generic_category()));
}
if (!responseFile.read(&_responseBuf[_responseBuf.size()], fileSize)) {
LOGLS_ERROR(_log, logger(_server) << logger(_socket) << "read failed for " << path << ": "
<< std::strerror(errno));
throw(boost::system::system_error(errno, boost::system::generic_category()));
}
_write();
}

Expand Down Expand Up @@ -194,15 +206,19 @@ void Response::_write() {
}

auto self = shared_from_this();
asio::async_write(*_socket, _responsebuf, [self](boost::system::error_code const& ec, std::size_t sent) {
if (ec) {
LOGLS_ERROR(_log, logger(self->_server)
<< logger(self->_socket) << "write failed: " << ec.message());
}
if (self->_doneCallback) {
self->_doneCallback(ec, sent);
}
});
asio::async_write(
*_socket, _responseBuf.data(),
_responseBuf.size()[self](boost::system::error_code const& ec, std::size_t sent) {
if (ec) {
LOGLS_ERROR(_log, logger(self->_server)
<< logger(self->_socket) << "write failed: " << ec.message());
}
if (self->_doneCallback) {
self->_doneCallback(ec, sent);
}
_responseBuf.clear(); // empty the buffer
_responseBuf.shrink_to_fit(); // deallocate memory
});
}

} // namespace lsst::qserv::qhttp
3 changes: 2 additions & 1 deletion src/qhttp/Response.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ class Response : public std::enable_shared_from_this<Response> {
std::shared_ptr<Server> const _server;

std::shared_ptr<boost::asio::ip::tcp::socket> const _socket;
boost::asio::streambuf _responsebuf;
std::ifstream _file;
std::string _responseBuf;
std::atomic_flag _transmissionStarted;

DoneCallback _doneCallback;
Expand Down

0 comments on commit afd37f2

Please sign in to comment.