diff --git a/src/ccontrol/UserQueryFactory.cc b/src/ccontrol/UserQueryFactory.cc index 28479d122..e7cb11f62 100644 --- a/src/ccontrol/UserQueryFactory.cc +++ b/src/ccontrol/UserQueryFactory.cc @@ -298,6 +298,11 @@ UserQuery::Ptr UserQueryFactory::newUserQuery(std::string const& aQuery, std::st } auto stmt = parser->getSelectStmt(); + // Parsing doesn't need protection, but CSS in analyze query does and + // some of the uq related calls may require protection, but it + // isn't clear. + std::lock_guard factoryLock(_factoryMtx); + // handle special database/table names if (_stmtRefersToProcessListTable(stmt, defaultDb)) { return _makeUserQueryProcessList(stmt, _userQuerySharedResources, userQueryId, resultDb, aQuery, @@ -378,12 +383,14 @@ UserQuery::Ptr UserQueryFactory::newUserQuery(std::string const& aQuery, std::st } return uq; } else if (UserQueryType::isSelectResult(query, userJobId)) { + std::lock_guard factoryLock(_factoryMtx); auto uq = std::make_shared(userJobId, _userQuerySharedResources->czarId, _userQuerySharedResources->queryMetadata); LOGS(_log, LOG_LVL_DEBUG, "make UserQueryAsyncResult: userJobId=" << userJobId); return uq; } else if (UserQueryType::isShowProcessList(query, full)) { LOGS(_log, LOG_LVL_DEBUG, "make UserQueryProcessList: full=" << (full ? 'y' : 'n')); + std::lock_guard factoryLock(_factoryMtx); try { return std::make_shared(full, _userQuerySharedResources->qMetaSelect, _userQuerySharedResources->czarId, userQueryId, @@ -392,10 +399,12 @@ UserQuery::Ptr UserQueryFactory::newUserQuery(std::string const& aQuery, std::st return std::make_shared(exc.what()); } } else if (UserQueryType::isCall(query)) { + std::lock_guard factoryLock(_factoryMtx); auto parser = std::make_shared( query, _userQuerySharedResources->makeUserQueryResources(userQueryId, resultDb)); return parser->getUserQuery(); } else if (UserQueryType::isSet(query)) { + std::lock_guard factoryLock(_factoryMtx); ParseRunner::Ptr parser; try { parser = std::make_shared(query); @@ -414,6 +423,7 @@ UserQuery::Ptr UserQueryFactory::newUserQuery(std::string const& aQuery, std::st } return uq; } else { + std::lock_guard factoryLock(_factoryMtx); // something that we don't recognize auto uq = std::make_shared("Invalid or unsupported query: " + query); return uq; diff --git a/src/ccontrol/UserQueryFactory.h b/src/ccontrol/UserQueryFactory.h index a467ea07a..a62575a26 100644 --- a/src/ccontrol/UserQueryFactory.h +++ b/src/ccontrol/UserQueryFactory.h @@ -103,6 +103,10 @@ class UserQueryFactory : private boost::noncopyable { boost::asio::io_service _asioIoService; std::unique_ptr _asioWork; std::unique_ptr _asioTimerThread; + + /// Protects CSS in `qs->analyzeQuery(query, stmt);` and + /// protects uq calls that alter the database. + std::mutex _factoryMtx; }; } // namespace lsst::qserv::ccontrol diff --git a/src/czar/Czar.cc b/src/czar/Czar.cc index bf44d539b..340922620 100644 --- a/src/czar/Czar.cc +++ b/src/czar/Czar.cc @@ -224,12 +224,8 @@ SubmitResult Czar::submitQuery(string const& query, map const& h // make new UserQuery // this is atomic - ccontrol::UserQuery::Ptr uq; - { - lock_guard lock(_mutex); - uq = _uqFactory->newUserQuery(query, defaultDb, getQdispSharedResources(), userQueryId, msgTableName, - resultDb); - } + ccontrol::UserQuery::Ptr uq = _uqFactory->newUserQuery(query, defaultDb, getQdispSharedResources(), + userQueryId, msgTableName, resultDb); // Add logging context with query ID QSERV_LOGCONTEXT_QUERY(uq->getQueryId());