Skip to content

Commit

Permalink
Merge branch 'tickets/DM-48846'
Browse files Browse the repository at this point in the history
  • Loading branch information
iagaponenko committed Feb 12, 2025
2 parents 1c6c274 + b23e5ee commit 7c2e4cb
Show file tree
Hide file tree
Showing 7 changed files with 36 additions and 35 deletions.
4 changes: 2 additions & 2 deletions src/qhttp/Server.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ class Server : public std::enable_shared_from_this<Server> {
// header files for details. Convenience functions are provided here to instantiate and install
// these.

void addStaticContent(std::string const& path, std::string const& rootDirectory);
AjaxEndpoint::Ptr addAjaxEndpoint(std::string const& path);
void addStaticContent(std::string const& pattern, std::string const& rootDirectory);
AjaxEndpoint::Ptr addAjaxEndpoint(std::string const& pattern);

//----- setRequestTimeout() allows the user to override the default 5 minute start-of-request to
// end-of-response timeout. Must be called before start(), or between calls to stop() and start().
Expand Down
12 changes: 6 additions & 6 deletions src/qhttp/StaticContent.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ class StaticContent {
//----- StaticContent is a specialized Handler to handle the common case of serving a tree of static
// content rooted beneath a single file system directory. add() will add an instance to the
// specified Server which will responding to GET requests on URL's that prefix match the pattern
// specified in the "path" argument and postfix match paths to existing files under rootDirectory in
// the local filesystem. Content-Type of responses is inferred from the file extension for several
// common file extensions (see the file type map near the top of Response.cc for a complete list of
// these.) Note that the Server::addStaticContent() convenience method would typically be called in
// preference to calling the add() method here directly.
// specified in the "pattern" argument and postfix match paths to existing files under rootDirectory
// in the local filesystem. Content-Type of responses is inferred from the file extension for
// several common file extensions (see the file type map near the top of Response.cc for a complete
// list of these.) Note that the Server::addStaticContent() convenience method would typically be
// called in preference to calling the add() method here directly.

static void add(Server& server, std::string const& path, std::string const& rootDirectory);
static void add(Server& server, std::string const& pattern, std::string const& rootDirectory);
};

} // namespace lsst::qserv::qhttp
Expand Down
1 change: 1 addition & 0 deletions src/replica/apps/QhttpTestApp.cc
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ int QhttpTestApp::runImpl() {
cout << ::timestamp() << "Request: " << ::senderIpAddr(req) << " /body/dump" << endl;
qhttp::MultiPartParser::parse(req, make_shared<::SimpleRequestProcessor>(resp));
}}});
httpServer->addStaticContent("/static/*", "/tmp");

// Make sure the service started before launching any BOOST ASIO threads.
// This will prevent threads from finishing due to a lack of work to be done.
Expand Down
2 changes: 1 addition & 1 deletion src/wbase/FileChannelShared.cc
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ bool FileChannelShared::_writeToFile(lock_guard<mutex> const& tMtxLock, shared_p
LOGS(_log, LOG_LVL_TRACE, __func__ << " file write " << task->getIdStr() << " start");
// Create the file if not open.
if (!_file.is_open()) {
_fileName = task->resultFilePath();
_fileName = task->resultFileAbsPath();
_file.open(_fileName, ios::out | ios::trunc | ios::binary);
if (!(_file.is_open() && _file.good())) {
throw runtime_error("FileChannelShared::" + string(__func__) +
Expand Down
27 changes: 15 additions & 12 deletions src/wbase/Task.cc
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,15 @@ namespace {

LOG_LOGGER _log = LOG_GET("lsst.qserv.wbase.Task");

string buildResultFilePath(shared_ptr<lsst::qserv::proto::TaskMsg> const& taskMsg,
string const& resultsDirname) {
string buildResultFileName(shared_ptr<lsst::qserv::proto::TaskMsg> const& taskMsg) {
return to_string(taskMsg->czarid()) + "-" + to_string(taskMsg->queryid()) + "-" +
to_string(taskMsg->jobid()) + "-" + to_string(taskMsg->chunkid()) + "-" +
to_string(taskMsg->attemptcount()) + ".proto";
}

string buildResultFilePath(string const& resultFileName, string const& resultsDirname) {
if (resultsDirname.empty()) return resultsDirname;
fs::path path(resultsDirname);
path /= to_string(taskMsg->czarid()) + "-" + to_string(taskMsg->queryid()) + "-" +
to_string(taskMsg->jobid()) + "-" + to_string(taskMsg->chunkid()) + "-" +
to_string(taskMsg->attemptcount()) + ".proto";
return path.string();
return fs::weakly_canonical(fs::path(resultsDirname) / resultFileName).string();
}

size_t const MB_SIZE_BYTES = 1024 * 1024;
Expand All @@ -84,6 +85,8 @@ size_t const MB_SIZE_BYTES = 1024 * 1024;

namespace lsst::qserv::wbase {

string const Task::_fqdn = util::get_current_host_fqdn();

// Task::ChunkEqual functor
bool Task::ChunkEqual::operator()(Task::Ptr const& x, Task::Ptr const& y) {
if (!x || !y) {
Expand Down Expand Up @@ -139,15 +142,15 @@ Task::Task(TaskMsgPtr const& t, int fragmentNumber, shared_ptr<UserQueryInfo> co
// to advice which result delivery channel to use.
auto const workerConfig = wconfig::WorkerConfig::instance();
auto const resultDeliveryProtocol = workerConfig->resultDeliveryProtocol();
_resultFilePath = ::buildResultFilePath(t, workerConfig->resultsDirname());
auto const fqdn = util::get_current_host_fqdn();
_resultFileName = ::buildResultFileName(t);
_resultFileAbsPath = ::buildResultFilePath(_resultFileName, workerConfig->resultsDirname());
if (resultDeliveryProtocol == wconfig::ConfigValResultDeliveryProtocol::XROOT) {
// NOTE: one extra '/' after the <host>[:<port>] spec is required to make
// a "valid" XROOTD url.
_resultFileXrootUrl = "xroot://" + fqdn + ":" + to_string(workerConfig->resultsXrootdPort()) + "/" +
_resultFilePath;
_resultFileXrootUrl = "xroot://" + _fqdn + ":" + to_string(workerConfig->resultsXrootdPort()) + "/" +
_resultFileAbsPath;
} else if (resultDeliveryProtocol == wconfig::ConfigValResultDeliveryProtocol::HTTP) {
_resultFileHttpUrl = "http://" + fqdn + ":" + to_string(resultsHttpPort) + _resultFilePath;
_resultFileHttpUrl = "http://" + _fqdn + ":" + to_string(resultsHttpPort) + "/" + _resultFileName;
} else {
throw runtime_error("wbase::Task::Task: unsupported results delivery protocol: " +
wconfig::ConfigValResultDeliveryProtocol::toString(resultDeliveryProtocol));
Expand Down
13 changes: 9 additions & 4 deletions src/wbase/Task.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ class Task : public util::CommandForThreadPool {
TaskState state() const { return _state; }
std::string getQueryString() const;
int getQueryFragmentNum() { return _queryFragmentNum; }
std::string const& resultFilePath() const { return _resultFilePath; }
std::string const& resultFileAbsPath() const { return _resultFileAbsPath; }
std::string const& resultFileXrootUrl() const { return _resultFileXrootUrl; }
std::string const& resultFileHttpUrl() const { return _resultFileHttpUrl; }
bool setTaskQueryRunner(
Expand Down Expand Up @@ -334,13 +334,16 @@ class Task : public util::CommandForThreadPool {
std::unique_ptr<DbTblsAndSubchunks> _dbTblsAndSubchunks;

/// The path to the result file.
std::string _resultFilePath;
std::string _resultFileAbsPath;

/// The XROOTD URL for the result file: "xroot://<host>:<xrootd-port>" + "/" + _resultFilePath
/// The name of the result file.
std::string _resultFileName;

/// The XROOTD URL for the result file: "xroot://<host>:<xrootd-port>" + "/" + _resultFileAbsPath
/// @note an extra '/' after server:port spec is required to make a "valid" XROOTD url
std::string _resultFileXrootUrl;

/// The HTTP URL for the result file: "http://<host>:<http-port>" + _resultFilePath
/// The HTTP URL for the result file: "http://<host>:<http-port>/" + _resultFileName
std::string _resultFileHttpUrl;

std::atomic<bool> _queryStarted{false}; ///< Set to true when the query is about to be run.
Expand Down Expand Up @@ -378,6 +381,8 @@ class Task : public util::CommandForThreadPool {
TIMEPOINT _bootedTime;

bool _unitTest = false; ///<

static std::string const _fqdn; ///< Fully qualified domain name of the host. Acquired once at startup.
};

} // namespace lsst::qserv::wbase
Expand Down
12 changes: 2 additions & 10 deletions src/wcontrol/Foreman.cc
Original file line number Diff line number Diff line change
Expand Up @@ -110,17 +110,9 @@ Foreman::Foreman(Scheduler::Ptr const& scheduler, unsigned int poolSize, unsigne
_mark = make_shared<util::HoldTrack::Mark>(ERR_LOC, "Forman Test Msg");

// Read-only access to the result files via the HTTP protocol's method "GET"
//
// NOTE: The following config doesn't seem to work due to multiple instances
// of '/' that's present in a value passed for the pattern parameter
// (the first parameter) of the called method.
//
// _httpServer->addStaticContent(workerConfig->resultsDirname() + "/*", "/");
//
// Using this insecure config instead. The problem will get fixed later.
auto const workerConfig = wconfig::WorkerConfig::instance();
_httpServer->addStaticContent("/*", "/");
_httpServer->addHandler("DELETE", workerConfig->resultsDirname() + "/:file",
_httpServer->addStaticContent("/*", workerConfig->resultsDirname());
_httpServer->addHandler("DELETE", "/:file",
[](qhttp::Request::Ptr const req, qhttp::Response::Ptr const resp) {
resp->sendStatus(::removeResultFile(req->path));
});
Expand Down

0 comments on commit 7c2e4cb

Please sign in to comment.