From 4dadd4a6e2fc198bee52b56aecbec0d821756422 Mon Sep 17 00:00:00 2001 From: Igor Gaponenko Date: Thu, 21 Nov 2024 14:45:44 -0800 Subject: [PATCH] Significant refactoring of dependencies in the Replication System's requests The dependency has been reversed to make the request classes depend on the Controller. In the previous version of the code, the Controller was the dependency "hub" by knowing about all possible request classes. The change fixes the original design mistake in the Replication Framework. The Controller class is no longer required to instantiate the requests. The instantiation is now done via each request's "create::" factory method that has been renamed into "::createAndStart" to reflect what the method actually does. The very same factory method is also used to start request immediatelly upon the instantiation. Note that in the new code each request object self-registeres (and unregisteres) itself with the Controller, which allows the Controller to keep a track of all active (started and not yet finished) requests. The management request classes that are meant for stopping o probing the worker-side requests have been redesigned. The complex template definitions have been replaced with simple classes. The older version of the request status class was replaced with the simpler status probe (explained in the previous paragraph) and a new request "tracking" message that is used internally by the corresponding requests to track progress of the requests at workers. Overall, all these changes have reduced the amnount of the boilerplate code that is needed for adding new request types to the Framework. --- src/replica/apps/AdminApp.cc | 44 +- src/replica/apps/ControllerApp.cc | 352 +++--------- src/replica/apps/MessengerTestApp.cc | 4 +- src/replica/contr/Controller.cc | 358 +----------- src/replica/contr/Controller.h | 508 +----------------- src/replica/contr/HttpQservSqlModule.cc | 3 +- src/replica/contr/Task.h | 15 +- src/replica/jobs/ClusterHealthJob.cc | 9 +- src/replica/jobs/CreateReplicaJob.cc | 55 +- src/replica/jobs/DeleteReplicaJob.cc | 43 +- src/replica/jobs/DeleteWorkerJob.cc | 52 +- src/replica/jobs/DirectorIndexJob.cc | 14 +- src/replica/jobs/DirectorIndexJob.h | 1 + src/replica/jobs/FindAllJob.cc | 25 +- src/replica/jobs/FixUpJob.cc | 42 +- src/replica/jobs/Job.cc | 10 +- src/replica/jobs/QservStatusJob.cc | 1 + src/replica/jobs/RebalanceJob.cc | 1 + src/replica/jobs/ServiceManagementJob.h | 60 +-- src/replica/jobs/SqlAlterTablesJob.cc | 20 +- src/replica/jobs/SqlAlterTablesJob.h | 6 - src/replica/jobs/SqlCreateDbJob.cc | 20 +- src/replica/jobs/SqlCreateDbJob.h | 42 +- src/replica/jobs/SqlCreateIndexesJob.cc | 20 +- src/replica/jobs/SqlCreateIndexesJob.h | 5 - src/replica/jobs/SqlCreateTableJob.cc | 20 +- src/replica/jobs/SqlCreateTableJob.h | 54 +- src/replica/jobs/SqlCreateTablesJob.cc | 20 +- src/replica/jobs/SqlCreateTablesJob.h | 9 - src/replica/jobs/SqlDeleteDbJob.cc | 20 +- src/replica/jobs/SqlDeleteDbJob.h | 42 +- src/replica/jobs/SqlDeleteTableJob.cc | 20 +- src/replica/jobs/SqlDeleteTableJob.h | 8 - .../jobs/SqlDeleteTablePartitionJob.cc | 20 +- src/replica/jobs/SqlDeleteTablePartitionJob.h | 8 - src/replica/jobs/SqlDisableDbJob.cc | 20 +- src/replica/jobs/SqlDisableDbJob.h | 42 +- src/replica/jobs/SqlDropIndexesJob.cc | 20 +- src/replica/jobs/SqlDropIndexesJob.h | 3 - src/replica/jobs/SqlEnableDbJob.cc | 20 +- src/replica/jobs/SqlEnableDbJob.h | 41 +- src/replica/jobs/SqlGetIndexesJob.cc | 21 +- src/replica/jobs/SqlGetIndexesJob.h | 6 - src/replica/jobs/SqlGrantAccessJob.cc | 19 +- src/replica/jobs/SqlGrantAccessJob.h | 46 +- src/replica/jobs/SqlJob.cc | 7 + src/replica/jobs/SqlJob.h | 19 +- src/replica/jobs/SqlQueryJob.cc | 19 +- src/replica/jobs/SqlQueryJob.h | 54 +- .../jobs/SqlRemoveTablePartitionsJob.cc | 19 +- .../jobs/SqlRemoveTablePartitionsJob.h | 8 - src/replica/jobs/SqlRowStatsJob.cc | 19 +- src/replica/jobs/SqlRowStatsJob.h | 6 - src/replica/jobs/VerifyJob.cc | 46 +- src/replica/proto/protocol.proto | 63 ++- src/replica/requests/CMakeLists.txt | 2 - src/replica/requests/DeleteRequest.cc | 52 +- src/replica/requests/DeleteRequest.h | 47 +- src/replica/requests/DirectorIndexRequest.cc | 84 ++- src/replica/requests/DirectorIndexRequest.h | 56 +- src/replica/requests/DisposeRequest.cc | 39 +- src/replica/requests/DisposeRequest.h | 40 +- src/replica/requests/EchoRequest.cc | 55 +- src/replica/requests/EchoRequest.h | 42 +- src/replica/requests/FindAllRequest.cc | 63 +-- src/replica/requests/FindAllRequest.h | 47 +- src/replica/requests/FindRequest.cc | 60 +-- src/replica/requests/FindRequest.h | 46 +- src/replica/requests/ReplicationRequest.cc | 66 +-- src/replica/requests/ReplicationRequest.h | 53 +- src/replica/requests/Request.cc | 49 +- src/replica/requests/Request.h | 67 +-- src/replica/requests/RequestMessenger.cc | 19 +- src/replica/requests/RequestMessenger.h | 26 +- .../requests/ServiceManagementRequest.h | 38 +- .../requests/ServiceManagementRequestBase.cc | 29 +- .../requests/ServiceManagementRequestBase.h | 22 +- src/replica/requests/SqlAlterTablesRequest.cc | 35 +- src/replica/requests/SqlAlterTablesRequest.h | 41 +- src/replica/requests/SqlCreateDbRequest.cc | 34 +- src/replica/requests/SqlCreateDbRequest.h | 34 +- .../requests/SqlCreateIndexesRequest.cc | 42 +- .../requests/SqlCreateIndexesRequest.h | 40 +- src/replica/requests/SqlCreateTableRequest.cc | 38 +- src/replica/requests/SqlCreateTableRequest.h | 50 +- .../requests/SqlCreateTablesRequest.cc | 39 +- src/replica/requests/SqlCreateTablesRequest.h | 45 +- src/replica/requests/SqlDeleteDbRequest.cc | 33 +- src/replica/requests/SqlDeleteDbRequest.h | 35 +- .../SqlDeleteTablePartitionRequest.cc | 34 +- .../requests/SqlDeleteTablePartitionRequest.h | 46 +- src/replica/requests/SqlDeleteTableRequest.cc | 36 +- src/replica/requests/SqlDeleteTableRequest.h | 38 +- src/replica/requests/SqlDisableDbRequest.cc | 35 +- src/replica/requests/SqlDisableDbRequest.h | 35 +- src/replica/requests/SqlDropIndexesRequest.cc | 36 +- src/replica/requests/SqlDropIndexesRequest.h | 37 +- src/replica/requests/SqlEnableDbRequest.cc | 34 +- src/replica/requests/SqlEnableDbRequest.h | 35 +- src/replica/requests/SqlGetIndexesRequest.cc | 34 +- src/replica/requests/SqlGetIndexesRequest.h | 34 +- src/replica/requests/SqlGrantAccessRequest.cc | 36 +- src/replica/requests/SqlGrantAccessRequest.h | 38 +- src/replica/requests/SqlQueryRequest.cc | 30 +- src/replica/requests/SqlQueryRequest.h | 44 +- .../SqlRemoveTablePartitionsRequest.cc | 31 +- .../SqlRemoveTablePartitionsRequest.h | 41 +- src/replica/requests/SqlRequest.cc | 38 +- src/replica/requests/SqlRequest.h | 26 +- src/replica/requests/SqlRowStatsRequest.cc | 28 +- src/replica/requests/SqlRowStatsRequest.h | 34 +- src/replica/requests/StatusRequest.cc | 266 +++++---- src/replica/requests/StatusRequest.h | 361 +++---------- src/replica/requests/StatusRequestBase.cc | 169 ------ src/replica/requests/StatusRequestBase.h | 123 ----- src/replica/requests/StopRequest.cc | 237 ++++---- src/replica/requests/StopRequest.h | 336 ++---------- src/replica/requests/StopRequestBase.cc | 181 ------- src/replica/requests/StopRequestBase.h | 132 ----- src/replica/worker/WorkerProcessor.cc | 51 +- src/replica/worker/WorkerProcessor.h | 39 +- src/replica/worker/WorkerServerConnection.cc | 89 +-- src/replica/worker/WorkerServerConnection.h | 9 + 123 files changed, 1959 insertions(+), 4711 deletions(-) delete mode 100644 src/replica/requests/StatusRequestBase.cc delete mode 100644 src/replica/requests/StatusRequestBase.h delete mode 100644 src/replica/requests/StopRequestBase.cc delete mode 100644 src/replica/requests/StopRequestBase.h diff --git a/src/replica/apps/AdminApp.cc b/src/replica/apps/AdminApp.cc index f56f97fc9..aec266c6d 100644 --- a/src/replica/apps/AdminApp.cc +++ b/src/replica/apps/AdminApp.cc @@ -29,6 +29,7 @@ #include // Qserv headers +#include "replica/config/Configuration.h" #include "replica/contr/Controller.h" #include "replica/requests/RequestTracker.h" #include "replica/util/Performance.h" @@ -57,7 +58,8 @@ AdminApp::AdminApp(int argc, char* argv[]) ::enableServiceProvider) { // Configure the command line parser - parser().commands("operation", {"STATUS", "SUSPEND", "RESUME", "REQUESTS", "DRAIN"}, _operation) + parser().commands("operation", {"STATUS", "SUSPEND", "RESUME", "REQUESTS", "DRAIN", "RECONFIG"}, + _operation) .flag("all-workers", "The flag for selecting all workers regardless of their status (DISABLED or READ-ONLY).", _allWorkers) @@ -85,6 +87,8 @@ AdminApp::AdminApp(int argc, char* argv[]) parser().command("DRAIN").description( "Cancel the in-progress (if any) requests on all workers, then empty all queues."); + + parser().command("RECONFIG").description("Re-configure the worker services."); } int AdminApp::runImpl() { @@ -93,51 +97,48 @@ int AdminApp::runImpl() { // Launch requests against a collection of workers CommonRequestTracker tracker(cout, _progressReport, _errorReport); - auto const workerNames = _allWorkers ? serviceProvider()->config()->allWorkers() : serviceProvider()->config()->workers(); - for (auto&& workerName : workerNames) { if (_operation == "STATUS") { - tracker.add(controller->statusOfWorkerService( - workerName, [&tracker](ServiceStatusRequest::Ptr const& ptr) { tracker.onFinish(ptr); })); - + tracker.add(ServiceStatusRequest::createAndStart( + controller, workerName, + [&tracker](ServiceStatusRequest::Ptr const& ptr) { tracker.onFinish(ptr); })); } else if (_operation == "SUSPEND") { - tracker.add(controller->suspendWorkerService( - workerName, + tracker.add(ServiceSuspendRequest::createAndStart( + controller, workerName, [&tracker](ServiceSuspendRequest::Ptr const& ptr) { tracker.onFinish(ptr); })); - } else if (_operation == "RESUME") { - tracker.add(controller->resumeWorkerService( - workerName, [&tracker](ServiceResumeRequest::Ptr const& ptr) { tracker.onFinish(ptr); })); - + tracker.add(ServiceResumeRequest::createAndStart( + controller, workerName, + [&tracker](ServiceResumeRequest::Ptr const& ptr) { tracker.onFinish(ptr); })); } else if (_operation == "REQUESTS") { - tracker.add(controller->requestsOfWorkerService( - workerName, + tracker.add(ServiceRequestsRequest::createAndStart( + controller, workerName, [&tracker](ServiceRequestsRequest::Ptr const& ptr) { tracker.onFinish(ptr); })); - } else if (_operation == "DRAIN") { - tracker.add(controller->drainWorkerService( - workerName, [&tracker](ServiceDrainRequest::Ptr const& ptr) { tracker.onFinish(ptr); })); - + tracker.add(ServiceDrainRequest::createAndStart( + controller, workerName, + [&tracker](ServiceDrainRequest::Ptr const& ptr) { tracker.onFinish(ptr); })); + } else if (_operation == "RECONFIG") { + tracker.add(ServiceReconfigRequest::createAndStart( + controller, workerName, + [&tracker](ServiceReconfigRequest::Ptr const& ptr) { tracker.onFinish(ptr); })); } else { throw logic_error("AdminApp::" + string(__func__) + " unsupported operation: " + _operation); } } // Wait before all request are finished - tracker.track(); // Analyze and display results - vector workerName; vector startedSecondsAgo; vector state; vector numNewRequests; vector numInProgressRequests; vector numFinishedRequests; - for (auto const& ptr : tracker.requests) { workerName.push_back(ptr->workerName()); if ((ptr->state() == Request::State::FINISHED) && @@ -174,7 +175,6 @@ int AdminApp::runImpl() { vector requestType; vector queue; vector priority; - auto analyzeRemoteRequestInfo = [&](string const& workerName_, string const& queueName, ProtocolServiceResponseInfo const& info) { workerName.push_back(workerName_); diff --git a/src/replica/apps/ControllerApp.cc b/src/replica/apps/ControllerApp.cc index 628621cf7..01c82a53d 100644 --- a/src/replica/apps/ControllerApp.cc +++ b/src/replica/apps/ControllerApp.cc @@ -28,6 +28,7 @@ #include // Qserv headers +#include "replica/config/Configuration.h" #include "replica/requests/DeleteRequest.h" #include "replica/requests/DisposeRequest.h" #include "replica/requests/EchoRequest.h" @@ -73,56 +74,6 @@ bool const injectDatabaseOptions = true; bool const boostProtobufVersionCheck = true; bool const enableServiceProvider = true; -/** - * This is the helper class for submitting the management requests - * which are meant to request a status or stop an on-going request. - */ -class ManagementRequestLauncher { -public: - // All (but the normal one) forms of construction are prohibited - - ManagementRequestLauncher() = delete; - ManagementRequestLauncher(ManagementRequestLauncher const&) = delete; - ManagementRequestLauncher& operator=(ManagementRequestLauncher const&) = delete; - - ManagementRequestLauncher(Controller::Ptr const& controller, string workerName, string affectedRequestId, - int priority, bool doNotTrackRequest) - : _controller(controller), - _workerName(workerName), - _affectedRequestId(affectedRequestId), - _priority(priority), - _doNotTrackRequest(doNotTrackRequest) {} - ~ManagementRequestLauncher() = default; - - template - typename REQUEST::Ptr status() const { - return _controller->statusById(_workerName, _affectedRequestId, REQUEST::extendedPrinter, - !_doNotTrackRequest); - } - - template - typename REQUEST::Ptr stop() const { - return _controller->stopById(_workerName, _affectedRequestId, REQUEST::extendedPrinter, - !_doNotTrackRequest); - } - -private: - /// Pointer to the controller for launching requests - Controller::Ptr const _controller; - - /// The name of a worker which will execute a request - std::string const _workerName; - - /// An identifier of a request for operations over known requests - std::string const _affectedRequestId; - - /// The priority level of a request - int const _priority; - - /// Do not track requests waiting before they finish - bool const _doNotTrackRequest; -}; - } // namespace namespace lsst::qserv::replica { @@ -406,76 +357,12 @@ void ControllerApp::_configureParserCommandINDEX() { void ControllerApp::_configureParserCommandSTATUS() { parser().command("STATUS") .description("Ask a worker to return a status of a request.") - .required("affected-request", - "The type of a request affected by the operation. Supported types:" - " REPLICATE, DELETE, FIND, FIND_ALL, ECHO, SQL_ALTER_TABLES, SQL_QUERY, " - "SQL_CREATE_DATABASE" - " SQL_DELETE_DATABASE, SQL_ENABLE_DATABASE, SQL_DISABLE_DATABASE" - " SQL_GRANT_ACCESS" - " SQL_CREATE_TABLE, SQL_CREATE_TABLES, SQL_DELETE_TABLE, SQL_REMOVE_TABLE_PARTITIONS," - " SQL_DELETE_TABLE_PARTITION," - " SQL_CREATE_TABLE_INDEXES, SQL_DROP_TABLE_INDEXES, SQL_GET_TABLE_INDEXES" - " INDEX", - _affectedRequest, - {"REPLICATE", - "DELETE", - "FIND", - "FIND_ALL", - "ECHO", - "SQL_ALTER_TABLES", - "SQL_QUERY", - "SQL_CREATE_DATABASE", - "SQL_DELETE_DATABASE", - "SQL_ENABLE_DATABASE", - "SQL_DISABLE_DATABASE", - "SQL_GRANT_ACCESS", - "SQL_CREATE_TABLE", - "SQL_CREATE_TABLES", - "SQL_DELETE_TABLE", - "SQL_REMOVE_TABLE_PARTITIONS", - "SQL_DELETE_TABLE_PARTITION", - "SQL_CREATE_TABLE_INDEXES", - "SQL_DROP_TABLE_INDEXES", - "SQL_GET_TABLE_INDEXES", - "INDEX"}) .required("id", "A valid identifier of a request to be probed.", _affectedRequestId); } void ControllerApp::_configureParserCommandSTOP() { parser().command("STOP") .description("Ask a worker to stop an on-going request of the given type.") - .required("affected-request", - "The type of a request affected by the operation. Supported types:" - " REPLICATE, DELETE, FIND, FIND_ALL, ECHO, SQL_ALTER_TABLES, SQL_QUERY, " - "SQL_CREATE_DATABASE" - " SQL_DELETE_DATABASE, SQL_ENABLE_DATABASE, SQL_DISABLE_DATABASE" - " SQL_GRANT_ACCESS" - " SQL_CREATE_TABLE, SQL_CREATE_TABLES, SQL_DELETE_TABLE, SQL_REMOVE_TABLE_PARTITIONS," - " SQL_DELETE_TABLE_PARTITION," - " SQL_CREATE_TABLE_INDEXES, SQL_DROP_TABLE_INDEXES, SQL_GET_TABLE_INDEXES" - " INDEX", - _affectedRequest, - {"REPLICATE", - "DELETE", - "FIND", - "FIND_ALL", - "ECHO", - "SQL_ALTER_TABLES", - "SQL_QUERY", - "SQL_CREATE_DATABASE", - "SQL_DELETE_DATABASE", - "SQL_ENABLE_DATABASE", - "SQL_DISABLE_DATABASE", - "SQL_GRANT_ACCESS", - "SQL_CREATE_TABLE", - "SQL_CREATE_TABLES", - "SQL_DELETE_TABLE", - "SQL_REMOVE_TABLE_PARTITIONS", - "SQL_DELETE_TABLE_PARTITION", - "SQL_CREATE_TABLE_INDEXES", - "SQL_DROP_TABLE_INDEXES", - "SQL_GET_TABLE_INDEXES", - "INDEX"}) .required("id", "A valid identifier of a request to be stopped.", _affectedRequestId); } @@ -525,31 +412,30 @@ int ControllerApp::runImpl() { Request::Ptr request; if ("REPLICATE" == _requestType) { - request = controller->replicate( - _workerName, _sourceWorkerName, _databaseName, _chunkNumber, - [](Request::Ptr const& request_) { request_->print(); }, _priority, !_doNotTrackRequest, - _allowDuplicates); - + request = ReplicationRequest::createAndStart( + controller, _workerName, _sourceWorkerName, _databaseName, _chunkNumber, + [](ReplicationRequest::Ptr const& request_) { request_->print(); }, _priority, + !_doNotTrackRequest, _allowDuplicates); } else if ("DELETE" == _requestType) { - request = controller->deleteReplica(_workerName, _databaseName, _chunkNumber, Request::defaultPrinter, - _priority, !_doNotTrackRequest, _allowDuplicates); - + request = DeleteRequest::createAndStart(controller, _workerName, _databaseName, _chunkNumber, + Request::defaultPrinter, _priority, !_doNotTrackRequest, + _allowDuplicates); } else if ("FIND" == _requestType) { - request = controller->findReplica(_workerName, _databaseName, _chunkNumber, Request::defaultPrinter, - _priority, _computeCheckSum, !_doNotTrackRequest); - + request = FindRequest::createAndStart(controller, _workerName, _databaseName, _chunkNumber, + Request::defaultPrinter, _priority, _computeCheckSum, + !_doNotTrackRequest); } else if ("FIND_ALL" == _requestType) { - request = controller->findAllReplicas(_workerName, _databaseName, !_doNotSaveReplicaInfo, - Request::defaultPrinter, _priority, !_doNotTrackRequest); - + request = + FindAllRequest::createAndStart(controller, _workerName, _databaseName, !_doNotSaveReplicaInfo, + Request::defaultPrinter, _priority, !_doNotTrackRequest); } else if ("ECHO" == _requestType) { - request = controller->echo(_workerName, _echoData, _echoDelayMilliseconds, Request::defaultPrinter, - _priority, !_doNotTrackRequest); - + request = EchoRequest::createAndStart(controller, _workerName, _echoData, _echoDelayMilliseconds, + Request::defaultPrinter, _priority, !_doNotTrackRequest); } else if ("INDEX" == _requestType) { bool const hasTransactions = _transactionId != numeric_limits::max(); - request = controller->directorIndex( - _workerName, _sqlDatabase, _sqlTable, _chunkNumber, hasTransactions, _transactionId, + request = DirectorIndexRequest::createAndStart( + controller, _workerName, _sqlDatabase, _sqlTable, _chunkNumber, hasTransactions, + _transactionId, [&](DirectorIndexRequest::Ptr const& request_) { Request::defaultPrinter(request_); auto const& responseData = request_->responseData(); @@ -570,132 +456,117 @@ int ControllerApp::runImpl() { } }, _priority, !_doNotTrackRequest); - } else if ("SQL_ALTER_TABLES" == _requestType) { vector const tables = {_sqlTable}; - request = controller->sqlAlterTables(_workerName, _sqlDatabase, tables, _sqlAlterSpec, - SqlRequest::extendedPrinter, _priority, !_doNotTrackRequest); - + request = SqlAlterTablesRequest::createAndStart(controller, _workerName, _sqlDatabase, tables, + _sqlAlterSpec, SqlRequest::extendedPrinter, _priority, + !_doNotTrackRequest); } else if ("SQL_QUERY" == _requestType) { - request = controller->sqlQuery(_workerName, _sqlQuery, _sqlUser, _sqlPassword, _sqlMaxRows, - SqlRequest::extendedPrinter, _priority, !_doNotTrackRequest); - + request = SqlQueryRequest::createAndStart(controller, _workerName, _sqlQuery, _sqlUser, _sqlPassword, + _sqlMaxRows, SqlRequest::extendedPrinter, _priority, + !_doNotTrackRequest); } else if ("SQL_CREATE_DATABASE" == _requestType) { - request = controller->sqlCreateDb(_workerName, _sqlDatabase, SqlRequest::extendedPrinter, _priority, - !_doNotTrackRequest); - + request = SqlCreateDbRequest::createAndStart(controller, _workerName, _sqlDatabase, + SqlRequest::extendedPrinter, _priority, + !_doNotTrackRequest); } else if ("SQL_DELETE_DATABASE" == _requestType) { - request = controller->sqlDeleteDb(_workerName, _sqlDatabase, SqlRequest::extendedPrinter, _priority, - !_doNotTrackRequest); - + request = SqlDeleteDbRequest::createAndStart(controller, _workerName, _sqlDatabase, + SqlRequest::extendedPrinter, _priority, + !_doNotTrackRequest); } else if ("SQL_ENABLE_DATABASE" == _requestType) { - request = controller->sqlEnableDb(_workerName, _sqlDatabase, SqlRequest::extendedPrinter, _priority, - !_doNotTrackRequest); - + request = SqlEnableDbRequest::createAndStart(controller, _workerName, _sqlDatabase, + SqlRequest::extendedPrinter, _priority, + !_doNotTrackRequest); } else if ("SQL_DISABLE_DATABASE" == _requestType) { - request = controller->sqlDisableDb(_workerName, _sqlDatabase, SqlRequest::extendedPrinter, _priority, - !_doNotTrackRequest); - + request = SqlDisableDbRequest::createAndStart(controller, _workerName, _sqlDatabase, + SqlRequest::extendedPrinter, _priority, + !_doNotTrackRequest); } else if ("SQL_GRANT_ACCESS" == _requestType) { - request = controller->sqlGrantAccess(_workerName, _sqlDatabase, _sqlUser, SqlRequest::extendedPrinter, - _priority, !_doNotTrackRequest); - + request = SqlGrantAccessRequest::createAndStart(controller, _workerName, _sqlDatabase, _sqlUser, + SqlRequest::extendedPrinter, _priority, + !_doNotTrackRequest); } else if ("SQL_CREATE_TABLE" == _requestType) { - request = controller->sqlCreateTable(_workerName, _sqlDatabase, _sqlTable, _sqlEngine, - _sqlPartitionByColumn, - SqlSchemaUtils::readFromTextFile(_sqlSchemaFile), - SqlRequest::extendedPrinter, _priority, !_doNotTrackRequest); - + request = SqlCreateTableRequest::createAndStart( + controller, _workerName, _sqlDatabase, _sqlTable, _sqlEngine, _sqlPartitionByColumn, + SqlSchemaUtils::readFromTextFile(_sqlSchemaFile), SqlRequest::extendedPrinter, _priority, + !_doNotTrackRequest); } else if ("SQL_CREATE_TABLES" == _requestType) { vector const tables = {_sqlTable}; - request = controller->sqlCreateTables(_workerName, _sqlDatabase, tables, _sqlEngine, - _sqlPartitionByColumn, - SqlSchemaUtils::readFromTextFile(_sqlSchemaFile), - SqlRequest::extendedPrinter, _priority, !_doNotTrackRequest); - + request = SqlCreateTablesRequest::createAndStart( + controller, _workerName, _sqlDatabase, tables, _sqlEngine, _sqlPartitionByColumn, + SqlSchemaUtils::readFromTextFile(_sqlSchemaFile), SqlRequest::extendedPrinter, _priority, + !_doNotTrackRequest); } else if ("SQL_DELETE_TABLE" == _requestType) { vector const tables = {_sqlTable}; - request = controller->sqlDeleteTable(_workerName, _sqlDatabase, tables, SqlRequest::extendedPrinter, - _priority, !_doNotTrackRequest); - + request = SqlDeleteTableRequest::createAndStart(controller, _workerName, _sqlDatabase, tables, + SqlRequest::extendedPrinter, _priority, + !_doNotTrackRequest); } else if ("SQL_REMOVE_TABLE_PARTITIONS" == _requestType) { vector const tables = {_sqlTable}; - request = controller->sqlRemoveTablePartitions(_workerName, _sqlDatabase, tables, - SqlRequest::extendedPrinter, _priority, - !_doNotTrackRequest); - + request = SqlRemoveTablePartitionsRequest::createAndStart(controller, _workerName, _sqlDatabase, + tables, SqlRequest::extendedPrinter, + _priority, !_doNotTrackRequest); } else if ("SQL_DELETE_TABLE_PARTITION" == _requestType) { vector const tables = {_sqlTable}; - request = controller->sqlDeleteTablePartition(_workerName, _sqlDatabase, tables, _transactionId, - SqlRequest::extendedPrinter, _priority, - !_doNotTrackRequest); - + request = SqlDeleteTablePartitionRequest::createAndStart( + controller, _workerName, _sqlDatabase, tables, _transactionId, SqlRequest::extendedPrinter, + _priority, !_doNotTrackRequest); } else if ("SQL_CREATE_TABLE_INDEXES" == _requestType) { vector const tables = {_sqlTable}; - request = controller->sqlCreateTableIndexes( - _workerName, _sqlDatabase, tables, SqlRequestParams::IndexSpec(_sqlIndexSpecStr), + request = SqlCreateIndexesRequest::createAndStart( + controller, _workerName, _sqlDatabase, tables, SqlRequestParams::IndexSpec(_sqlIndexSpecStr), _sqlIndexName, _sqlIndexComment, SqlSchemaUtils::readIndexSpecFromTextFile(_sqlIndexColumnsFile), SqlRequest::extendedPrinter, _priority, !_doNotTrackRequest); - } else if ("SQL_DROP_TABLE_INDEXES" == _requestType) { vector const tables = {_sqlTable}; - request = - controller->sqlDropTableIndexes(_workerName, _sqlDatabase, tables, _sqlIndexName, - SqlRequest::extendedPrinter, _priority, !_doNotTrackRequest); - + request = SqlDropIndexesRequest::createAndStart(controller, _workerName, _sqlDatabase, tables, + _sqlIndexName, SqlRequest::extendedPrinter, _priority, + !_doNotTrackRequest); } else if ("SQL_GET_TABLE_INDEXES" == _requestType) { vector const tables = {_sqlTable}; - request = controller->sqlGetTableIndexes(_workerName, _sqlDatabase, tables, - SqlRequest::extendedPrinter, _priority, !_doNotTrackRequest); - + request = SqlGetIndexesRequest::createAndStart(controller, _workerName, _sqlDatabase, tables, + SqlRequest::extendedPrinter, _priority, + !_doNotTrackRequest); } else if ("SQL_TABLE_ROW_STATS" == _requestType) { auto const databaseInfo = controller->serviceProvider()->config()->databaseInfo(_sqlDatabase); bool const isPartitioned = databaseInfo.findTable(_sqlTable).isPartitioned; vector const tables = { isPartitioned ? ChunkedTable(_sqlTable, _chunkNumber, _isOverlap).name() : _sqlTable}; - request = controller->sqlRowStats(_workerName, _sqlDatabase, tables, SqlRequest::extendedPrinter, - _priority, !_doNotTrackRequest); - + request = SqlRowStatsRequest::createAndStart(controller, _workerName, _sqlDatabase, tables, + SqlRequest::extendedPrinter, _priority, + !_doNotTrackRequest); } else if ("STATUS" == _requestType) { request = _launchStatusRequest(controller); - } else if ("STOP" == _requestType) { - request = _launchStatusRequest(controller); - + request = _launchStopRequest(controller); } else if ("DISPOSE" == _requestType) { vector const targetIds = {_affectedRequestId}; - request = controller->dispose(_workerName, targetIds, Request::defaultPrinter); - + request = DisposeRequest::createAndStart(controller, _workerName, targetIds, Request::defaultPrinter); } else if ("SERVICE_SUSPEND" == _requestType) { - request = - controller->suspendWorkerService(_workerName, ServiceManagementRequestBase::extendedPrinter); - + request = ServiceSuspendRequest::createAndStart(controller, _workerName, + ServiceManagementRequestBase::extendedPrinter); } else if ("SERVICE_RESUME" == _requestType) { - request = controller->resumeWorkerService(_workerName, ServiceManagementRequestBase::extendedPrinter); - + request = ServiceResumeRequest::createAndStart(controller, _workerName, + ServiceManagementRequestBase::extendedPrinter); } else if ("SERVICE_STATUS" == _requestType) { - request = - controller->statusOfWorkerService(_workerName, ServiceManagementRequestBase::extendedPrinter); - + request = ServiceStatusRequest::createAndStart(controller, _workerName, + ServiceManagementRequestBase::extendedPrinter); } else if ("SERVICE_REQUESTS" == _requestType) { - request = controller->requestsOfWorkerService(_workerName, - ServiceManagementRequestBase::extendedPrinter); - + request = ServiceRequestsRequest::createAndStart(controller, _workerName, + ServiceManagementRequestBase::extendedPrinter); } else if ("SERVICE_DRAIN" == _requestType) { - request = controller->drainWorkerService(_workerName, ServiceManagementRequestBase::extendedPrinter); - + request = ServiceDrainRequest::createAndStart(controller, _workerName, + ServiceManagementRequestBase::extendedPrinter); } else if ("SERVICE_RECONFIG" == _requestType) { - request = - controller->reconfigWorkerService(_workerName, ServiceManagementRequestBase::extendedPrinter); - + request = ServiceReconfigRequest::createAndStart(controller, _workerName, + ServiceManagementRequestBase::extendedPrinter); } else { throw logic_error(context + "unsupported request: " + _affectedRequest); } // Cancel the last request if required, or just block the thread waiting // before it will finish. - if (_cancelDelayMilliseconds != 0) { util::BlockPost blockPost(_cancelDelayMilliseconds, _cancelDelayMilliseconds + 1); blockPost.wait(); @@ -707,62 +578,15 @@ int ControllerApp::runImpl() { } Request::Ptr ControllerApp::_launchStatusRequest(Controller::Ptr const& controller) const { - ::ManagementRequestLauncher l(controller, _workerName, _affectedRequestId, _priority, _doNotTrackRequest); - - if ("REPLICATE" == _affectedRequest) return l.status(); - if ("DELETE" == _affectedRequest) return l.status(); - if ("FIND" == _affectedRequest) return l.status(); - if ("FIND_ALL" == _affectedRequest) return l.status(); - if ("ECHO" == _affectedRequest) return l.status(); - if ("INDEX" == _affectedRequest) return l.status(); - if ("SQL_ALTER_TABLES" == _affectedRequest) return l.status(); - if ("SQL_QUERY" == _affectedRequest) return l.status(); - if ("SQL_CREATE_DATABASE" == _affectedRequest) return l.status(); - if ("SQL_DELETE_DATABASE" == _affectedRequest) return l.status(); - if ("SQL_ENABLE_DATABASE" == _affectedRequest) return l.status(); - if ("SQL_DISABLE_DATABASE" == _affectedRequest) return l.status(); - if ("SQL_GRANT_ACCESS" == _affectedRequest) return l.status(); - if ("SQL_CREATE_TABLE" == _affectedRequest) return l.status(); - if ("SQL_CREATE_TABLES" == _affectedRequest) return l.status(); - if ("SQL_CREATE_TABLE_INDEXES" == _affectedRequest) return l.status(); - if ("SQL_DELETE_TABLE" == _affectedRequest) return l.status(); - if ("SQL_DROP_TABLE_INDEXES" == _affectedRequest) return l.status(); - if ("SQL_GET_TABLE_INDEXES" == _affectedRequest) return l.status(); - if ("SQL_REMOVE_TABLE_PARTITIONS" == _affectedRequest) - return l.status(); - if ("SQL_DELETE_TABLE_PARTITION" == _affectedRequest) - return l.status(); - - throw logic_error("ControllerApp::" + string(__func__) + " unsupported request: " + _affectedRequest); + return StatusRequest::createAndStart( + controller, _workerName, _affectedRequestId, + [](StatusRequest::Ptr const& request_) { request_->print(); }, !_doNotTrackRequest); } Request::Ptr ControllerApp::_launchStopRequest(Controller::Ptr const& controller) const { - ::ManagementRequestLauncher l(controller, _workerName, _affectedRequestId, _priority, _doNotTrackRequest); - - if ("REPLICATE" == _affectedRequest) return l.stop(); - if ("DELETE" == _affectedRequest) return l.stop(); - if ("FIND" == _affectedRequest) return l.stop(); - if ("FIND_ALL" == _affectedRequest) return l.stop(); - if ("ECHO" == _affectedRequest) return l.stop(); - if ("INDEX" == _affectedRequest) return l.stop(); - if ("SQL_ALTER_TABLES" == _affectedRequest) return l.stop(); - if ("SQL_QUERY" == _affectedRequest) return l.stop(); - if ("SQL_CREATE_DATABASE" == _affectedRequest) return l.stop(); - if ("SQL_DELETE_DATABASE" == _affectedRequest) return l.stop(); - if ("SQL_ENABLE_DATABASE" == _affectedRequest) return l.stop(); - if ("SQL_DISABLE_DATABASE" == _affectedRequest) return l.stop(); - if ("SQL_GRANT_ACCESS" == _affectedRequest) return l.stop(); - if ("SQL_CREATE_TABLE" == _affectedRequest) return l.stop(); - if ("SQL_CREATE_TABLES" == _affectedRequest) return l.stop(); - if ("SQL_CREATE_TABLE_INDEXES" == _affectedRequest) return l.stop(); - if ("SQL_DELETE_TABLE" == _affectedRequest) return l.stop(); - if ("SQL_DROP_TABLE_INDEXES" == _affectedRequest) return l.stop(); - if ("SQL_GET_TABLE_INDEXES" == _affectedRequest) return l.stop(); - if ("SQL_REMOVE_TABLE_PARTITIONS" == _affectedRequest) - return l.stop(); - if ("SQL_DELETE_TABLE_PARTITION" == _affectedRequest) return l.stop(); - - throw logic_error("ControllerApp::" + string(__func__) + " unsupported request: " + _affectedRequest); + return StopRequest::createAndStart( + controller, _workerName, _affectedRequestId, + [](StopRequest::Ptr const& request_) { request_->print(); }, !_doNotTrackRequest); } } // namespace lsst::qserv::replica diff --git a/src/replica/apps/MessengerTestApp.cc b/src/replica/apps/MessengerTestApp.cc index 220471fa6..255da98c0 100644 --- a/src/replica/apps/MessengerTestApp.cc +++ b/src/replica/apps/MessengerTestApp.cc @@ -117,8 +117,8 @@ int MessengerTestApp::runImpl() { _onNumActiveCv.wait(lock, [&] { return _numActive < _maxActiveRequests; }); // Submit the next request. - auto const request = controller->echo( - _workerName, _data, _proccesingTimeSec, + auto const request = EchoRequest::createAndStart( + controller, _workerName, _data, _proccesingTimeSec, [&](EchoRequest::Ptr request) { { unique_lock lock(_mtx); diff --git a/src/replica/contr/Controller.cc b/src/replica/contr/Controller.cc index 5ff0a0871..f891e040a 100644 --- a/src/replica/contr/Controller.cc +++ b/src/replica/contr/Controller.cc @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include // Qserv headers @@ -35,33 +37,7 @@ #include "replica/config/Configuration.h" #include "replica/config/ConfigWorker.h" #include "replica/registry/Registry.h" -#include "replica/requests/DeleteRequest.h" -#include "replica/requests/DisposeRequest.h" -#include "replica/requests/EchoRequest.h" -#include "replica/requests/FindRequest.h" -#include "replica/requests/FindAllRequest.h" -#include "replica/requests/DirectorIndexRequest.h" -#include "replica/requests/Messenger.h" -#include "replica/requests/ReplicationRequest.h" -#include "replica/requests/ServiceManagementRequest.h" -#include "replica/requests/SqlAlterTablesRequest.h" -#include "replica/requests/SqlQueryRequest.h" -#include "replica/requests/SqlCreateDbRequest.h" -#include "replica/requests/SqlCreateIndexesRequest.h" -#include "replica/requests/SqlCreateTableRequest.h" -#include "replica/requests/SqlCreateTablesRequest.h" -#include "replica/requests/SqlDeleteDbRequest.h" -#include "replica/requests/SqlDeleteTablePartitionRequest.h" -#include "replica/requests/SqlDeleteTableRequest.h" -#include "replica/requests/SqlDisableDbRequest.h" -#include "replica/requests/SqlDropIndexesRequest.h" -#include "replica/requests/SqlGetIndexesRequest.h" -#include "replica/requests/SqlEnableDbRequest.h" -#include "replica/requests/SqlGrantAccessRequest.h" -#include "replica/requests/SqlRemoveTablePartitionsRequest.h" -#include "replica/requests/SqlRowStatsRequest.h" -#include "replica/requests/StatusRequest.h" -#include "replica/requests/StopRequest.h" +#include "replica/requests/Request.h" #include "replica/services/DatabaseServices.h" #include "replica/services/ServiceProvider.h" #include "replica/util/Common.h" @@ -166,7 +142,7 @@ ostream& operator<<(ostream& os, ControllerIdentity const& identity) { return os; } -Controller::Ptr Controller::create(ServiceProvider::Ptr const& serviceProvider) { +Controller::Ptr Controller::create(shared_ptr const& serviceProvider) { auto const ptr = Controller::Ptr(new Controller(serviceProvider)); // The code below is starting the worker status tracking algorithm that would @@ -180,7 +156,6 @@ Controller::Ptr Controller::create(ServiceProvider::Ptr const& serviceProvider) // iteration of the 'for' loop to allow external control over enabling/disabling // new workers to join the cluster. Also note that the automatic registration of // workers should be only allowed in the Master Replication Controller. - string const context = ptr->_context(__func__) + " "; weak_ptr w = ptr; thread t([controller = move(w), context]() { ::tracker(controller, context); }); @@ -188,10 +163,10 @@ Controller::Ptr Controller::create(ServiceProvider::Ptr const& serviceProvider) return ptr; } -Controller::Controller(ServiceProvider::Ptr const& serviceProvider) - : _identity({Generators::uniqueId(), boost::asio::ip::host_name(), getpid()}), - _startTime(util::TimeUtils::now()), - _serviceProvider(serviceProvider) { +Controller::Controller(shared_ptr const& serviceProvider) + : _serviceProvider(serviceProvider), + _identity({Generators::uniqueId(), boost::asio::ip::host_name(), getpid()}), + _startTime(util::TimeUtils::now()) { serviceProvider->databaseServices()->saveState(_identity, _startTime); } @@ -205,321 +180,14 @@ void Controller::verifyFolders(bool createMissingFolders) const { FileUtils::verifyFolders("CONTROLLER", folders, createMissingFolders); } -ReplicationRequest::Ptr Controller::replicate(string const& workerName, string const& sourceWorkerName, - string const& database, unsigned int chunk, - ReplicationRequest::CallbackType const& onFinish, int priority, - bool keepTracking, bool allowDuplicate, string const& jobId, - unsigned int requestExpirationIvalSec) { - LOGS(_log, LOG_LVL_TRACE, _context(__func__)); - return _submit(workerName, sourceWorkerName, database, chunk, allowDuplicate, - onFinish, priority, keepTracking, jobId, - requestExpirationIvalSec); -} - -DeleteRequest::Ptr Controller::deleteReplica(string const& workerName, string const& database, - unsigned int chunk, DeleteRequest::CallbackType const& onFinish, - int priority, bool keepTracking, bool allowDuplicate, - string const& jobId, unsigned int requestExpirationIvalSec) { - LOGS(_log, LOG_LVL_TRACE, _context(__func__)); - return _submit( - workerName, database, chunk, allowDuplicate, onFinish, priority, keepTracking, jobId, - requestExpirationIvalSec); -} - -FindRequest::Ptr Controller::findReplica(string const& workerName, string const& database, unsigned int chunk, - FindRequest::CallbackType const& onFinish, int priority, - bool computeCheckSum, bool keepTracking, string const& jobId, - unsigned int requestExpirationIvalSec) { - LOGS(_log, LOG_LVL_TRACE, _context(__func__)); - return _submit( - workerName, database, chunk, computeCheckSum, onFinish, priority, keepTracking, jobId, - requestExpirationIvalSec); -} - -FindAllRequest::Ptr Controller::findAllReplicas(string const& workerName, string const& database, - bool saveReplicaInfo, - FindAllRequest::CallbackType const& onFinish, int priority, - bool keepTracking, string const& jobId, - unsigned int requestExpirationIvalSec) { - LOGS(_log, LOG_LVL_TRACE, _context(__func__)); - return _submit( - workerName, database, saveReplicaInfo, onFinish, priority, keepTracking, jobId, - requestExpirationIvalSec); -} - -EchoRequest::Ptr Controller::echo(string const& workerName, string const& data, uint64_t delay, - EchoRequest::CallbackType const& onFinish, int priority, bool keepTracking, - string const& jobId, unsigned int requestExpirationIvalSec) { - LOGS(_log, LOG_LVL_TRACE, _context(__func__)); - return _submit( - workerName, data, delay, onFinish, priority, keepTracking, jobId, requestExpirationIvalSec); -} - -DirectorIndexRequest::Ptr Controller::directorIndex(string const& workerName, string const& database, - string const& directorTable, unsigned int chunk, - bool hasTransactions, TransactionId transactionId, - DirectorIndexRequest::CallbackType const& onFinish, - int priority, bool keepTracking, string const& jobId, - unsigned int requestExpirationIvalSec) { - LOGS(_log, LOG_LVL_TRACE, _context(__func__)); - return _submit( - workerName, database, directorTable, chunk, hasTransactions, transactionId, onFinish, priority, - keepTracking, jobId, requestExpirationIvalSec); -} - -SqlAlterTablesRequest::Ptr Controller::sqlAlterTables( - string const& workerName, string const& database, vector const& tables, - string const& alterSpec, function const& onFinish, int priority, - bool keepTracking, string const& jobId, unsigned int requestExpirationIvalSec) { - LOGS(_log, LOG_LVL_TRACE, _context(__func__)); - return _submit( - workerName, database, tables, alterSpec, onFinish, priority, keepTracking, jobId, - requestExpirationIvalSec); -} - -SqlQueryRequest::Ptr Controller::sqlQuery(string const& workerName, string const& query, string const& user, - string const& password, uint64_t maxRows, - SqlQueryRequest::CallbackType const& onFinish, int priority, - bool keepTracking, string const& jobId, - unsigned int requestExpirationIvalSec) { - LOGS(_log, LOG_LVL_TRACE, _context(__func__)); - return _submit( - workerName, query, user, password, maxRows, onFinish, priority, keepTracking, jobId, - requestExpirationIvalSec); -} - -SqlCreateDbRequest::Ptr Controller::sqlCreateDb(string const& workerName, string const& database, - SqlCreateDbRequest::CallbackType const& onFinish, - int priority, bool keepTracking, string const& jobId, - unsigned int requestExpirationIvalSec) { - LOGS(_log, LOG_LVL_TRACE, _context(__func__)); - return _submit(workerName, database, onFinish, priority, - keepTracking, jobId, requestExpirationIvalSec); -} - -SqlDeleteDbRequest::Ptr Controller::sqlDeleteDb(string const& workerName, string const& database, - SqlDeleteDbRequest::CallbackType const& onFinish, - int priority, bool keepTracking, string const& jobId, - unsigned int requestExpirationIvalSec) { - LOGS(_log, LOG_LVL_TRACE, _context(__func__)); - return _submit(workerName, database, onFinish, priority, - keepTracking, jobId, requestExpirationIvalSec); -} - -SqlEnableDbRequest::Ptr Controller::sqlEnableDb(string const& workerName, string const& database, - SqlEnableDbRequest::CallbackType const& onFinish, - int priority, bool keepTracking, string const& jobId, - unsigned int requestExpirationIvalSec) { - LOGS(_log, LOG_LVL_TRACE, _context(__func__)); - return _submit(workerName, database, onFinish, priority, - keepTracking, jobId, requestExpirationIvalSec); -} - -SqlDisableDbRequest::Ptr Controller::sqlDisableDb(string const& workerName, string const& database, - SqlDisableDbRequest::CallbackType const& onFinish, - int priority, bool keepTracking, string const& jobId, - unsigned int requestExpirationIvalSec) { - LOGS(_log, LOG_LVL_TRACE, _context(__func__)); - return _submit(workerName, database, onFinish, priority, - keepTracking, jobId, requestExpirationIvalSec); -} - -SqlGrantAccessRequest::Ptr Controller::sqlGrantAccess(string const& workerName, string const& database, - string const& user, - SqlGrantAccessRequest::CallbackType const& onFinish, - int priority, bool keepTracking, string const& jobId, - unsigned int requestExpirationIvalSec) { - LOGS(_log, LOG_LVL_TRACE, _context(__func__)); - return _submit( - workerName, database, user, onFinish, priority, keepTracking, jobId, requestExpirationIvalSec); -} - -SqlCreateIndexesRequest::Ptr Controller::sqlCreateTableIndexes( - string const& workerName, string const& database, vector const& tables, - SqlRequestParams::IndexSpec const& indexSpec, string const& indexName, string const& indexComment, - vector const& indexColumns, - function const& onFinish, int priority, bool keepTracking, - string const& jobId, unsigned int requestExpirationIvalSec) { - LOGS(_log, LOG_LVL_TRACE, _context(__func__)); - return _submit( - workerName, database, tables, indexSpec, indexName, indexComment, indexColumns, onFinish, - priority, keepTracking, jobId, requestExpirationIvalSec); -} - -SqlCreateTableRequest::Ptr Controller::sqlCreateTable(string const& workerName, string const& database, - string const& table, string const& engine, - string const& partitionByColumn, - list const& columns, - SqlCreateTableRequest::CallbackType const& onFinish, - int priority, bool keepTracking, string const& jobId, - unsigned int requestExpirationIvalSec) { - LOGS(_log, LOG_LVL_TRACE, _context(__func__)); - return _submit( - workerName, database, table, engine, partitionByColumn, columns, onFinish, priority, keepTracking, - jobId, requestExpirationIvalSec); -} - -SqlCreateTablesRequest::Ptr Controller::sqlCreateTables(string const& workerName, string const& database, - vector const& tables, string const& engine, - string const& partitionByColumn, - list const& columns, - SqlCreateTablesRequest::CallbackType const& onFinish, - int priority, bool keepTracking, string const& jobId, - unsigned int requestExpirationIvalSec) { - LOGS(_log, LOG_LVL_TRACE, _context(__func__)); - return _submit( - workerName, database, tables, engine, partitionByColumn, columns, onFinish, priority, - keepTracking, jobId, requestExpirationIvalSec); -} - -SqlDeleteTableRequest::Ptr Controller::sqlDeleteTable(string const& workerName, string const& database, - vector const& tables, - SqlDeleteTableRequest::CallbackType const& onFinish, - int priority, bool keepTracking, string const& jobId, - unsigned int requestExpirationIvalSec) { - LOGS(_log, LOG_LVL_TRACE, _context(__func__)); - return _submit( - workerName, database, tables, onFinish, priority, keepTracking, jobId, requestExpirationIvalSec); -} - -SqlRemoveTablePartitionsRequest::Ptr Controller::sqlRemoveTablePartitions( - string const& workerName, string const& database, vector const& tables, - SqlRemoveTablePartitionsRequest::CallbackType const& onFinish, int priority, bool keepTracking, - string const& jobId, unsigned int requestExpirationIvalSec) { - LOGS(_log, LOG_LVL_TRACE, _context(__func__)); - return _submit( - workerName, database, tables, onFinish, priority, keepTracking, jobId, requestExpirationIvalSec); -} - -SqlDeleteTablePartitionRequest::Ptr Controller::sqlDeleteTablePartition( - string const& workerName, string const& database, vector const& tables, - TransactionId transactionId, SqlDeleteTablePartitionRequest::CallbackType const& onFinish, - int priority, bool keepTracking, string const& jobId, unsigned int requestExpirationIvalSec) { - LOGS(_log, LOG_LVL_TRACE, _context(__func__)); - return _submit(workerName, database, tables, transactionId, onFinish, priority, - keepTracking, jobId, requestExpirationIvalSec); -} - -SqlDropIndexesRequest::Ptr Controller::sqlDropTableIndexes( - string const& workerName, string const& database, vector const& tables, - string const& indexName, function const& onFinish, int priority, - bool keepTracking, string const& jobId, unsigned int requestExpirationIvalSec) { - LOGS(_log, LOG_LVL_TRACE, _context(__func__)); - return _submit( - workerName, database, tables, indexName, onFinish, priority, keepTracking, jobId, - requestExpirationIvalSec); -} - -SqlGetIndexesRequest::Ptr Controller::sqlGetTableIndexes( - string const& workerName, string const& database, vector const& tables, - function const& onFinish, int priority, bool keepTracking, - string const& jobId, unsigned int requestExpirationIvalSec) { - LOGS(_log, LOG_LVL_TRACE, _context(__func__)); - return _submit( - workerName, database, tables, onFinish, priority, keepTracking, jobId, requestExpirationIvalSec); -} - -SqlRowStatsRequest::Ptr Controller::sqlRowStats( - std::string const& workerName, string const& database, std::vector const& tables, - std::function)> const& onFinish, int priority, - bool keepTracking, std::string const& jobId, unsigned int requestExpirationIvalSec) { - LOGS(_log, LOG_LVL_TRACE, _context(__func__)); - return _submit( - workerName, database, tables, onFinish, priority, keepTracking, jobId, requestExpirationIvalSec); -} - -DisposeRequest::Ptr Controller::dispose(string const& workerName, vector const& targetIds, - function const& onFinish, int priority, - bool keepTracking, string const& jobId, - unsigned int requestExpirationIvalSec) { - LOGS(_log, LOG_LVL_TRACE, _context(__func__)); - return _submit(workerName, targetIds, onFinish, priority, - keepTracking, jobId, requestExpirationIvalSec); -} - -ServiceSuspendRequest::Ptr Controller::suspendWorkerService( - string const& workerName, ServiceSuspendRequest::CallbackType const& onFinish, int priority, - string const& jobId, unsigned int requestExpirationIvalSec) { - LOGS(_log, LOG_LVL_TRACE, _context(__func__) << " workerName: " << workerName); - return _submit(workerName, onFinish, priority, jobId, requestExpirationIvalSec); -} - -ServiceResumeRequest::Ptr Controller::resumeWorkerService(string const& workerName, - ServiceResumeRequest::CallbackType const& onFinish, - int priority, string const& jobId, - unsigned int requestExpirationIvalSec) { - LOGS(_log, LOG_LVL_TRACE, _context(__func__) << " workerName: " << workerName); - return _submit(workerName, onFinish, priority, jobId, requestExpirationIvalSec); -} - -ServiceStatusRequest::Ptr Controller::statusOfWorkerService( - string const& workerName, ServiceStatusRequest::CallbackType const& onFinish, int priority, - string const& jobId, unsigned int requestExpirationIvalSec) { - LOGS(_log, LOG_LVL_TRACE, _context(__func__) << " workerName: " << workerName); - return _submit(workerName, onFinish, priority, jobId, requestExpirationIvalSec); -} - -ServiceRequestsRequest::Ptr Controller::requestsOfWorkerService( - string const& workerName, ServiceRequestsRequest::CallbackType const& onFinish, int priority, - string const& jobId, unsigned int requestExpirationIvalSec) { - LOGS(_log, LOG_LVL_TRACE, _context(__func__) + " workerName: " << workerName); - return _submit(workerName, onFinish, priority, jobId, requestExpirationIvalSec); -} - -ServiceDrainRequest::Ptr Controller::drainWorkerService(string const& workerName, - ServiceDrainRequest::CallbackType const& onFinish, - int priority, string const& jobId, - unsigned int requestExpirationIvalSec) { - LOGS(_log, LOG_LVL_TRACE, _context(__func__) << " workerName: " << workerName); - return _submit(workerName, onFinish, priority, jobId, requestExpirationIvalSec); -} - -ServiceReconfigRequest::Ptr Controller::reconfigWorkerService( - string const& workerName, ServiceReconfigRequest::CallbackType const& onFinish, int priority, - string const& jobId, unsigned int requestExpirationIvalSec) { - LOGS(_log, LOG_LVL_TRACE, _context(__func__) << " workerName: " << workerName); - return _submit(workerName, onFinish, priority, jobId, requestExpirationIvalSec); -} - -size_t Controller::numActiveRequests() const { +void Controller::_add(std::shared_ptr const& request) { replica::Lock lock(_mtx, _context(__func__)); - return _registry.size(); + _registry[request->id()] = request; } -void Controller::_debug(string const& func, string const& msg) const { - LOGS(_log, LOG_LVL_TRACE, _context(func) << " " << msg); -} - -void Controller::_finish(string const& id) { - // IMPORTANT: Make sure the lock is released before sending notifications: - // - to avoid a possibility of deadlocking in case if the callback function - // to be notified will be doing any API calls of the controller. - // - to reduce the controller API dead-time due to a prolonged - // execution time of of the callback function. - RequestWrapper::Ptr request; - { - replica::Lock lock(_mtx, _context(__func__)); - request = _registry[id]; - _registry.erase(id); - } - request->notify(); -} - -void Controller::_assertIsRunning() const { - if (not serviceProvider()->isRunning()) { - throw runtime_error("ServiceProvider::" + string(__func__) + " not running"); - } -} - -void Controller::_logManagementRequest(string const& requestName, string const& workerName) { - LOGS(_log, LOG_LVL_TRACE, - _context(__func__) << " workerName: " << workerName << " requestName: " << requestName); +void Controller::_remove(std::shared_ptr const& request) { + replica::Lock lock(_mtx, _context(__func__)); + _registry.erase(request->id()); } } // namespace lsst::qserv::replica diff --git a/src/replica/contr/Controller.h b/src/replica/contr/Controller.h index 9741eb8a1..faa156b8b 100644 --- a/src/replica/contr/Controller.h +++ b/src/replica/contr/Controller.h @@ -28,129 +28,17 @@ // System headers #include -#include #include #include -#include -#include // Qserv headers -#include "replica/requests/Request.h" -#include "replica/services/ServiceProvider.h" #include "replica/util/Common.h" #include "replica/util/Mutex.h" // Forward declarations namespace lsst::qserv::replica { - -class ReplicationRequest; -class DeleteRequest; -class FindRequest; -class FindAllRequest; -class EchoRequest; -class DirectorIndexRequest; -class SqlAlterTablesRequest; -class SqlQueryRequest; -class SqlCreateDbRequest; -class SqlDeleteDbRequest; -class SqlEnableDbRequest; -class SqlDisableDbRequest; -class SqlGrantAccessRequest; -class SqlCreateIndexesRequest; -class SqlCreateTableRequest; -class SqlCreateTablesRequest; -class SqlDeleteTableRequest; -class SqlDropIndexesRequest; -class SqlGetIndexesRequest; -class SqlRemoveTablePartitionsRequest; -class SqlDeleteTablePartitionRequest; -class SqlRowStatsRequest; -class DisposeRequest; - -class StopReplicationRequestPolicy; -class StopDeleteRequestPolicy; -class StopFindRequestPolicy; -class StopFindAllRequestPolicy; -class StopEchoRequestPolicy; -class StopDirectorIndexRequestPolicy; -class StopSqlRequestPolicy; - -template -class StopRequest; - -using StopReplicationRequest = StopRequest; -using StopDeleteRequest = StopRequest; -using StopFindRequest = StopRequest; -using StopFindAllRequest = StopRequest; -using StopEchoRequest = StopRequest; -using StopDirectorIndexRequest = StopRequest; -using StopSqlAlterTablesRequest = StopRequest; -using StopSqlQueryRequest = StopRequest; -using StopSqlCreateDbRequest = StopRequest; -using StopSqlDeleteDbRequest = StopRequest; -using StopSqlEnableDbRequest = StopRequest; -using StopSqlDisableDbRequest = StopRequest; -using StopSqlGrantAccessRequest = StopRequest; -using StopSqlCreateIndexesRequest = StopRequest; -using StopSqlCreateTableRequest = StopRequest; -using StopSqlCreateTablesRequest = StopRequest; -using StopSqlDeleteTableRequest = StopRequest; -using StopSqlDropIndexesRequest = StopRequest; -using StopSqlGetIndexesRequest = StopRequest; -using StopSqlRemoveTablePartitionsRequest = StopRequest; -using StopSqlDeleteTablePartitionRequest = StopRequest; -using StopSqlRowStatsRequest = StopRequest; - -class StatusReplicationRequestPolicy; -class StatusDeleteRequestPolicy; -class StatusFindRequestPolicy; -class StatusFindAllRequestPolicy; -class StatusEchoRequestPolicy; -class StatusDirectorIndexRequestPolicy; -class StatusSqlRequestPolicy; - -template -class StatusRequest; - -using StatusReplicationRequest = StatusRequest; -using StatusDeleteRequest = StatusRequest; -using StatusFindRequest = StatusRequest; -using StatusFindAllRequest = StatusRequest; -using StatusEchoRequest = StatusRequest; -using StatusDirectorIndexRequest = StatusRequest; -using StatusSqlAlterTablesRequest = StatusRequest; -using StatusSqlQueryRequest = StatusRequest; -using StatusSqlCreateDbRequest = StatusRequest; -using StatusSqlDeleteDbRequest = StatusRequest; -using StatusSqlEnableDbRequest = StatusRequest; -using StatusSqlDisableDbRequest = StatusRequest; -using StatusSqlGrantAccessRequest = StatusRequest; -using StatusSqlCreateIndexesRequest = StatusRequest; -using StatusSqlCreateTableRequest = StatusRequest; -using StatusSqlCreateTablesRequest = StatusRequest; -using StatusSqlDeleteTableRequest = StatusRequest; -using StatusSqlDropIndexesRequest = StatusRequest; -using StatusSqlGetIndexesRequest = StatusRequest; -using StatusSqlRemoveTablePartitionsRequest = StatusRequest; -using StatusSqlDeleteTablePartitionRequest = StatusRequest; -using StatusSqlRowStatsRequest = StatusRequest; - -class ServiceSuspendRequestPolicy; -class ServiceResumeRequestPolicy; -class ServiceStatusRequestPolicy; -class ServiceRequestsRequestPolicy; -class ServiceDrainRequestPolicy; -class ServiceReconfigRequestPolicy; - -template -class ServiceManagementRequest; - -using ServiceSuspendRequest = ServiceManagementRequest; -using ServiceResumeRequest = ServiceManagementRequest; -using ServiceStatusRequest = ServiceManagementRequest; -using ServiceRequestsRequest = ServiceManagementRequest; -using ServiceDrainRequest = ServiceManagementRequest; -using ServiceReconfigRequest = ServiceManagementRequest; +class Request; +class ServiceProvider; } // namespace lsst::qserv::replica // This header declarations @@ -191,7 +79,7 @@ class Controller : public std::enable_shared_from_this { friend class ControllerImpl; typedef std::shared_ptr Ptr; - static Ptr create(ServiceProvider::Ptr const& serviceProvider); + static Ptr create(std::shared_ptr const& serviceProvider); Controller() = delete; Controller(Controller const&) = delete; @@ -199,12 +87,8 @@ class Controller : public std::enable_shared_from_this { ~Controller() = default; ControllerIdentity const& identity() const { return _identity; } - uint64_t startTime() const { return _startTime; } - - ServiceProvider::Ptr const& serviceProvider() const { return _serviceProvider; } - - boost::asio::io_service& io_service() { return serviceProvider()->io_service(); } + std::shared_ptr const& serviceProvider() const { return _serviceProvider; } /** * Check if required folders exist and they're write-enabled for an effective user @@ -215,395 +99,33 @@ class Controller : public std::enable_shared_from_this { */ void verifyFolders(bool createMissingFolders = false) const; - std::shared_ptr replicate( - std::string const& workerName, std::string const& sourceWorkerName, std::string const& database, - unsigned int chunk, - std::function)> const& onFinish = nullptr, - int priority = PRIORITY_NORMAL, bool keepTracking = true, bool allowDuplicate = true, - std::string const& jobId = "", unsigned int requestExpirationIvalSec = 0); - - std::shared_ptr deleteReplica( - std::string const& workerName, std::string const& database, unsigned int chunk, - std::function)> const& onFinish = nullptr, - int priority = PRIORITY_NORMAL, bool keepTracking = true, bool allowDuplicate = true, - std::string const& jobId = "", unsigned int requestExpirationIvalSec = 0); - - std::shared_ptr findReplica( - std::string const& workerName, std::string const& database, unsigned int chunk, - std::function)> const& onFinish = nullptr, - int priority = PRIORITY_NORMAL, bool computeCheckSum = false, bool keepTracking = true, - std::string const& jobId = "", unsigned int requestExpirationIvalSec = 0); - - std::shared_ptr findAllReplicas( - std::string const& workerName, std::string const& database, bool saveReplicaInfo = true, - std::function)> const& onFinish = nullptr, - int priority = PRIORITY_NORMAL, bool keepTracking = true, std::string const& jobId = "", - unsigned int requestExpirationIvalSec = 0); - - std::shared_ptr echo( - std::string const& workerName, std::string const& data, uint64_t delay, - std::function)> const& onFinish = nullptr, - int priority = PRIORITY_NORMAL, bool keepTracking = true, std::string const& jobId = "", - unsigned int requestExpirationIvalSec = 0); - - std::shared_ptr directorIndex( - std::string const& workerName, std::string const& database, std::string const& directorTable, - unsigned int chunk, bool hasTransactions, TransactionId transactionId, - std::function)> const& onFinish = nullptr, - int priority = PRIORITY_NORMAL, bool keepTracking = true, std::string const& jobId = "", - unsigned int requestExpirationIvalSec = 0); - - std::shared_ptr sqlAlterTables( - std::string const& workerName, std::string const& database, - std::vector const& tables, std::string const& alterSpec, - std::function)> const& onFinish = nullptr, - int priority = PRIORITY_NORMAL, bool keepTracking = true, std::string const& jobId = "", - unsigned int requestExpirationIvalSec = 0); - - std::shared_ptr sqlQuery( - std::string const& workerName, std::string const& query, std::string const& user, - std::string const& password, uint64_t maxRows, - std::function)> const& onFinish = nullptr, - int priority = PRIORITY_NORMAL, bool keepTracking = true, std::string const& jobId = "", - unsigned int requestExpirationIvalSec = 0); - - std::shared_ptr sqlCreateDb( - std::string const& workerName, std::string const& database, - std::function)> const& onFinish = nullptr, - int priority = PRIORITY_NORMAL, bool keepTracking = true, std::string const& jobId = "", - unsigned int requestExpirationIvalSec = 0); - - std::shared_ptr sqlDeleteDb( - std::string const& workerName, std::string const& database, - std::function)> const& onFinish = nullptr, - int priority = PRIORITY_NORMAL, bool keepTracking = true, std::string const& jobId = "", - unsigned int requestExpirationIvalSec = 0); - - std::shared_ptr sqlEnableDb( - std::string const& workerName, std::string const& database, - std::function)> const& onFinish = nullptr, - int priority = PRIORITY_NORMAL, bool keepTracking = true, std::string const& jobId = "", - unsigned int requestExpirationIvalSec = 0); - - std::shared_ptr sqlDisableDb( - std::string const& workerName, std::string const& database, - std::function)> const& onFinish = nullptr, - int priority = PRIORITY_NORMAL, bool keepTracking = true, std::string const& jobId = "", - unsigned int requestExpirationIvalSec = 0); - - std::shared_ptr sqlGrantAccess( - std::string const& workerName, std::string const& database, std::string const& user, - std::function)> const& onFinish = nullptr, - int priority = PRIORITY_NORMAL, bool keepTracking = true, std::string const& jobId = "", - unsigned int requestExpirationIvalSec = 0); - - std::shared_ptr sqlCreateTableIndexes( - std::string const& workerName, std::string const& database, - std::vector const& tables, SqlRequestParams::IndexSpec const& indexSpec, - std::string const& indexName, std::string const& indexComment, - std::vector const& indexColumns, - std::function)> const& onFinish = nullptr, - int priority = PRIORITY_NORMAL, bool keepTracking = true, std::string const& jobId = "", - unsigned int requestExpirationIvalSec = 0); - - std::shared_ptr sqlCreateTable( - std::string const& workerName, std::string const& database, std::string const& table, - std::string const& engine, std::string const& partitionByColumn, - std::list const& columns, - std::function)> const& onFinish = nullptr, - int priority = PRIORITY_NORMAL, bool keepTracking = true, std::string const& jobId = "", - unsigned int requestExpirationIvalSec = 0); - - std::shared_ptr sqlCreateTables( - std::string const& workerName, std::string const& database, - std::vector const& tables, std::string const& engine, - std::string const& partitionByColumn, std::list const& columns, - std::function)> const& onFinish = nullptr, - int priority = PRIORITY_NORMAL, bool keepTracking = true, std::string const& jobId = "", - unsigned int requestExpirationIvalSec = 0); - - std::shared_ptr sqlDeleteTable( - std::string const& workerName, std::string const& database, - std::vector const& tables, - std::function)> const& onFinish = nullptr, - int priority = PRIORITY_NORMAL, bool keepTracking = true, std::string const& jobId = "", - unsigned int requestExpirationIvalSec = 0); - - std::shared_ptr sqlRemoveTablePartitions( - std::string const& workerName, std::string const& database, - std::vector const& tables, - std::function)> const& onFinish = nullptr, - int priority = PRIORITY_NORMAL, bool keepTracking = true, std::string const& jobId = "", - unsigned int requestExpirationIvalSec = 0); - - std::shared_ptr sqlDeleteTablePartition( - std::string const& workerName, std::string const& database, - std::vector const& tables, TransactionId transactionId, - std::function)> const& onFinish = nullptr, - int priority = PRIORITY_NORMAL, bool keepTracking = true, std::string const& jobId = "", - unsigned int requestExpirationIvalSec = 0); - - std::shared_ptr sqlDropTableIndexes( - std::string const& workerName, std::string const& database, - std::vector const& tables, std::string const& indexName, - std::function)> const& onFinish = nullptr, - int priority = PRIORITY_NORMAL, bool keepTracking = true, std::string const& jobId = "", - unsigned int requestExpirationIvalSec = 0); - - std::shared_ptr sqlGetTableIndexes( - std::string const& workerName, std::string const& database, - std::vector const& tables, - std::function)> const& onFinish = nullptr, - int priority = PRIORITY_NORMAL, bool keepTracking = true, std::string const& jobId = "", - unsigned int requestExpirationIvalSec = 0); - - std::shared_ptr sqlRowStats( - std::string const& workerName, std::string const& database, - std::vector const& tables, - std::function)> const& onFinish = nullptr, - int priority = PRIORITY_NORMAL, bool keepTracking = true, std::string const& jobId = "", - unsigned int requestExpirationIvalSec = 0); - - std::shared_ptr dispose( - std::string const& workerName, std::vector const& targetIds, - std::function)> const& onFinish = nullptr, - int priority = PRIORITY_NORMAL, bool keepTracking = true, std::string const& jobId = "", - unsigned int requestExpirationIvalSec = 0); - - template - typename REQUEST::Ptr stopById(std::string const& workerName, std::string const& targetRequestId, - typename REQUEST::CallbackType const& onFinish = nullptr, - int priority = PRIORITY_NORMAL, bool keepTracking = true, - std::string const& jobId = "", unsigned int requestExpirationIvalSec = 0) { - _debug(__func__, "targetRequestId: " + targetRequestId); - return _submit(workerName, targetRequestId, onFinish, priority, - keepTracking, jobId, requestExpirationIvalSec); - } - - template - typename REQUEST::Ptr statusById(std::string const& workerName, std::string const& targetRequestId, - typename REQUEST::CallbackType const& onFinish = nullptr, - int priority = PRIORITY_NORMAL, bool keepTracking = true, - std::string const& jobId = "", - unsigned int requestExpirationIvalSec = 0) { - _debug(__func__, "targetRequestId: " + targetRequestId); - return _submit(workerName, targetRequestId, onFinish, priority, - keepTracking, jobId, requestExpirationIvalSec); - } - - std::shared_ptr suspendWorkerService( - std::string const& workerName, - std::function)> const& onFinish = nullptr, - int priority = PRIORITY_VERY_HIGH, std::string const& jobId = "", - unsigned int requestExpirationIvalSec = 0); - - std::shared_ptr resumeWorkerService( - std::string const& workerName, - std::function)> const& onFinish = nullptr, - int priority = PRIORITY_VERY_HIGH, std::string const& jobId = "", - unsigned int requestExpirationIvalSec = 0); - - std::shared_ptr statusOfWorkerService( - std::string const& workerName, - std::function)> const& onFinish = nullptr, - int priority = PRIORITY_VERY_HIGH, std::string const& jobId = "", - unsigned int requestExpirationIvalSec = 0); - - std::shared_ptr requestsOfWorkerService( - std::string const& workerName, - std::function)> const& onFinish = nullptr, - int priority = PRIORITY_VERY_HIGH, std::string const& jobId = "", - unsigned int requestExpirationIvalSec = 0); - - std::shared_ptr drainWorkerService( - std::string const& workerName, - std::function)> const& onFinish = nullptr, - int priority = PRIORITY_VERY_HIGH, std::string const& jobId = "", - unsigned int requestExpirationIvalSec = 0); - - std::shared_ptr reconfigWorkerService( - std::string const& workerName, - std::function)> const& onFinish = nullptr, - int priority = PRIORITY_VERY_HIGH, std::string const& jobId = "", - unsigned int requestExpirationIvalSec = 0); - - /** - * Specialized version of the requests launcher for the worker service - * management requests. This is an alternative request launching method - * for the above defined operations. It allows upstream template specialization - * in those cases when a generic code is desired. - * @see Controller::suspendWorkerService() - * @see Controller::resumeWorkerService() - * @see Controller::statusOfWorkerService() - * @see Controller::requestsOfWorkerService() - * @see Controller::drainWorkerService() - * @see Controller::reconfigWorkerService() - * @see Controller::_submit() - */ - template - typename REQUEST::Ptr workerServiceRequest(std::string const& workerName, - typename REQUEST::CallbackType const& onFinish = nullptr, - int priority = PRIORITY_VERY_HIGH, - std::string const& jobId = "", - unsigned int requestExpirationIvalSec = 0) { - _logManagementRequest(REQUEST::Policy::requestName(), workerName); - return _submit(workerName, onFinish, priority, jobId, requestExpirationIvalSec); - } - - template - void requestsOfType(std::vector& requests) const { - replica::Lock lock(_mtx, _context(__func__)); - requests.clear(); - for (auto&& itr : _registry) - if (typename REQUEST::Ptr ptr = std::dynamic_pointer_cast(itr.second->request())) { - requests.push_back(ptr); - } - } - - template - size_t numRequestsOfType() const { - replica::Lock lock(_mtx, _context(__func__)); - size_t result(0); - for (auto&& itr : _registry) { - if (typename REQUEST::Ptr request = std::dynamic_pointer_cast(itr.second->request())) { - ++result; - } - } - return result; - } - - size_t numActiveRequests() const; - - /** - * Class RequestWrapper is the base class for implementing requests - * registry as a polymorphic collection to store active requests. Pure virtual - * methods of the class will be overridden by request-type-specific implementations. - * @see class RequestWrapperImpl - */ - class RequestWrapper { - public: - typedef std::shared_ptr Ptr; - - virtual ~RequestWrapper() = default; - - /// to be called on completion of a request - virtual void notify() = 0; - - /// @return stored request object by a pointer to its base class - virtual std::shared_ptr request() const = 0; - }; - - /** - * Class RequestWrapperImpl extends its base class to implement request-specific - * pointer extraction and call-back notification. - * @see class RequestWrapper - */ - template - class RequestWrapperImpl : public RequestWrapper { - public: - void notify() override { - if (nullptr != _onFinish) { - // Clearing the stored callback after finishing the up-stream notification - // has two purposes: - // 1. it guaranties (exactly) one time notification - // 2. it breaks the up-stream dependency on a caller object if a shared - // pointer to the object was mentioned as the lambda-function's closure - auto onFinish = move(_onFinish); - _onFinish = nullptr; - onFinish(_request); - } - } - - RequestWrapperImpl(typename T::Ptr const& request, typename T::CallbackType const& onFinish) - : RequestWrapper(), _request(request), _onFinish(onFinish) {} - - ~RequestWrapperImpl() override = default; - - std::shared_ptr request() const override { return _request; } - - private: - typename T::Ptr _request; - typename T::CallbackType _onFinish; - }; - private: - explicit Controller(ServiceProvider::Ptr const& serviceProvider); + explicit Controller(std::shared_ptr const& serviceProvider); std::string _context(std::string const& func = std::string()) const; - void _debug(std::string const& func, std::string const& msg = std::string()) const; - void _finish(std::string const& id); - void _assertIsRunning() const; - - /// Logger for the management requests. - void _logManagementRequest(std::string const& requestName, std::string const& workerName); - /** - * A generic version of the request creation and submission - * for a variable collection of the request-specific parameters. - */ - template - typename REQUEST::Ptr _submit(std::string const& workerName, Targs... Fargs, - typename REQUEST::CallbackType const& onFinish, int priority, - bool keepTracking, std::string const& jobId, - unsigned int requestExpirationIvalSec) { - _assertIsRunning(); - replica::Lock lock(_mtx, _context(__func__)); - auto const controller = shared_from_this(); - auto const request = REQUEST::create( - serviceProvider(), serviceProvider()->io_service(), workerName, Fargs..., - [controller](typename REQUEST::Ptr const& request) { controller->_finish(request->id()); }, - priority, keepTracking, serviceProvider()->messenger()); - - // Register the request (along with its callback) by its unique - // identifier in the local registry. Once it's complete it'll - // be automatically removed from the Registry. - _registry[request->id()] = std::make_shared>(request, onFinish); + // Methods _add and _remove are used by the request classes to register and unregister + // themselves in the Controller's registry. + friend class Request; + void _add(std::shared_ptr const& request); + void _remove(std::shared_ptr const& request); - // Initiate the request - request->start(controller, jobId, requestExpirationIvalSec); - return request; - } + // Input parameters + std::shared_ptr const _serviceProvider; - /** - * Specialized version of the requests launcher for the worker service - * management requests. - */ - template - typename REQUEST::Ptr _submit(std::string const& workerName, - typename REQUEST::CallbackType const& onFinish, int priority, - std::string const& jobId, unsigned int requestExpirationIvalSec) { - _assertIsRunning(); - replica::Lock lock(_mtx, _context(__func__)); - auto const controller = shared_from_this(); - auto const request = REQUEST::create( - serviceProvider(), serviceProvider()->io_service(), workerName, - [controller](typename REQUEST::Ptr const& request) { controller->_finish(request->id()); }, - priority, serviceProvider()->messenger()); - - // Register the request (along with its callback) by its unique - // identifier in the local registry. Once it's complete it'll - // be automatically removed from the Registry. - _registry[request->id()] = std::make_shared>(request, onFinish); - - // Initiate the request - request->start(controller, jobId, requestExpirationIvalSec); - return request; - } - - /// The unique identity of the instance/ + /// The unique identity of the instance ControllerIdentity const _identity; /// The number of milliseconds since UNIX Epoch when an instance of /// the Controller was created. uint64_t const _startTime; - ServiceProvider::Ptr const _serviceProvider; - /// For enforcing thread safety of the class's public API /// and internal operations. mutable replica::Mutex _mtx; - std::map> _registry; + /// The registry of the requests + std::map> _registry; }; } // namespace lsst::qserv::replica diff --git a/src/replica/contr/HttpQservSqlModule.cc b/src/replica/contr/HttpQservSqlModule.cc index a58f66086..bc9feb6c5 100644 --- a/src/replica/contr/HttpQservSqlModule.cc +++ b/src/replica/contr/HttpQservSqlModule.cc @@ -68,7 +68,8 @@ json HttpQservSqlModule::_execute() { debug(__func__, "user=" + user); debug(__func__, "maxRows=" + to_string(maxRows)); - auto const request = controller()->sqlQuery(worker, query, user, password, maxRows); + auto const request = + SqlQueryRequest::createAndStart(controller(), worker, query, user, password, maxRows); request->wait(); json result; diff --git a/src/replica/contr/Task.h b/src/replica/contr/Task.h index b805b32f5..6efee40f2 100644 --- a/src/replica/contr/Task.h +++ b/src/replica/contr/Task.h @@ -29,6 +29,7 @@ #include // Qserv headers +#include "replica/config/Configuration.h" #include "replica/contr/Controller.h" #include "replica/contr/EventLogger.h" #include "replica/jobs/Job.h" @@ -216,32 +217,24 @@ class Task : public EventLogger, public std::enable_shared_from_this { info(T::typeName()); // Launch the jobs - - auto self = shared_from_this(); - std::vector jobs; _numFinishedJobs = 0; - std::string const parentJobId; // no parent for these jobs - for (auto&& family : serviceProvider()->config()->databaseFamilies()) { auto job = T::create( family, Fargs..., controller(), parentJobId, - [self](typename T::Ptr const& job) { + [self = shared_from_this()](typename T::Ptr const& job) { self->_numFinishedJobs++; // FIXME: analyze job status and report it here }, priority); job->start(); jobs.push_back(job); - logJobStartedEvent(T::typeName(), job, job->databaseFamily()); } // Track the completion of all jobs - track(T::typeName(), jobs, _numFinishedJobs); - for (auto&& job : jobs) { logJobFinishedEvent(T::typeName(), job, job->databaseFamily()); } @@ -271,9 +264,7 @@ class Task : public EventLogger, public std::enable_shared_from_this { void track(std::string const& typeName, std::vector const& jobs, std::atomic const& numFinishedJobs) { info(typeName + ": tracking started"); - util::BlockPost blockPost(1000, 1001); // ~1 second wait time between iterations - while (numFinishedJobs != jobs.size()) { if (stopRequested()) { for (auto&& job : jobs) { @@ -291,8 +282,6 @@ class Task : public EventLogger, public std::enable_shared_from_this { /// This method is launched by the task when it starts void _startImpl(); - // Input parameters - /// The callback (if provided) to be called upon an abnormal termination /// of the user-supplied algorithm run in a context of the task. AbnormalTerminationCallbackType _onTerminated; diff --git a/src/replica/jobs/ClusterHealthJob.cc b/src/replica/jobs/ClusterHealthJob.cc index 3d5dc01ac..5f7778d84 100644 --- a/src/replica/jobs/ClusterHealthJob.cc +++ b/src/replica/jobs/ClusterHealthJob.cc @@ -27,6 +27,7 @@ #include // Qserv headers +#include "replica/config/Configuration.h" #include "replica/contr/Controller.h" #include "replica/qserv/QservMgtServices.h" #include "replica/services/ServiceProvider.h" @@ -158,10 +159,10 @@ void ClusterHealthJob::startImpl(replica::Lock const& lock) { : controller()->serviceProvider()->config()->workers(); for (auto const& worker : workers) { - auto const replicationRequest = controller()->statusOfWorkerService( - worker, [self](ServiceStatusRequest::Ptr request) { self->_onRequestFinish(request); }, - priority(), id(), /* jobId */ - timeoutSec()); + auto const replicationRequest = ServiceStatusRequest::createAndStart( + controller(), worker, + [self](ServiceStatusRequest::Ptr request) { self->_onRequestFinish(request); }, priority(), + id(), timeoutSec()); _requests[replicationRequest->id()] = replicationRequest; ++_numStarted; diff --git a/src/replica/jobs/CreateReplicaJob.cc b/src/replica/jobs/CreateReplicaJob.cc index 410e97507..94a393ca8 100644 --- a/src/replica/jobs/CreateReplicaJob.cc +++ b/src/replica/jobs/CreateReplicaJob.cc @@ -72,9 +72,7 @@ CreateReplicaJob::CreateReplicaJob(string const& databaseFamily, unsigned int ch CreateReplicaJobResult const& CreateReplicaJob::getReplicaData() const { LOGS(_log, LOG_LVL_DEBUG, context() << __func__); - if (state() == State::FINISHED) return _replicaData; - throw logic_error("CreateReplicaJob::" + string(__func__) + " the method can't be called while the job hasn't finished"); } @@ -90,7 +88,6 @@ list> CreateReplicaJob::extendedPersistentState() const { list> CreateReplicaJob::persistentLogData() const { list> result; - auto&& replicaData = getReplicaData(); // Per-worker counters for the following categories: @@ -98,16 +95,13 @@ list> CreateReplicaJob::persistentLogData() const { // created-chunks: // the total number of chunks created on the workers as a result // of the operation - map> workerCategoryCounter; - for (auto&& info : replicaData.replicas) { workerCategoryCounter[info.worker()]["created-chunks"]++; } for (auto&& workerItr : workerCategoryCounter) { auto&& worker = workerItr.first; string val = "worker=" + worker; - for (auto&& categoryItr : workerItr.second) { auto&& category = categoryItr.first; size_t const counter = categoryItr.second; @@ -122,9 +116,7 @@ void CreateReplicaJob::startImpl(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << "startImpl"); // Check if configuration parameters are valid - auto const& config = controller()->serviceProvider()->config(); - if (not(config->isKnownDatabaseFamily(databaseFamily()) and config->isKnownWorker(sourceWorker()) and config->isKnownWorker(destinationWorker()) and (sourceWorker() != destinationWorker()))) { LOGS(_log, LOG_LVL_ERROR, @@ -132,32 +124,26 @@ void CreateReplicaJob::startImpl(replica::Lock const& lock) { << " database family: '" << databaseFamily() << "'" << " source worker: '" << sourceWorker() << "'" << " destination worker: '" << destinationWorker() << "'"); - finish(lock, ExtendedState::CONFIG_ERROR); return; } // Make sure no such replicas exist yet at the destination - vector destinationReplicas; try { controller()->serviceProvider()->databaseServices()->findWorkerReplicas( destinationReplicas, chunk(), destinationWorker(), databaseFamily()); - } catch (invalid_argument const& ex) { LOGS(_log, LOG_LVL_ERROR, context() << string(__func__) << " ** MISCONFIGURED ** " << " chunk: " << chunk() << " destinationWorker: " << destinationWorker() << " databaseFamily: " << databaseFamily() << " exception: " << ex.what()); - throw; - } catch (exception const& ex) { LOGS(_log, LOG_LVL_ERROR, context() << string(__func__) << " ** failed to find replicas ** " << " chunk: " << chunk() << " destinationWorker: " << destinationWorker() << " databaseFamily: " << databaseFamily() << " exception: " << ex.what()); - finish(lock, ExtendedState::FAILED); return; } @@ -167,7 +153,6 @@ void CreateReplicaJob::startImpl(replica::Lock const& lock) { << destinationReplicas.size() << " replicas ** " << " chunk: " << chunk() << " destinationWorker: " << destinationWorker() << " databaseFamily: " << databaseFamily()); - finish(lock, ExtendedState::FAILED); return; } @@ -181,7 +166,6 @@ void CreateReplicaJob::startImpl(replica::Lock const& lock) { // // 2. launching FindRequest for each member of the database family to // see if the chunk is available on a source node. - vector sourceReplicas; try { controller()->serviceProvider()->databaseServices()->findWorkerReplicas( @@ -194,7 +178,6 @@ void CreateReplicaJob::startImpl(replica::Lock const& lock) { << " databaseFamily: " << databaseFamily() << " exception: " << ex.what()); throw; - } catch (exception const& ex) { LOGS(_log, LOG_LVL_ERROR, context() << string(__func__) << " ** failed to find replicas ** " @@ -219,17 +202,15 @@ void CreateReplicaJob::startImpl(replica::Lock const& lock) { // // VERY IMPORTANT: the requests are sent for participating databases // only because some catalogs may not have a full coverage - - auto self = shared_from_base(); - + bool const keepTracking = true; + bool const allowDuplicate = true; for (auto&& replica : sourceReplicas) { - _requests.push_back(controller()->replicate( - destinationWorker(), sourceWorker(), replica.database(), chunk(), - [self](ReplicationRequest::Ptr ptr) { self->_onRequestFinish(ptr); }, priority(), - true, /* keepTracking */ - true, /* allowDuplicate */ - id() /* jobId */ - )); + _requests.push_back(ReplicationRequest::createAndStart( + controller(), destinationWorker(), sourceWorker(), replica.database(), chunk(), + [self = shared_from_base()](ReplicationRequest::Ptr ptr) { + self->_onRequestFinish(ptr); + }, + priority(), keepTracking, allowDuplicate, id())); } } @@ -238,18 +219,17 @@ void CreateReplicaJob::cancelImpl(replica::Lock const& lock) { // The algorithm will also clear resources taken by various // locally created objects. - + // // To ensure no lingering "side effects" will be left after cancelling this // job the request cancellation should be also followed (where it makes a sense) // by stopping the request at corresponding worker service. - + auto const noCallbackOnFinish = nullptr; + bool const keepTracking = true; for (auto&& ptr : _requests) { ptr->cancel(); if (ptr->state() != Request::State::FINISHED) - controller()->stopById(destinationWorker(), ptr->id(), - nullptr, /* onFinish */ - priority(), true, /* keepTracking */ - id() /* jobId */); + StopRequest::createAndStart(controller(), destinationWorker(), ptr->id(), noCallbackOnFinish, + priority(), keepTracking, id()); } _requests.clear(); } @@ -266,9 +246,7 @@ void CreateReplicaJob::_onRequestFinish(ReplicationRequest::Ptr const& request) << " sourceWorker=" << sourceWorker() << " chunk=" << chunk()); if (state() == State::FINISHED) return; - replica::Lock lock(_mtx, context() + string(__func__) + "(ReplicationeRequest)"); - if (state() == State::FINISHED) return; ++_numRequestsFinished; @@ -280,7 +258,6 @@ void CreateReplicaJob::_onRequestFinish(ReplicationRequest::Ptr const& request) // Evaluate the status of on-going operations to see if the replica creation // stage has finished. - if (_numRequestsFinished == _requests.size()) { if (_numRequestsSuccess == _requests.size()) { // Notify Qserv about the change in a disposition of replicas. @@ -290,12 +267,10 @@ void CreateReplicaJob::_onRequestFinish(ReplicationRequest::Ptr const& request) // NOTE: The current implementation will not be affected by a result // of the operation. Neither any upstream notifications will be // sent to a requester of this job. - vector databases; for (auto&& databaseEntry : _replicaData.chunks[chunk()]) { databases.push_back(databaseEntry.first); } - ServiceProvider::Ptr const serviceProvider = controller()->serviceProvider(); if (serviceProvider->config()->get("xrootd", "auto-notify") != 0) { _qservAddReplica(lock, chunk(), databases, destinationWorker()); @@ -314,11 +289,9 @@ void CreateReplicaJob::_qservAddReplica(replica::Lock const& lock, unsigned int context() << __func__ << " ** START ** Qserv notification on ADD replica:" << ", chunk=" << chunk << ", databases=" << util::String::toString(databases) << " worker=" << worker); - - auto self = shared_from_this(); controller()->serviceProvider()->qservMgtServices()->addReplica( chunk, databases, worker, - [self, onFinish](AddReplicaQservMgtRequest::Ptr const& request) { + [self = shared_from_this(), onFinish](AddReplicaQservMgtRequest::Ptr const& request) { LOGS(_log, LOG_LVL_DEBUG, self->context() << __func__ << " ** FINISH ** Qserv notification on ADD replica:" << " chunk=" << request->chunk() diff --git a/src/replica/jobs/DeleteReplicaJob.cc b/src/replica/jobs/DeleteReplicaJob.cc index e9ab9a94a..b9c288727 100644 --- a/src/replica/jobs/DeleteReplicaJob.cc +++ b/src/replica/jobs/DeleteReplicaJob.cc @@ -70,9 +70,7 @@ DeleteReplicaJob::DeleteReplicaJob(string const& databaseFamily, unsigned int ch DeleteReplicaJobResult const& DeleteReplicaJob::getReplicaData() const { LOGS(_log, LOG_LVL_DEBUG, context() << __func__); - if (state() == State::FINISHED) return _replicaData; - throw logic_error("DeleteReplicaJob::" + string(__func__) + " the method can't be called while the job hasn't finished"); } @@ -87,7 +85,6 @@ list> DeleteReplicaJob::extendedPersistentState() const { list> DeleteReplicaJob::persistentLogData() const { list> result; - auto&& replicaData = getReplicaData(); // Per-worker counters for the following categories: @@ -95,16 +92,13 @@ list> DeleteReplicaJob::persistentLogData() const { // deleted-chunks: // the total number of chunks deleted from the workers as a result // of the operation - map> workerCategoryCounter; - for (auto&& info : replicaData.replicas) { workerCategoryCounter[info.worker()]["deleted-chunks"]++; } for (auto&& workerItr : workerCategoryCounter) { auto&& workerName = workerItr.first; string val = "worker=" + workerName; - for (auto&& categoryItr : workerItr.second) { auto&& category = categoryItr.first; size_t const counter = categoryItr.second; @@ -119,9 +113,7 @@ void DeleteReplicaJob::startImpl(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__); // Check if configuration parameters are valid - auto const& config = controller()->serviceProvider()->config(); - if (not(config->isKnownDatabaseFamily(databaseFamily()) and config->isKnownWorker(workerName()))) { LOGS(_log, LOG_LVL_ERROR, context() << __func__ << " ** MISCONFIGURED ** " @@ -141,17 +133,14 @@ void DeleteReplicaJob::startImpl(replica::Lock const& lock) { // // 2. launching FindRequest for each member of the database family to // see if the chunk is available on a source node. - try { controller()->serviceProvider()->databaseServices()->findWorkerReplicas( _replicas, chunk(), workerName(), databaseFamily()); - } catch (invalid_argument const& ex) { LOGS(_log, LOG_LVL_ERROR, context() << __func__ << " ** MISCONFIGURED ** " << " chunk: " << chunk() << " worker: " << workerName() << " databaseFamily: " << databaseFamily() << " exception: " << ex.what()); - finish(lock, ExtendedState::CONFIG_ERROR); return; @@ -160,7 +149,6 @@ void DeleteReplicaJob::startImpl(replica::Lock const& lock) { context() << __func__ << " ** failed to find replicas ** " << " chunk: " << chunk() << " worker: " << workerName() << " databaseFamily: " << databaseFamily() << " exception: " << ex.what()); - finish(lock, ExtendedState::FAILED); return; } @@ -169,7 +157,6 @@ void DeleteReplicaJob::startImpl(replica::Lock const& lock) { context() << __func__ << " ** worker has no replicas to be deleted ** " << " chunk: " << chunk() << " worker: " << workerName() << " databaseFamily: " << databaseFamily()); - finish(lock, ExtendedState::FAILED); return; } @@ -181,23 +168,20 @@ void DeleteReplicaJob::startImpl(replica::Lock const& lock) { if (serviceProvider->config()->get("xrootd", "auto-notify") != 0) { // Start right away _beginDeleteReplica(lock); - } else { // Notify Qserv first. Then start once a confirmation is received - vector databases; for (auto&& replica : _replicas) { databases.push_back(replica.database()); } - auto self = shared_from_base(); - // Force the removal regardless of the replica usage status. // See the implementation of the corresponding worker management service // for specific detail on what "remove" means in that service's context. bool const force = true; _qservRemoveReplica(lock, chunk(), databases, workerName(), force, - [self](RemoveReplicaQservMgtRequest::Ptr const& request) { + [self = shared_from_base()]( + RemoveReplicaQservMgtRequest::Ptr const& request) { replica::Lock lock(self->_mtx, self->context() + string(__func__) + "::qservRemoveReplica"); switch (request->extendedState()) { @@ -226,18 +210,17 @@ void DeleteReplicaJob::cancelImpl(replica::Lock const& lock) { // The algorithm will also clear resources taken by various // locally created objects. - + // // To ensure no lingering "side effects" will be left after cancelling this // job the request cancellation should be also followed (where it makes a sense) // by stopping the request at corresponding worker service. - auto const noCallbackOnFinish = nullptr; bool const keepTracking = true; for (auto&& ptr : _requests) { ptr->cancel(); if (ptr->state() != Request::State::FINISHED) { - controller()->stopById(workerName(), ptr->id(), noCallbackOnFinish, priority(), - keepTracking, id()); + StopRequest::createAndStart(controller(), workerName(), ptr->id(), noCallbackOnFinish, priority(), + keepTracking, id()); } } _requests.clear(); @@ -249,18 +232,17 @@ void DeleteReplicaJob::notify(replica::Lock const& lock) { } void DeleteReplicaJob::_beginDeleteReplica(replica::Lock const& lock) { - auto self = shared_from_base(); - // VERY IMPORTANT: the requests are sent for participating databases // only because some catalogs may not have a full coverage - bool const keepTracking = true; bool const allowDuplicate = true; for (auto&& replica : _replicas) { - _requests.push_back(controller()->deleteReplica( - workerName(), replica.database(), chunk(), - [self](DeleteRequest::Ptr ptr) { self->_onRequestFinish(ptr); }, priority(), keepTracking, - allowDuplicate, id())); + _requests.push_back(DeleteRequest::createAndStart( + controller(), workerName(), replica.database(), chunk(), + [self = shared_from_base()](DeleteRequest::Ptr ptr) { + self->_onRequestFinish(ptr); + }, + priority(), keepTracking, allowDuplicate, id())); } } @@ -298,10 +280,9 @@ void DeleteReplicaJob::_qservRemoveReplica(replica::Lock const& lock, unsigned i << " chunk=" << chunk << ", databases=" << util::String::toString(databases) << ", worker=" << workerName << ", force=" << (force ? "true" : "false")); - auto self = shared_from_this(); controller()->serviceProvider()->qservMgtServices()->removeReplica( chunk, databases, workerName, force, - [self, onFinish](RemoveReplicaQservMgtRequest::Ptr const& request) { + [self = shared_from_this(), onFinish](RemoveReplicaQservMgtRequest::Ptr const& request) { LOGS(_log, LOG_LVL_DEBUG, self->context() << __func__ << " ** FINISH ** Qserv notification on REMOVE replica:" << " chunk=" << request->chunk() diff --git a/src/replica/jobs/DeleteWorkerJob.cc b/src/replica/jobs/DeleteWorkerJob.cc index 2868cdce4..675dfddf9 100644 --- a/src/replica/jobs/DeleteWorkerJob.cc +++ b/src/replica/jobs/DeleteWorkerJob.cc @@ -67,9 +67,7 @@ DeleteWorkerJob::DeleteWorkerJob(string const& workerName, bool permanentDelete, DeleteWorkerJobResult const& DeleteWorkerJob::getReplicaData() const { LOGS(_log, LOG_LVL_DEBUG, context()); - if (state() == State::FINISHED) return _replicaData; - throw logic_error("DeleteWorkerJob::" + string(__func__) + " the method can't be called while the job hasn't finished"); } @@ -84,22 +82,17 @@ list> DeleteWorkerJob::extendedPersistentState() const { list> DeleteWorkerJob::persistentLogData() const { list> result; - auto&& replicaData = getReplicaData(); - // Encode new chunk replicas (if any) which had to be created to compensate // for lost ones. + auto&& replicaData = getReplicaData(); for (auto&& familyChunkDatabaseWorkerInfo : replicaData.chunks) { auto&& family = familyChunkDatabaseWorkerInfo.first; - for (auto&& chunkDatabaseWorkerInfo : familyChunkDatabaseWorkerInfo.second) { auto&& chunk = chunkDatabaseWorkerInfo.first; - for (auto&& databaseWorkerInfo : chunkDatabaseWorkerInfo.second) { auto&& database = databaseWorkerInfo.first; - for (auto&& workerInfo : databaseWorkerInfo.second) { auto&& workerName = workerInfo.first; - result.emplace_back("new-replica", "family=" + family + " chunk=" + to_string(chunk) + " database=" + database + " worker=" + workerName); @@ -111,10 +104,8 @@ list> DeleteWorkerJob::persistentLogData() const { // Encode orphan replicas (if any) which only existed on the evicted worker for (auto&& chunkDatabaseReplicaInfo : replicaData.orphanChunks) { auto&& chunk = chunkDatabaseReplicaInfo.first; - for (auto&& databaseReplicaInfo : chunkDatabaseReplicaInfo.second) { auto&& database = databaseReplicaInfo.first; - result.emplace_back("orphan-replica", "chunk=" + to_string(chunk) + " database=" + database); } } @@ -129,29 +120,29 @@ void DeleteWorkerJob::startImpl(replica::Lock const& lock) { // Check the status of the worker service, and if it's still running // try to get as much info from it as possible - auto const statusRequest = controller()->statusOfWorkerService( - workerName(), noCallbackOnFinish, priority(), id(), requestExpirationIvalSec); + auto const statusRequest = ServiceStatusRequest::createAndStart( + controller(), workerName(), noCallbackOnFinish, priority(), id(), requestExpirationIvalSec); statusRequest->wait(); if (statusRequest->extendedState() == Request::ExtendedState::SUCCESS) { if (statusRequest->getServiceState().state == ServiceState::State::RUNNING) { // Make sure the service won't be executing any other "leftover" // requests which may be interfering with the current job's requests - auto const drainRequest = controller()->drainWorkerService( - workerName(), noCallbackOnFinish, priority(), id(), requestExpirationIvalSec); + auto const drainRequest = + ServiceDrainRequest::createAndStart(controller(), workerName(), noCallbackOnFinish, + priority(), id(), requestExpirationIvalSec); drainRequest->wait(); - if (drainRequest->extendedState() == Request::ExtendedState::SUCCESS) { if (drainRequest->getServiceState().state == ServiceState::State::RUNNING) { // Try to get the most recent state the worker's replicas // for all known databases bool const saveReplicaInfo = true; // always save the replica info in a database because // the algorithm depends on it. - auto self = shared_from_base(); for (auto&& database : controller()->serviceProvider()->config()->databases()) { - auto const request = controller()->findAllReplicas( - workerName(), database, saveReplicaInfo, - [self](FindAllRequest::Ptr const& request) { + auto const request = FindAllRequest::createAndStart( + controller(), workerName(), database, saveReplicaInfo, + [self = shared_from_base()]( + FindAllRequest::Ptr const& request) { self->_onRequestFinish(request); }, priority()); @@ -174,22 +165,20 @@ void DeleteWorkerJob::startImpl(replica::Lock const& lock) { void DeleteWorkerJob::cancelImpl(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__); - auto const noCallbackOnFinish = nullptr; - auto const keepTracking = true; - // To ensure no lingering "side effects" will be left after cancelling this // job the request cancellation should be also followed (where it makes a sense) // by stopping the request at corresponding worker service. + auto const noCallbackOnFinish = nullptr; + auto const keepTracking = true; for (auto&& ptr : _findAllRequests) { ptr->cancel(); if (ptr->state() != Request::State::FINISHED) { - controller()->stopById(ptr->workerName(), ptr->id(), noCallbackOnFinish, - priority(), keepTracking, id()); + StopRequest::createAndStart(controller(), ptr->workerName(), ptr->id(), noCallbackOnFinish, + priority(), keepTracking, id()); } } // Stop chained jobs (if any) as well - for (auto&& ptr : _replicateJobs) ptr->cancel(); } @@ -227,13 +216,14 @@ void DeleteWorkerJob::_disableWorker(replica::Lock const& lock) { _numLaunched = 0; _numFinished = 0; _numSuccess = 0; - - auto self = shared_from_base(); - for (auto&& databaseFamily : controller()->serviceProvider()->config()->databaseFamilies()) { ReplicateJob::Ptr const job = ReplicateJob::create( databaseFamily, 0, /* numReplicas -- pull from Configuration */ - controller(), id(), [self](ReplicateJob::Ptr job) { self->_onJobFinish(job); }, priority()); + controller(), id(), + [self = shared_from_base()](ReplicateJob::Ptr job) { + self->_onJobFinish(job); + }, + priority()); job->start(); _replicateJobs.push_back(job); _numLaunched++; @@ -251,7 +241,6 @@ void DeleteWorkerJob::_onJobFinish(ReplicateJob::Ptr const& job) { if (state() == State::FINISHED) return; _numFinished++; - if (job->extendedState() != ExtendedState::SUCCESS) { finish(lock, ExtendedState::FAILED); return; @@ -259,14 +248,12 @@ void DeleteWorkerJob::_onJobFinish(ReplicateJob::Ptr const& job) { // Process the normal completion of the child job _numSuccess++; - LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "(ReplicateJob) " << "job->getReplicaData().chunks.size(): " << job->getReplicaData().chunks.size()); // Merge results into the current job's result object _replicaData.chunks[job->databaseFamily()] = job->getReplicaData().chunks; - if (_numFinished == _numLaunched) { // Construct a collection of orphan replicas if possible ReplicaInfoCollection replicas; @@ -275,7 +262,6 @@ void DeleteWorkerJob::_onJobFinish(ReplicateJob::Ptr const& job) { for (ReplicaInfo const& replica : replicas) { unsigned int const chunk = replica.chunk(); string const& database = replica.database(); - bool replicated = false; for (auto&& databaseFamilyEntry : _replicaData.chunks) { auto const& chunks = databaseFamilyEntry.second; diff --git a/src/replica/jobs/DirectorIndexJob.cc b/src/replica/jobs/DirectorIndexJob.cc index eeb044a56..4cddc1980 100644 --- a/src/replica/jobs/DirectorIndexJob.cc +++ b/src/replica/jobs/DirectorIndexJob.cc @@ -33,8 +33,10 @@ // Qserv headers #include "global/constants.h" #include "replica/config/Configuration.h" +#include "replica/ingest/TransactionContrib.h" #include "replica/mysql/DatabaseMySQL.h" #include "replica/requests/StopRequest.h" +#include "replica/services/DatabaseServices.h" #include "replica/services/ServiceProvider.h" #include "replica/util/Common.h" @@ -282,22 +284,19 @@ void DirectorIndexJob::cancelImpl(replica::Lock const& lock) { // The algorithm will also clear resources taken by various // locally created objects. - _chunks.clear(); // To ensure no lingering "side effects" will be left after cancelling this // job the request cancellation should be also followed (where it makes a sense) // by stopping the request at corresponding worker service. - auto const noCallbackOnFinish = nullptr; bool const keepTracking = true; - for (auto&& itr : _inFlightRequests) { auto&& ptr = itr.second; ptr->cancel(); if (ptr->state() != Request::State::FINISHED) { - controller()->stopById(ptr->workerName(), ptr->id(), noCallbackOnFinish, - priority(), keepTracking, id()); + StopRequest::createAndStart(controller(), ptr->workerName(), ptr->id(), noCallbackOnFinish, + priority(), keepTracking, id()); } } _inFlightRequests.clear(); @@ -515,8 +514,9 @@ list DirectorIndexJob::_launchRequests(replica::Lock auto const chunk = _chunks[workerName].front(); _chunks[workerName].pop(); - requests.push_back(controller()->directorIndex( - workerName, database(), directorTable(), chunk, hasTransactions(), transactionId(), + requests.push_back(DirectorIndexRequest::createAndStart( + controller(), workerName, database(), directorTable(), chunk, hasTransactions(), + transactionId(), [self](DirectorIndexRequest::Ptr const& request) { self->_onRequestFinish(request); }, priority(), keepTracking, id())); } diff --git a/src/replica/jobs/DirectorIndexJob.h b/src/replica/jobs/DirectorIndexJob.h index 76040bcc1..a25c05335 100644 --- a/src/replica/jobs/DirectorIndexJob.h +++ b/src/replica/jobs/DirectorIndexJob.h @@ -37,6 +37,7 @@ #include "nlohmann/json.hpp" // Qserv headers +#include "replica/config/ConfigDatabase.h" #include "replica/jobs/Job.h" #include "replica/requests/DirectorIndexRequest.h" #include "replica/util/Common.h" diff --git a/src/replica/jobs/FindAllJob.cc b/src/replica/jobs/FindAllJob.cc index 2591fd9f1..9b6495d87 100644 --- a/src/replica/jobs/FindAllJob.cc +++ b/src/replica/jobs/FindAllJob.cc @@ -144,20 +144,19 @@ list> FindAllJob::persistentLogData() const { void FindAllJob::startImpl(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__); - auto const self = shared_from_base(); - auto const workerNames = allWorkers() ? controller()->serviceProvider()->config()->allWorkers() : controller()->serviceProvider()->config()->workers(); - for (auto&& workerName : workerNames) { _replicaData.workers[workerName] = false; for (auto&& database : _databases) { _workerDatabaseSuccess[workerName][database] = false; - _requests.push_back(controller()->findAllReplicas( - workerName, database, saveReplicaInfo(), - [self](FindAllRequest::Ptr request) { self->_onRequestFinish(request); }, priority(), - true, /* keepTracking*/ - id() /* jobId */ + _requests.push_back(FindAllRequest::createAndStart( + controller(), workerName, database, saveReplicaInfo(), + [self = shared_from_base()](FindAllRequest::Ptr request) { + self->_onRequestFinish(request); + }, + priority(), true, /* keepTracking*/ + id() /* jobId */ )); _numLaunched++; } @@ -172,18 +171,16 @@ void FindAllJob::startImpl(replica::Lock const& lock) { void FindAllJob::cancelImpl(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__); - auto const noCallbackOnFinish = nullptr; - bool const keepTracking = true; - // To ensure no lingering "side effects" will be left after cancelling this // job the request cancellation should be also followed (where it makes a sense) // by stopping the request at corresponding worker service. - + auto const noCallbackOnFinish = nullptr; + bool const keepTracking = true; for (auto&& ptr : _requests) { ptr->cancel(); if (ptr->state() != Request::State::FINISHED) { - controller()->stopById(ptr->workerName(), ptr->id(), noCallbackOnFinish, - priority(), keepTracking, id()); + StopRequest::createAndStart(controller(), ptr->workerName(), ptr->id(), noCallbackOnFinish, + priority(), keepTracking, id()); } } _requests.clear(); diff --git a/src/replica/jobs/FixUpJob.cc b/src/replica/jobs/FixUpJob.cc index 6be4e1854..8aa67874e 100644 --- a/src/replica/jobs/FixUpJob.cc +++ b/src/replica/jobs/FixUpJob.cc @@ -59,9 +59,7 @@ FixUpJob::FixUpJob(string const& databaseFamily, Controller::Ptr const& controll FixUpJobResult const& FixUpJob::getReplicaData() const { LOGS(_log, LOG_LVL_DEBUG, context() << __func__); - if (state() == State::FINISHED) return _replicaData; - throw logic_error(typeName() + "::" + string(__func__) + " the method can't be called while the job hasn't finished"); } @@ -74,11 +72,9 @@ list> FixUpJob::extendedPersistentState() const { list> FixUpJob::persistentLogData() const { list> result; - auto&& replicaData = getReplicaData(); // Report workers failed to respond to the requests - for (auto&& workerInfo : replicaData.workers) { auto&& workerName = workerInfo.first; auto const numFailedRequests = workerInfo.second; @@ -93,16 +89,13 @@ list> FixUpJob::persistentLogData() const { // created-chunks: // the total number of chunks created on the workers as a result // of the operation - map> workerCategoryCounter; - for (auto&& info : replicaData.replicas) { workerCategoryCounter[info.worker()]["created-chunks"]++; } for (auto&& workerItr : workerCategoryCounter) { auto&& workerName = workerItr.first; string val = "worker=" + workerName; - for (auto&& categoryItr : workerItr.second) { auto&& category = categoryItr.first; size_t const counter = categoryItr.second; @@ -117,14 +110,13 @@ void FixUpJob::startImpl(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__); // Launch the chained job to get chunk disposition - - auto self = shared_from_base(); bool const saveReplicInfo = true; // always save the replica info in a database because // the algorithm depends on it. bool const allWorkers = false; // only consider enabled workers _findAllJob = FindAllJob::create( databaseFamily(), saveReplicInfo, allWorkers, controller(), id(), - [self](FindAllJob::Ptr job) { self->_onPrecursorJobFinish(); }, priority()); + [self = shared_from_base()](FindAllJob::Ptr job) { self->_onPrecursorJobFinish(); }, + priority()); _findAllJob->start(); } @@ -133,7 +125,6 @@ void FixUpJob::cancelImpl(replica::Lock const& lock) { // The algorithm will also clear resources taken by various // locally created objects. - if (_findAllJob and (_findAllJob->state() != State::FINISHED)) { _findAllJob->cancel(); } @@ -142,15 +133,13 @@ void FixUpJob::cancelImpl(replica::Lock const& lock) { // To ensure no lingering "side effects" will be left after cancelling this // job the request cancellation should be also followed (where it makes a sense) // by stopping the request at corresponding worker service. - auto const noCallbackOnFinish = nullptr; bool const keepTracking = true; - for (auto&& ptr : _requests) { ptr->cancel(); if (ptr->state() != Request::State::FINISHED) - controller()->stopById(ptr->workerName(), ptr->id(), noCallbackOnFinish, - priority(), keepTracking, id()); + StopRequest::createAndStart(controller(), ptr->workerName(), ptr->id(), noCallbackOnFinish, + priority(), keepTracking, id()); } _destinationWorker2tasks.clear(); _requests.clear(); @@ -165,14 +154,11 @@ void FixUpJob::_onPrecursorJobFinish() { LOGS(_log, LOG_LVL_DEBUG, context() << __func__); if (state() == State::FINISHED) return; - replica::Lock lock(_mtx, context() + __func__); - if (state() == State::FINISHED) return; // Proceed with the replication effort only if the precursor job // has succeeded. - if (_findAllJob->extendedState() != ExtendedState::SUCCESS) { finish(lock, ExtendedState::FAILED); return; @@ -180,22 +166,18 @@ void FixUpJob::_onPrecursorJobFinish() { // Analyze results and prepare a replication plan to fix chunk // co-location for under-represented chunks - FindAllJobResult const& replicaData = _findAllJob->getReplicaData(); for (auto&& chunk2workers : replicaData.isColocated) { unsigned int chunk = chunk2workers.first; - for (auto&& worker2colocated : chunk2workers.second) { string const& destinationWorker = worker2colocated.first; bool const isColocated = worker2colocated.second; - if (isColocated) continue; // Iterate over all participating databases, find the ones which aren't // represented on the worker, find a suitable source worker which has // a complete chunk for the database and which (the worker) is not the same // as the current one and submit the replication request. - for (auto&& database : replicaData.databases.at(chunk)) { if (not replicaData.chunks.chunk(chunk).database(database).workerExists(destinationWorker)) { // Finding a source worker first @@ -250,9 +232,7 @@ void FixUpJob::_onRequestFinish(ReplicationRequest::Ptr const& request) { << " database=" << database << " worker=" << workerName << " chunk=" << chunk); if (state() == State::FINISHED) return; - replica::Lock lock(_mtx, context() + __func__); - if (state() == State::FINISHED) return; _numFinished++; @@ -275,8 +255,6 @@ void FixUpJob::_onRequestFinish(ReplicationRequest::Ptr const& request) { size_t FixUpJob::_launchNext(replica::Lock const& lock, string const& destinationWorker, size_t maxRequests) { if (maxRequests == 0) return 0; - - auto const self = shared_from_base(); auto&& tasks = _destinationWorker2tasks[destinationWorker]; bool const keepTracking = true; bool const allowDuplicate = true; @@ -286,13 +264,13 @@ size_t FixUpJob::_launchNext(replica::Lock const& lock, string const& destinatio // Launch the replication request and register it for further // tracking (or cancellation, should the one be requested) - ReplicationTask const& task = tasks.front(); - - _requests.push_back(controller()->replicate( - task.destinationWorker, task.sourceWorker, task.database, task.chunk, - [self](ReplicationRequest::Ptr const& ptr) { self->_onRequestFinish(ptr); }, 0, /* priority */ - keepTracking, allowDuplicate, id())); + _requests.push_back(ReplicationRequest::createAndStart( + controller(), task.destinationWorker, task.sourceWorker, task.database, task.chunk, + [self = shared_from_base()](ReplicationRequest::Ptr ptr) { + self->_onRequestFinish(ptr); + }, + priority(), keepTracking, allowDuplicate, id())); tasks.pop(); numLaunched++; } diff --git a/src/replica/jobs/Job.cc b/src/replica/jobs/Job.cc index 84c268ebe..907d8bbfd 100644 --- a/src/replica/jobs/Job.cc +++ b/src/replica/jobs/Job.cc @@ -256,8 +256,9 @@ void Job::_startHeartbeatTimer(replica::Lock const& lock) { // The timer needs to be initialized each time a new interval // is about to begin. Otherwise it will immediately expire when // async_wait() will be called. - _heartbeatTimerPtr.reset(new boost::asio::deadline_timer( - controller()->io_service(), boost::posix_time::seconds(_heartbeatTimerIvalSec))); + _heartbeatTimerPtr.reset( + new boost::asio::deadline_timer(controller()->serviceProvider()->io_service(), + boost::posix_time::seconds(_heartbeatTimerIvalSec))); _heartbeatTimerPtr->async_wait(bind(&Job::_heartbeat, shared_from_this(), _1)); } } @@ -286,8 +287,9 @@ void Job::_startExpirationTimer(replica::Lock const& lock) { // The timer needs to be initialized each time a new interval // is about to begin. Otherwise it will immediately expire when // async_wait() will be called. - _expirationTimerPtr.reset(new boost::asio::deadline_timer( - controller()->io_service(), boost::posix_time::seconds(_expirationIvalSec))); + _expirationTimerPtr.reset( + new boost::asio::deadline_timer(controller()->serviceProvider()->io_service(), + boost::posix_time::seconds(_expirationIvalSec))); _expirationTimerPtr->async_wait(bind(&Job::_expired, shared_from_this(), _1)); } } diff --git a/src/replica/jobs/QservStatusJob.cc b/src/replica/jobs/QservStatusJob.cc index 7e5e0105b..bc40cd98a 100644 --- a/src/replica/jobs/QservStatusJob.cc +++ b/src/replica/jobs/QservStatusJob.cc @@ -28,6 +28,7 @@ // Qserv headers #include "lsst/log/Log.h" +#include "replica/config/Configuration.h" #include "replica/contr/Controller.h" #include "replica/qserv/QservMgtServices.h" #include "replica/services/ServiceProvider.h" diff --git a/src/replica/jobs/RebalanceJob.cc b/src/replica/jobs/RebalanceJob.cc index cee7756df..348f727bc 100644 --- a/src/replica/jobs/RebalanceJob.cc +++ b/src/replica/jobs/RebalanceJob.cc @@ -29,6 +29,7 @@ #include // Qserv headers +#include "replica/config/Configuration.h" #include "replica/services/ServiceProvider.h" #include "replica/util/Common.h" #include "replica/util/ErrorReporting.h" diff --git a/src/replica/jobs/ServiceManagementJob.h b/src/replica/jobs/ServiceManagementJob.h index 7b57b755e..e54273821 100644 --- a/src/replica/jobs/ServiceManagementJob.h +++ b/src/replica/jobs/ServiceManagementJob.h @@ -62,66 +62,41 @@ class ServiceManagementBaseJob : public Job { /// @return the unique name distinguishing this class from other types of jobs static std::string typeName(); - // Default construction and copy semantics are prohibited - ServiceManagementBaseJob() = delete; ServiceManagementBaseJob(ServiceManagementBaseJob const&) = delete; ServiceManagementBaseJob& operator=(ServiceManagementBaseJob const&) = delete; ~ServiceManagementBaseJob() override = default; - // Trivial get methods - bool allWorkers() const { return _allWorkers; } - unsigned int requestExpirationIvalSec() const { return _requestExpirationIvalSec; } /** * Return the combined result of the operation * - * @note: - * The method should be invoked only after the job has finished (primary + * @note The method should be invoked only after the job has finished (primary * status is set to Job::Status::FINISHED). Otherwise exception * std::logic_error will be thrown * - * @return - * the data structure to be filled upon the completion of the job. - * - * @throws std::logic_error - * if the job didn't finished at a time when the method was called + * @return the data structure to be filled upon the completion of the job. + * @throws std::logic_error if the job didn't finished at a time when the method was called */ ServiceManagementJobResult const& getResultData() const; protected: - /// @see Job::startImpl() void startImpl(replica::Lock const& lock) final; - - /// @see Job::cancelImpl() void cancelImpl(replica::Lock const& lock) final; /** - * Normal constructor. - * - * @param requestName - * the name of a specific request (as defined by a subclass) - * - * @param allWorkers - * engage all known workers regardless of their status. If the flag - * is set to 'false' then only 'ENABLED' workers which are not in - * the 'READ-ONLY' state will be involved into the operation. - * - * @param requestExpirationIvalSec - * the number of seconds before the requests will be declared as expired - * unless receiving responses from them. - * - * @param controller - * is needed launching requests and accessing the Configuration - * - * @param parentJobId - * an identifier of a parent job - * - * @param priority - * defines the job priority + * @param requestName the name of a specific request (as defined by a subclass) + * @param allWorkers engage all known workers regardless of their status. + * If the flag is set to 'false' then only 'ENABLED' workers which are not in + * the 'READ-ONLY' state will be involved into the operation. + * @param requestExpirationIvalSec the number of seconds before the requests will + * be declared as expired unless receiving responses from them. + * @param controller is needed launching requests and accessing the Configuration + * @param parentJobId an identifier of a parent job + * @param priority defines the job priority */ ServiceManagementBaseJob(std::string const& requestName, bool allWorkers, unsigned int requestExpirationIvalSec, Controller::Ptr const& controller, @@ -129,7 +104,6 @@ class ServiceManagementBaseJob : public Job { /** * Submit type-specific request - * * @param worker the name of a worker to which the request will be sent * @return a newly created & submitted object */ @@ -206,10 +180,12 @@ class ServiceManagementJob : public ServiceManagementBaseJob { /// @see ServiceManagementBaseJob::submitRequest() ServiceManagementRequestBase::Ptr submitRequest(std::string const& worker) final { - auto const self = shared_from_base>(); - return controller()->template workerServiceRequest( - worker, [self](typename REQUEST::Ptr const& ptr) { self->onRequestFinish(ptr); }, priority(), - id(), requestExpirationIvalSec()); + return REQUEST::createAndStart( + controller(), worker, + [self = shared_from_base>()](typename REQUEST::Ptr const& ptr) { + self->onRequestFinish(ptr); + }, + priority(), id(), requestExpirationIvalSec()); } private: diff --git a/src/replica/jobs/SqlAlterTablesJob.cc b/src/replica/jobs/SqlAlterTablesJob.cc index c27a87768..2002f0f4f 100644 --- a/src/replica/jobs/SqlAlterTablesJob.cc +++ b/src/replica/jobs/SqlAlterTablesJob.cc @@ -24,7 +24,6 @@ // Qserv headers #include "replica/requests/SqlAlterTablesRequest.h" -#include "replica/requests/StopRequest.h" // LSST headers #include "lsst/log/Log.h" @@ -73,7 +72,6 @@ list> SqlAlterTablesJob::extendedPersistentState() const { list SqlAlterTablesJob::launchRequests(replica::Lock const& lock, string const& worker, size_t maxRequestsPerWorker) { list requests; - if (maxRequestsPerWorker == 0) return requests; // Make sure this worker has already been served @@ -86,22 +84,18 @@ list SqlAlterTablesJob::launchRequests(replica::Lock const& loc // Divide tables into subsets allocated to the "batch" requests. Then launch // the requests for the current worker. - auto const self = shared_from_base(); for (auto&& tables : distributeTables(tables2process, maxRequestsPerWorker)) { - requests.push_back(controller()->sqlAlterTables( - worker, database(), tables, alterSpec(), - [self](SqlAlterTablesRequest::Ptr const& request) { self->onRequestFinish(request); }, - priority(), true, /* keepTracking*/ - id() /* jobId */ - )); + bool const keepTracking = true; + requests.push_back(SqlAlterTablesRequest::createAndStart( + controller(), worker, database(), tables, alterSpec(), + [self = shared_from_base()](SqlAlterTablesRequest::Ptr const& request) { + self->onRequestFinish(request); + }, + priority(), keepTracking, id())); } return requests; } -void SqlAlterTablesJob::stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) { - stopRequestDefaultImpl(lock, request); -} - void SqlAlterTablesJob::notify(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "[" << typeName() << "]"); notifyDefaultImpl(lock, _onFinish); diff --git a/src/replica/jobs/SqlAlterTablesJob.h b/src/replica/jobs/SqlAlterTablesJob.h index 0e1d62d4c..80ae1e14d 100644 --- a/src/replica/jobs/SqlAlterTablesJob.h +++ b/src/replica/jobs/SqlAlterTablesJob.h @@ -89,28 +89,22 @@ class SqlAlterTablesJob : public SqlJob { std::string const& database() const { return _database; } std::string const& table() const { return _table; } std::string const& alterSpec() const { return _alterSpec; } - std::list> extendedPersistentState() const final; protected: void notify(replica::Lock const& lock) final; - std::list launchRequests(replica::Lock const& lock, std::string const& worker, size_t maxRequestsPerWorker) final; - void stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) final; - private: SqlAlterTablesJob(std::string const& database, std::string const& table, std::string const& alterSpec, bool allWorkers, Controller::Ptr const& controller, std::string const& parentJobId, CallbackType const& onFinish, int priority); // Input parameters - std::string const _database; std::string const _table; std::string const _alterSpec; - CallbackType _onFinish; /// @note is reset when the job finishes /// A registry of workers to mark those for which request has been sent. diff --git a/src/replica/jobs/SqlCreateDbJob.cc b/src/replica/jobs/SqlCreateDbJob.cc index 61befd54d..b466e66fc 100644 --- a/src/replica/jobs/SqlCreateDbJob.cc +++ b/src/replica/jobs/SqlCreateDbJob.cc @@ -29,7 +29,6 @@ // Qserv headers #include "replica/config/Configuration.h" #include "replica/requests/SqlCreateDbRequest.h" -#include "replica/requests/StopRequest.h" #include "replica/services/ServiceProvider.h" // LSST headers @@ -70,25 +69,20 @@ list SqlCreateDbJob::launchRequests(replica::Lock const& lock, size_t maxRequestsPerWorker) { // Launch exactly one request per worker unless it was already // launched earlier - list requests; if (not _workers.count(worker) and maxRequestsPerWorker != 0) { - auto const self = shared_from_base(); - requests.push_back(controller()->sqlCreateDb( - worker, database(), - [self](SqlCreateDbRequest::Ptr const& request) { self->onRequestFinish(request); }, - priority(), true, /* keepTracking*/ - id() /* jobId */ - )); + bool const keepTracking = true; + requests.push_back(SqlCreateDbRequest::createAndStart( + controller(), worker, database(), + [self = shared_from_base()](SqlCreateDbRequest::Ptr const& request) { + self->onRequestFinish(request); + }, + priority(), keepTracking, id())); _workers.insert(worker); } return requests; } -void SqlCreateDbJob::stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) { - stopRequestDefaultImpl(lock, request); -} - void SqlCreateDbJob::notify(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "[" << typeName() << "]"); notifyDefaultImpl(lock, _onFinish); diff --git a/src/replica/jobs/SqlCreateDbJob.h b/src/replica/jobs/SqlCreateDbJob.h index a7c30f4fd..886186f77 100644 --- a/src/replica/jobs/SqlCreateDbJob.h +++ b/src/replica/jobs/SqlCreateDbJob.h @@ -55,67 +55,39 @@ class SqlCreateDbJob : public SqlJob { * and memory management of instances created otherwise (as values or via * low-level pointers). * - * @param database - * the name of a database to be created - * - * @param allWorkers - * engage all known workers regardless of their status. If the flag + * @param database the name of a database to be created + * @param allWorkers engage all known workers regardless of their status. If the flag * is set to 'false' then only 'ENABLED' workers which are not in * the 'READ-ONLY' state will be involved into the operation. - * - * @param controller - * is needed launching requests and accessing the Configuration - * - * @param parentJobId - * an identifier of a parent job - * - * @param onFinish - * a callback function to be called upon a completion of the job - * - * @param priority - * the priority level of the job - * - * @return - * pointer to the created object + * @param controller is needed launching requests and accessing the Configuration + * @param parentJobId an identifier of a parent job + * @param onFinish a callback function to be called upon a completion of the job + * @param priority the priority level of the job + * @return pointer to the created object */ static Ptr create(std::string const& database, bool allWorkers, Controller::Ptr const& controller, std::string const& parentJobId, CallbackType const& onFinish, int priority); - // Default construction and copy semantics are prohibited - SqlCreateDbJob() = delete; SqlCreateDbJob(SqlCreateDbJob const&) = delete; SqlCreateDbJob& operator=(SqlCreateDbJob const&) = delete; ~SqlCreateDbJob() final = default; - // Trivial get methods - std::string const& database() const { return _database; } - - /// @see Job::extendedPersistentState() std::list> extendedPersistentState() const final; protected: - /// @see Job::notify() void notify(replica::Lock const& lock) final; - - /// @see SqlJob::launchRequests() std::list launchRequests(replica::Lock const& lock, std::string const& worker, size_t maxRequestsPerWorker) final; - /// @see SqlJob::stopRequest() - void stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) final; - private: - /// @see SqlCreateDbJob::create() SqlCreateDbJob(std::string const& database, bool allWorkers, Controller::Ptr const& controller, std::string const& parentJobId, CallbackType const& onFinish, int priority); // Input parameters - std::string const _database; - CallbackType _onFinish; /// @note is reset when the job finishes /// A registry of workers to mark those for which request has been sent. diff --git a/src/replica/jobs/SqlCreateIndexesJob.cc b/src/replica/jobs/SqlCreateIndexesJob.cc index 9eebb9df0..deed72d93 100644 --- a/src/replica/jobs/SqlCreateIndexesJob.cc +++ b/src/replica/jobs/SqlCreateIndexesJob.cc @@ -24,7 +24,6 @@ // Qserv headers #include "replica/requests/SqlCreateIndexesRequest.h" -#include "replica/requests/StopRequest.h" // LSST headers #include "lsst/log/Log.h" @@ -91,7 +90,6 @@ list> SqlCreateIndexesJob::extendedPersistentState() const list SqlCreateIndexesJob::launchRequests(replica::Lock const& lock, string const& worker, size_t maxRequestsPerWorker) { list requests; - if (maxRequestsPerWorker == 0) return requests; // Make sure this worker has already been served @@ -104,22 +102,18 @@ list SqlCreateIndexesJob::launchRequests(replica::Lock const& l // Divide tables into subsets allocated to the "batch" requests. Then launch // the requests for the current worker. - auto const self = shared_from_base(); for (auto&& tables : distributeTables(tables2process, maxRequestsPerWorker)) { - requests.push_back(controller()->sqlCreateTableIndexes( - worker, database(), tables, indexSpec(), indexName(), indexComment(), indexColumns(), - [self](SqlCreateIndexesRequest::Ptr const& request) { self->onRequestFinish(request); }, - priority(), true, /* keepTracking*/ - id() /* jobId */ - )); + bool const keepTracking = true; + requests.push_back(SqlCreateIndexesRequest::createAndStart( + controller(), worker, database(), tables, indexSpec(), indexName(), indexComment(), + indexColumns(), + [self = shared_from_base()]( + SqlCreateIndexesRequest::Ptr const& request) { self->onRequestFinish(request); }, + priority(), keepTracking, id())); } return requests; } -void SqlCreateIndexesJob::stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) { - stopRequestDefaultImpl(lock, request); -} - void SqlCreateIndexesJob::notify(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "[" << typeName() << "]"); notifyDefaultImpl(lock, _onFinish); diff --git a/src/replica/jobs/SqlCreateIndexesJob.h b/src/replica/jobs/SqlCreateIndexesJob.h index 140c92c1c..3cd7ee031 100644 --- a/src/replica/jobs/SqlCreateIndexesJob.h +++ b/src/replica/jobs/SqlCreateIndexesJob.h @@ -111,12 +111,9 @@ class SqlCreateIndexesJob : public SqlJob { protected: void notify(replica::Lock const& lock) final; - std::list launchRequests(replica::Lock const& lock, std::string const& worker, size_t maxRequestsPerWorker) final; - void stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) final; - private: SqlCreateIndexesJob(std::string const& database, std::string const& table, bool overlap, SqlRequestParams::IndexSpec const& indexSpec, std::string const& indexName, @@ -125,7 +122,6 @@ class SqlCreateIndexesJob : public SqlJob { std::string const& parentJobId, CallbackType const& onFinish, int priority); // Input parameters - std::string const _database; std::string const _table; bool const _overlap; @@ -133,7 +129,6 @@ class SqlCreateIndexesJob : public SqlJob { std::string const _indexName; std::string const _indexComment; std::vector const _indexColumns; - CallbackType _onFinish; /// @note is reset when the job finishes /// A registry of workers to mark those for which request has been sent. diff --git a/src/replica/jobs/SqlCreateTableJob.cc b/src/replica/jobs/SqlCreateTableJob.cc index 625e85f77..ac1d5d9ad 100644 --- a/src/replica/jobs/SqlCreateTableJob.cc +++ b/src/replica/jobs/SqlCreateTableJob.cc @@ -29,7 +29,6 @@ // Qserv headers #include "replica/config/Configuration.h" #include "replica/requests/SqlCreateTableRequest.h" -#include "replica/requests/StopRequest.h" #include "replica/services/ServiceProvider.h" // LSST headers @@ -83,25 +82,20 @@ list SqlCreateTableJob::launchRequests(replica::Lock const& loc size_t maxRequestsPerWorker) { // Launch exactly one request per worker unless it was already // launched earlier - list requests; if (not _workers.count(worker) and maxRequestsPerWorker != 0) { - auto const self = shared_from_base(); - requests.push_back(controller()->sqlCreateTable( - worker, database(), table(), engine(), partitionByColumn(), columns(), - [self](SqlCreateTableRequest::Ptr const& request) { self->onRequestFinish(request); }, - priority(), true, /* keepTracking*/ - id() /* jobId */ - )); + bool const keepTracking = true; + requests.push_back(SqlCreateTableRequest::createAndStart( + controller(), worker, database(), table(), engine(), partitionByColumn(), columns(), + [self = shared_from_base()](SqlCreateTableRequest::Ptr const& request) { + self->onRequestFinish(request); + }, + priority(), keepTracking, id())); _workers.insert(worker); } return requests; } -void SqlCreateTableJob::stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) { - stopRequestDefaultImpl(lock, request); -} - void SqlCreateTableJob::notify(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "[" << typeName() << "]"); notifyDefaultImpl(lock, _onFinish); diff --git a/src/replica/jobs/SqlCreateTableJob.h b/src/replica/jobs/SqlCreateTableJob.h index c066e9a37..fa24c215d 100644 --- a/src/replica/jobs/SqlCreateTableJob.h +++ b/src/replica/jobs/SqlCreateTableJob.h @@ -56,43 +56,22 @@ class SqlCreateTableJob : public SqlJob { * and memory management of instances created otherwise (as values or via * low-level pointers). * - * @param database - * the name of a database where a new table will be created - * - * @param table - * the name of a table to be created - * - * @param engine - * the name of the MySQL engine for the new table - * - * @pram partitionByColumn - * (optional, if not empty) the name of a column which will be used + * @param database the name of a database where a new table will be created + * @param table the name of a table to be created + * @param engine the name of the MySQL engine for the new table + * @param partitionByColumn (optional, if not empty) the name of a column which will be used * as a key to configure MySQL partitions for the new table. * This variation of table schema will be used for the super-transaction-based * ingest into the table. - * - * @param columns - * column definitions (name,type) of the table - * - * @param allWorkers - * engage all known workers regardless of their status. If the flag + * @param columns column definitions (name,type) of the table + * @param allWorkers engage all known workers regardless of their status. If the flag * is set to 'false' then only 'ENABLED' workers which are not in * the 'READ-ONLY' state will be involved into the operation. - * - * @param controller - * is needed launching requests and accessing the Configuration - * - * @param parentJobId - * an identifier of the parent job - * - * @param onFinish - * a callback function to be called upon a completion of the job - * - * @param priority - * defines the job priority - * - * @return - * pointer to the created object + * @param controller is needed launching requests and accessing the Configuration + * @param parentJobId an identifier of the parent job + * @param onFinish a callback function to be called upon a completion of the job + * @param priority defines the job priority + * @return pointer to the created object */ static Ptr create(std::string const& database, std::string const& table, std::string const& engine, std::string const& partitionByColumn, std::list const& columns, @@ -105,26 +84,18 @@ class SqlCreateTableJob : public SqlJob { ~SqlCreateTableJob() final = default; - // Trivial get methods - std::string const& database() const { return _database; } std::string const& table() const { return _table; } std::string const& engine() const { return _engine; } - std::string const& partitionByColumn() const { return _partitionByColumn; } - std::list const& columns() const { return _columns; } - std::list> extendedPersistentState() const final; protected: void notify(replica::Lock const& lock) final; - std::list launchRequests(replica::Lock const& lock, std::string const& worker, size_t maxRequestsPerWorker) final; - void stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) final; - private: SqlCreateTableJob(std::string const& database, std::string const& table, std::string const& engine, std::string const& partitionByColumn, std::list const& columns, @@ -132,14 +103,11 @@ class SqlCreateTableJob : public SqlJob { CallbackType const& onFinish, int priority); // Input parameters - std::string const _database; std::string const _table; std::string const _engine; std::string const _partitionByColumn; - std::list const _columns; - CallbackType _onFinish; /// @note is reset when the job finishes /// A registry of workers to mark those for which request has been sent. diff --git a/src/replica/jobs/SqlCreateTablesJob.cc b/src/replica/jobs/SqlCreateTablesJob.cc index 2900438f1..68dafcef8 100644 --- a/src/replica/jobs/SqlCreateTablesJob.cc +++ b/src/replica/jobs/SqlCreateTablesJob.cc @@ -24,7 +24,6 @@ // Qserv headers #include "replica/requests/SqlCreateTablesRequest.h" -#include "replica/requests/StopRequest.h" // LSST headers #include "lsst/log/Log.h" @@ -80,7 +79,6 @@ list> SqlCreateTablesJob::extendedPersistentState() const { list SqlCreateTablesJob::launchRequests(replica::Lock const& lock, string const& worker, size_t maxRequestsPerWorker) { list requests; - if (maxRequestsPerWorker == 0) return requests; // Make sure this worker has already been served @@ -92,22 +90,18 @@ list SqlCreateTablesJob::launchRequests(replica::Lock const& lo // Divide tables into subsets allocated to the "batch" requests. Then launch // the requests for the current worker. - auto const self = shared_from_base(); for (auto&& tables : distributeTables(allTables, maxRequestsPerWorker)) { - requests.push_back(controller()->sqlCreateTables( - worker, database(), tables, engine(), partitionByColumn(), columns(), - [self](SqlCreateTablesRequest::Ptr const& request) { self->onRequestFinish(request); }, - priority(), true, /* keepTracking*/ - id() /* jobId */ - )); + bool const keepTracking = true; + requests.push_back(SqlCreateTablesRequest::createAndStart( + controller(), worker, database(), tables, engine(), partitionByColumn(), columns(), + [self = shared_from_base()](SqlCreateTablesRequest::Ptr const& request) { + self->onRequestFinish(request); + }, + priority(), keepTracking, id())); } return requests; } -void SqlCreateTablesJob::stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) { - stopRequestDefaultImpl(lock, request); -} - void SqlCreateTablesJob::notify(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "[" << typeName() << "]"); notifyDefaultImpl(lock, _onFinish); diff --git a/src/replica/jobs/SqlCreateTablesJob.h b/src/replica/jobs/SqlCreateTablesJob.h index fdd2f686f..2824da068 100644 --- a/src/replica/jobs/SqlCreateTablesJob.h +++ b/src/replica/jobs/SqlCreateTablesJob.h @@ -93,21 +93,15 @@ class SqlCreateTablesJob : public SqlJob { std::string const& database() const { return _database; } std::string const& table() const { return _table; } std::string const& engine() const { return _engine; } - std::string const& partitionByColumn() const { return _partitionByColumn; } - std::list const& columns() const { return _columns; } - std::list> extendedPersistentState() const final; protected: void notify(replica::Lock const& lock) final; - std::list launchRequests(replica::Lock const& lock, std::string const& worker, size_t maxRequestsPerWorker) final; - void stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) final; - private: SqlCreateTablesJob(std::string const& database, std::string const& table, std::string const& engine, std::string const& partitionByColumn, std::list const& columns, @@ -115,14 +109,11 @@ class SqlCreateTablesJob : public SqlJob { CallbackType const& onFinish, int priority); // Input parameters - std::string const _database; std::string const _table; std::string const _engine; std::string const _partitionByColumn; - std::list const _columns; - CallbackType _onFinish; /// @note is reset when the job finishes /// A registry of workers to mark those for which request has been sent. diff --git a/src/replica/jobs/SqlDeleteDbJob.cc b/src/replica/jobs/SqlDeleteDbJob.cc index 30f84c284..7d42f2cb6 100644 --- a/src/replica/jobs/SqlDeleteDbJob.cc +++ b/src/replica/jobs/SqlDeleteDbJob.cc @@ -29,7 +29,6 @@ // Qserv headers #include "replica/config/Configuration.h" #include "replica/requests/SqlDeleteDbRequest.h" -#include "replica/requests/StopRequest.h" #include "replica/services/ServiceProvider.h" // LSST headers @@ -70,25 +69,20 @@ list SqlDeleteDbJob::launchRequests(replica::Lock const& lock, size_t maxRequestsPerWorker) { // Launch exactly one request per worker unless it was already // launched earlier - list requests; if (not _workers.count(worker) and maxRequestsPerWorker != 0) { - auto const self = shared_from_base(); - requests.push_back(controller()->sqlDeleteDb( - worker, database(), - [self](SqlDeleteDbRequest::Ptr const& request) { self->onRequestFinish(request); }, - priority(), true, /* keepTracking*/ - id() /* jobId */ - )); + bool const keepTracking = true; + requests.push_back(SqlDeleteDbRequest::createAndStart( + controller(), worker, database(), + [self = shared_from_base()](SqlDeleteDbRequest::Ptr const& request) { + self->onRequestFinish(request); + }, + priority(), keepTracking, id())); _workers.insert(worker); } return requests; } -void SqlDeleteDbJob::stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) { - stopRequestDefaultImpl(lock, request); -} - void SqlDeleteDbJob::notify(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "[" << typeName() << "]"); notifyDefaultImpl(lock, _onFinish); diff --git a/src/replica/jobs/SqlDeleteDbJob.h b/src/replica/jobs/SqlDeleteDbJob.h index a827d9f6f..68d87c56f 100644 --- a/src/replica/jobs/SqlDeleteDbJob.h +++ b/src/replica/jobs/SqlDeleteDbJob.h @@ -55,67 +55,39 @@ class SqlDeleteDbJob : public SqlJob { * and memory management of instances created otherwise (as values or via * low-level pointers). * - * @param database - * the name of a database to be deleted - * - * @param allWorkers - * engage all known workers regardless of their status. If the flag + * @param database the name of a database to be deleted + * @param allWorkers engage all known workers regardless of their status. If the flag * is set to 'false' then only 'ENABLED' workers which are not in * the 'READ-ONLY' state will be involved into the operation. - * - * @param controller - * is needed launching requests and accessing the Configuration - * - * @param parentJobId - * an identifier of a parent job - * - * @param onFinish - * a callback function to be called upon a completion of the job - * - * @param priority - * defines the job priority - * - * @return - * pointer to the created object + * @param controller is needed launching requests and accessing the Configuration + * @param parentJobId an identifier of a parent job + * @param onFinish a callback function to be called upon a completion of the job + * @param priority defines the job priority + * @return pointer to the created object */ static Ptr create(std::string const& database, bool allWorkers, Controller::Ptr const& controller, std::string const& parentJobId, CallbackType const& onFinish, int priority); - // Default construction and copy semantics are prohibited - SqlDeleteDbJob() = delete; SqlDeleteDbJob(SqlDeleteDbJob const&) = delete; SqlDeleteDbJob& operator=(SqlDeleteDbJob const&) = delete; ~SqlDeleteDbJob() final = default; - // Trivial get methods - std::string const& database() const { return _database; } - - /// @see Job::extendedPersistentState() std::list> extendedPersistentState() const final; protected: - /// @see Job::notify() void notify(replica::Lock const& lock) final; - - /// @see SqlJob::launchRequests() std::list launchRequests(replica::Lock const& lock, std::string const& worker, size_t maxRequestsPerWorker) final; - /// @see SqlJob::stopRequest() - void stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) final; - private: - /// @see SqlDeleteDbJob::create() SqlDeleteDbJob(std::string const& database, bool allWorkers, Controller::Ptr const& controller, std::string const& parentJobId, CallbackType const& onFinish, int priority); // Input parameters - std::string const _database; - CallbackType _onFinish; /// @note is reset when the job finishes /// A registry of workers to mark those for which request has been sent. diff --git a/src/replica/jobs/SqlDeleteTableJob.cc b/src/replica/jobs/SqlDeleteTableJob.cc index a99775ced..2ec8f47f7 100644 --- a/src/replica/jobs/SqlDeleteTableJob.cc +++ b/src/replica/jobs/SqlDeleteTableJob.cc @@ -27,7 +27,6 @@ // Qserv headers #include "replica/requests/SqlDeleteTableRequest.h" -#include "replica/requests/StopRequest.h" // LSST headers #include "lsst/log/Log.h" @@ -70,7 +69,6 @@ list> SqlDeleteTableJob::extendedPersistentState() const { list SqlDeleteTableJob::launchRequests(replica::Lock const& lock, string const& worker, size_t maxRequestsPerWorker) { list requests; - if (maxRequestsPerWorker == 0) return requests; // Make sure this worker has already been served @@ -82,22 +80,18 @@ list SqlDeleteTableJob::launchRequests(replica::Lock const& loc // Divide tables into subsets allocated to the "batch" requests. Then launch // the requests for the current worker. - auto const self = shared_from_base(); for (auto&& tables : distributeTables(allTables, maxRequestsPerWorker)) { - requests.push_back(controller()->sqlDeleteTable( - worker, database(), tables, - [self](SqlDeleteTableRequest::Ptr const& request) { self->onRequestFinish(request); }, - priority(), true, /* keepTracking*/ - id() /* jobId */ - )); + bool const keepTracking = true; + requests.push_back(SqlDeleteTableRequest::createAndStart( + controller(), worker, database(), tables, + [self = shared_from_base()](SqlDeleteTableRequest::Ptr const& request) { + self->onRequestFinish(request); + }, + priority(), keepTracking, id())); } return requests; } -void SqlDeleteTableJob::stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) { - stopRequestDefaultImpl(lock, request); -} - void SqlDeleteTableJob::notify(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "[" << typeName() << "]"); notifyDefaultImpl(lock, _onFinish); diff --git a/src/replica/jobs/SqlDeleteTableJob.h b/src/replica/jobs/SqlDeleteTableJob.h index 73a1cfe2d..0dadf57e4 100644 --- a/src/replica/jobs/SqlDeleteTableJob.h +++ b/src/replica/jobs/SqlDeleteTableJob.h @@ -83,31 +83,23 @@ class SqlDeleteTableJob : public SqlJob { ~SqlDeleteTableJob() final = default; - // Trivial get methods - std::string const& database() const { return _database; } std::string const& table() const { return _table; } - std::list> extendedPersistentState() const final; protected: void notify(replica::Lock const& lock) final; - std::list launchRequests(replica::Lock const& lock, std::string const& worker, size_t maxRequestsPerWorker) final; - void stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) final; - private: SqlDeleteTableJob(std::string const& database, std::string const& table, bool allWorkers, Controller::Ptr const& controller, std::string const& parentJobId, CallbackType const& onFinish, int priority); // Input parameters - std::string const _database; std::string const _table; - CallbackType _onFinish; /// @note is reset when the job finishes /// A registry of workers to mark those for which request has been sent. diff --git a/src/replica/jobs/SqlDeleteTablePartitionJob.cc b/src/replica/jobs/SqlDeleteTablePartitionJob.cc index 26b7728a2..9746b7ba6 100644 --- a/src/replica/jobs/SqlDeleteTablePartitionJob.cc +++ b/src/replica/jobs/SqlDeleteTablePartitionJob.cc @@ -23,9 +23,9 @@ #include "replica/jobs/SqlDeleteTablePartitionJob.h" // Qserv headers +#include "replica/config/Configuration.h" #include "replica/contr/Controller.h" #include "replica/requests/SqlDeleteTablePartitionRequest.h" -#include "replica/requests/StopRequest.h" #include "replica/services/DatabaseServices.h" #include "replica/services/ServiceProvider.h" @@ -95,7 +95,6 @@ list SqlDeleteTablePartitionJob::launchRequests(replica::Lock c string const& worker, size_t maxRequestsPerWorker) { list requests; - if (maxRequestsPerWorker == 0) return requests; // Make sure this worker has already been served @@ -107,24 +106,19 @@ list SqlDeleteTablePartitionJob::launchRequests(replica::Lock c // Divide tables into subsets allocated to the "batch" requests. Then launch // the requests for the current worker. - bool const keepTracking = true; - string const jobId = id(); - auto const self = shared_from_base(); for (auto&& tables : distributeTables(allTables, maxRequestsPerWorker)) { - requests.push_back(controller()->sqlDeleteTablePartition( - worker, database(), tables, transactionId(), - [self](SqlDeleteTablePartitionRequest::Ptr const& request) { + bool const keepTracking = true; + requests.push_back(SqlDeleteTablePartitionRequest::createAndStart( + controller(), worker, database(), tables, transactionId(), + [self = shared_from_base()]( + SqlDeleteTablePartitionRequest::Ptr const& request) { self->onRequestFinish(request); }, - priority(), keepTracking, jobId)); + priority(), keepTracking, id())); } return requests; } -void SqlDeleteTablePartitionJob::stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) { - stopRequestDefaultImpl(lock, request); -} - void SqlDeleteTablePartitionJob::notify(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "[" << typeName() << "]"); notifyDefaultImpl(lock, _onFinish); diff --git a/src/replica/jobs/SqlDeleteTablePartitionJob.h b/src/replica/jobs/SqlDeleteTablePartitionJob.h index 63620ac58..a1cde7c4e 100644 --- a/src/replica/jobs/SqlDeleteTablePartitionJob.h +++ b/src/replica/jobs/SqlDeleteTablePartitionJob.h @@ -86,30 +86,22 @@ class SqlDeleteTablePartitionJob : public SqlJob { ~SqlDeleteTablePartitionJob() final = default; - // Trivial get methods - std::string const& database() const { return _database; } std::string const& table() const { return _table; } - TransactionId transactionId() const { return _transactionId; } - std::list> extendedPersistentState() const final; protected: void notify(replica::Lock const& lock) final; - std::list launchRequests(replica::Lock const& lock, std::string const& worker, size_t maxRequestsPerWorker) final; - void stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) final; - private: SqlDeleteTablePartitionJob(TransactionId transactionId, std::string const& table, bool allWorkers, Controller::Ptr const& controller, std::string const& parentJobId, CallbackType const& onFinish, int priority); // Input parameters - TransactionId const _transactionId; std::string const _table; CallbackType _onFinish; /// @note is reset when the job finishes diff --git a/src/replica/jobs/SqlDisableDbJob.cc b/src/replica/jobs/SqlDisableDbJob.cc index eb6712e6d..c1431da3b 100644 --- a/src/replica/jobs/SqlDisableDbJob.cc +++ b/src/replica/jobs/SqlDisableDbJob.cc @@ -29,7 +29,6 @@ // Qserv headers #include "replica/config/Configuration.h" #include "replica/requests/SqlDisableDbRequest.h" -#include "replica/requests/StopRequest.h" #include "replica/services/ServiceProvider.h" // LSST headers @@ -70,25 +69,20 @@ list SqlDisableDbJob::launchRequests(replica::Lock const& lock, size_t maxRequestsPerWorker) { // Launch exactly one request per worker unless it was already // launched earlier - list requests; if (not _workers.count(worker) and maxRequestsPerWorker != 0) { - auto const self = shared_from_base(); - requests.push_back(controller()->sqlDisableDb( - worker, database(), - [self](SqlDisableDbRequest::Ptr const& request) { self->onRequestFinish(request); }, - priority(), true, /* keepTracking*/ - id() /* jobId */ - )); + bool const keepTracking = true; + requests.push_back(SqlDisableDbRequest::createAndStart( + controller(), worker, database(), + [self = shared_from_base()](SqlDisableDbRequest::Ptr const& request) { + self->onRequestFinish(request); + }, + priority(), keepTracking, id())); _workers.insert(worker); } return requests; } -void SqlDisableDbJob::stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) { - stopRequestDefaultImpl(lock, request); -} - void SqlDisableDbJob::notify(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "[" << typeName() << "]"); notifyDefaultImpl(lock, _onFinish); diff --git a/src/replica/jobs/SqlDisableDbJob.h b/src/replica/jobs/SqlDisableDbJob.h index 1b473fbab..552389a34 100644 --- a/src/replica/jobs/SqlDisableDbJob.h +++ b/src/replica/jobs/SqlDisableDbJob.h @@ -55,67 +55,39 @@ class SqlDisableDbJob : public SqlJob { * and memory management of instances created otherwise (as values or via * low-level pointers). * - * @param database - * the name of a database to be disabled - * - * @param allWorkers - * engage all known workers regardless of their status. If the flag + * @param database the name of a database to be disabled + * @param allWorkers engage all known workers regardless of their status. If the flag * is set to 'false' then only 'ENABLED' workers which are not in * the 'READ-ONLY' state will be involved into the operation. - * - * @param controller - * is needed launching requests and accessing the Configuration - * - * @param parentJobId - * an identifier of a parent job - * - * @param onFinish - * a callback function to be called upon a completion of the job - * - * @param priority - * defines the job priority - * - * @return - * pointer to the created object + * @param controller is needed launching requests and accessing the Configuration + * @param parentJobId an identifier of a parent job + * @param onFinish a callback function to be called upon a completion of the job + * @param priority defines the job priority + * @return pointer to the created object */ static Ptr create(std::string const& database, bool allWorkers, Controller::Ptr const& controller, std::string const& parentJobId, CallbackType const& onFinish, int priority); - // Default construction and copy semantics are prohibited - SqlDisableDbJob() = delete; SqlDisableDbJob(SqlDisableDbJob const&) = delete; SqlDisableDbJob& operator=(SqlDisableDbJob const&) = delete; ~SqlDisableDbJob() final = default; - // Trivial get methods - std::string const& database() const { return _database; } - - /// @see Job::extendedPersistentState() std::list> extendedPersistentState() const final; protected: - /// @see Job::notify() void notify(replica::Lock const& lock) final; - - /// @see SqlJob::launchRequests() std::list launchRequests(replica::Lock const& lock, std::string const& worker, size_t maxRequestsPerWorker) final; - /// @see SqlJob::stopRequest() - void stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) final; - private: - /// @see SqlDisableDbJob::create() SqlDisableDbJob(std::string const& database, bool allWorkers, Controller::Ptr const& controller, std::string const& parentJobId, CallbackType const& onFinish, int priority); // Input parameters - std::string const _database; - CallbackType _onFinish; /// @note is reset when the job finishes /// A registry of workers to mark those for which request has been sent. diff --git a/src/replica/jobs/SqlDropIndexesJob.cc b/src/replica/jobs/SqlDropIndexesJob.cc index 81db7da47..f901d67f3 100644 --- a/src/replica/jobs/SqlDropIndexesJob.cc +++ b/src/replica/jobs/SqlDropIndexesJob.cc @@ -24,7 +24,6 @@ // Qserv headers #include "replica/requests/SqlDropIndexesRequest.h" -#include "replica/requests/StopRequest.h" // LSST headers #include "lsst/log/Log.h" @@ -76,7 +75,6 @@ list> SqlDropIndexesJob::extendedPersistentState() const { list SqlDropIndexesJob::launchRequests(replica::Lock const& lock, string const& worker, size_t maxRequestsPerWorker) { list requests; - if (maxRequestsPerWorker == 0) return requests; // Make sure this worker has already been served @@ -89,22 +87,18 @@ list SqlDropIndexesJob::launchRequests(replica::Lock const& loc // Divide tables into subsets allocated to the "batch" requests. Then launch // the requests for the current worker. - auto const self = shared_from_base(); for (auto&& tables : distributeTables(tables2process, maxRequestsPerWorker)) { - requests.push_back(controller()->sqlDropTableIndexes( - worker, database(), tables, indexName(), - [self](SqlDropIndexesRequest::Ptr const& request) { self->onRequestFinish(request); }, - priority(), true, /* keepTracking*/ - id() /* jobId */ - )); + bool const keepTracking = true; + requests.push_back(SqlDropIndexesRequest::createAndStart( + controller(), worker, database(), tables, indexName(), + [self = shared_from_base()](SqlDropIndexesRequest::Ptr const& request) { + self->onRequestFinish(request); + }, + priority(), keepTracking, id())); } return requests; } -void SqlDropIndexesJob::stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) { - stopRequestDefaultImpl(lock, request); -} - void SqlDropIndexesJob::notify(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "[" << typeName() << "]"); notifyDefaultImpl(lock, _onFinish); diff --git a/src/replica/jobs/SqlDropIndexesJob.h b/src/replica/jobs/SqlDropIndexesJob.h index bf8aea55d..b5d0fb868 100644 --- a/src/replica/jobs/SqlDropIndexesJob.h +++ b/src/replica/jobs/SqlDropIndexesJob.h @@ -100,12 +100,9 @@ class SqlDropIndexesJob : public SqlJob { protected: void notify(replica::Lock const& lock) final; - std::list launchRequests(replica::Lock const& lock, std::string const& worker, size_t maxRequestsPerWorker) final; - void stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) final; - private: SqlDropIndexesJob(std::string const& database, std::string const& table, bool overlap, std::string const& indexName, bool allWorkers, Controller::Ptr const& controller, diff --git a/src/replica/jobs/SqlEnableDbJob.cc b/src/replica/jobs/SqlEnableDbJob.cc index 06e548978..77a7ec0b4 100644 --- a/src/replica/jobs/SqlEnableDbJob.cc +++ b/src/replica/jobs/SqlEnableDbJob.cc @@ -29,7 +29,6 @@ // Qserv headers #include "replica/config/Configuration.h" #include "replica/requests/SqlEnableDbRequest.h" -#include "replica/requests/StopRequest.h" #include "replica/services/ServiceProvider.h" // LSST headers @@ -70,25 +69,20 @@ list SqlEnableDbJob::launchRequests(replica::Lock const& lock, size_t maxRequestsPerWorker) { // Launch exactly one request per worker unless it was already // launched earlier - list requests; if (not _workers.count(worker) and maxRequestsPerWorker != 0) { - auto const self = shared_from_base(); - requests.push_back(controller()->sqlEnableDb( - worker, database(), - [self](SqlEnableDbRequest::Ptr const& request) { self->onRequestFinish(request); }, - priority(), true, /* keepTracking*/ - id() /* jobId */ - )); + bool const keepTracking = true; + requests.push_back(SqlEnableDbRequest::createAndStart( + controller(), worker, database(), + [self = shared_from_base()](SqlEnableDbRequest::Ptr const& request) { + self->onRequestFinish(request); + }, + priority(), keepTracking, id())); _workers.insert(worker); } return requests; } -void SqlEnableDbJob::stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) { - stopRequestDefaultImpl(lock, request); -} - void SqlEnableDbJob::notify(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "[" << typeName() << "]"); notifyDefaultImpl(lock, _onFinish); diff --git a/src/replica/jobs/SqlEnableDbJob.h b/src/replica/jobs/SqlEnableDbJob.h index b545de3fb..89394d181 100644 --- a/src/replica/jobs/SqlEnableDbJob.h +++ b/src/replica/jobs/SqlEnableDbJob.h @@ -55,67 +55,40 @@ class SqlEnableDbJob : public SqlJob { * and memory management of instances created otherwise (as values or via * low-level pointers). * - * @param database - * the name of a database to be enabled - * - * @param allWorkers - * engage all known workers regardless of their status. If the flag + * @param database the name of a database to be enabled + * @param allWorkers engage all known workers regardless of their status. If the flag * is set to 'false' then only 'ENABLED' workers which are not in * the 'READ-ONLY' state will be involved into the operation. - * - * @param controller - * is needed launching requests and accessing the Configuration - * - * @param parentJobId - * an identifier of a parent job - * - * @param onFinish - * a callback function to be called upon a completion of the job - * - * @param priority - * defines the job priority - * - * @return - * pointer to the created object + * @param controller is needed launching requests and accessing the Configuration + * @param parentJobId an identifier of a parent job + * @param onFinish a callback function to be called upon a completion of the job + * @param priority defines the job priority + * @return pointer to the created object */ static Ptr create(std::string const& database, bool allWorkers, Controller::Ptr const& controller, std::string const& parentJobId, CallbackType const& onFinish, int priority); - // Default construction and copy semantics are prohibited - SqlEnableDbJob() = delete; SqlEnableDbJob(SqlEnableDbJob const&) = delete; SqlEnableDbJob& operator=(SqlEnableDbJob const&) = delete; ~SqlEnableDbJob() final = default; - // Trivial get methods - std::string const& database() const { return _database; } - - /// @see Job::extendedPersistentState() std::list> extendedPersistentState() const final; protected: - /// @see Job::notify() void notify(replica::Lock const& lock) final; - - /// @see SqlJob::launchRequests() std::list launchRequests(replica::Lock const& lock, std::string const& worker, size_t maxRequestsPerWorker) final; - /// @see SqlJob::stopRequest() - void stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) final; - private: - /// @see SqlEnableDbJob::create() SqlEnableDbJob(std::string const& database, bool allWorkers, Controller::Ptr const& controller, std::string const& parentJobId, CallbackType const& onFinish, int priority); // Input parameters std::string const _database; - CallbackType _onFinish; /// @note is reset when the job finishes /// A registry of workers to mark those for which request has been sent. diff --git a/src/replica/jobs/SqlGetIndexesJob.cc b/src/replica/jobs/SqlGetIndexesJob.cc index a45e208d3..283594517 100644 --- a/src/replica/jobs/SqlGetIndexesJob.cc +++ b/src/replica/jobs/SqlGetIndexesJob.cc @@ -23,8 +23,8 @@ #include "replica/jobs/SqlGetIndexesJob.h" // Qserv headers +#include "replica/mysql/DatabaseMySQLRow.h" #include "replica/requests/SqlGetIndexesRequest.h" -#include "replica/requests/StopRequest.h" // LSST headers #include "lsst/log/Log.h" @@ -249,7 +249,6 @@ SqlIndexes SqlGetIndexesJob::indexes() const { list SqlGetIndexesJob::launchRequests(replica::Lock const& lock, string const& worker, size_t maxRequestsPerWorker) { list requests; - if (maxRequestsPerWorker == 0) return requests; // Make sure this worker has already been served @@ -261,22 +260,18 @@ list SqlGetIndexesJob::launchRequests(replica::Lock const& lock // Divide tables into subsets allocated to the "batch" requests. Then launch // the requests for the current worker. - auto const self = shared_from_base(); for (auto&& tables : distributeTables(_workers2tables[worker], maxRequestsPerWorker)) { - requests.push_back(controller()->sqlGetTableIndexes( - worker, database(), tables, - [self](SqlGetIndexesRequest::Ptr const& request) { self->onRequestFinish(request); }, - priority(), true, /* keepTracking*/ - id() /* jobId */ - )); + bool const keepTracking = true; + requests.push_back(SqlGetIndexesRequest::createAndStart( + controller(), worker, database(), tables, + [self = shared_from_base()](SqlGetIndexesRequest::Ptr const& request) { + self->onRequestFinish(request); + }, + priority(), keepTracking, id())); } return requests; } -void SqlGetIndexesJob::stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) { - stopRequestDefaultImpl(lock, request); -} - void SqlGetIndexesJob::notify(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "[" << typeName() << "]"); notifyDefaultImpl(lock, _onFinish); diff --git a/src/replica/jobs/SqlGetIndexesJob.h b/src/replica/jobs/SqlGetIndexesJob.h index 160b035b5..775926db4 100644 --- a/src/replica/jobs/SqlGetIndexesJob.h +++ b/src/replica/jobs/SqlGetIndexesJob.h @@ -170,7 +170,6 @@ class SqlGetIndexesJob : public SqlJob { std::string const& database() const { return _database; } std::string const& table() const { return _table; } bool overlap() const { return _overlap; } - std::list> extendedPersistentState() const final; /** @@ -184,23 +183,18 @@ class SqlGetIndexesJob : public SqlJob { protected: void notify(replica::Lock const& lock) final; - std::list launchRequests(replica::Lock const& lock, std::string const& worker, size_t maxRequestsPerWorker) final; - void stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) final; - private: SqlGetIndexesJob(std::string const& database, std::string const& table, bool overlap, bool allWorkers, Controller::Ptr const& controller, std::string const& parentJobId, CallbackType const& onFinish, int priority); // Input parameters - std::string const _database; std::string const _table; bool const _overlap; - CallbackType _onFinish; /// @note is reset when the job finishes /// A collection of tables to be processed by workers. The collection diff --git a/src/replica/jobs/SqlGrantAccessJob.cc b/src/replica/jobs/SqlGrantAccessJob.cc index 220fed935..60a451076 100644 --- a/src/replica/jobs/SqlGrantAccessJob.cc +++ b/src/replica/jobs/SqlGrantAccessJob.cc @@ -29,7 +29,6 @@ // Qserv headers #include "replica/config/Configuration.h" #include "replica/requests/SqlGrantAccessRequest.h" -#include "replica/requests/StopRequest.h" #include "replica/services/ServiceProvider.h" // LSST headers @@ -77,22 +76,18 @@ list SqlGrantAccessJob::launchRequests(replica::Lock const& loc list requests; if (not _workers.count(worker) and maxRequestsPerWorker != 0) { - auto const self = shared_from_base(); - requests.push_back(controller()->sqlGrantAccess( - worker, database(), user(), - [self](SqlGrantAccessRequest::Ptr const& request) { self->onRequestFinish(request); }, - priority(), true, /* keepTracking*/ - id() /* jobId */ - )); + bool const keepTracking = true; + requests.push_back(SqlGrantAccessRequest::createAndStart( + controller(), worker, database(), user(), + [self = shared_from_base()](SqlGrantAccessRequest::Ptr const& request) { + self->onRequestFinish(request); + }, + priority(), keepTracking, id())); _workers.insert(worker); } return requests; } -void SqlGrantAccessJob::stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) { - stopRequestDefaultImpl(lock, request); -} - void SqlGrantAccessJob::notify(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "[" << typeName() << "]"); notifyDefaultImpl(lock, _onFinish); diff --git a/src/replica/jobs/SqlGrantAccessJob.h b/src/replica/jobs/SqlGrantAccessJob.h index 19b71dba2..88f3ce323 100644 --- a/src/replica/jobs/SqlGrantAccessJob.h +++ b/src/replica/jobs/SqlGrantAccessJob.h @@ -55,74 +55,44 @@ class SqlGrantAccessJob : public SqlJob { * and memory management of instances created otherwise (as values or via * low-level pointers). * - * @param database - * the name of a database to be accessed by the user - * - * @param user - * the name of a user affected by the operation - * - * @param allWorkers - * engage all known workers regardless of their status. If the flag + * @param database the name of a database to be accessed by the user + * @param user the name of a user affected by the operation + * @param allWorkers engage all known workers regardless of their status. If the flag * is set to 'false' then only 'ENABLED' workers which are not in * the 'READ-ONLY' state will be involved into the operation. - * - * @param controller - * is needed launching requests and accessing the Configuration - * - * @param parentJobId - * identifier of a parent job - * - * @param onFinish - * callback function to be called upon a completion of the job - * - * @param priority - * defines the job priority - * - * @return - * pointer to the created object + * @param controller is needed launching requests and accessing the Configuration + * @param parentJobId identifier of a parent job + * @param onFinish callback function to be called upon a completion of the job + * @param priority defines the job priority + * @return pointer to the created object */ static Ptr create(std::string const& database, std::string const& user, bool allWorkers, Controller::Ptr const& controller, std::string const& parentJobId, CallbackType const& onFinish, int priority); - // Default construction and copy semantics are prohibited - SqlGrantAccessJob() = delete; SqlGrantAccessJob(SqlGrantAccessJob const&) = delete; SqlGrantAccessJob& operator=(SqlGrantAccessJob const&) = delete; ~SqlGrantAccessJob() final = default; - // Trivial get methods - std::string const& database() const { return _database; } std::string const& user() const { return _user; } - - /// @see Job::extendedPersistentState() std::list> extendedPersistentState() const final; protected: - /// @see Job::notify() void notify(replica::Lock const& lock) final; - - /// @see SqlJob::launchRequests() std::list launchRequests(replica::Lock const& lock, std::string const& worker, size_t maxRequestsPerWorker) final; - /// @see SqlJob::stopRequest() - void stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) final; - private: - /// @see SqlGrantAccessJob::create() SqlGrantAccessJob(std::string const& database, std::string const& user, bool allWorkers, Controller::Ptr const& controller, std::string const& parentJobId, CallbackType const& onFinish, int priority); // Input parameters - std::string const _database; std::string const _user; - CallbackType _onFinish; /// @note is reset when the job finishes /// A registry of workers to mark those for which request has been sent. diff --git a/src/replica/jobs/SqlJob.cc b/src/replica/jobs/SqlJob.cc index 7523cfa08..45c96d080 100644 --- a/src/replica/jobs/SqlJob.cc +++ b/src/replica/jobs/SqlJob.cc @@ -121,6 +121,13 @@ json SqlJob::getExtendedErrorReport() const { return report; } +void SqlJob::stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) const { + auto const noCallBackOnFinish = nullptr; + bool const keepTracking = true; + StopRequest::createAndStart(controller(), request->workerName(), request->id(), noCallBackOnFinish, + priority(), keepTracking, id()); +} + void SqlJob::startImpl(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__); auto const workerNames = allWorkers() ? controller()->serviceProvider()->config()->allWorkers() diff --git a/src/replica/jobs/SqlJob.h b/src/replica/jobs/SqlJob.h index f91338391..3fe11404c 100644 --- a/src/replica/jobs/SqlJob.h +++ b/src/replica/jobs/SqlJob.h @@ -154,23 +154,9 @@ class SqlJob : public Job { size_t maxRequestsPerWorker = 1) = 0; /** - * This method lets a request type-specific subclass to stop requests - * of the corresponding subtype. + * Stop the specified request if it's still running. */ - virtual void stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) = 0; - - /** - * This method is called by subclass-specific implementations of - * the virtual method SqlJob::stopRequest in order to reduce code - * duplication. - */ - template - void stopRequestDefaultImpl(replica::Lock const& lock, SqlRequest::Ptr const& request) const { - auto const noCallBackOnFinish = nullptr; - bool const keepTracking = true; - controller()->stopById(request->workerName(), request->id(), noCallBackOnFinish, priority(), - keepTracking, id()); - } + void stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) const; /** * This method lets a request type-specific subclass a chance to process @@ -282,7 +268,6 @@ class SqlJob : public Job { bool _isPartitioned(std::string const& databaseName, std::string const& tableName) const; // Input parameters - uint64_t const _maxRows; bool const _allWorkers; bool const _ignoreNonPartitioned; diff --git a/src/replica/jobs/SqlQueryJob.cc b/src/replica/jobs/SqlQueryJob.cc index dbbf8269d..862648cfe 100644 --- a/src/replica/jobs/SqlQueryJob.cc +++ b/src/replica/jobs/SqlQueryJob.cc @@ -29,7 +29,6 @@ // Qserv headers #include "replica/config/Configuration.h" #include "replica/requests/SqlQueryRequest.h" -#include "replica/requests/StopRequest.h" #include "replica/services/ServiceProvider.h" // LSST headers @@ -76,25 +75,21 @@ list SqlQueryJob::launchRequests(replica::Lock const& lock, str size_t maxRequestsPerWorker) { // Launch exactly one request per worker unless it was already // launched earlier - list requests; if (not _workers.count(worker) and maxRequestsPerWorker != 0) { - auto const self = shared_from_base(); - requests.push_back(controller()->sqlQuery( - worker, query(), user(), password(), maxRows(), - [self](SqlQueryRequest::Ptr const& request) { self->onRequestFinish(request); }, priority(), - true, /* keepTracking*/ - id() /* jobId */ + requests.push_back(SqlQueryRequest::createAndStart( + controller(), worker, query(), user(), password(), maxRows(), + [self = shared_from_base()](SqlQueryRequest::Ptr const& request) { + self->onRequestFinish(request); + }, + priority(), true, /* keepTracking*/ + id() /* jobId */ )); _workers.insert(worker); } return requests; } -void SqlQueryJob::stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) { - stopRequestDefaultImpl(lock, request); -} - void SqlQueryJob::notify(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "[" << typeName() << "]"); notifyDefaultImpl(lock, _onFinish); diff --git a/src/replica/jobs/SqlQueryJob.h b/src/replica/jobs/SqlQueryJob.h index 1764c7259..fdafb706a 100644 --- a/src/replica/jobs/SqlQueryJob.h +++ b/src/replica/jobs/SqlQueryJob.h @@ -56,86 +56,52 @@ class SqlQueryJob : public SqlJob { * and memory management of instances created otherwise (as values or via * low-level pointers). * - * @param query - * the query to be executed on all workers - * - * @param user - * the name of a database account for connecting to the database service - * - * @param password - * a database for connecting to the database service - * - * @param maxRows - * (optional) limit for the maximum number of rows to be returned with the request. + * @param query the query to be executed on all workers + * @param user the name of a database account for connecting to the database service + * @param password a database for connecting to the database service + * @param maxRows (optional) limit for the maximum number of rows to be returned with the request. * Leaving the default value of the parameter to 0 will result in not imposing any * explicit restrictions on a size of the result set. Note that other, resource-defined * restrictions will still apply. The later includes the maximum size of the Google Protobuf * objects, the amount of available memory, etc. - * - * @param allWorkers - * engage all known workers regardless of their status. If the flag + * @param allWorkers engage all known workers regardless of their status. If the flag * is set to 'false' then only 'ENABLED' workers which are not in * the 'READ-ONLY' state will be involved into the operation. - * - * @param controller - * is needed launching requests and accessing the Configuration - * - * @param parentJobId - * an identifier of the parent job - * - * @param onFinish - * a callback function to be called upon a completion of the job - * - * @param priority - * defines the job priority - * - * @return - * pointer to the created object + * @param controller is needed launching requests and accessing the Configuration + * @param parentJobId an identifier of the parent job + * @param onFinish a callback function to be called upon a completion of the job + * @param priority defines the job priority + * @return pointer to the created object */ static Ptr create(std::string const& query, std::string const& user, std::string const& password, uint64_t maxRows, bool allWorkers, Controller::Ptr const& controller, std::string const& parentJobId, CallbackType const& onFinish, int priority); - // Default construction and copy semantics are prohibited - SqlQueryJob() = delete; SqlQueryJob(SqlQueryJob const&) = delete; SqlQueryJob& operator=(SqlQueryJob const&) = delete; ~SqlQueryJob() final = default; - // Trivial get methods - std::string const& query() const { return _query; } std::string const& user() const { return _user; } std::string const& password() const { return _password; } - - /// @see Job::extendedPersistentState() std::list> extendedPersistentState() const final; protected: - /// @see Job::notify() void notify(replica::Lock const& lock) final; - - /// @see SqlJob::launchRequests() std::list launchRequests(replica::Lock const& lock, std::string const& worker, size_t maxRequestsPerWorker) final; - /// @see SqlJob::stopRequest() - void stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) final; - private: - /// @see SqlQueryJob::create() SqlQueryJob(std::string const& query, std::string const& user, std::string const& password, uint64_t maxRows, bool allWorkers, Controller::Ptr const& controller, std::string const& parentJobId, CallbackType const& onFinish, int priority); // Input parameters - std::string const _query; std::string const _user; std::string const _password; - CallbackType _onFinish; /// @note is reset when the job finishes /// A registry of workers to mark those for which request has been sent. diff --git a/src/replica/jobs/SqlRemoveTablePartitionsJob.cc b/src/replica/jobs/SqlRemoveTablePartitionsJob.cc index 8c3f5288d..01f98e839 100644 --- a/src/replica/jobs/SqlRemoveTablePartitionsJob.cc +++ b/src/replica/jobs/SqlRemoveTablePartitionsJob.cc @@ -24,7 +24,6 @@ // Qserv headers #include "replica/requests/SqlRemoveTablePartitionsRequest.h" -#include "replica/requests/StopRequest.h" // LSST headers #include "lsst/log/Log.h" @@ -76,7 +75,6 @@ list SqlRemoveTablePartitionsJob::launchRequests(replica::Lock string const& worker, size_t maxRequestsPerWorker) { list requests; - if (maxRequestsPerWorker == 0) return requests; // Make sure this worker has already been served @@ -88,24 +86,19 @@ list SqlRemoveTablePartitionsJob::launchRequests(replica::Lock // Divide tables into subsets allocated to the "batch" requests. Then launch // the requests for the current worker. - auto const self = shared_from_base(); for (auto&& tables : distributeTables(allTables, maxRequestsPerWorker)) { - requests.push_back(controller()->sqlRemoveTablePartitions( - worker, database(), tables, - [self](SqlRemoveTablePartitionsRequest::Ptr const& request) { + bool const keepTracking = true; + requests.push_back(SqlRemoveTablePartitionsRequest::createAndStart( + controller(), worker, database(), tables, + [self = shared_from_base()]( + SqlRemoveTablePartitionsRequest::Ptr const& request) { self->onRequestFinish(request); }, - priority(), true, /* keepTracking*/ - id() /* jobId */ - )); + priority(), keepTracking, id())); } return requests; } -void SqlRemoveTablePartitionsJob::stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) { - stopRequestDefaultImpl(lock, request); -} - void SqlRemoveTablePartitionsJob::notify(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "[" << typeName() << "]"); notifyDefaultImpl(lock, _onFinish); diff --git a/src/replica/jobs/SqlRemoveTablePartitionsJob.h b/src/replica/jobs/SqlRemoveTablePartitionsJob.h index dd65364c4..680c6e2aa 100644 --- a/src/replica/jobs/SqlRemoveTablePartitionsJob.h +++ b/src/replica/jobs/SqlRemoveTablePartitionsJob.h @@ -123,31 +123,23 @@ class SqlRemoveTablePartitionsJob : public SqlJob { ~SqlRemoveTablePartitionsJob() final = default; - // Trivial get methods - std::string const& database() const { return _database; } std::string const& table() const { return _table; } - std::list> extendedPersistentState() const final; protected: void notify(replica::Lock const& lock) final; - std::list launchRequests(replica::Lock const& lock, std::string const& worker, size_t maxRequestsPerWorker) final; - void stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) final; - private: SqlRemoveTablePartitionsJob(std::string const& database, std::string const& table, bool allWorkers, bool ignoreNonPartitioned, Controller::Ptr const& controller, std::string const& parentJobId, CallbackType const& onFinish, int priority); // Input parameters - std::string const _database; std::string const _table; - CallbackType _onFinish; /// @note is reset when the job finishes /// A registry of workers to mark the ones that has been processed. diff --git a/src/replica/jobs/SqlRowStatsJob.cc b/src/replica/jobs/SqlRowStatsJob.cc index 70ca77030..738237f3e 100644 --- a/src/replica/jobs/SqlRowStatsJob.cc +++ b/src/replica/jobs/SqlRowStatsJob.cc @@ -25,9 +25,10 @@ // Qserv headers #include "global/constants.h" #include "global/stringUtil.h" +#include "replica/config/Configuration.h" #include "replica/jobs/SqlJobResult.h" #include "replica/requests/SqlRowStatsRequest.h" -#include "replica/requests/StopRequest.h" +#include "replica/services/DatabaseServices.h" #include "replica/util/ChunkedTable.h" #include "util/TimeUtils.h" @@ -129,21 +130,18 @@ list SqlRowStatsJob::launchRequests(replica::Lock const& lock, // Divide tables into subsets allocated to the "batch" requests. Then launch // the requests for the current worker. - bool const keepTracking = true; - auto const self = shared_from_base(); for (auto&& tables : distributeTables(tables2process, maxRequestsPerWorker)) { - requests.push_back(controller()->sqlRowStats( - worker, database(), tables, - [self](SqlRowStatsRequest::Ptr const& request) { self->onRequestFinish(request); }, + bool const keepTracking = true; + requests.push_back(SqlRowStatsRequest::createAndStart( + controller(), worker, database(), tables, + [self = shared_from_base()](SqlRowStatsRequest::Ptr const& request) { + self->onRequestFinish(request); + }, priority(), keepTracking, id())); } return requests; } -void SqlRowStatsJob::stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) { - stopRequestDefaultImpl(lock, request); -} - void SqlRowStatsJob::notify(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "[" << typeName() << "]"); notifyDefaultImpl(lock, _onFinish); @@ -170,7 +168,6 @@ void SqlRowStatsJob::processResultAndFinish(replica::Lock const& lock, ExtendedS ->databaseInfo(database()) .findTable(table()) .isPartitioned; - bool dataError = false; getResultData(lock).iterate([&](SqlJobResult::Worker const& worker, SqlJobResult::Scope const& internalTable, diff --git a/src/replica/jobs/SqlRowStatsJob.h b/src/replica/jobs/SqlRowStatsJob.h index d95ab80b1..a608f10fd 100644 --- a/src/replica/jobs/SqlRowStatsJob.h +++ b/src/replica/jobs/SqlRowStatsJob.h @@ -117,16 +117,12 @@ class SqlRowStatsJob : public SqlJob { std::string const& table() const { return _table; } ChunkOverlapSelector overlapSelector() const { return _overlapSelector; } StateUpdatePolicy stateUpdatePolicy() const { return _stateUpdatePolicy; } - std::list> extendedPersistentState() const final; protected: void notify(replica::Lock const& lock) final; - std::list launchRequests(replica::Lock const& lock, std::string const& worker, size_t maxRequestsPerWorker) final; - - void stopRequest(replica::Lock const& lock, SqlRequest::Ptr const& request) final; void processResultAndFinish(replica::Lock const& lock, ExtendedState extendedState) final; private: @@ -152,12 +148,10 @@ class SqlRowStatsJob : public SqlJob { std::map>>& counters) const; // Input parameters - std::string const _database; std::string const _table; ChunkOverlapSelector const _overlapSelector; StateUpdatePolicy const _stateUpdatePolicy; - CallbackType _onFinish; /// @note is reset when the job finishes /// A registry of workers to mark those for which request has been sent. diff --git a/src/replica/jobs/VerifyJob.cc b/src/replica/jobs/VerifyJob.cc index c58c2abb7..97643c287 100644 --- a/src/replica/jobs/VerifyJob.cc +++ b/src/replica/jobs/VerifyJob.cc @@ -187,13 +187,9 @@ list> VerifyJob::extendedPersistentState() const { void VerifyJob::startImpl(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__); - auto self = shared_from_base(); - // Launch the first batch of requests - vector replicas; _nextReplicas(lock, replicas, maxReplicas()); - if (replicas.empty()) { // In theory this should never happen unless the installation // doesn't have a single chunk. @@ -206,10 +202,12 @@ void VerifyJob::startImpl(replica::Lock const& lock) { auto const currentJobPriority = priority(); bool const keepTracking = true; for (ReplicaInfo const& replica : replicas) { - auto request = controller()->findReplica( - replica.worker(), replica.database(), replica.chunk(), - [self](FindRequest::Ptr request) { self->_onRequestFinish(request); }, currentJobPriority, - computeCheckSum(), keepTracking, id()); + auto request = FindRequest::createAndStart( + controller(), replica.worker(), replica.database(), replica.chunk(), + [self = shared_from_base()](FindRequest::Ptr request) { + self->_onRequestFinish(request); + }, + currentJobPriority, computeCheckSum(), keepTracking, id()); _replicas[request->id()] = replica; _requests[request->id()] = request; } @@ -221,17 +219,14 @@ void VerifyJob::cancelImpl(replica::Lock const& lock) { // To ensure no lingering "side effects" will be left after cancelling this // job the request cancellation should be also followed (where it makes a sense) // by stopping the request at corresponding worker service. - auto const noCallbackOnFinish = nullptr; - auto const currentJobPriority = priority(); bool const keepTracking = true; - for (auto&& entry : _requests) { auto const& request = entry.second; request->cancel(); if (request->state() != Request::State::FINISHED) { - controller()->stopById(request->workerName(), request->id(), noCallbackOnFinish, - currentJobPriority, keepTracking, id()); + StopRequest::createAndStart(controller(), request->workerName(), request->id(), + noCallbackOnFinish, priority(), keepTracking, id()); } } _replicas.clear(); @@ -249,9 +244,7 @@ void VerifyJob::_onRequestFinish(FindRequest::Ptr const& request) { << " chunk=" << request->chunk()); if (state() == State::FINISHED) return; - replica::Lock lock(_mtx, context() + __func__); - if (state() == State::FINISHED) return; // The default version of the object won't have any difference @@ -259,15 +252,12 @@ void VerifyJob::_onRequestFinish(FindRequest::Ptr const& request) { ReplicaDiff selfReplicaDiff; // against the previous state of the current replica vector otherReplicaDiff; // against other known replicas - auto self = shared_from_base(); - if (request->extendedState() == Request::ExtendedState::SUCCESS) { // TODO: // - check if the replica still exists. It's fine if it's gone // because some jobs may choose either to purge extra replicas // or re-balance the cluster. So, no subscriber notification is needed // here. - ; // Compare new state of the replica against its older one which was @@ -280,17 +270,14 @@ void VerifyJob::_onRequestFinish(FindRequest::Ptr const& request) { // ATTENTIONS: Replica differences are reported into the log stream only // when no interest to be notified in the differences // expressed by a caller (no callback provided). - ReplicaInfo const& oldReplica = _replicas[request->id()]; selfReplicaDiff = ReplicaDiff(oldReplica, request->responseData()); if (selfReplicaDiff() and not _onReplicaDifference) { LOGS(_log, LOG_LVL_INFO, context() << "replica mismatch for self\n" << selfReplicaDiff); } - vector otherReplicas; controller()->serviceProvider()->databaseServices()->findReplicas(otherReplicas, oldReplica.chunk(), oldReplica.database()); - for (auto&& replica : otherReplicas) { ReplicaDiff diff(request->responseData(), replica); if (not diff.isSelf()) { @@ -302,33 +289,30 @@ void VerifyJob::_onRequestFinish(FindRequest::Ptr const& request) { } else { // Report the error and keep going - LOGS(_log, LOG_LVL_ERROR, context() << "failed request " << request->context() << " worker: " << request->workerName() << " database: " << request->database() << " chunk: " << request->chunk()); } // Remove the processed replica, fetch another one and begin processing it - _replicas.erase(request->id()); _requests.erase(request->id()); - vector replicas; _nextReplicas(lock, replicas, 1); - if (0 == replicas.size()) { LOGS(_log, LOG_LVL_ERROR, context() << __func__ << " ** no replicas found in the database **"); // In theory this should never happen unless all replicas are gone // from the installation. - finish(lock, ExtendedState::FAILED); return; } for (ReplicaInfo const& replica : replicas) { - auto request = controller()->findReplica( - replica.worker(), replica.database(), replica.chunk(), - [self](FindRequest::Ptr request) { self->_onRequestFinish(request); }, + auto request = FindRequest::createAndStart( + controller(), replica.worker(), replica.database(), replica.chunk(), + [self = shared_from_base()](FindRequest::Ptr request) { + self->_onRequestFinish(request); + }, priority(), /* inherited from the one of the current job */ computeCheckSum(), true, /* keepTracking*/ id() /* jobId */ @@ -339,10 +323,8 @@ void VerifyJob::_onRequestFinish(FindRequest::Ptr const& request) { // The callback is being made asynchronously in a separate thread // to avoid blocking the current thread. - if (_onReplicaDifference) { - auto self = shared_from_base(); - thread notifier([self, selfReplicaDiff, otherReplicaDiff]() { + thread notifier([self = shared_from_base(), selfReplicaDiff, otherReplicaDiff]() { self->_onReplicaDifference(self, selfReplicaDiff, otherReplicaDiff); }); notifier.detach(); diff --git a/src/replica/proto/protocol.proto b/src/replica/proto/protocol.proto index 25c291e29..b50558de4 100644 --- a/src/replica/proto/protocol.proto +++ b/src/replica/proto/protocol.proto @@ -63,9 +63,10 @@ enum ProtocolQueuedRequestType { // enum ProtocolManagementRequestType { - REQUEST_STATUS = 0; // check a status of a request - REQUEST_STOP = 1; // stop a previously requested request - REQUEST_DISPOSE = 2; // garbage collect the request (in-progress ones will be also stopped) + REQUEST_STATUS = 0; // check a status the previously submitted request + REQUEST_STOP = 1; // stop the previously submitted request + REQUEST_TRACK = 2; // track the previously submitted request + REQUEST_DISPOSE = 3; // garbage collect the request (in-progress ones will be also stopped) } // Request types affecting the overall state of the worker replication service @@ -295,13 +296,22 @@ message ProtocolRequestDirectorIndex { optional uint64 offset = 7 [default = 0]; } -// This request is sent to stop an on-going replication (if any is still in progress). +// This request is sent to stop an on-going request. // This message is sent once after the header. // message ProtocolRequestStop { /// an identifier of a request to be stopped required string id = 1; +} + +// This request is sent to track a status of a target request (if any +// is still in progress). This message is sent once after the header. +// +message ProtocolRequestTrack { + + /// an identifier of a request to be inspected + required string id = 1; // A specific type of the request will affect a choice of the status // object returned in response. The type needs to match a value set @@ -310,19 +320,13 @@ message ProtocolRequestStop { optional ProtocolQueuedRequestType queued_type = 2; } -// This request is sent to request a status of an on-going replication (if any +// This request is sent to get a status of a target request (if any // is still in progress). This message is sent once after the header. // message ProtocolRequestStatus { /// an identifier of a request to be inspected required string id = 1; - - // A specific type of the request will affect a choice of the status - // object returned in response. The type needs to match a value set - // in the preceding header at: ProtocolRequestHeader::type - - optional ProtocolQueuedRequestType queued_type = 2; } // This request is sent to explicitly require to garbage-collect a set @@ -791,6 +795,43 @@ message ProtocolResponseDispose { optional ProtocolStatusExt status_ext = 3 [default = NONE]; } +message ProtocolResponseStop { + + /// The completion status of the operation + required ProtocolStatus status = 8; + + /// Extended status of this operation + optional ProtocolStatusExt status_ext = 2 [default = NONE]; + + /// The performance of this operation + required ProtocolPerformance performance = 4; +} + +message ProtocolResponseStatus { + + /// The completion status of the operation + required ProtocolStatus status = 1; + + /// Extended status of this operation + optional ProtocolStatusExt status_ext = 2 [default = NONE]; + + /// The performance of this operation + required ProtocolPerformance performance = 3; + + // The following atributes are set only if the target request was found at the worker. + // Otherwise, there is no point in setting any default values of the attributes. + + /// The completion status of the target request + optional ProtocolStatus target_status = 4; + + /// Extended status of the target request + optional ProtocolStatusExt target_status_ext = 5; + + /// The performance of the target request + optional ProtocolPerformance target_performance = 6; + +} + ///////////////////////////////////////////////////////////////////////// // The message returned in response to requests related to (or affecting) // the overall state of the server-side replication service. diff --git a/src/replica/requests/CMakeLists.txt b/src/replica/requests/CMakeLists.txt index c7555a288..58ec36d00 100644 --- a/src/replica/requests/CMakeLists.txt +++ b/src/replica/requests/CMakeLists.txt @@ -34,9 +34,7 @@ target_sources(replica_requests PRIVATE SqlResultSet.cc SqlRowStatsRequest.cc StatusRequest.cc - StatusRequestBase.cc StopRequest.cc - StopRequestBase.cc ) target_link_libraries(replica_requests PUBLIC log diff --git a/src/replica/requests/DeleteRequest.cc b/src/replica/requests/DeleteRequest.cc index 33fffd88f..d8f6163a6 100644 --- a/src/replica/requests/DeleteRequest.cc +++ b/src/replica/requests/DeleteRequest.cc @@ -44,34 +44,32 @@ using namespace std; using namespace std::placeholders; namespace { - LOG_LOGGER _log = LOG_GET("lsst.qserv.replica.DeleteRequest"); - +bool const disposeRequired = true; } // namespace namespace lsst::qserv::replica { -DeleteRequest::Ptr DeleteRequest::create(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, string const& worker, - string const& database, unsigned int chunk, bool allowDuplicate, - CallbackType const& onFinish, int priority, bool keepTracking, - shared_ptr const& messenger) { - return DeleteRequest::Ptr(new DeleteRequest(serviceProvider, io_service, worker, database, chunk, - allowDuplicate, onFinish, priority, keepTracking, messenger)); +DeleteRequest::Ptr DeleteRequest::createAndStart(shared_ptr const& controller, + string const& workerName, string const& database, + unsigned int chunk, CallbackType const& onFinish, + int priority, bool keepTracking, bool allowDuplicate, + string const& jobId, unsigned int requestExpirationIvalSec) { + auto ptr = DeleteRequest::Ptr(new DeleteRequest(controller, workerName, database, chunk, onFinish, + priority, keepTracking, allowDuplicate)); + ptr->start(jobId, requestExpirationIvalSec); + return ptr; } -DeleteRequest::DeleteRequest(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - string const& worker, string const& database, unsigned int chunk, - bool allowDuplicate, CallbackType const& onFinish, int priority, - bool keepTracking, shared_ptr const& messenger) - : RequestMessenger(serviceProvider, io_service, "REPLICA_DELETE", worker, priority, keepTracking, - allowDuplicate, - true, // disposeRequired - messenger), +DeleteRequest::DeleteRequest(shared_ptr const& controller, string const& workerName, + string const& database, unsigned int chunk, CallbackType const& onFinish, + int priority, bool keepTracking, bool allowDuplicate) + : RequestMessenger(controller, "REPLICA_DELETE", workerName, priority, keepTracking, allowDuplicate, + ::disposeRequired), _database(database), _chunk(chunk), _onFinish(onFinish) { - Request::serviceProvider()->config()->assertDatabaseIsValid(database); + controller->serviceProvider()->config()->assertDatabaseIsValid(database); } void DeleteRequest::startImpl(replica::Lock const& lock) { @@ -79,7 +77,6 @@ void DeleteRequest::startImpl(replica::Lock const& lock) { // Serialize the Request message header and the request itself into // the network buffer. - buffer()->resize(); ProtocolRequestHeader hdr; @@ -88,14 +85,12 @@ void DeleteRequest::startImpl(replica::Lock const& lock) { hdr.set_queued_type(ProtocolQueuedRequestType::REPLICA_DELETE); hdr.set_timeout(requestExpirationIvalSec()); hdr.set_priority(priority()); - hdr.set_instance_id(serviceProvider()->instanceId()); - + hdr.set_instance_id(controller()->serviceProvider()->instanceId()); buffer()->serialize(hdr); ProtocolRequestDelete message; message.set_database(database()); message.set_chunk(chunk()); - buffer()->serialize(message); _send(lock); @@ -112,21 +107,18 @@ void DeleteRequest::awaken(boost::system::error_code const& ec) { // Serialize the Status message header and the request itself into // the network buffer. - buffer()->resize(); ProtocolRequestHeader hdr; hdr.set_id(id()); hdr.set_type(ProtocolRequestHeader::REQUEST); - hdr.set_management_type(ProtocolManagementRequestType::REQUEST_STATUS); - hdr.set_instance_id(serviceProvider()->instanceId()); - + hdr.set_management_type(ProtocolManagementRequestType::REQUEST_TRACK); + hdr.set_instance_id(controller()->serviceProvider()->instanceId()); buffer()->serialize(hdr); - ProtocolRequestStatus message; + ProtocolRequestTrack message; message.set_id(remoteId()); message.set_queued_type(ProtocolQueuedRequestType::REPLICA_DELETE); - buffer()->serialize(message); _send(lock); @@ -134,7 +126,7 @@ void DeleteRequest::awaken(boost::system::error_code const& ec) { void DeleteRequest::_send(replica::Lock const& lock) { auto self = shared_from_base(); - messenger()->send( + controller()->serviceProvider()->messenger()->send( workerName(), id(), priority(), buffer(), [self](string const& id, bool success, ProtocolResponseDelete const& response) { self->_analyze(success, response); @@ -181,7 +173,7 @@ void DeleteRequest::_analyze(bool success, ProtocolResponseDelete const& message } switch (message.status()) { case ProtocolStatus::SUCCESS: - serviceProvider()->databaseServices()->saveReplicaInfo(_replicaInfo); + controller()->serviceProvider()->databaseServices()->saveReplicaInfo(_replicaInfo); finish(lock, SUCCESS); break; diff --git a/src/replica/requests/DeleteRequest.h b/src/replica/requests/DeleteRequest.h index db92b43fa..e705c27f0 100644 --- a/src/replica/requests/DeleteRequest.h +++ b/src/replica/requests/DeleteRequest.h @@ -34,7 +34,7 @@ // Forward declarations namespace lsst::qserv::replica { -class Messenger; +class Controller; } // namespace lsst::qserv::replica // This header declarations @@ -76,45 +76,32 @@ class DeleteRequest : public RequestMessenger { * and memory management of instances created otherwise (as values or via * low-level pointers). * - * @param serviceProvider a host of services for various communications - * @param worker the identifier of a worker node (the one where the chunk is supposed - * to be located) at a destination of the chunk. - * @param database the name of a database - * @param chunk the number of a chunk to replicate (implies all relevant tables) - * @param allowDuplicate follow a previously made request if the current one duplicates it - * @param onFinish an optional callback function to be called upon a completion of the request. - * @param priority a priority level of the request - * @param keepTracking keep tracking the request before it finishes or fails - * @param messenger an interface for communicating with workers - * @return pointer to the created object + * Class-specific parameters are documented below: + * @param database The name of a database. + * @param chunk The number of a chunk to replicate (implies all relevant tables). + * + * @see The very base class Request for the description of the common parameters + * of all subclasses. + * + * @return A pointer to the created object. */ - static Ptr create(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& database, unsigned int chunk, - bool allowDuplicate, CallbackType const& onFinish, int priority, bool keepTracking, - std::shared_ptr const& messenger); + static Ptr createAndStart(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, unsigned int chunk, + CallbackType const& onFinish = nullptr, int priority = PRIORITY_NORMAL, + bool keepTracking = true, bool allowDuplicate = true, + std::string const& jobId = "", unsigned int requestExpirationIvalSec = 0); protected: - /// @see Request::startImpl() void startImpl(replica::Lock const& lock) final; - - /// @see Request::notify() void notify(replica::Lock const& lock) final; - - /// @see Request::savePersistentState() void savePersistentState(replica::Lock const& lock) final; - - /// @see Request::extendedPersistentState() std::list> extendedPersistentState() const override; - - /// @see Request::awaken() void awaken(boost::system::error_code const& ec) final; private: - /// @see DeleteRequest::create() - DeleteRequest(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& database, unsigned int chunk, - bool allowDuplicate, CallbackType const& onFinish, int priority, bool keepTracking, - std::shared_ptr const& messenger); + DeleteRequest(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, unsigned int chunk, CallbackType const& onFinish, int priority, + bool keepTracking, bool allowDuplicate); /** * Send the serialized content of the buffer to a worker. diff --git a/src/replica/requests/DirectorIndexRequest.cc b/src/replica/requests/DirectorIndexRequest.cc index 4ec4a0760..0b469810f 100644 --- a/src/replica/requests/DirectorIndexRequest.cc +++ b/src/replica/requests/DirectorIndexRequest.cc @@ -32,6 +32,7 @@ #include "boost/filesystem.hpp" // Qserv headers +#include "replica/config/Configuration.h" #include "replica/contr/Controller.h" #include "replica/requests/Messenger.h" #include "replica/services/DatabaseServices.h" @@ -46,9 +47,9 @@ using namespace std::placeholders; namespace fs = boost::filesystem; namespace { - LOG_LOGGER _log = LOG_GET("lsst.qserv.replica.DirectorIndexRequest"); - +bool const allowDuplicateNo = false; +bool const disposeRequired = true; } // namespace namespace lsst::qserv::replica { @@ -59,37 +60,36 @@ ostream& operator<<(ostream& os, DirectorIndexRequestInfo const& info) { return os; } -DirectorIndexRequest::Ptr DirectorIndexRequest::create( - ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - string const& workerName, string const& database, string const& directorTable, unsigned int chunk, - bool hasTransactions, TransactionId transactionId, CallbackType const& onFinish, int priority, - bool keepTracking, shared_ptr const& messenger) { - return DirectorIndexRequest::Ptr(new DirectorIndexRequest( - serviceProvider, io_service, workerName, database, directorTable, chunk, hasTransactions, - transactionId, onFinish, priority, keepTracking, messenger)); +DirectorIndexRequest::Ptr DirectorIndexRequest::createAndStart( + std::shared_ptr const& controller, string const& workerName, string const& database, + string const& directorTable, unsigned int chunk, bool hasTransactions, TransactionId transactionId, + CallbackType const& onFinish, int priority, bool keepTracking, string const& jobId, + unsigned int requestExpirationIvalSec) { + auto ptr = DirectorIndexRequest::Ptr( + new DirectorIndexRequest(controller, workerName, database, directorTable, chunk, hasTransactions, + transactionId, onFinish, priority, keepTracking)); + ptr->start(jobId, requestExpirationIvalSec); + return ptr; } -DirectorIndexRequest::DirectorIndexRequest(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, string const& workerName, - string const& database, string const& directorTable, - unsigned int chunk, bool hasTransactions, - TransactionId transactionId, CallbackType const& onFinish, - int priority, bool keepTracking, - shared_ptr const& messenger) - : RequestMessenger(serviceProvider, io_service, "INDEX", workerName, priority, keepTracking, - false, // allowDuplicate - true, // disposeRequired - messenger), +DirectorIndexRequest::DirectorIndexRequest(std::shared_ptr const& controller, + string const& workerName, string const& database, + string const& directorTable, unsigned int chunk, + bool hasTransactions, TransactionId transactionId, + CallbackType const& onFinish, int priority, bool keepTracking) + : RequestMessenger(controller, "INDEX", workerName, priority, keepTracking, ::allowDuplicateNo, + ::disposeRequired), _database(database), _directorTable(directorTable), _chunk(chunk), _hasTransactions(hasTransactions), _transactionId(transactionId), _onFinish(onFinish) { - Request::serviceProvider()->config()->assertDatabaseIsValid(database); - _responseData.fileName = serviceProvider->config()->get("database", "qserv-master-tmp-dir") + - "/" + database + "_" + directorTable + "_" + to_string(chunk) + - (hasTransactions ? "_p" + to_string(transactionId) : ""); + controller->serviceProvider()->config()->assertDatabaseIsValid(database); + _responseData.fileName = + controller->serviceProvider()->config()->get("database", "qserv-master-tmp-dir") + "/" + + database + "_" + directorTable + "_" + to_string(chunk) + + (hasTransactions ? "_p" + to_string(transactionId) : ""); } DirectorIndexRequest::~DirectorIndexRequest() { @@ -121,7 +121,6 @@ void DirectorIndexRequest::_sendInitialRequest(replica::Lock const& lock) { // Serialize the Request message header and the request itself into // the network buffer. - buffer()->resize(); ProtocolRequestHeader hdr; @@ -130,8 +129,7 @@ void DirectorIndexRequest::_sendInitialRequest(replica::Lock const& lock) { hdr.set_queued_type(ProtocolQueuedRequestType::INDEX); hdr.set_timeout(requestExpirationIvalSec()); hdr.set_priority(priority()); - hdr.set_instance_id(serviceProvider()->instanceId()); - + hdr.set_instance_id(controller()->serviceProvider()->instanceId()); buffer()->serialize(hdr); ProtocolRequestDirectorIndex message; @@ -150,34 +148,28 @@ void DirectorIndexRequest::_sendInitialRequest(replica::Lock const& lock) { void DirectorIndexRequest::awaken(boost::system::error_code const& ec) { string const context_ = context() + string(__func__) + " "; LOGS(_log, LOG_LVL_DEBUG, context_); - if (isAborted(ec)) return; - if (state() == State::FINISHED) return; replica::Lock lock(_mtx, context_); if (state() == State::FINISHED) return; - _sendStatusRequest(lock); } void DirectorIndexRequest::_sendStatusRequest(replica::Lock const& lock) { // Serialize the Status message header and the request itself into // the network buffer. - buffer()->resize(); ProtocolRequestHeader hdr; hdr.set_id(id()); hdr.set_type(ProtocolRequestHeader::REQUEST); - hdr.set_management_type(ProtocolManagementRequestType::REQUEST_STATUS); - hdr.set_instance_id(serviceProvider()->instanceId()); - + hdr.set_management_type(ProtocolManagementRequestType::REQUEST_TRACK); + hdr.set_instance_id(controller()->serviceProvider()->instanceId()); buffer()->serialize(hdr); - ProtocolRequestStatus message; + ProtocolRequestTrack message; message.set_id(id()); message.set_queued_type(ProtocolQueuedRequestType::INDEX); - buffer()->serialize(message); _send(lock); @@ -185,10 +177,10 @@ void DirectorIndexRequest::_sendStatusRequest(replica::Lock const& lock) { void DirectorIndexRequest::_send(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__); - auto self = shared_from_base(); - messenger()->send( + controller()->serviceProvider()->messenger()->send( workerName(), id(), priority(), buffer(), - [self](string const& id, bool success, ProtocolResponseDirectorIndex const& response) { + [self = shared_from_base()](string const& id, bool success, + ProtocolResponseDirectorIndex const& response) { self->_analyze(success, response); }); } @@ -205,7 +197,6 @@ void DirectorIndexRequest::_analyze(bool success, ProtocolResponseDirectorIndex if (state() == State::FINISHED) return; replica::Lock lock(_mtx, context_); if (state() == State::FINISHED) return; - if (!success) { finish(lock, CLIENT_ERROR); return; @@ -252,10 +243,11 @@ void DirectorIndexRequest::_analyze(bool success, ProtocolResponseDirectorIndex // Also note the elevated priority level for the request disposal operations. // This will guarantee (in most cases) that such requests will be fast-track delivered // to (and processed by) the worker. - auto self = shared_from_base(); - dispose(lock, PRIORITY_VERY_HIGH, [self](auto id, auto success, auto message) { - self->_disposed(success, message); - }); + dispose(lock, PRIORITY_VERY_HIGH, + [self = shared_from_base()](auto id, auto success, + auto message) { + self->_disposed(success, message); + }); } } catch (exception const& ex) { _responseData.error = ex.what(); @@ -294,11 +286,9 @@ void DirectorIndexRequest::_analyze(bool success, ProtocolResponseDirectorIndex void DirectorIndexRequest::_disposed(bool success, ProtocolResponseDispose const& message) { string const context_ = context() + string(__func__) + " success=" + bool2str(success) + " "; LOGS(_log, LOG_LVL_DEBUG, context_); - if (state() == State::FINISHED) return; replica::Lock lock(_mtx, context_); if (state() == State::FINISHED) return; - if (!success) { finish(lock, CLIENT_ERROR); return; diff --git a/src/replica/requests/DirectorIndexRequest.h b/src/replica/requests/DirectorIndexRequest.h index 9b0909f41..17d24e014 100644 --- a/src/replica/requests/DirectorIndexRequest.h +++ b/src/replica/requests/DirectorIndexRequest.h @@ -35,7 +35,7 @@ // Forward declarations namespace lsst::qserv::replica { -class Messenger; +class Controller; } // namespace lsst::qserv::replica // This header declarations @@ -96,50 +96,40 @@ class DirectorIndexRequest : public RequestMessenger { * and memory management of instances created otherwise (as values or via * low-level pointers). * - * @param serviceProvider a host of services for various communications - * @param workerName the identifier of a worker node (the one where the chunks - * expected to be located) - * @param database the name of a database - * @param directorTable the name of the director table - * @param chunk the number of a chunk to be inspected - * @param hasTransactions if set to 'true' then the result will also include a column which - * stores a value of the corresponding super-transaction - * @param transactionId (optional) identifier of a super-transaction. This parameter is used + * Class-specific parameters are documented below: + * @param database The name of a database. + * @param directorTable The name of the director table. + * @param chunk The number of a chunk to be inspected. + * @param hasTransactions If set to 'true' then the result will also include a column which + * stores a value of the corresponding super-transaction. + * @param transactionId The (optional) identifier of a super-transaction. This parameter is used * only if the above defined flag 'hasTransactions' is set. - * @param onFinish an optional callback function to be called upon a completion of - * the request - * @param priority a priority level of the request - * @param keepTracking keep tracking the request before it finishes or fails - * @param messenger an interface for communicating with workers - * @return pointer to the created object + * + * @see The very base class Request for the description of the common parameters + * of all subclasses. + * + * @return A pointer to the created object. */ - static Ptr create(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& workerName, std::string const& database, - std::string const& directorTable, unsigned int chunk, bool hasTransactions, - TransactionId transactionId, CallbackType const& onFinish, int priority, - bool keepTracking, std::shared_ptr const& messenger); + static Ptr createAndStart(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, std::string const& directorTable, + unsigned int chunk, bool hasTransactions, TransactionId transactionId, + CallbackType const& onFinish = nullptr, int priority = PRIORITY_NORMAL, + bool keepTracking = true, std::string const& jobId = "", + unsigned int requestExpirationIvalSec = 0); std::list> extendedPersistentState() const final; protected: - /// @see Request::startImpl() void startImpl(replica::Lock const& lock) final; - - /// @see Request::notify() void notify(replica::Lock const& lock) final; - - /// @see Request::savePersistentState() void savePersistentState(replica::Lock const& lock) final; - - /// @see Request::awaken() void awaken(boost::system::error_code const& ec) final; private: - DirectorIndexRequest(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& workerName, std::string const& database, - std::string const& directorTable, unsigned int chunk, bool hasTransactions, - TransactionId transactionId, CallbackType const& onFinish, int priority, - bool keepTracking, std::shared_ptr const& messenger); + DirectorIndexRequest(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, std::string const& directorTable, unsigned int chunk, + bool hasTransactions, TransactionId transactionId, CallbackType const& onFinish, + int priority, bool keepTracking); /** * Send the initial request for pulling data from the server. diff --git a/src/replica/requests/DisposeRequest.cc b/src/replica/requests/DisposeRequest.cc index dd668d021..699707158 100644 --- a/src/replica/requests/DisposeRequest.cc +++ b/src/replica/requests/DisposeRequest.cc @@ -27,7 +27,9 @@ #include // Qserv headers +#include "replica/contr/Controller.h" #include "replica/requests/Messenger.h" +#include "replica/services/ServiceProvider.h" #include "replica/util/ProtocolBuffer.h" // LSST headers @@ -39,7 +41,8 @@ using namespace std::placeholders; namespace { LOG_LOGGER _log = LOG_GET("lsst.qserv.replica.DisposeRequest"); - +bool const allowDuplicateNo = false; +bool const disposeRequiredNo = false; } // namespace namespace lsst::qserv::replica { @@ -65,23 +68,23 @@ string DisposeRequest::toString(bool extended) const { return oss.str(); } -DisposeRequest::Ptr DisposeRequest::create(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, string const& workerName, - std::vector const& targetIds, - CallbackType const& onFinish, int priority, bool keepTracking, - shared_ptr const& messenger) { - return DisposeRequest::Ptr(new DisposeRequest(serviceProvider, io_service, workerName, targetIds, - onFinish, priority, keepTracking, messenger)); +DisposeRequest::Ptr DisposeRequest::createAndStart(shared_ptr const& controller, + string const& workerName, + std::vector const& targetIds, + CallbackType const& onFinish, int priority, + bool keepTracking, string const& jobId, + unsigned int requestExpirationIvalSec) { + auto ptr = DisposeRequest::Ptr( + new DisposeRequest(controller, workerName, targetIds, onFinish, priority, keepTracking)); + ptr->start(jobId, requestExpirationIvalSec); + return ptr; } -DisposeRequest::DisposeRequest(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, string const& workerName, +DisposeRequest::DisposeRequest(shared_ptr const& controller, string const& workerName, std::vector const& targetIds, CallbackType const& onFinish, - int priority, bool keepTracking, shared_ptr const& messenger) - : RequestMessenger(serviceProvider, io_service, "DISPOSE", workerName, priority, keepTracking, - false, // allowDuplicate - false, // disposeRequired - messenger), + int priority, bool keepTracking) + : RequestMessenger(controller, "DISPOSE", workerName, priority, keepTracking, ::allowDuplicateNo, + ::disposeRequiredNo), _targetIds(targetIds), _onFinish(onFinish) {} @@ -93,15 +96,13 @@ void DisposeRequest::startImpl(replica::Lock const& lock) { // Serialize the Request message header and the request itself into // the network buffer. - buffer()->resize(); ProtocolRequestHeader hdr; hdr.set_id(id()); hdr.set_type(ProtocolRequestHeader::REQUEST); hdr.set_management_type(ProtocolManagementRequestType::REQUEST_DISPOSE); - hdr.set_instance_id(serviceProvider()->instanceId()); - + hdr.set_instance_id(controller()->serviceProvider()->instanceId()); buffer()->serialize(hdr); ProtocolRequestDispose message; @@ -115,7 +116,7 @@ void DisposeRequest::startImpl(replica::Lock const& lock) { void DisposeRequest::_send(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__); - messenger()->send( + controller()->serviceProvider()->messenger()->send( workerName(), id(), priority(), buffer(), // Don't forward the first parameter (request's identifier) of the callback // to the response's analyzer. A value of the identifier is already known diff --git a/src/replica/requests/DisposeRequest.h b/src/replica/requests/DisposeRequest.h index 81340c3bf..cd1bbf13c 100644 --- a/src/replica/requests/DisposeRequest.h +++ b/src/replica/requests/DisposeRequest.h @@ -35,7 +35,7 @@ // Forward declarations namespace lsst::qserv::replica { -class Messenger; +class Controller; } // namespace lsst::qserv::replica // This header declarations @@ -104,38 +104,28 @@ class DisposeRequest : public RequestMessenger { * and memory management of instances created otherwise (as values or via * low-level pointers). * - * @param serviceProvider provider of various services - * @param workerName identifier of a worker node - * @param targetIds a collection unique identifiers of requests to be disposed - * @param onFinish (optional) callback function to call upon completion - * of the request - * @param priority priority level of the request - * @param keepTracking keep tracking the request before it finishes or fails - * @param messenger interface for communicating with workers + * Class-specific parameters are documented below: + * @param targetIds A collection unique identifiers of requests to be disposed. * - * @return pointer to the created object + * @see The very base class Request for the description of the common parameters + * of all subclasses. + * + * @return A pointer to the created object. */ - static Ptr create(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& workerName, std::vector const& targetIds, - CallbackType const& onFinish, int priority, bool keepTracking, - std::shared_ptr const& messenger); + static Ptr createAndStart(std::shared_ptr const& controller, std::string const& workerName, + std::vector const& targetIds, + CallbackType const& onFinish = nullptr, int priority = PRIORITY_NORMAL, + bool keepTracking = true, std::string const& jobId = "", + unsigned int requestExpirationIvalSec = 0); protected: - /// @see Request::startImpl void startImpl(replica::Lock const& lock) final; - - /// @see Request::notify void notify(replica::Lock const& lock) final; - /// @note No persistent state for this type of requests - /// @see Request::savePersistentState - void savePersistentState(replica::Lock const& lock) final {} - private: - DisposeRequest(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& workerName, std::vector const& targetIds, - CallbackType const& onFinish, int priority, bool keepTracking, - std::shared_ptr const& messenger); + DisposeRequest(std::shared_ptr const& controller, std::string const& workerName, + std::vector const& targetIds, CallbackType const& onFinish, int priority, + bool keepTracking); /** * Send the serialized content of the buffer to a worker diff --git a/src/replica/requests/EchoRequest.cc b/src/replica/requests/EchoRequest.cc index b62bd8ba9..d713128e6 100644 --- a/src/replica/requests/EchoRequest.cc +++ b/src/replica/requests/EchoRequest.cc @@ -44,30 +44,29 @@ using namespace std; using namespace std::placeholders; namespace { - LOG_LOGGER _log = LOG_GET("lsst.qserv.replica.EchoRequest"); - +bool const allowDuplicateNo = false; +bool const disposeRequired = true; } // namespace namespace lsst::qserv::replica { -EchoRequest::Ptr EchoRequest::create(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, string const& workerName, - string const& data, uint64_t delay, CallbackType const& onFinish, - int priority, bool keepTracking, - shared_ptr const& messenger) { - return EchoRequest::Ptr(new EchoRequest(serviceProvider, io_service, workerName, data, delay, onFinish, - priority, keepTracking, messenger)); +EchoRequest::Ptr EchoRequest::createAndStart(shared_ptr const& controller, + string const& workerName, string const& data, uint64_t delay, + CallbackType const& onFinish, int priority, bool keepTracking, + std::string const& jobId, + unsigned int requestExpirationIvalSec) { + auto ptr = EchoRequest::Ptr( + new EchoRequest(controller, workerName, data, delay, onFinish, priority, keepTracking)); + ptr->start(jobId, requestExpirationIvalSec); + return ptr; } -EchoRequest::EchoRequest(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - string const& workerName, string const& data, uint64_t delay, - CallbackType const& onFinish, int priority, bool keepTracking, - shared_ptr const& messenger) - : RequestMessenger(serviceProvider, io_service, "TEST_ECHO", workerName, priority, keepTracking, - false, // allowDuplicate - true, // disposeRequired - messenger), +EchoRequest::EchoRequest(shared_ptr const& controller, string const& workerName, + string const& data, uint64_t delay, CallbackType const& onFinish, int priority, + bool keepTracking) + : RequestMessenger(controller, "TEST_ECHO", workerName, priority, keepTracking, ::allowDuplicateNo, + ::disposeRequired), _data(data), _delay(delay), _onFinish(onFinish) {} @@ -81,7 +80,6 @@ void EchoRequest::startImpl(replica::Lock const& lock) { // Serialize the Request message header and the request itself into // the network buffer. - buffer()->resize(); ProtocolRequestHeader hdr; @@ -90,14 +88,12 @@ void EchoRequest::startImpl(replica::Lock const& lock) { hdr.set_queued_type(ProtocolQueuedRequestType::TEST_ECHO); hdr.set_timeout(requestExpirationIvalSec()); hdr.set_priority(priority()); - hdr.set_instance_id(serviceProvider()->instanceId()); - + hdr.set_instance_id(controller()->serviceProvider()->instanceId()); buffer()->serialize(hdr); ProtocolRequestEcho message; message.set_data(data()); message.set_delay(delay()); - buffer()->serialize(message); _send(lock); @@ -107,28 +103,24 @@ void EchoRequest::awaken(boost::system::error_code const& ec) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__); if (isAborted(ec)) return; - if (state() == State::FINISHED) return; replica::Lock lock(_mtx, context() + __func__); if (state() == State::FINISHED) return; // Serialize the Status message header and the request itself into // the network buffer. - buffer()->resize(); ProtocolRequestHeader hdr; hdr.set_id(id()); hdr.set_type(ProtocolRequestHeader::REQUEST); - hdr.set_management_type(ProtocolManagementRequestType::REQUEST_STATUS); - hdr.set_instance_id(serviceProvider()->instanceId()); - + hdr.set_management_type(ProtocolManagementRequestType::REQUEST_TRACK); + hdr.set_instance_id(controller()->serviceProvider()->instanceId()); buffer()->serialize(hdr); - ProtocolRequestStatus message; + ProtocolRequestTrack message; message.set_id(id()); message.set_queued_type(ProtocolQueuedRequestType::TEST_ECHO); - buffer()->serialize(message); _send(lock); @@ -136,10 +128,10 @@ void EchoRequest::awaken(boost::system::error_code const& ec) { void EchoRequest::_send(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__); - auto self = shared_from_base(); - messenger()->send( + controller()->serviceProvider()->messenger()->send( workerName(), id(), priority(), buffer(), - [self](string const& id, bool success, ProtocolResponseEcho const& response) { + [self = shared_from_base()](string const& id, bool success, + ProtocolResponseEcho const& response) { self->_analyze(success, response); }); } @@ -155,7 +147,6 @@ void EchoRequest::_analyze(bool success, ProtocolResponseEcho const& message) { if (state() == State::FINISHED) return; replica::Lock lock(_mtx, context() + __func__); if (state() == State::FINISHED) return; - if (not success) { finish(lock, CLIENT_ERROR); return; diff --git a/src/replica/requests/EchoRequest.h b/src/replica/requests/EchoRequest.h index f155e76d5..870d353b4 100644 --- a/src/replica/requests/EchoRequest.h +++ b/src/replica/requests/EchoRequest.h @@ -34,7 +34,7 @@ // Forward declarations namespace lsst::qserv::replica { -class Messenger; +class Controller; } // namespace lsst::qserv::replica // This header declarations @@ -78,43 +78,33 @@ class EchoRequest : public RequestMessenger { * and memory management of instances created otherwise (as values or via * low-level pointers). * - * @param serviceProvider provider of various services - * @param workerName identifier of a worker node - * @param data data string to be echoed back by a worker - * @param delay execution time (milliseconds) of the request at worker - * @param onFinish (optional) callback function to call upon completion of the request - * @param priority priority level of the request - * @param keepTracking keep tracking the request before it finishes or fails - * @param messenger interface for communicating with workers - * @return pointer to the created object + * Class-specific parameters are documented below: + * @param data The data string to be echoed back by a worker. + * @param delay The execution time (milliseconds) of the request at worker. + * + * @see The very base class Request for the description of the common parameters + * of all subclasses. + * + * @return A pointer to the created object. */ - static Ptr create(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& workerName, std::string const& data, uint64_t delay, - CallbackType const& onFinish, int priority, bool keepTracking, - std::shared_ptr const& messenger); + static Ptr createAndStart(std::shared_ptr const& controller, std::string const& workerName, + std::string const& data, uint64_t delay, CallbackType const& onFinish = nullptr, + int priority = PRIORITY_NORMAL, bool keepTracking = true, + std::string const& jobId = "", unsigned int requestExpirationIvalSec = 0); /// @see Request::extendedPersistentState() std::list> extendedPersistentState() const override; protected: - /// @see Request::startImpl() void startImpl(replica::Lock const& lock) final; - - /// @see Request::notify() void notify(replica::Lock const& lock) final; - - /// @see Request::savePersistentState() void savePersistentState(replica::Lock const& lock) final; - - /// @see Request::awaken() void awaken(boost::system::error_code const& ec) final; private: - /// @see EchoRequest::create() - EchoRequest(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& workerName, std::string const& data, uint64_t delay, - CallbackType const& onFinish, int priority, bool keepTracking, - std::shared_ptr const& messenger); + EchoRequest(std::shared_ptr const& controller, std::string const& workerName, + std::string const& data, uint64_t delay, CallbackType const& onFinish, int priority, + bool keepTracking); /** * Send the serialized content of the buffer to a worker diff --git a/src/replica/requests/FindAllRequest.cc b/src/replica/requests/FindAllRequest.cc index 46d799fe2..c3f501fda 100644 --- a/src/replica/requests/FindAllRequest.cc +++ b/src/replica/requests/FindAllRequest.cc @@ -30,6 +30,7 @@ #include "boost/date_time/posix_time/posix_time.hpp" // Qserv headers +#include "replica/config/Configuration.h" #include "replica/contr/Controller.h" #include "replica/requests/Messenger.h" #include "replica/services/DatabaseServices.h" @@ -43,36 +44,33 @@ using namespace std; using namespace std::placeholders; namespace { - LOG_LOGGER _log = LOG_GET("lsst.qserv.replica.FindAllRequest"); - +bool const allowDuplicateNo = false; +bool const disposeRequired = true; } // namespace namespace lsst::qserv::replica { -FindAllRequest::Ptr FindAllRequest::create(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, string const& workerName, - string const& database, bool saveReplicaInfo, - CallbackType const& onFinish, int priority, bool keepTracking, - shared_ptr const& messenger) { - return FindAllRequest::Ptr(new FindAllRequest(serviceProvider, io_service, workerName, database, - saveReplicaInfo, onFinish, priority, keepTracking, - messenger)); +FindAllRequest::Ptr FindAllRequest::createAndStart(shared_ptr const& controller, + string const& workerName, string const& database, + bool saveReplicaInfo, CallbackType const& onFinish, + int priority, bool keepTracking, string const& jobId, + unsigned int requestExpirationIvalSec) { + auto ptr = FindAllRequest::Ptr(new FindAllRequest(controller, workerName, database, saveReplicaInfo, + onFinish, priority, keepTracking)); + ptr->start(jobId, requestExpirationIvalSec); + return ptr; } -FindAllRequest::FindAllRequest(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, string const& workerName, +FindAllRequest::FindAllRequest(shared_ptr const& controller, string const& workerName, string const& database, bool saveReplicaInfo, CallbackType const& onFinish, - int priority, bool keepTracking, shared_ptr const& messenger) - : RequestMessenger(serviceProvider, io_service, "REPLICA_FIND_ALL", workerName, priority, - keepTracking, - false, // allowDuplicate - true, // disposeRequired - messenger), + int priority, bool keepTracking) + : RequestMessenger(controller, "REPLICA_FIND_ALL", workerName, priority, keepTracking, + ::allowDuplicateNo, ::disposeRequired), _database(database), _saveReplicaInfo(saveReplicaInfo), _onFinish(onFinish) { - Request::serviceProvider()->config()->assertDatabaseIsValid(database); + controller->serviceProvider()->config()->assertDatabaseIsValid(database); } const ReplicaInfoCollection& FindAllRequest::responseData() const { return _replicaInfoCollection; } @@ -82,7 +80,6 @@ void FindAllRequest::startImpl(replica::Lock const& lock) { // Serialize the Request message header and the request itself into // the network buffer. - buffer()->resize(); ProtocolRequestHeader hdr; @@ -91,13 +88,11 @@ void FindAllRequest::startImpl(replica::Lock const& lock) { hdr.set_queued_type(ProtocolQueuedRequestType::REPLICA_FIND_ALL); hdr.set_timeout(requestExpirationIvalSec()); hdr.set_priority(priority()); - hdr.set_instance_id(serviceProvider()->instanceId()); - + hdr.set_instance_id(controller()->serviceProvider()->instanceId()); buffer()->serialize(hdr); ProtocolRequestFindAll message; message.set_database(database()); - buffer()->serialize(message); _send(lock); @@ -107,39 +102,34 @@ void FindAllRequest::awaken(boost::system::error_code const& ec) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__); if (isAborted(ec)) return; - if (state() == State::FINISHED) return; replica::Lock lock(_mtx, context() + __func__); if (state() == State::FINISHED) return; // Serialize the Status message header and the request itself into // the network buffer. - buffer()->resize(); ProtocolRequestHeader hdr; hdr.set_id(id()); hdr.set_type(ProtocolRequestHeader::REQUEST); - hdr.set_management_type(ProtocolManagementRequestType::REQUEST_STATUS); - hdr.set_instance_id(serviceProvider()->instanceId()); - + hdr.set_management_type(ProtocolManagementRequestType::REQUEST_TRACK); + hdr.set_instance_id(controller()->serviceProvider()->instanceId()); buffer()->serialize(hdr); - ProtocolRequestStatus message; + ProtocolRequestTrack message; message.set_id(id()); message.set_queued_type(ProtocolQueuedRequestType::REPLICA_FIND_ALL); - buffer()->serialize(message); - // Send the message _send(lock); } void FindAllRequest::_send(replica::Lock const& lock) { - auto self = shared_from_base(); - messenger()->send( + controller()->serviceProvider()->messenger()->send( workerName(), id(), priority(), buffer(), - [self](string const& id, bool success, ProtocolResponseFindAll const& response) { + [self = shared_from_base()](string const& id, bool success, + ProtocolResponseFindAll const& response) { self->_analyze(success, response); }); } @@ -155,7 +145,6 @@ void FindAllRequest::_analyze(bool success, ProtocolResponseFindAll const& messa if (state() == State::FINISHED) return; replica::Lock lock(_mtx, context() + __func__); if (state() == State::FINISHED) return; - if (not success) { finish(lock, CLIENT_ERROR); return; @@ -187,8 +176,8 @@ void FindAllRequest::_analyze(bool success, ProtocolResponseFindAll const& messa switch (message.status()) { case ProtocolStatus::SUCCESS: if (saveReplicaInfo()) { - serviceProvider()->databaseServices()->saveReplicaInfoCollection(workerName(), database(), - _replicaInfoCollection); + controller()->serviceProvider()->databaseServices()->saveReplicaInfoCollection( + workerName(), database(), _replicaInfoCollection); } finish(lock, SUCCESS); break; diff --git a/src/replica/requests/FindAllRequest.h b/src/replica/requests/FindAllRequest.h index 9b25da410..41a75582c 100644 --- a/src/replica/requests/FindAllRequest.h +++ b/src/replica/requests/FindAllRequest.h @@ -34,7 +34,7 @@ // Forward declarations namespace lsst::qserv::replica { -class Messenger; +class Controller; } // namespace lsst::qserv::replica // This header declarations @@ -58,7 +58,6 @@ class FindAllRequest : public RequestMessenger { ~FindAllRequest() final = default; std::string const& database() const { return _database; } - bool saveReplicaInfo() const { return _saveReplicaInfo; } /// @return target request specific parameters @@ -78,45 +77,33 @@ class FindAllRequest : public RequestMessenger { * and memory management of instances created otherwise (as values or via * low-level pointers). * - * @param serviceProvider a host of services for various communications - * @param workerName the identifier of a worker node (the one where the chunks - * expected to be located) - * @param database the name of a database - * @param saveReplicaInfo save replica info in a database - * @param onFinish an optional callback function to be called upon a completion of - * the request - * @param priority a priority level of the request - * @param keepTracking keep tracking the request before it finishes or fails - * @param messenger an interface for communicating with workers - * @return pointer to the created object + * Class-specific parameters are documented below: + * @param database The name of a database. + * @param saveReplicaInfo The (optional) save-replica info in a database. + * + * @see The very base class Request for the description of the common parameters + * of all subclasses. + * + * @return A pointer to the created object. */ - static Ptr create(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& workerName, std::string const& database, bool saveReplicaInfo, - CallbackType const& onFinish, int priority, bool keepTracking, - std::shared_ptr const& messenger); + static Ptr createAndStart(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, bool saveReplicaInfo = true, + CallbackType const& onFinish = nullptr, int priority = PRIORITY_NORMAL, + bool keepTracking = true, std::string const& jobId = "", + unsigned int requestExpirationIvalSec = 0); - /// @see Request::extendedPersistentState() std::list> extendedPersistentState() const final; protected: - /// @see Request::startImpl() void startImpl(replica::Lock const& lock) final; - - /// @see Request::notify() void notify(replica::Lock const& lock) final; - - /// @see Request::savePersistentState() void savePersistentState(replica::Lock const& lock) final; - - /// @see Request::awaken() void awaken(boost::system::error_code const& ec) final; private: - /// @see FindAllRequest::create() - FindAllRequest(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& workerName, std::string const& database, bool saveReplicaInfo, - CallbackType const& onFinish, int priority, bool keepTracking, - std::shared_ptr const& messenger); + FindAllRequest(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, bool saveReplicaInfo, CallbackType const& onFinish, + int priority, bool keepTracking); /** * Send the serialized content of the buffer to a worker diff --git a/src/replica/requests/FindRequest.cc b/src/replica/requests/FindRequest.cc index 708f7c316..fc6d25547 100644 --- a/src/replica/requests/FindRequest.cc +++ b/src/replica/requests/FindRequest.cc @@ -30,6 +30,7 @@ #include "boost/date_time/posix_time/posix_time.hpp" // Qserv headers +#include "replica/config/Configuration.h" #include "replica/contr/Controller.h" #include "replica/requests/Messenger.h" #include "replica/services/DatabaseServices.h" @@ -44,35 +45,34 @@ using namespace std; using namespace std::placeholders; namespace { - LOG_LOGGER _log = LOG_GET("lsst.qserv.replica.FindRequest"); - +bool const allowDuplicateNo = false; +bool const disposeRequired = true; } // namespace namespace lsst::qserv::replica { -FindRequest::Ptr FindRequest::create(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, string const& workerName, - string const& database, unsigned int chunk, bool computeCheckSum, - CallbackType const& onFinish, int priority, bool keepTracking, - shared_ptr const& messenger) { - return FindRequest::Ptr(new FindRequest(serviceProvider, io_service, workerName, database, chunk, - computeCheckSum, onFinish, priority, keepTracking, messenger)); +FindRequest::Ptr FindRequest::createAndStart(shared_ptr const& controller, + string const& workerName, string const& database, + unsigned int chunk, CallbackType const& onFinish, int priority, + bool computeCheckSum, bool keepTracking, string const& jobId, + unsigned int requestExpirationIvalSec) { + auto ptr = FindRequest::Ptr(new FindRequest(controller, workerName, database, chunk, onFinish, priority, + computeCheckSum, keepTracking)); + ptr->start(jobId, requestExpirationIvalSec); + return ptr; } -FindRequest::FindRequest(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - string const& workerName, string const& database, unsigned int chunk, - bool computeCheckSum, CallbackType const& onFinish, int priority, bool keepTracking, - shared_ptr const& messenger) - : RequestMessenger(serviceProvider, io_service, "REPLICA_FIND", workerName, priority, keepTracking, - false, // allowDuplicate - true, // disposeRequired - messenger), +FindRequest::FindRequest(shared_ptr const& controller, string const& workerName, + string const& database, unsigned int chunk, CallbackType const& onFinish, + int priority, bool computeCheckSum, bool keepTracking) + : RequestMessenger(controller, "REPLICA_FIND", workerName, priority, keepTracking, ::allowDuplicateNo, + ::disposeRequired), _database(database), _chunk(chunk), _computeCheckSum(computeCheckSum), _onFinish(onFinish) { - Request::serviceProvider()->config()->assertDatabaseIsValid(database); + controller->serviceProvider()->config()->assertDatabaseIsValid(database); } ReplicaInfo const& FindRequest::responseData() const { return _replicaInfo; } @@ -85,7 +85,6 @@ void FindRequest::startImpl(replica::Lock const& lock) { // Serialize the Request message header and the request itself into // the network buffer. - buffer()->resize(); ProtocolRequestHeader hdr; @@ -94,15 +93,13 @@ void FindRequest::startImpl(replica::Lock const& lock) { hdr.set_queued_type(ProtocolQueuedRequestType::REPLICA_FIND); hdr.set_timeout(requestExpirationIvalSec()); hdr.set_priority(priority()); - hdr.set_instance_id(serviceProvider()->instanceId()); - + hdr.set_instance_id(controller()->serviceProvider()->instanceId()); buffer()->serialize(hdr); ProtocolRequestFind message; message.set_database(database()); message.set_chunk(chunk()); message.set_compute_cs(computeCheckSum()); - buffer()->serialize(message); _send(lock); @@ -112,28 +109,24 @@ void FindRequest::awaken(boost::system::error_code const& ec) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__); if (isAborted(ec)) return; - if (state() == State::FINISHED) return; replica::Lock lock(_mtx, context() + __func__); if (state() == State::FINISHED) return; // Serialize the Status message header and the request itself into // the network buffer. - buffer()->resize(); ProtocolRequestHeader hdr; hdr.set_id(id()); hdr.set_type(ProtocolRequestHeader::REQUEST); - hdr.set_management_type(ProtocolManagementRequestType::REQUEST_STATUS); - hdr.set_instance_id(serviceProvider()->instanceId()); - + hdr.set_management_type(ProtocolManagementRequestType::REQUEST_TRACK); + hdr.set_instance_id(controller()->serviceProvider()->instanceId()); buffer()->serialize(hdr); - ProtocolRequestStatus message; + ProtocolRequestTrack message; message.set_id(id()); message.set_queued_type(ProtocolQueuedRequestType::REPLICA_FIND); - buffer()->serialize(message); _send(lock); @@ -141,10 +134,10 @@ void FindRequest::awaken(boost::system::error_code const& ec) { void FindRequest::_send(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__); - auto self = shared_from_base(); - messenger()->send( + controller()->serviceProvider()->messenger()->send( workerName(), id(), priority(), buffer(), - [self](string const& id, bool success, ProtocolResponseFind const& response) { + [self = shared_from_base()](string const& id, bool success, + ProtocolResponseFind const& response) { self->_analyze(success, response); }); } @@ -160,7 +153,6 @@ void FindRequest::_analyze(bool success, ProtocolResponseFind const& message) { if (state() == State::FINISHED) return; replica::Lock lock(_mtx, context() + __func__); if (state() == State::FINISHED) return; - if (not success) { finish(lock, CLIENT_ERROR); return; @@ -189,7 +181,7 @@ void FindRequest::_analyze(bool success, ProtocolResponseFind const& message) { } switch (message.status()) { case ProtocolStatus::SUCCESS: - serviceProvider()->databaseServices()->saveReplicaInfo(_replicaInfo); + controller()->serviceProvider()->databaseServices()->saveReplicaInfo(_replicaInfo); finish(lock, SUCCESS); break; case ProtocolStatus::CREATED: diff --git a/src/replica/requests/FindRequest.h b/src/replica/requests/FindRequest.h index 9d6f0f946..686d1b5e8 100644 --- a/src/replica/requests/FindRequest.h +++ b/src/replica/requests/FindRequest.h @@ -34,7 +34,7 @@ // Forward declarations namespace lsst::qserv::replica { -class Messenger; +class Controller; } // namespace lsst::qserv::replica // This header declarations @@ -78,45 +78,33 @@ class FindRequest : public RequestMessenger { * and memory management of instances created otherwise (as values or via * low-level pointers). * - * @param serviceProvider a host of services for various communications - * @param workerName the identifier of a worker node (the one where the chunk is - * expected to be located) at a destination of the chunk - * @param database the name of a database - * @param chunk the number of a chunk to find (implies all relevant tables) - * @param computeCheckSum tell a worker server to compute check/control sum on each file - * @param onFinish an optional callback function to be called upon a completion of - * the request. - * @param priority a priority level of the request - * @param keepTracking keep tracking the request before it finishes or fails - * @param messenger an interface for communicating with workers - * @return pointer to the created object + * Class-specific parameters are documented below: + * @param database The name of a database. + * @param chunk The number of a chunk to find (implies all relevant tables) + * + * @see The very base class Request for the description of the common parameters + * of all subclasses. + * + * @return A pointer to the created object. */ - static Ptr create(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& workerName, std::string const& database, unsigned int chunk, - bool computeCheckSum, CallbackType const& onFinish, int priority, bool keepTracking, - std::shared_ptr const& messenger); + static Ptr createAndStart(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, unsigned int chunk, + CallbackType const& onFinish = nullptr, int priority = PRIORITY_NORMAL, + bool computeCheckSum = false, bool keepTracking = true, + std::string const& jobId = "", unsigned int requestExpirationIvalSec = 0); - /// @see Request::extendedPersistentState() std::list> extendedPersistentState() const final; protected: - /// @see Request::startImpl() void startImpl(replica::Lock const& lock) final; - - /// @see Request::notify() void notify(replica::Lock const& lock) final; - - /// @see Request::savePersistentState() void savePersistentState(replica::Lock const& lock) final; - - /// @see Request::awaken() void awaken(boost::system::error_code const& ec) final; private: - FindRequest(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& workerName, std::string const& database, unsigned int chunk, - bool computeCheckSum, CallbackType const& onFinish, int priority, bool keepTracking, - std::shared_ptr const& messenger); + FindRequest(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, unsigned int chunk, CallbackType const& onFinish, int priority, + bool computeCheckSum, bool keepTracking); /** * Send the serialized content of the buffer to a worker diff --git a/src/replica/requests/ReplicationRequest.cc b/src/replica/requests/ReplicationRequest.cc index 9292e53e0..f44d8e436 100644 --- a/src/replica/requests/ReplicationRequest.cc +++ b/src/replica/requests/ReplicationRequest.cc @@ -44,53 +44,47 @@ using namespace std; using namespace std::placeholders; namespace { - LOG_LOGGER _log = LOG_GET("lsst.qserv.replica.ReplicationRequest"); - +bool const disposeRequired = true; } // namespace namespace lsst::qserv::replica { -ReplicationRequest::Ptr ReplicationRequest::create(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, - string const& workerName, string const& sourceWorkerName, - string const& database, unsigned int chunk, - bool allowDuplicate, CallbackType const& onFinish, - int priority, bool keepTracking, - shared_ptr const& messenger) { - return ReplicationRequest::Ptr(new ReplicationRequest(serviceProvider, io_service, workerName, - sourceWorkerName, database, chunk, allowDuplicate, - onFinish, priority, keepTracking, messenger)); +ReplicationRequest::Ptr ReplicationRequest::createAndStart( + shared_ptr const& controller, string const& workerName, string const& sourceWorkerName, + string const& database, unsigned int chunk, CallbackType const& onFinish, int priority, + bool keepTracking, bool allowDuplicate, string const& jobId, unsigned int requestExpirationIvalSec) { + auto ptr = ReplicationRequest::Ptr(new ReplicationRequest(controller, workerName, sourceWorkerName, + database, chunk, onFinish, priority, + keepTracking, allowDuplicate)); + ptr->start(jobId, requestExpirationIvalSec); + return ptr; } -ReplicationRequest::ReplicationRequest(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, string const& workerName, +ReplicationRequest::ReplicationRequest(shared_ptr const& controller, string const& workerName, string const& sourceWorkerName, string const& database, - unsigned int chunk, bool allowDuplicate, CallbackType const& onFinish, - int priority, bool keepTracking, - shared_ptr const& messenger) - : RequestMessenger(serviceProvider, io_service, "REPLICA_CREATE", workerName, priority, keepTracking, - allowDuplicate, - true, // disposeRequired - messenger), + unsigned int chunk, CallbackType const& onFinish, int priority, + bool keepTracking, bool allowDuplicate) + : RequestMessenger(controller, "REPLICA_CREATE", workerName, priority, keepTracking, allowDuplicate, + ::disposeRequired), _database(database), _chunk(chunk), _sourceWorkerName(sourceWorkerName), _onFinish(onFinish), _replicaInfo() { - Request::serviceProvider()->config()->assertWorkerIsValid(sourceWorkerName); - Request::serviceProvider()->config()->assertWorkersAreDifferent(sourceWorkerName, workerName); - Request::serviceProvider()->config()->assertDatabaseIsValid(database); + controller->serviceProvider()->config()->assertWorkerIsValid(sourceWorkerName); + controller->serviceProvider()->config()->assertWorkersAreDifferent(sourceWorkerName, workerName); + controller->serviceProvider()->config()->assertDatabaseIsValid(database); } void ReplicationRequest::startImpl(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__); - ConfigWorker const sourceConfigWorker = serviceProvider()->config()->worker(sourceWorkerName()); + ConfigWorker const sourceConfigWorker = + controller()->serviceProvider()->config()->worker(sourceWorkerName()); // Serialize the Request message header and the request itself into // the network buffer. - buffer()->resize(); ProtocolRequestHeader hdr; @@ -99,8 +93,7 @@ void ReplicationRequest::startImpl(replica::Lock const& lock) { hdr.set_queued_type(ProtocolQueuedRequestType::REPLICA_CREATE); hdr.set_timeout(requestExpirationIvalSec()); hdr.set_priority(priority()); - hdr.set_instance_id(serviceProvider()->instanceId()); - + hdr.set_instance_id(controller()->serviceProvider()->instanceId()); buffer()->serialize(hdr); ProtocolRequestReplicate message; @@ -110,7 +103,6 @@ void ReplicationRequest::startImpl(replica::Lock const& lock) { message.set_worker_host(sourceConfigWorker.fsHost.addr); message.set_worker_port(sourceConfigWorker.fsPort); message.set_worker_data_dir(sourceConfigWorker.dataDir); - buffer()->serialize(message); _send(lock); @@ -118,30 +110,25 @@ void ReplicationRequest::startImpl(replica::Lock const& lock) { void ReplicationRequest::awaken(boost::system::error_code const& ec) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__); - if (isAborted(ec)) return; - if (state() == State::FINISHED) return; replica::Lock lock(_mtx, context() + __func__); if (state() == State::FINISHED) return; // Serialize the Status message header and the request itself into // the network buffer. - buffer()->resize(); ProtocolRequestHeader hdr; hdr.set_id(id()); hdr.set_type(ProtocolRequestHeader::REQUEST); - hdr.set_management_type(ProtocolManagementRequestType::REQUEST_STATUS); - hdr.set_instance_id(serviceProvider()->instanceId()); - + hdr.set_management_type(ProtocolManagementRequestType::REQUEST_TRACK); + hdr.set_instance_id(controller()->serviceProvider()->instanceId()); buffer()->serialize(hdr); - ProtocolRequestStatus message; + ProtocolRequestTrack message; message.set_id(remoteId()); message.set_queued_type(ProtocolQueuedRequestType::REPLICA_CREATE); - buffer()->serialize(message); _send(lock); @@ -149,7 +136,7 @@ void ReplicationRequest::awaken(boost::system::error_code const& ec) { void ReplicationRequest::_send(replica::Lock const& lock) { auto self = shared_from_base(); - messenger()->send( + controller()->serviceProvider()->messenger()->send( workerName(), id(), priority(), buffer(), [self](string const& id, bool success, ProtocolResponseReplicate const& response) { self->_analyze(success, response); @@ -167,7 +154,6 @@ void ReplicationRequest::_analyze(bool success, ProtocolResponseReplicate const& if (state() == State::FINISHED) return; replica::Lock lock(_mtx, context() + __func__); if (state() == State::FINISHED) return; - if (not success) { finish(lock, CLIENT_ERROR); return; @@ -195,7 +181,7 @@ void ReplicationRequest::_analyze(bool success, ProtocolResponseReplicate const& } switch (message.status()) { case ProtocolStatus::SUCCESS: - serviceProvider()->databaseServices()->saveReplicaInfo(_replicaInfo); + controller()->serviceProvider()->databaseServices()->saveReplicaInfo(_replicaInfo); finish(lock, SUCCESS); break; case ProtocolStatus::CREATED: diff --git a/src/replica/requests/ReplicationRequest.h b/src/replica/requests/ReplicationRequest.h index 3ae0631b6..33943965f 100644 --- a/src/replica/requests/ReplicationRequest.h +++ b/src/replica/requests/ReplicationRequest.h @@ -37,7 +37,7 @@ // Forward declarations namespace lsst::qserv::replica { -class Messenger; +class Controller; } // namespace lsst::qserv::replica // This header declarations @@ -74,55 +74,42 @@ class ReplicationRequest : public RequestMessenger { ReplicaInfo const& responseData() const { return _replicaInfo; } /** - * Create a new request with specified parameters. + * Create and start a new request with specified parameters. * * Static factory method is needed to prevent issue with the lifespan * and memory management of instances created otherwise (as values or via * low-level pointers). * - * @param serviceProvider a host of services for various communications - * @param io_service BOOST ASIO API - * @param workerName the identifier of a worker node (the one to be affected by the replication) - * at a destination of the chunk - * @param sourceWorkerName the identifier of a worker node at a source of the chunk - * @param database the name of a database - * @param chunk the number of a chunk to replicate (implies all relevant tables) - * @param allowDuplicate follow a previously made request if the current one duplicates it - * @param onFinish an optional callback function to be called upon a completion of the request. - * @param priority a priority level of the request - * @param keepTracking keep tracking the request before it finishes or fails - * @param messenger worker messaging service - * @return pointer to the created object + * Class-specific parameters are documented below: + * @param sourceWorkerName An identifier of a worker node at a source of the chunk. + * @param database The name of a database. + * @param chunk The number of a chunk to replicate (implies all relevant tables). + * + * @see The very base class Request for the description of the common parameters + * of all subclasses. + * + * @return A pointer to the created object. */ - static Ptr create(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& workerName, std::string const& sourceWorkerName, - std::string const& database, unsigned int chunk, bool allowDuplicate, - CallbackType const& onFinish, int priority, bool keepTracking, - std::shared_ptr const& messenger); + static Ptr createAndStart(std::shared_ptr const& controller, std::string const& workerName, + std::string const& sourceWorkerName, std::string const& database, + unsigned int chunk, CallbackType const& onFinish = nullptr, + int priority = PRIORITY_NORMAL, bool keepTracking = true, + bool allowDuplicate = true, std::string const& jobId = "", + unsigned int requestExpirationIvalSec = 0); /// @see Request::extendedPersistentState() std::list> extendedPersistentState() const override; protected: - /// @see Request::startImpl() void startImpl(replica::Lock const& lock) final; - - /// @see Request::notify() void notify(replica::Lock const& lock) final; - - /// @see Request::savePersistentState() void savePersistentState(replica::Lock const& lock) final; - - /// @see Request::awaken() void awaken(boost::system::error_code const& ec) final; private: - /// @see ReplicationRequest::create() - ReplicationRequest(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& workerName, std::string const& sourceWorkerName, - std::string const& database, unsigned int chunk, bool allowDuplicate, - CallbackType const& onFinish, int priority, bool keepTracking, - std::shared_ptr const& messenger); + ReplicationRequest(std::shared_ptr const& controller, std::string const& workerName, + std::string const& sourceWorkerName, std::string const& database, unsigned int chunk, + CallbackType const& onFinish, int priority, bool keepTracking, bool allowDuplicate); /** * Send the serialized content of the buffer to a worker diff --git a/src/replica/requests/Request.cc b/src/replica/requests/Request.cc index 32f225e68..4f6c2a617 100644 --- a/src/replica/requests/Request.cc +++ b/src/replica/requests/Request.cc @@ -104,10 +104,9 @@ string Request::state2string(State state, ExtendedState extendedState, return state2string(state, extendedState) + "::" + replica::status2string(serverStatus); } -Request::Request(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - string const& type, string const& workerName, int priority, bool keepTracking, - bool allowDuplicate, bool disposeRequired) - : _serviceProvider(serviceProvider), +Request::Request(shared_ptr const& controller, string const& type, string const& workerName, + int priority, bool keepTracking, bool allowDuplicate, bool disposeRequired) + : _controller(controller), _type(type), _id(Generators::uniqueId()), _workerName(workerName), @@ -119,14 +118,15 @@ Request::Request(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_se _extendedState(NONE), _extendedServerStatus(ProtocolStatusExt::NONE), _bufferPtr(new ProtocolBuffer( - serviceProvider->config()->get("common", "request-buf-size-bytes"))), - _worker(serviceProvider->config()->worker(workerName)), - _timerIvalSec(serviceProvider->config()->get("common", "request-retry-interval-sec")), - _timer(io_service), - _requestExpirationIvalSec( - serviceProvider->config()->get("controller", "request-timeout-sec")), - _requestExpirationTimer(io_service) { - _serviceProvider->config()->assertWorkerIsValid(workerName); + controller->serviceProvider()->config()->get("common", "request-buf-size-bytes"))), + _worker(controller->serviceProvider()->config()->worker(workerName)), + _timerIvalSec(controller->serviceProvider()->config()->get( + "common", "request-retry-interval-sec")), + _timer(controller->serviceProvider()->io_service()), + _requestExpirationIvalSec(controller->serviceProvider()->config()->get( + "controller", "request-timeout-sec")), + _requestExpirationTimer(controller->serviceProvider()->io_service()) { + controller->serviceProvider()->config()->assertWorkerIsValid(workerName); // This report is used solely for debugging purposes to allow tracking // potential memory leaks within applications. @@ -182,8 +182,7 @@ string Request::toString(bool extended) const { return oss.str(); } -void Request::start(shared_ptr const& controller, string const& jobId, - unsigned int requestExpirationIvalSec) { +void Request::start(string const& jobId, unsigned int requestExpirationIvalSec) { replica::Lock lock(_mtx, context() + __func__); assertState(lock, CREATED, context() + __func__); @@ -195,16 +194,10 @@ void Request::start(shared_ptr const& controller, string const& jobI LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << " _requestExpirationIvalSec: " << _requestExpirationIvalSec); - // Build optional associations with the corresponding Controller and the job - // - // NOTE: this is done only once, the first time a non-trivial value - // of each parameter is presented to the method. - - if (not _controller and controller) _controller = controller; + // Build optional associations with the corresponding the job if (_jobId.empty() and not jobId.empty()) _jobId = jobId; _performance.setUpdateStart(); - if (_requestExpirationIvalSec) { _requestExpirationTimer.cancel(); _requestExpirationTimer.expires_from_now(boost::posix_time::seconds(_requestExpirationIvalSec)); @@ -212,19 +205,19 @@ void Request::start(shared_ptr const& controller, string const& jobI } // Let a subclass to proceed with its own sequence of actions - startImpl(lock); // Finalize state transition before saving the persistent state - setState(lock, IN_PROGRESS); + + // Register the request with the controller. The request will be unregistered + // when the request is finished. + _controller->_add(shared_from_this()); } void Request::wait() { LOGS(_log, LOG_LVL_DEBUG, context() << __func__); - if (_finished) return; - unique_lock onFinishLock(_onFinishMtx); _onFinishCv.wait(onFinishLock, [&] { return _finished; }); } @@ -288,6 +281,10 @@ void Request::finish(replica::Lock const& lock, ExtendedState extendedState) { // this scenario and avoid making any modifications to the request's state. setState(lock, FINISHED, extendedState); + // Unregister the request from the controller. Note that the request gest removed + // from the controller's list of active requests only if the request is finished. + _controller->_remove(shared_from_this()); + // Stop the timer if the one is still running _requestExpirationTimer.cancel(); @@ -330,4 +327,6 @@ void Request::setState(replica::Lock const& lock, State newState, ExtendedState savePersistentState(lock); } +boost::asio::io_service& Request::_ioService() { return controller()->serviceProvider()->io_service(); } + } // namespace lsst::qserv::replica diff --git a/src/replica/requests/Request.h b/src/replica/requests/Request.h index 944464afe..3f66b4ece 100644 --- a/src/replica/requests/Request.h +++ b/src/replica/requests/Request.h @@ -24,7 +24,7 @@ // System headers #include #include -#include +#include #include #include #include @@ -33,16 +33,15 @@ #include "boost/asio.hpp" // Qserv headers -#include "replica/config/Configuration.h" -#include "replica/services/ServiceProvider.h" -#include "replica/util/Common.h" +#include "replica/config/ConfigWorker.h" +#include "replica/proto/protocol.pb.h" #include "replica/util/Performance.h" -#include "replica/util/ProtocolBuffer.h" #include "replica/util/Mutex.h" // Forward declarations namespace lsst::qserv::replica { class Controller; +class ProtocolBuffer; } // namespace lsst::qserv::replica // This header declarations @@ -50,7 +49,24 @@ namespace lsst::qserv::replica { /** * Class Request is a base class for a family of requests within - * the master server. + * the master Replication Controller service. + * + * The class is not intended to be used directly. Instead, it should be subclassed + * by a specific request type. Objects of the subclassed request type are created + * by a factory method "createAndStart" that is provided by each such class. + * + * The following parameters of the method "createAndStart" are common for all subclasses: + * @param controller The Controller associated with the request. + * @param workerName An identifier of a worker node. + * @param onFinish The (optional) callback function to call upon completion of + * the request. The functin type is specific for each subclass. + * @param priority The (optional) priority level of the request. + * @param keepTracking The (optional) flagg to keep tracking the request before it finishes or fails. + * @param allowDuplicate (optional) Follow a previously made request if the current one duplicates it. + * @param jobId The (optional) unique identifier of a job to which the request belongs. + * @param requestExpirationIvalSec The (optional) time in seconds after which the request + * will expire. The default value of '0' means an effective expiration time will be pull + * from the configuration. */ class Request : public std::enable_shared_from_this { public: @@ -137,8 +153,8 @@ class Request : public std::enable_shared_from_this { virtual ~Request(); - /// @return reference to the service provider, - ServiceProvider::Ptr const& serviceProvider() const { return _serviceProvider; } + /// @return the Controller + std::shared_ptr const& controller() const { return _controller; } /// @return a string representing a type of a request. std::string const& type() const { return _type; } @@ -172,28 +188,19 @@ class Request : public std::enable_shared_from_this { /// @return the performance info Performance performance() const; - /// @return the Controller (if set) - std::shared_ptr const& controller() const { return _controller; } - /** * Reset the state (if needed) and begin processing the request. * * This is supposed to be the first operation to be called upon a creation - * of the request. A caller may optionally provide a pointer to an instance - * of the Controller class which (if set) may be used by subclasses for saving - * their state in a database. + * of the request. * - * @note Only the first call with the non-default pointer to the Controller - * will be considering for building an association with the Controller. - * @param controller A (optional) pointer to an instance of the Controller. * @param jobId An (optional) identifier of a job specifying a context * in which a request will be executed. * @param requestExpirationIvalSecAn (optional) parameter (if differs from 0) * allowing to override the default value of the corresponding parameter from * the Configuration. */ - void start(std::shared_ptr const& controller = nullptr, std::string const& jobId = "", - unsigned int requestExpirationIvalSec = 0); + void start(std::string const& jobId = "", unsigned int requestExpirationIvalSec = 0); /// Wait for the completion of the request void wait(); @@ -260,8 +267,7 @@ class Request : public std::enable_shared_from_this { * @note options 'keepTracking', 'allowDuplicate' and 'disposeRequired' * have effect for specific request only. * - * @param serviceProvider A provider of various services (Configuration, etc.). - * @param io_service BOOST ASIO service object + * @param controller The Controller associated with the request. * @param type The type name of a request (used informally for debugging, and it's * also stored in the persistent state of the Replication system). * @param workerName The name of a worker. @@ -275,9 +281,9 @@ class Request : public std::enable_shared_from_this { * disposal is needed for a particular request. Normally, it's required for * requests which are queued by workers in its processing queues. */ - Request(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& type, std::string const& workerName, int priority, bool keepTracking, - bool allowDuplicate, bool disposeRequired); + Request(std::shared_ptr const& controller, std::string const& type, + std::string const& workerName, int priority, bool keepTracking, bool allowDuplicate, + bool disposeRequired); /// @return A shared pointer of the desired subclass (no dynamic type checking) template @@ -296,7 +302,7 @@ class Request : public std::enable_shared_from_this { /// Callback handler for the asynchronous operation. It's invoked in a series /// of the timer-triggered events to track a progress of the request. - /// @note The metgod must get the subclass-specif implementation for cases + /// @note The metgod must get the subclass-specific implementation for cases /// where the subclass enables the tracking. /// @see request::keepTracking /// @throw std::runtime_error If the default implementation of the method is called. @@ -499,7 +505,7 @@ class Request : public std::enable_shared_from_this { // 1. it guaranties (exactly) one time notification // 2. it breaks the up-stream dependency on a caller object if a shared // pointer to the object was mentioned as the lambda-function's closure - serviceProvider()->io_service().post(std::bind(std::move(onFinish), shared_from_base())); + _ioService().post(std::bind(std::move(onFinish), shared_from_base())); onFinish = nullptr; } } @@ -514,12 +520,14 @@ class Request : public std::enable_shared_from_this { mutable replica::Mutex _mtx; private: + /// @return The global IO service object retreived from the service provider + boost::asio::io_service& _ioService(); + /// The global counter for the number of instances of any subclasses static std::atomic _numClassInstances; // Input parameters - - ServiceProvider::Ptr const _serviceProvider; + std::shared_ptr _controller; std::string const _type; std::string const _id; /// @note UUID generated by the constructor @@ -578,9 +586,6 @@ class Request : public std::enable_shared_from_this { unsigned int _requestExpirationIvalSec; boost::asio::deadline_timer _requestExpirationTimer; - /// The optional association with the Controller - std::shared_ptr _controller; - /// The job context of a request std::string _jobId; diff --git a/src/replica/requests/RequestMessenger.cc b/src/replica/requests/RequestMessenger.cc index 5a72ff57e..032f68b36 100644 --- a/src/replica/requests/RequestMessenger.cc +++ b/src/replica/requests/RequestMessenger.cc @@ -23,7 +23,10 @@ #include "replica/requests/RequestMessenger.h" // Qserv headers +#include "replica/contr/Controller.h" #include "replica/proto/protocol.pb.h" +#include "replica/requests/Messenger.h" +#include "replica/services/ServiceProvider.h" #include "replica/util/ProtocolBuffer.h" // LSST headers @@ -39,13 +42,10 @@ LOG_LOGGER _log = LOG_GET("lsst.qserv.replica.RequestMessenger"); namespace lsst::qserv::replica { -RequestMessenger::RequestMessenger(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, string const& type, +RequestMessenger::RequestMessenger(shared_ptr const& controller, string const& type, string const& workerName, int priority, bool keepTracking, - bool allowDuplicate, bool disposeRequired, Messenger::Ptr const& messenger) - : Request(serviceProvider, io_service, type, workerName, priority, keepTracking, allowDuplicate, - disposeRequired), - _messenger(messenger) {} + bool allowDuplicate, bool disposeRequired) + : Request(controller, type, workerName, priority, keepTracking, allowDuplicate, disposeRequired) {} void RequestMessenger::finishImpl(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__); @@ -56,7 +56,7 @@ void RequestMessenger::finishImpl(replica::Lock const& lock) { // will be at the messenger's queue. This optimization also reduces extra // locking (and delays) in the messenger because the operation is synchronized. if (extendedState() != Request::ExtendedState::SUCCESS) { - _messenger->cancel(workerName(), id()); + controller()->serviceProvider()->messenger()->cancel(workerName(), id()); } // Tell the worker to dispose the request if a subclass made such requirement, @@ -88,14 +88,15 @@ void RequestMessenger::dispose(replica::Lock const& lock, int priority, hdr.set_id(id()); hdr.set_type(ProtocolRequestHeader::REQUEST); hdr.set_management_type(ProtocolManagementRequestType::REQUEST_DISPOSE); - hdr.set_instance_id(serviceProvider()->instanceId()); + hdr.set_instance_id(controller()->serviceProvider()->instanceId()); buffer()->serialize(hdr); ProtocolRequestDispose message; message.add_ids(id()); buffer()->serialize(message); - _messenger->send(workerName(), id(), priority, buffer(), onFinish); + controller()->serviceProvider()->messenger()->send(workerName(), id(), priority, + buffer(), onFinish); } } // namespace lsst::qserv::replica diff --git a/src/replica/requests/RequestMessenger.h b/src/replica/requests/RequestMessenger.h index 0517c4f9d..13802907d 100644 --- a/src/replica/requests/RequestMessenger.h +++ b/src/replica/requests/RequestMessenger.h @@ -26,17 +26,17 @@ #include #include -// Third party headers -#include "boost/asio.hpp" - // Qserv headers #include "replica/proto/protocol.pb.h" -#include "replica/requests/Messenger.h" #include "replica/requests/Request.h" -#include "replica/services/ServiceProvider.h" #include "replica/util/Common.h" #include "replica/util/Mutex.h" +// Forward declarations +namespace lsst::qserv::replica { +class Controller; +} // namespace lsst::qserv::replica + // This header declarations namespace lsst::qserv::replica { @@ -67,17 +67,11 @@ class RequestMessenger : public Request { protected: /** * Construct the request with the pointer to the services provider. - * - * @param messenger An interface for communicating with workers. - * @see class Request for an explanation of other parameters. * @return A pointer to the created object. */ - RequestMessenger(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& type, std::string const& workerName, int priority, bool keepTracking, - bool allowDuplicate, bool disposeRequired, Messenger::Ptr const& messenger); - - /// @return pointer to the messaging service - Messenger::Ptr const& messenger() const { return _messenger; } + RequestMessenger(std::shared_ptr const& controller, std::string const& type, + std::string const& workerName, int priority, bool keepTracking, bool allowDuplicate, + bool disposeRequired); /// @see Request::finishImpl() void finishImpl(replica::Lock const& lock) override; @@ -97,10 +91,6 @@ class RequestMessenger : public Request { * the request disposal operation. */ void dispose(replica::Lock const& lock, int priority, OnDisposeCallbackType const& onFinish = nullptr); - - // Input parameters - - Messenger::Ptr const _messenger; }; } // namespace lsst::qserv::replica diff --git a/src/replica/requests/ServiceManagementRequest.h b/src/replica/requests/ServiceManagementRequest.h index 31689fad7..ef97bce41 100644 --- a/src/replica/requests/ServiceManagementRequest.h +++ b/src/replica/requests/ServiceManagementRequest.h @@ -46,7 +46,7 @@ // Forward declarations namespace lsst::qserv::replica { -class Messenger; +class Controller; } // namespace lsst::qserv::replica // This header declarations @@ -120,19 +120,21 @@ class ServiceManagementRequest : public ServiceManagementRequestBase { * and memory management of instances created otherwise (as values or via * low-level pointers). * - * @param serviceProvider provides various services for the application - * @param io_service network communication service (BOOST ASIO) - * @param workerName identifier of a worker node (the one to be affected by the request) - * @param priority a priority level of the request - * @param onFinish callback function to be called upon a completion of the request - * @param messenger messenger service for workers + * Class-specific parameters are documented below: + * @param priority The priority level of the request. + * + * @see The very base class Request for the description of the common parameters + * of all subclasses. + * + * @return A pointer to the created object. */ - static Ptr create(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& workerName, CallbackType const& onFinish, int priority, - std::shared_ptr const& messenger) { - return ServiceManagementRequest::Ptr(new ServiceManagementRequest( - serviceProvider, io_service, POLICY::requestName(), workerName, POLICY::requestType(), - priority, onFinish, messenger)); + static Ptr createAndStart(std::shared_ptr const& controller, std::string const& workerName, + CallbackType const& onFinish = nullptr, int priority = PRIORITY_VERY_HIGH, + std::string const& jobId = "", unsigned int requestExpirationIvalSec = 0) { + auto ptr = ServiceManagementRequest::Ptr(new ServiceManagementRequest( + controller, POLICY::requestName(), workerName, POLICY::requestType(), priority, onFinish)); + ptr->start(jobId, requestExpirationIvalSec); + return ptr; } protected: @@ -141,12 +143,10 @@ class ServiceManagementRequest : public ServiceManagementRequestBase { } private: - ServiceManagementRequest(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - char const* requestName, std::string const& workerName, - ProtocolServiceRequestType requestType, int priority, - CallbackType const& onFinish, std::shared_ptr const& messenger) - : ServiceManagementRequestBase(serviceProvider, io_service, requestName, workerName, requestType, - priority, messenger), + ServiceManagementRequest(std::shared_ptr const& controller, char const* requestName, + std::string const& workerName, ProtocolServiceRequestType requestType, + int priority, CallbackType const& onFinish) + : ServiceManagementRequestBase(controller, requestName, workerName, requestType, priority), _onFinish(onFinish) {} // Input parameters diff --git a/src/replica/requests/ServiceManagementRequestBase.cc b/src/replica/requests/ServiceManagementRequestBase.cc index a42e4b707..2919899bf 100644 --- a/src/replica/requests/ServiceManagementRequestBase.cc +++ b/src/replica/requests/ServiceManagementRequestBase.cc @@ -56,6 +56,10 @@ void dumpRequestInfo(ostream& os, vector const& req } } +bool const keepTrackingNo = false; +bool const allowDuplicateNo = false; +bool const disposeRequiredNo = false; + } // namespace namespace lsst::qserv::replica { @@ -161,17 +165,12 @@ ServiceState const& ServiceManagementRequestBase::getServiceState() const { " not allowed in the current state of the request"); } -ServiceManagementRequestBase::ServiceManagementRequestBase(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, +ServiceManagementRequestBase::ServiceManagementRequestBase(shared_ptr const& controller, char const* requestName, string const& workerName, ProtocolServiceRequestType requestType, - int priority, - shared_ptr const& messenger) - : RequestMessenger(serviceProvider, io_service, requestName, workerName, priority, - false, // keepTracking - false, // allowDuplicate - false, // disposeRequired - messenger), + int priority) + : RequestMessenger(controller, requestName, workerName, priority, ::keepTrackingNo, + ::allowDuplicateNo, ::disposeRequiredNo), _requestType(requestType) {} void ServiceManagementRequestBase::startImpl(replica::Lock const& lock) { @@ -179,22 +178,20 @@ void ServiceManagementRequestBase::startImpl(replica::Lock const& lock) { // Serialize the Request message header and the request itself into // the network buffer. - buffer()->resize(); ProtocolRequestHeader hdr; hdr.set_id(id()); hdr.set_type(ProtocolRequestHeader::SERVICE); hdr.set_service_type(_requestType); - hdr.set_instance_id(serviceProvider()->instanceId()); - + hdr.set_instance_id(controller()->serviceProvider()->instanceId()); buffer()->serialize(hdr); // Send the message - auto self = shared_from_base(); - messenger()->send( + controller()->serviceProvider()->messenger()->send( workerName(), id(), priority(), buffer(), - [self](string const& id, bool success, ProtocolServiceResponse const& response) { + [self = shared_from_base()]( + string const& id, bool success, ProtocolServiceResponse const& response) { self->_analyze(success, response); }); } @@ -210,7 +207,6 @@ void ServiceManagementRequestBase::_analyze(bool success, ProtocolServiceRespons if (state() == State::FINISHED) return; replica::Lock lock(_mtx, context() + __func__); if (state() == State::FINISHED) return; - if (not success) { finish(lock, CLIENT_ERROR); return; @@ -227,7 +223,6 @@ void ServiceManagementRequestBase::_analyze(bool success, ProtocolServiceRespons _serviceState.set(message); finish(lock, SUCCESS); break; - default: finish(lock, SERVER_ERROR); break; diff --git a/src/replica/requests/ServiceManagementRequestBase.h b/src/replica/requests/ServiceManagementRequestBase.h index 5bc64db34..ae63a0b86 100644 --- a/src/replica/requests/ServiceManagementRequestBase.h +++ b/src/replica/requests/ServiceManagementRequestBase.h @@ -35,7 +35,7 @@ // Forward declarations namespace lsst::qserv::replica { -class Messenger; +class Controller; } // namespace lsst::qserv::replica // This header declarations @@ -110,23 +110,17 @@ class ServiceManagementRequestBase : public RequestMessenger { protected: /** * Construct the request with the pointer to the services provider. - * @param serviceProvider Provides various services for the application. - * @param io_service The asynchronous I/O communication services (BOOST ASIO). - * @param requestName The name of a request. - * @param workerName The name of a worker. - * @param requestType A type of a request. - * @param priority A priority level of a request. - * @param messenger The messaging service for workers. + * @param controller the Controller associated with the request + * @param requestName The name of a request. + * @param workerName The name of a worker. + * @param requestType A type of a request. + * @param priority A priority level of a request. */ - ServiceManagementRequestBase(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, char const* requestName, + ServiceManagementRequestBase(std::shared_ptr const& controller, char const* requestName, std::string const& workerName, ProtocolServiceRequestType requestType, - int priority, std::shared_ptr const& messenger); + int priority); - /// @see Request::startImpl() void startImpl(replica::Lock const& lock) final; - - /// @see Request::savePersistentState() void savePersistentState(replica::Lock const& lock) final; private: diff --git a/src/replica/requests/SqlAlterTablesRequest.cc b/src/replica/requests/SqlAlterTablesRequest.cc index cea86e1ba..8efc29504 100644 --- a/src/replica/requests/SqlAlterTablesRequest.cc +++ b/src/replica/requests/SqlAlterTablesRequest.cc @@ -22,39 +22,33 @@ // Class header #include "replica/requests/SqlAlterTablesRequest.h" -// Qserv headers -#include "replica/services/ServiceProvider.h" - // LSST headers #include "lsst/log/Log.h" using namespace std; namespace { - LOG_LOGGER _log = LOG_GET("lsst.qserv.replica.SqlAlterTablesRequest"); - +const uint64_t unlimitedMaxRows = 0; } // namespace namespace lsst::qserv::replica { -SqlAlterTablesRequest::Ptr SqlAlterTablesRequest::create( - ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - string const& worker, string const& database, vector const& tables, string const& alterSpec, - CallbackType const& onFinish, int priority, bool keepTracking, - shared_ptr const& messenger) { - return Ptr(new SqlAlterTablesRequest(serviceProvider, io_service, worker, database, tables, alterSpec, - onFinish, priority, keepTracking, messenger)); +SqlAlterTablesRequest::Ptr SqlAlterTablesRequest::createAndStart( + shared_ptr const& controller, string const& workerName, string const& database, + vector const& tables, string const& alterSpec, CallbackType const& onFinish, int priority, + bool keepTracking, string const& jobId, unsigned int requestExpirationIvalSec) { + auto ptr = Ptr(new SqlAlterTablesRequest(controller, workerName, database, tables, alterSpec, onFinish, + priority, keepTracking)); + ptr->start(jobId, requestExpirationIvalSec); + return ptr; } -SqlAlterTablesRequest::SqlAlterTablesRequest(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, string const& worker, - string const& database, vector const& tables, - string const& alterSpec, CallbackType const& onFinish, - int priority, bool keepTracking, - shared_ptr const& messenger) - : SqlRequest(serviceProvider, io_service, "SQL_ALTER_TABLES", worker, 0, /* maxRows */ - priority, keepTracking, messenger), +SqlAlterTablesRequest::SqlAlterTablesRequest(shared_ptr const& controller, + string const& workerName, string const& database, + vector const& tables, string const& alterSpec, + CallbackType const& onFinish, int priority, bool keepTracking) + : SqlRequest(controller, "SQL_ALTER_TABLES", workerName, ::unlimitedMaxRows, priority, keepTracking), _onFinish(onFinish) { // Finish initializing the request body's content requestBody.set_type(ProtocolRequestSql::ALTER_TABLE); @@ -70,7 +64,6 @@ SqlAlterTablesRequest::SqlAlterTablesRequest(ServiceProvider::Ptr const& service void SqlAlterTablesRequest::notify(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "[" << ProtocolRequestSql_Type_Name(requestBody.type()) << "]"); - notifyDefaultImpl(lock, _onFinish); } diff --git a/src/replica/requests/SqlAlterTablesRequest.h b/src/replica/requests/SqlAlterTablesRequest.h index 59a6ca7b1..cf31478dc 100644 --- a/src/replica/requests/SqlAlterTablesRequest.h +++ b/src/replica/requests/SqlAlterTablesRequest.h @@ -33,6 +33,11 @@ #include "replica/requests/SqlRequest.h" #include "replica/util/Common.h" +// Forward declarations +namespace lsst::qserv::replica { +class Controller; +} // namespace lsst::qserv::replica + // This header declarations namespace lsst::qserv::replica { @@ -55,35 +60,31 @@ class SqlAlterTablesRequest : public SqlRequest { /** * Create a new request with specified parameters. - * @param serviceProvider Is needed to access the Configuration and - * the Controller for communicating with the worker. - * @param io_service The BOOST ASIO communication end-point. - * @param worker An identifier of a worker node. + * + * Class-specific parameters are documented below: * @param database The name of an existing database where the tables are residing. * @param tables The names of tables affected by the operation. - * @param alterSpec A specification of what to change following 'ALTER TABLE '. - * @param onFinish (optional) A callback function to call upon completion of - * the request. - * @param priority A priority level of the request. - * @param keepTracking Keep tracking the request before it finishes or fails. - * @param messenger An interface for communicating with workers. + * @param alterSpec A specification of what to change following 'ALTER TABLE
'. + * + * @see The very base class Request for the description of the common parameters + * of all subclasses. + * * @return A smart pointer to the created object. */ - static Ptr create(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& database, - std::vector const& tables, std::string const& alterSpec, - CallbackType const& onFinish, int priority, bool keepTracking, - std::shared_ptr const& messenger); + static Ptr createAndStart(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, std::vector const& tables, + std::string const& alterSpec, CallbackType const& onFinish = nullptr, + int priority = PRIORITY_NORMAL, bool keepTracking = true, + std::string const& jobId = "", unsigned int requestExpirationIvalSec = 0); protected: void notify(replica::Lock const& lock) final; private: - SqlAlterTablesRequest(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& database, - std::vector const& tables, std::string const& alterSpec, - CallbackType const& onFinish, int priority, bool keepTracking, - std::shared_ptr const& messenger); + SqlAlterTablesRequest(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, std::vector const& tables, + std::string const& alterSpec, CallbackType const& onFinish, int priority, + bool keepTracking); CallbackType _onFinish; ///< @note is reset when the request finishes }; diff --git a/src/replica/requests/SqlCreateDbRequest.cc b/src/replica/requests/SqlCreateDbRequest.cc index 7f349581e..9f70c4d84 100644 --- a/src/replica/requests/SqlCreateDbRequest.cc +++ b/src/replica/requests/SqlCreateDbRequest.cc @@ -22,38 +22,35 @@ // Class header #include "replica/requests/SqlCreateDbRequest.h" -// Qserv headers -#include "replica/services/ServiceProvider.h" - // LSST headers #include "lsst/log/Log.h" using namespace std; namespace { - LOG_LOGGER _log = LOG_GET("lsst.qserv.replica.SqlCreateDbRequest"); - +const uint64_t unlimitedMaxRows = 0; } // namespace namespace lsst::qserv::replica { -SqlCreateDbRequest::Ptr SqlCreateDbRequest::create(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, string const& worker, - std::string const& database, CallbackType const& onFinish, - int priority, bool keepTracking, - shared_ptr const& messenger) { - return Ptr(new SqlCreateDbRequest(serviceProvider, io_service, worker, database, onFinish, priority, - keepTracking, messenger)); +SqlCreateDbRequest::Ptr SqlCreateDbRequest::createAndStart(shared_ptr const& controller, + string const& workerName, + std::string const& database, + CallbackType const& onFinish, int priority, + bool keepTracking, string const& jobId, + unsigned int requestExpirationIvalSec) { + auto ptr = + Ptr(new SqlCreateDbRequest(controller, workerName, database, onFinish, priority, keepTracking)); + ptr->start(jobId, requestExpirationIvalSec); + return ptr; } -SqlCreateDbRequest::SqlCreateDbRequest(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, string const& worker, +SqlCreateDbRequest::SqlCreateDbRequest(shared_ptr const& controller, string const& workerName, std::string const& database, CallbackType const& onFinish, - int priority, bool keepTracking, - shared_ptr const& messenger) - : SqlRequest(serviceProvider, io_service, "SQL_CREATE_DATABASE", worker, 0 /* maxRows */, priority, - keepTracking, messenger), + int priority, bool keepTracking) + : SqlRequest(controller, "SQL_CREATE_DATABASE", workerName, ::unlimitedMaxRows, priority, + keepTracking), _onFinish(onFinish) { // Finish initializing the request body's content requestBody.set_type(ProtocolRequestSql::CREATE_DATABASE); @@ -63,7 +60,6 @@ SqlCreateDbRequest::SqlCreateDbRequest(ServiceProvider::Ptr const& serviceProvid void SqlCreateDbRequest::notify(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "[" << ProtocolRequestSql_Type_Name(requestBody.type()) << "]"); - notifyDefaultImpl(lock, _onFinish); } diff --git a/src/replica/requests/SqlCreateDbRequest.h b/src/replica/requests/SqlCreateDbRequest.h index 287d899f3..431815ef5 100644 --- a/src/replica/requests/SqlCreateDbRequest.h +++ b/src/replica/requests/SqlCreateDbRequest.h @@ -29,6 +29,11 @@ // Qserv headers #include "replica/requests/SqlRequest.h" +// Forward declarations +namespace lsst::qserv::replica { +class Controller; +} // namespace lsst::qserv::replica + // This header declarations namespace lsst::qserv::replica { @@ -58,29 +63,26 @@ class SqlCreateDbRequest : public SqlRequest { * and memory management of instances created otherwise (as values or via * low-level pointers). * - * @param serviceProvider Services of the Replication framework. - * @param io_service Asynchronous communication services. - * @param worker A unique identifier of a worker node. - * @param database The name of a database to be created. - * @param onFinish The (optional) callback function to call upon completion of the request. - * @param priority A priority level of the request. - * @param keepTracking Keep tracking the request before it finishes or fails. - * @param messenger An service for communications with workers. + * Class-specific parameters are documented below: + * @param database The name of a database to be created. + * + * @see The very base class Request for the description of the common parameters + * of all subclasses. + * * @return A pointer to the created object. */ - static Ptr create(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& database, CallbackType const& onFinish, - int priority, bool keepTracking, std::shared_ptr const& messenger); + static Ptr createAndStart(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, CallbackType const& onFinish = nullptr, + int priority = PRIORITY_NORMAL, bool keepTracking = true, + std::string const& jobId = "", unsigned int requestExpirationIvalSec = 0); protected: - /// @see Request::notify() void notify(replica::Lock const& lock) final; private: - /// @see SqlCreateDbRequest::create() - SqlCreateDbRequest(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& database, CallbackType const& onFinish, - int priority, bool keepTracking, std::shared_ptr const& messenger); + SqlCreateDbRequest(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, CallbackType const& onFinish, int priority, + bool keepTracking); CallbackType _onFinish; ///< @note is reset when the request finishes }; diff --git a/src/replica/requests/SqlCreateIndexesRequest.cc b/src/replica/requests/SqlCreateIndexesRequest.cc index 467780dda..8a6bf68ff 100644 --- a/src/replica/requests/SqlCreateIndexesRequest.cc +++ b/src/replica/requests/SqlCreateIndexesRequest.cc @@ -22,43 +22,36 @@ // Class header #include "replica/requests/SqlCreateIndexesRequest.h" -// Qserv headers -#include "replica/services/ServiceProvider.h" - // LSST headers #include "lsst/log/Log.h" using namespace std; namespace { - LOG_LOGGER _log = LOG_GET("lsst.qserv.replica.SqlCreateIndexesRequest"); - +const uint64_t unlimitedMaxRows = 0; } // namespace namespace lsst::qserv::replica { -SqlCreateIndexesRequest::Ptr SqlCreateIndexesRequest::create( - ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - string const& worker, string const& database, vector const& tables, - SqlRequestParams::IndexSpec const& indexSpec, string const& indexName, string const& indexComment, - vector const& indexColumns, CallbackType const& onFinish, int priority, - bool keepTracking, shared_ptr const& messenger) { - return Ptr(new SqlCreateIndexesRequest(serviceProvider, io_service, worker, database, tables, indexSpec, - indexName, indexComment, indexColumns, onFinish, priority, - keepTracking, messenger)); +SqlCreateIndexesRequest::Ptr SqlCreateIndexesRequest::createAndStart( + shared_ptr const& controller, string const& workerName, string const& database, + vector const& tables, SqlRequestParams::IndexSpec const& indexSpec, string const& indexName, + string const& indexComment, vector const& indexColumns, CallbackType const& onFinish, + int priority, bool keepTracking, string const& jobId, unsigned int requestExpirationIvalSec) { + auto ptr = Ptr(new SqlCreateIndexesRequest(controller, workerName, database, tables, indexSpec, indexName, + indexComment, indexColumns, onFinish, priority, keepTracking)); + ptr->start(jobId, requestExpirationIvalSec); + return ptr; } -SqlCreateIndexesRequest::SqlCreateIndexesRequest(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, string const& worker, - string const& database, vector const& tables, - SqlRequestParams::IndexSpec const& indexSpec, - string const& indexName, string const& indexComment, - vector const& indexColumns, - CallbackType const& onFinish, int priority, - bool keepTracking, shared_ptr const& messenger) - : SqlRequest(serviceProvider, io_service, "SQL_CREATE_TABLE_INDEXES", worker, 0, /* maxRows */ - priority, keepTracking, messenger), +SqlCreateIndexesRequest::SqlCreateIndexesRequest( + shared_ptr const& controller, string const& workerName, string const& database, + vector const& tables, SqlRequestParams::IndexSpec const& indexSpec, string const& indexName, + string const& indexComment, vector const& indexColumns, CallbackType const& onFinish, + int priority, bool keepTracking) + : SqlRequest(controller, "SQL_CREATE_TABLE_INDEXES", workerName, ::unlimitedMaxRows, priority, + keepTracking), _onFinish(onFinish) { // Finish initializing the request body's content requestBody.set_type(ProtocolRequestSql::CREATE_TABLE_INDEX); @@ -83,7 +76,6 @@ SqlCreateIndexesRequest::SqlCreateIndexesRequest(ServiceProvider::Ptr const& ser void SqlCreateIndexesRequest::notify(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "[" << ProtocolRequestSql_Type_Name(requestBody.type()) << "]"); - notifyDefaultImpl(lock, _onFinish); } diff --git a/src/replica/requests/SqlCreateIndexesRequest.h b/src/replica/requests/SqlCreateIndexesRequest.h index 4a958398c..0c14bc31b 100644 --- a/src/replica/requests/SqlCreateIndexesRequest.h +++ b/src/replica/requests/SqlCreateIndexesRequest.h @@ -33,6 +33,11 @@ #include "replica/requests/SqlRequest.h" #include "replica/util/Common.h" +// Forward declarations +namespace lsst::qserv::replica { +class Controller; +} // namespace lsst::qserv::replica + // This header declarations namespace lsst::qserv::replica { @@ -62,42 +67,37 @@ class SqlCreateIndexesRequest : public SqlRequest { * and memory management of instances created otherwise (as values or via * low-level pointers). * - * @param serviceProvider Is needed to access the Configuration and - * the Controller for communicating with the worker. - * @param io_service The BOOST ASIO communication end-point. - * @param worker An identifier of a worker node. + * Class-specific parameters are documented below: * @param database The name of an existing database where the tables are residing. * @param tables The names of tables affected by the operation. * @param indexSpec The type specification of the index. * @param indexName The name of the index. * @param indexComment An arbitrary comment string documenting the index. * @param indexColumns Column definitions (name,length,ordering) for the index. - * @param onFinish (optional) A callback function to call upon completion of - * the request. - * @param priority A priority level of the request. - * @param keepTracking Keep tracking the request before it finishes or fails. - * @param messenger An interface for communicating with workers. + * + * @see The very base class Request for the description of the common parameters + * of all subclasses. * * @return A pointer to the created object. */ - static Ptr create(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& database, - std::vector const& tables, SqlRequestParams::IndexSpec const& indexSpec, - std::string const& indexName, std::string const& indexComment, - std::vector const& indexColumns, CallbackType const& onFinish, - int priority, bool keepTracking, std::shared_ptr const& messenger); + static Ptr createAndStart(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, std::vector const& tables, + SqlRequestParams::IndexSpec const& indexSpec, std::string const& indexName, + std::string const& indexComment, + std::vector const& indexColumns, + CallbackType const& onFinish = nullptr, int priority = PRIORITY_NORMAL, + bool keepTracking = true, std::string const& jobId = "", + unsigned int requestExpirationIvalSec = 0); protected: void notify(replica::Lock const& lock) final; private: - SqlCreateIndexesRequest(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& database, - std::vector const& tables, + SqlCreateIndexesRequest(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, std::vector const& tables, SqlRequestParams::IndexSpec const& indexSpec, std::string const& indexName, std::string const& indexComment, std::vector const& indexColumns, - CallbackType const& onFinish, int priority, bool keepTracking, - std::shared_ptr const& messenger); + CallbackType const& onFinish, int priority, bool keepTracking); CallbackType _onFinish; ///< @note is reset when the request finishes }; diff --git a/src/replica/requests/SqlCreateTableRequest.cc b/src/replica/requests/SqlCreateTableRequest.cc index 475c72d0f..331976ccf 100644 --- a/src/replica/requests/SqlCreateTableRequest.cc +++ b/src/replica/requests/SqlCreateTableRequest.cc @@ -22,42 +22,37 @@ // Class header #include "replica/requests/SqlCreateTableRequest.h" -// Qserv headers -#include "replica/services/ServiceProvider.h" - // LSST headers #include "lsst/log/Log.h" using namespace std; namespace { - LOG_LOGGER _log = LOG_GET("lsst.qserv.replica.SqlCreateTableRequest"); +const uint64_t unlimitedMaxRows = 0; } // namespace namespace lsst::qserv::replica { -SqlCreateTableRequest::Ptr SqlCreateTableRequest::create( - ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - string const& worker, std::string const& database, std::string const& table, - std::string const& engine, string const& partitionByColumn, std::list const& columns, - CallbackType const& onFinish, int priority, bool keepTracking, - shared_ptr const& messenger) { - return Ptr(new SqlCreateTableRequest(serviceProvider, io_service, worker, database, table, engine, - partitionByColumn, columns, onFinish, priority, keepTracking, - messenger)); +SqlCreateTableRequest::Ptr SqlCreateTableRequest::createAndStart( + shared_ptr const& controller, string const& workerName, std::string const& database, + std::string const& table, std::string const& engine, string const& partitionByColumn, + std::list const& columns, CallbackType const& onFinish, int priority, bool keepTracking, + string const& jobId, unsigned int requestExpirationIvalSec) { + auto ptr = Ptr(new SqlCreateTableRequest(controller, workerName, database, table, engine, + partitionByColumn, columns, onFinish, priority, keepTracking)); + ptr->start(jobId, requestExpirationIvalSec); + return ptr; } -SqlCreateTableRequest::SqlCreateTableRequest(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, string const& worker, - std::string const& database, std::string const& table, - std::string const& engine, string const& partitionByColumn, +SqlCreateTableRequest::SqlCreateTableRequest(shared_ptr const& controller, + string const& workerName, std::string const& database, + std::string const& table, std::string const& engine, + string const& partitionByColumn, std::list const& columns, - CallbackType const& onFinish, int priority, bool keepTracking, - shared_ptr const& messenger) - : SqlRequest(serviceProvider, io_service, "SQL_CREATE_TABLE", worker, 0, /* maxRows */ - priority, keepTracking, messenger), + CallbackType const& onFinish, int priority, bool keepTracking) + : SqlRequest(controller, "SQL_CREATE_TABLE", workerName, ::unlimitedMaxRows, priority, keepTracking), _onFinish(onFinish) { // Finish initializing the request body's content requestBody.set_type(ProtocolRequestSql::CREATE_TABLE); @@ -75,7 +70,6 @@ SqlCreateTableRequest::SqlCreateTableRequest(ServiceProvider::Ptr const& service void SqlCreateTableRequest::notify(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "[" << ProtocolRequestSql_Type_Name(requestBody.type()) << "]"); - notifyDefaultImpl(lock, _onFinish); } diff --git a/src/replica/requests/SqlCreateTableRequest.h b/src/replica/requests/SqlCreateTableRequest.h index c8cb7ef29..640b4a029 100644 --- a/src/replica/requests/SqlCreateTableRequest.h +++ b/src/replica/requests/SqlCreateTableRequest.h @@ -32,6 +32,11 @@ #include "replica/requests/SqlRequest.h" #include "replica/util/Common.h" +// Forward declarations +namespace lsst::qserv::replica { +class Controller; +} // namespace lsst::qserv::replica + // This header declarations namespace lsst::qserv::replica { @@ -63,40 +68,37 @@ class SqlCreateTableRequest : public SqlRequest { * Static factory method is needed to prevent issue with the lifespan * and memory management of instances created otherwise (as values or via * low-level pointers). - * @param serviceProvider Services of the Replication framework. - * @param io_service Asynchronous communication services. - * @param worker A unique identifier of a worker node. - * @param database The name of an existing database where the new table will be created. - * @param table The name of a table to be created. - * @param engine The name of the MySQL engine for the new table. - * @param partitionByColumn (optional, if not empty) The name of a column which + * + * Class-specific parameters are documented below: + * @param database The name of an existing database where the new table will be created. + * @param table The name of a table to be created. + * @param engine The name of the MySQL engine for the new table. + * @param partitionByColumn The (optional, if not empty) name of a column which * will be used as a key to configure MySQL partitions for the new table. * This variation of table schema will be used for the super-transaction-based * ingest into the table. - * @param columns Column definitions (name,type) of the table. - * @param onFinish The (optional) callback function to call upon completion of the request. - * @param priority A priority level of the request. - * @param keepTracking Keep tracking the request before it finishes or fails. - * @param messenger An service for communications with workers. + * @param columns Column definitions (name,type) of the table. + * + * @see The very base class Request for the description of the common parameters + * of all subclasses. + * * @return A pointer to the created object. */ - static Ptr create(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& database, std::string const& table, - std::string const& engine, std::string const& partitionByColumn, - std::list const& columns, CallbackType const& onFinish, int priority, - bool keepTracking, std::shared_ptr const& messenger); + static Ptr createAndStart(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, std::string const& table, + std::string const& engine, std::string const& partitionByColumn, + std::list const& columns, CallbackType const& onFinish = nullptr, + int priority = PRIORITY_NORMAL, bool keepTracking = true, + std::string const& jobId = "", unsigned int requestExpirationIvalSec = 0); protected: - /// @see Request::notify() void notify(replica::Lock const& lock) final; private: - /// @see SqlCreateTableRequest::create() - SqlCreateTableRequest(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& database, std::string const& table, - std::string const& engine, std::string const& partitionByColumn, - std::list const& columns, CallbackType const& onFinish, int priority, - bool keepTracking, std::shared_ptr const& messenger); + SqlCreateTableRequest(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, std::string const& table, std::string const& engine, + std::string const& partitionByColumn, std::list const& columns, + CallbackType const& onFinish, int priority, bool keepTracking); CallbackType _onFinish; ///< @note is reset when the request finishes }; diff --git a/src/replica/requests/SqlCreateTablesRequest.cc b/src/replica/requests/SqlCreateTablesRequest.cc index 7eb936e8c..f15473582 100644 --- a/src/replica/requests/SqlCreateTablesRequest.cc +++ b/src/replica/requests/SqlCreateTablesRequest.cc @@ -22,40 +22,36 @@ // Class header #include "replica/requests/SqlCreateTablesRequest.h" -// Qserv headers -#include "replica/services/ServiceProvider.h" - // LSST headers #include "lsst/log/Log.h" using namespace std; namespace { - LOG_LOGGER _log = LOG_GET("lsst.qserv.replica.SqlCreateTablesRequest"); - +const uint64_t unlimitedMaxRows = 0; } // namespace namespace lsst::qserv::replica { -SqlCreateTablesRequest::Ptr SqlCreateTablesRequest::create( - ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - string const& worker, std::string const& database, std::vector const& tables, - std::string const& engine, string const& partitionByColumn, std::list const& columns, - CallbackType const& onFinish, int priority, bool keepTracking, - shared_ptr const& messenger) { - return Ptr(new SqlCreateTablesRequest(serviceProvider, io_service, worker, database, tables, engine, - partitionByColumn, columns, onFinish, priority, keepTracking, - messenger)); +SqlCreateTablesRequest::Ptr SqlCreateTablesRequest::createAndStart( + shared_ptr const& controller, string const& workerName, std::string const& database, + std::vector const& tables, std::string const& engine, string const& partitionByColumn, + std::list const& columns, CallbackType const& onFinish, int priority, bool keepTracking, + string const& jobId, unsigned int requestExpirationIvalSec) { + auto ptr = Ptr(new SqlCreateTablesRequest(controller, workerName, database, tables, engine, + partitionByColumn, columns, onFinish, priority, keepTracking)); + ptr->start(jobId, requestExpirationIvalSec); + return ptr; } -SqlCreateTablesRequest::SqlCreateTablesRequest( - ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - string const& worker, std::string const& database, std::vector const& tables, - std::string const& engine, string const& partitionByColumn, std::list const& columns, - CallbackType const& onFinish, int priority, bool keepTracking, shared_ptr const& messenger) - : SqlRequest(serviceProvider, io_service, "SQL_CREATE_TABLES", worker, 0, /* maxRows */ - priority, keepTracking, messenger), +SqlCreateTablesRequest::SqlCreateTablesRequest(shared_ptr const& controller, + string const& workerName, std::string const& database, + std::vector const& tables, + std::string const& engine, string const& partitionByColumn, + std::list const& columns, + CallbackType const& onFinish, int priority, bool keepTracking) + : SqlRequest(controller, "SQL_CREATE_TABLES", workerName, ::unlimitedMaxRows, priority, keepTracking), _onFinish(onFinish) { // Finish initializing the request body's content requestBody.set_type(ProtocolRequestSql::CREATE_TABLE); @@ -77,7 +73,6 @@ SqlCreateTablesRequest::SqlCreateTablesRequest( void SqlCreateTablesRequest::notify(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "[" << ProtocolRequestSql_Type_Name(requestBody.type()) << "]"); - notifyDefaultImpl(lock, _onFinish); } diff --git a/src/replica/requests/SqlCreateTablesRequest.h b/src/replica/requests/SqlCreateTablesRequest.h index db97aea6d..867e5621b 100644 --- a/src/replica/requests/SqlCreateTablesRequest.h +++ b/src/replica/requests/SqlCreateTablesRequest.h @@ -33,6 +33,11 @@ #include "replica/requests/SqlRequest.h" #include "replica/util/Common.h" +// Forward declarations +namespace lsst::qserv::replica { +class Controller; +} // namespace lsst::qserv::replica + // This header declarations namespace lsst::qserv::replica { @@ -63,43 +68,39 @@ class SqlCreateTablesRequest : public SqlRequest { * Static factory method is needed to prevent issue with the lifespan * and memory management of instances created otherwise (as values or via * low-level pointers). - * @param serviceProvider Is needed to access the Configuration and - * the Controller for communicating with the worker. - * @param io_service The BOOST ASIO communication end-point. - * @param worker An identifier of a worker node. + * + * Class-specific parameters are documented below: * @param database The name of an existing database where the new table will * be created. * @param tables The names of tables to be created. * @param engine The name of the MySQL engine for the new table. - * @param partitionByColumn (optional, if not empty) The name of a column which + * @param partitionByColumn The (optional, if not empty) name of a column which * will be used as a key to configure MySQL partitions for the new table. * This variation of table schema will be used for the super-transaction-based * ingest into the table. * @param columns Column definitions (name,type) of the table. - * @param onFinish (optional) A callback function to call upon completion of - * the request. - * @param priority A priority level of the request. - * @param keepTracking Keep tracking the request before it finishes or fails. - * @param messenger An interface for communicating with workers. + * + * @see The very base class Request for the description of the common parameters + * of all subclasses. + * * @return A pointer to the created object. */ - static Ptr create(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& database, - std::vector const& tables, std::string const& engine, - std::string const& partitionByColumn, std::list const& columns, - CallbackType const& onFinish, int priority, bool keepTracking, - std::shared_ptr const& messenger); + static Ptr createAndStart(std::shared_ptr const& controller, std::string const& worker, + std::string const& database, std::vector const& tables, + std::string const& engine, std::string const& partitionByColumn, + std::list const& columns, CallbackType const& onFinish = nullptr, + int priority = PRIORITY_NORMAL, bool keepTracking = true, + std::string const& jobId = "", unsigned int requestExpirationIvalSec = 0); protected: void notify(replica::Lock const& lock) final; private: - SqlCreateTablesRequest(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& database, - std::vector const& tables, std::string const& engine, - std::string const& partitionByColumn, std::list const& columns, - CallbackType const& onFinish, int priority, bool keepTracking, - std::shared_ptr const& messenger); + SqlCreateTablesRequest(std::shared_ptr const& controller, std::string const& worker, + std::string const& database, std::vector const& tables, + std::string const& engine, std::string const& partitionByColumn, + std::list const& columns, CallbackType const& onFinish, int priority, + bool keepTracking); CallbackType _onFinish; ///< @note is reset when the request finishes }; diff --git a/src/replica/requests/SqlDeleteDbRequest.cc b/src/replica/requests/SqlDeleteDbRequest.cc index 3d465866b..ad78766ce 100644 --- a/src/replica/requests/SqlDeleteDbRequest.cc +++ b/src/replica/requests/SqlDeleteDbRequest.cc @@ -22,38 +22,34 @@ // Class header #include "replica/requests/SqlDeleteDbRequest.h" -// Qserv headers -#include "replica/services/ServiceProvider.h" - // LSST headers #include "lsst/log/Log.h" using namespace std; namespace { - LOG_LOGGER _log = LOG_GET("lsst.qserv.replica.SqlDeleteDbRequest"); - +const uint64_t unlimitedMaxRows = 0; } // namespace namespace lsst::qserv::replica { -SqlDeleteDbRequest::Ptr SqlDeleteDbRequest::create(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, string const& worker, - std::string const& database, CallbackType const& onFinish, - int priority, bool keepTracking, - shared_ptr const& messenger) { - return Ptr(new SqlDeleteDbRequest(serviceProvider, io_service, worker, database, onFinish, priority, - keepTracking, messenger)); +SqlDeleteDbRequest::Ptr SqlDeleteDbRequest::createAndStart(shared_ptr const& controller, + string const& workerName, + std::string const& database, + CallbackType const& onFinish, int priority, + bool keepTracking, string const& jobId, + unsigned int requestExpirationIvalSec) { + auto ptr = + Ptr(new SqlDeleteDbRequest(controller, workerName, database, onFinish, priority, keepTracking)); + ptr->start(jobId, requestExpirationIvalSec); + return ptr; } -SqlDeleteDbRequest::SqlDeleteDbRequest(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, string const& worker, +SqlDeleteDbRequest::SqlDeleteDbRequest(shared_ptr const& controller, string const& workerName, std::string const& database, CallbackType const& onFinish, - int priority, bool keepTracking, - shared_ptr const& messenger) - : SqlRequest(serviceProvider, io_service, "SQL_DROP_DATABASE", worker, 0 /* maxRows */, priority, - keepTracking, messenger), + int priority, bool keepTracking) + : SqlRequest(controller, "SQL_DROP_DATABASE", workerName, ::unlimitedMaxRows, priority, keepTracking), _onFinish(onFinish) { // Finish initializing the request body's content requestBody.set_type(ProtocolRequestSql::DROP_DATABASE); @@ -63,7 +59,6 @@ SqlDeleteDbRequest::SqlDeleteDbRequest(ServiceProvider::Ptr const& serviceProvid void SqlDeleteDbRequest::notify(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "[" << ProtocolRequestSql_Type_Name(requestBody.type()) << "]"); - notifyDefaultImpl(lock, _onFinish); } diff --git a/src/replica/requests/SqlDeleteDbRequest.h b/src/replica/requests/SqlDeleteDbRequest.h index b3fb1e38c..c67ff4f69 100644 --- a/src/replica/requests/SqlDeleteDbRequest.h +++ b/src/replica/requests/SqlDeleteDbRequest.h @@ -29,6 +29,11 @@ // Qserv headers #include "replica/requests/SqlRequest.h" +// Forward declarations +namespace lsst::qserv::replica { +class Controller; +} // namespace lsst::qserv::replica + // This header declarations namespace lsst::qserv::replica { @@ -57,31 +62,27 @@ class SqlDeleteDbRequest : public SqlRequest { * Static factory method is needed to prevent issue with the lifespan * and memory management of instances created otherwise (as values or via * low-level pointers). - * @param serviceProvider Is needed to access the Configuration and - * the Controller for communicating with the worker. - * @param io_service The BOOST ASIO communication end-point. - * @param worker An identifier of a worker node. + * + * Class-specific parameters are documented below: * @param database The name of an existing database to be deleted. - * @param onFinish The (optional) callback function to call upon completion of - * the request. - * @param priority The priority level of the request. - * @param keepTracking Keep tracking the request before it finishes or fails. - * @param messenger An interface for communicating with workers. + * + * @see The very base class Request for the description of the common parameters + * of all subclasses. + * * @return A pointer to the created object. */ - static Ptr create(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& database, CallbackType const& onFinish, - int priority, bool keepTracking, std::shared_ptr const& messenger); + static Ptr createAndStart(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, CallbackType const& onFinish = nullptr, + int priority = PRIORITY_NORMAL, bool keepTracking = true, + std::string const& jobId = "", unsigned int requestExpirationIvalSec = 0); protected: - /// @see Request::notify() void notify(replica::Lock const& lock) final; private: - /// @see SqlDeleteDbRequest::create() - SqlDeleteDbRequest(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& database, CallbackType const& onFinish, - int priority, bool keepTracking, std::shared_ptr const& messenger); + SqlDeleteDbRequest(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, CallbackType const& onFinish, int priority, + bool keepTracking); CallbackType _onFinish; ///< @note is reset when the request finishes }; diff --git a/src/replica/requests/SqlDeleteTablePartitionRequest.cc b/src/replica/requests/SqlDeleteTablePartitionRequest.cc index 0ce60e159..74b0ad41e 100644 --- a/src/replica/requests/SqlDeleteTablePartitionRequest.cc +++ b/src/replica/requests/SqlDeleteTablePartitionRequest.cc @@ -22,39 +22,34 @@ // Class header #include "replica/requests/SqlDeleteTablePartitionRequest.h" -// Qserv headers -#include "replica/services/ServiceProvider.h" - // LSST headers #include "lsst/log/Log.h" using namespace std; namespace { - LOG_LOGGER _log = LOG_GET("lsst.qserv.replica.SqlDeleteTablePartitionRequest"); - +const uint64_t unlimitedMaxRows = 0; } // namespace namespace lsst::qserv::replica { -SqlDeleteTablePartitionRequest::Ptr SqlDeleteTablePartitionRequest::create( - ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - string const& worker, string const& database, vector const& tables, - TransactionId transactionId, CallbackType const& onFinish, int priority, bool keepTracking, - shared_ptr const& messenger) { - return Ptr(new SqlDeleteTablePartitionRequest(serviceProvider, io_service, worker, database, tables, - transactionId, onFinish, priority, keepTracking, - messenger)); +SqlDeleteTablePartitionRequest::Ptr SqlDeleteTablePartitionRequest::createAndStart( + shared_ptr const& controller, string const& workerName, string const& database, + vector const& tables, TransactionId transactionId, CallbackType const& onFinish, int priority, + bool keepTracking, string const& jobId, unsigned int requestExpirationIvalSec) { + auto ptr = Ptr(new SqlDeleteTablePartitionRequest(controller, workerName, database, tables, transactionId, + onFinish, priority, keepTracking)); + ptr->start(jobId, requestExpirationIvalSec); + return ptr; } SqlDeleteTablePartitionRequest::SqlDeleteTablePartitionRequest( - ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - string const& worker, string const& database, vector const& tables, - TransactionId transactionId, CallbackType const& onFinish, int priority, bool keepTracking, - shared_ptr const& messenger) - : SqlRequest(serviceProvider, io_service, "SQL_DROP_TABLE_PARTITION", worker, 0, /* maxRows */ - priority, keepTracking, messenger), + shared_ptr const& controller, string const& workerName, string const& database, + vector const& tables, TransactionId transactionId, CallbackType const& onFinish, int priority, + bool keepTracking) + : SqlRequest(controller, "SQL_DROP_TABLE_PARTITION", workerName, ::unlimitedMaxRows, priority, + keepTracking), _onFinish(onFinish) { // Finish initializing the request body's content requestBody.set_type(ProtocolRequestSql::DROP_TABLE_PARTITION); @@ -70,7 +65,6 @@ SqlDeleteTablePartitionRequest::SqlDeleteTablePartitionRequest( void SqlDeleteTablePartitionRequest::notify(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "[" << ProtocolRequestSql_Type_Name(requestBody.type()) << "]"); - notifyDefaultImpl(lock, _onFinish); } diff --git a/src/replica/requests/SqlDeleteTablePartitionRequest.h b/src/replica/requests/SqlDeleteTablePartitionRequest.h index 7cb1676e0..6eefa1606 100644 --- a/src/replica/requests/SqlDeleteTablePartitionRequest.h +++ b/src/replica/requests/SqlDeleteTablePartitionRequest.h @@ -32,6 +32,11 @@ #include "replica/requests/SqlRequest.h" #include "replica/util/Common.h" +// Forward declarations +namespace lsst::qserv::replica { +class Controller; +} // namespace lsst::qserv::replica + // This header declarations namespace lsst::qserv::replica { @@ -62,37 +67,32 @@ class SqlDeleteTablePartitionRequest : public SqlRequest { * and memory management of instances created otherwise (as values or via * low-level pointers). * - * @param serviceProvider is needed to access the Configuration and the Controller - * for communicating with the worker - * @param io_service a communication end-point - * @param worker identifier of a worker node - * @param database the name of an existing database where the table is residing - * @param tables a collection of tables (given by their names) affected by - * the operation - * @param transactionId a unique identifier of a transaction which corresponds + * Class-specific parameters are documented below: + * @param database The name of an existing database where the table is residing. + * @param tables A collection of tables (given by their names) affected by + * the operation. + * @param transactionId The unique identifier of a transaction which corresponds * to a MySQL partition to be removed. - * @param onFinish (optional) callback function to call upon completion of - * the request - * @param priority priority level of the request - * @param keepTracking keep tracking the request before it finishes or fails - * @param messenger interface for communicating with workers + * + * @see The very base class Request for the description of the common parameters + * of all subclasses. + * * @return pointer to the created object */ - static Ptr create(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& database, - std::vector const& tables, TransactionId transactionId, - CallbackType const& onFinish, int priority, bool keepTracking, - std::shared_ptr const& messenger); + static Ptr createAndStart(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, std::vector const& tables, + TransactionId transactionId, CallbackType const& onFinish = nullptr, + int priority = PRIORITY_NORMAL, bool keepTracking = true, + std::string const& jobId = "", unsigned int requestExpirationIvalSec = 0); protected: void notify(replica::Lock const& lock) final; private: - SqlDeleteTablePartitionRequest(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, std::string const& worker, - std::string const& database, std::vector const& tables, - TransactionId transactionId, CallbackType const& onFinish, int priority, - bool keepTracking, std::shared_ptr const& messenger); + SqlDeleteTablePartitionRequest(std::shared_ptr const& controller, + std::string const& workerName, std::string const& database, + std::vector const& tables, TransactionId transactionId, + CallbackType const& onFinish, int priority, bool keepTracking); CallbackType _onFinish; ///< @note is reset when the request finishes }; diff --git a/src/replica/requests/SqlDeleteTableRequest.cc b/src/replica/requests/SqlDeleteTableRequest.cc index 2fd4161d7..159099d94 100644 --- a/src/replica/requests/SqlDeleteTableRequest.cc +++ b/src/replica/requests/SqlDeleteTableRequest.cc @@ -22,40 +22,33 @@ // Class header #include "replica/requests/SqlDeleteTableRequest.h" -// Qserv headers -#include "replica/services/ServiceProvider.h" - // LSST headers #include "lsst/log/Log.h" using namespace std; namespace { - LOG_LOGGER _log = LOG_GET("lsst.qserv.replica.SqlDeleteTableRequest"); - +const uint64_t unlimitedMaxRows = 0; } // namespace namespace lsst::qserv::replica { -SqlDeleteTableRequest::Ptr SqlDeleteTableRequest::create(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, - string const& worker, string const& database, - vector const& tables, - CallbackType const& onFinish, int priority, - bool keepTracking, - shared_ptr const& messenger) { - return Ptr(new SqlDeleteTableRequest(serviceProvider, io_service, worker, database, tables, onFinish, - priority, keepTracking, messenger)); +SqlDeleteTableRequest::Ptr SqlDeleteTableRequest::createAndStart( + shared_ptr const& controller, string const& workerName, string const& database, + vector const& tables, CallbackType const& onFinish, int priority, bool keepTracking, + string const& jobId, unsigned int requestExpirationIvalSec) { + auto ptr = Ptr(new SqlDeleteTableRequest(controller, workerName, database, tables, onFinish, priority, + keepTracking)); + ptr->start(jobId, requestExpirationIvalSec); + return ptr; } -SqlDeleteTableRequest::SqlDeleteTableRequest(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, string const& worker, - string const& database, vector const& tables, - CallbackType const& onFinish, int priority, bool keepTracking, - shared_ptr const& messenger) - : SqlRequest(serviceProvider, io_service, "SQL_DROP_TABLE", worker, 0, /* maxRows */ - priority, keepTracking, messenger), +SqlDeleteTableRequest::SqlDeleteTableRequest(shared_ptr const& controller, + string const& workerName, string const& database, + vector const& tables, CallbackType const& onFinish, + int priority, bool keepTracking) + : SqlRequest(controller, "SQL_DROP_TABLE", workerName, ::unlimitedMaxRows, priority, keepTracking), _onFinish(onFinish) { // Finish initializing the request body's content requestBody.set_type(ProtocolRequestSql::DROP_TABLE); @@ -69,7 +62,6 @@ SqlDeleteTableRequest::SqlDeleteTableRequest(ServiceProvider::Ptr const& service void SqlDeleteTableRequest::notify(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "[" << ProtocolRequestSql_Type_Name(requestBody.type()) << "]"); - notifyDefaultImpl(lock, _onFinish); } diff --git a/src/replica/requests/SqlDeleteTableRequest.h b/src/replica/requests/SqlDeleteTableRequest.h index c80c12d32..6063862ec 100644 --- a/src/replica/requests/SqlDeleteTableRequest.h +++ b/src/replica/requests/SqlDeleteTableRequest.h @@ -30,6 +30,11 @@ // Qserv headers #include "replica/requests/SqlRequest.h" +// Forward declarations +namespace lsst::qserv::replica { +class Controller; +} // namespace lsst::qserv::replica + // This header declarations namespace lsst::qserv::replica { @@ -59,31 +64,28 @@ class SqlDeleteTableRequest : public SqlRequest { * and memory management of instances created otherwise (as values or via * low-level pointers). * - * @param serviceProvider is needed to access the Configuration and the Controller - * for communicating with the worker - * @param io_service a communication end-point - * @param worker identifier of a worker node - * @param database the name of an existing database where the table is residing - * @param tables the names of tables to be deleted - * @param onFinish (optional) callback function to call upon completion of the request - * @param priority priority level of the request - * @param keepTracking keep tracking the request before it finishes or fails - * @param messenger interface for communicating with workers + * Class-specific parameters are documented below: + * @param database The name of an existing database where the table is residing. + * @param tables The names of tables to be deleted. + * + * @see The very base class Request for the description of the common parameters + * of all subclasses. + * * @return a pointer to the created object */ - static Ptr create(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& database, - std::vector const& tables, CallbackType const& onFinish, int priority, - bool keepTracking, std::shared_ptr const& messenger); + static Ptr createAndStart(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, std::vector const& tables, + CallbackType const& onFinish = nullptr, int priority = PRIORITY_NORMAL, + bool keepTracking = true, std::string const& jobId = "", + unsigned int requestExpirationIvalSec = 0); protected: void notify(replica::Lock const& lock) final; private: - SqlDeleteTableRequest(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& database, - std::vector const& tables, CallbackType const& onFinish, int priority, - bool keepTracking, std::shared_ptr const& messenger); + SqlDeleteTableRequest(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, std::vector const& tables, + CallbackType const& onFinish, int priority, bool keepTracking); CallbackType _onFinish; ///< @note is reset when the request finishes }; diff --git a/src/replica/requests/SqlDisableDbRequest.cc b/src/replica/requests/SqlDisableDbRequest.cc index 152c8159d..c08ee9145 100644 --- a/src/replica/requests/SqlDisableDbRequest.cc +++ b/src/replica/requests/SqlDisableDbRequest.cc @@ -22,39 +22,35 @@ // Class header #include "replica/requests/SqlDisableDbRequest.h" -// Qserv headers -#include "replica/services/ServiceProvider.h" - // LSST headers #include "lsst/log/Log.h" using namespace std; namespace { - LOG_LOGGER _log = LOG_GET("lsst.qserv.replica.SqlDisableDbRequest"); - +const uint64_t unlimitedMaxRows = 0; } // namespace namespace lsst::qserv::replica { -SqlDisableDbRequest::Ptr SqlDisableDbRequest::create(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, - string const& worker, std::string const& database, - CallbackType const& onFinish, int priority, - bool keepTracking, - shared_ptr const& messenger) { - return Ptr(new SqlDisableDbRequest(serviceProvider, io_service, worker, database, onFinish, priority, - keepTracking, messenger)); +SqlDisableDbRequest::Ptr SqlDisableDbRequest::createAndStart(shared_ptr const& controller, + string const& workerName, + std::string const& database, + CallbackType const& onFinish, int priority, + bool keepTracking, string const& jobId, + unsigned int requestExpirationIvalSec) { + auto ptr = + Ptr(new SqlDisableDbRequest(controller, workerName, database, onFinish, priority, keepTracking)); + ptr->start(jobId, requestExpirationIvalSec); + return ptr; } -SqlDisableDbRequest::SqlDisableDbRequest(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, string const& worker, +SqlDisableDbRequest::SqlDisableDbRequest(shared_ptr const& controller, string const& workerName, std::string const& database, CallbackType const& onFinish, - int priority, bool keepTracking, - shared_ptr const& messenger) - : SqlRequest(serviceProvider, io_service, "SQL_DISABLE_DATABASE", worker, 0 /* maxRows */, priority, - keepTracking, messenger), + int priority, bool keepTracking) + : SqlRequest(controller, "SQL_DISABLE_DATABASE", workerName, ::unlimitedMaxRows, priority, + keepTracking), _onFinish(onFinish) { // Finish initializing the request body's content requestBody.set_type(ProtocolRequestSql::DISABLE_DATABASE); @@ -64,7 +60,6 @@ SqlDisableDbRequest::SqlDisableDbRequest(ServiceProvider::Ptr const& serviceProv void SqlDisableDbRequest::notify(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "[" << ProtocolRequestSql_Type_Name(requestBody.type()) << "]"); - notifyDefaultImpl(lock, _onFinish); } diff --git a/src/replica/requests/SqlDisableDbRequest.h b/src/replica/requests/SqlDisableDbRequest.h index c8e87b533..56a7abe71 100644 --- a/src/replica/requests/SqlDisableDbRequest.h +++ b/src/replica/requests/SqlDisableDbRequest.h @@ -29,6 +29,11 @@ // Qserv headers #include "replica/requests/SqlRequest.h" +// Forward declarations +namespace lsst::qserv::replica { +class Controller; +} // namespace lsst::qserv::replica + // This header declarations namespace lsst::qserv::replica { @@ -57,31 +62,27 @@ class SqlDisableDbRequest : public SqlRequest { * Static factory method is needed to prevent issue with the lifespan * and memory management of instances created otherwise (as values or via * low-level pointers). - * @param serviceProvider Is needed to access the Configuration and - * the Controller for communicating with the worker. - * @param io_service The BOOST ASIO communication end-point. - * @param worker An identifier of a worker node. + * + * Class-specific parameters are documented below: * @param database The name of an existing database to be disabled. - * @param onFinish The (optional) callback function to call upon completion of - * the request. - * @param priority The priority level of the request. - * @param keepTracking Keep tracking the request before it finishes or fails. - * @param messenger An interface for communicating with workers. + * + * @see The very base class Request for the description of the common parameters + * of all subclasses. + * * @return A pointer to the created object. */ - static Ptr create(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& database, CallbackType const& onFinish, - int priority, bool keepTracking, std::shared_ptr const& messenger); + static Ptr createAndStart(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, CallbackType const& onFinish = nullptr, + int priority = PRIORITY_NORMAL, bool keepTracking = true, + std::string const& jobId = "", unsigned int requestExpirationIvalSec = 0); protected: - /// @see Request::notify() void notify(replica::Lock const& lock) final; private: - /// @see SqlDisableDbRequest::create() - SqlDisableDbRequest(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& database, CallbackType const& onFinish, - int priority, bool keepTracking, std::shared_ptr const& messenger); + SqlDisableDbRequest(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, CallbackType const& onFinish, int priority, + bool keepTracking); CallbackType _onFinish; ///< @note is reset when the request finishes }; diff --git a/src/replica/requests/SqlDropIndexesRequest.cc b/src/replica/requests/SqlDropIndexesRequest.cc index edc6ba791..e37bc496d 100644 --- a/src/replica/requests/SqlDropIndexesRequest.cc +++ b/src/replica/requests/SqlDropIndexesRequest.cc @@ -22,39 +22,34 @@ // Class header #include "replica/requests/SqlDropIndexesRequest.h" -// Qserv headers -#include "replica/services/ServiceProvider.h" - // LSST headers #include "lsst/log/Log.h" using namespace std; namespace { - LOG_LOGGER _log = LOG_GET("lsst.qserv.replica.SqlDropIndexesRequest"); - +const uint64_t unlimitedMaxRows = 0; } // namespace namespace lsst::qserv::replica { -SqlDropIndexesRequest::Ptr SqlDropIndexesRequest::create( - ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - string const& worker, string const& database, vector const& tables, string const& indexName, - CallbackType const& onFinish, int priority, bool keepTracking, - shared_ptr const& messenger) { - return Ptr(new SqlDropIndexesRequest(serviceProvider, io_service, worker, database, tables, indexName, - onFinish, priority, keepTracking, messenger)); +SqlDropIndexesRequest::Ptr SqlDropIndexesRequest::createAndStart( + shared_ptr const& controller, string const& workerName, string const& database, + vector const& tables, string const& indexName, CallbackType const& onFinish, int priority, + bool keepTracking, string const& jobId, unsigned int requestExpirationIvalSec) { + auto ptr = Ptr(new SqlDropIndexesRequest(controller, workerName, database, tables, indexName, onFinish, + priority, keepTracking)); + ptr->start(jobId, requestExpirationIvalSec); + return ptr; } -SqlDropIndexesRequest::SqlDropIndexesRequest(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, string const& worker, - string const& database, vector const& tables, - string const& indexName, CallbackType const& onFinish, - int priority, bool keepTracking, - shared_ptr const& messenger) - : SqlRequest(serviceProvider, io_service, "SQL_DROP_TABLE_INDEXES", worker, 0, /* maxRows */ - priority, keepTracking, messenger), +SqlDropIndexesRequest::SqlDropIndexesRequest(shared_ptr const& controller, + string const& workerName, string const& database, + vector const& tables, string const& indexName, + CallbackType const& onFinish, int priority, bool keepTracking) + : SqlRequest(controller, "SQL_DROP_TABLE_INDEXES", workerName, ::unlimitedMaxRows, priority, + keepTracking), _onFinish(onFinish) { // Finish initializing the request body's content requestBody.set_type(ProtocolRequestSql::DROP_TABLE_INDEX); @@ -70,7 +65,6 @@ SqlDropIndexesRequest::SqlDropIndexesRequest(ServiceProvider::Ptr const& service void SqlDropIndexesRequest::notify(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "[" << ProtocolRequestSql_Type_Name(requestBody.type()) << "]"); - notifyDefaultImpl(lock, _onFinish); } diff --git a/src/replica/requests/SqlDropIndexesRequest.h b/src/replica/requests/SqlDropIndexesRequest.h index 435c29389..580863488 100644 --- a/src/replica/requests/SqlDropIndexesRequest.h +++ b/src/replica/requests/SqlDropIndexesRequest.h @@ -33,6 +33,11 @@ #include "replica/requests/SqlRequest.h" #include "replica/util/Common.h" +// Forward declarations +namespace lsst::qserv::replica { +class Controller; +} // namespace lsst::qserv::replica + // This header declarations namespace lsst::qserv::replica { @@ -60,36 +65,30 @@ class SqlDropIndexesRequest : public SqlRequest { * and memory management of instances created otherwise (as values or via * low-level pointers). * - * @param serviceProvider Is needed to access the Configuration and - * the Controller for communicating with the worker. - * @param io_service The BOOST ASIO communication end-point. - * @param worker An identifier of a worker node. + * Class-specific parameters are documented below: * @param database The name of an existing database where the tables are residing. * @param tables The names of tables affected by the operation. * @param indexName The name of the index. - * @param onFinish (optional) A callback function to call upon completion of - * the request. - * @param priority A priority level of the request. - * @param keepTracking Keep tracking the request before it finishes or fails. - * @param messenger An interface for communicating with workers. + * + * @see The very base class Request for the description of the common parameters + * of all subclasses. * * @return A pointer to the created object. */ - static Ptr create(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& database, - std::vector const& tables, std::string const& indexName, - CallbackType const& onFinish, int priority, bool keepTracking, - std::shared_ptr const& messenger); + static Ptr createAndStart(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, std::vector const& tables, + std::string const& indexName, CallbackType const& onFinish = nullptr, + int priority = PRIORITY_NORMAL, bool keepTracking = true, + std::string const& jobId = "", unsigned int requestExpirationIvalSec = 0); protected: void notify(replica::Lock const& lock) final; private: - SqlDropIndexesRequest(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& database, - std::vector const& tables, std::string const& indexName, - CallbackType const& onFinish, int priority, bool keepTracking, - std::shared_ptr const& messenger); + SqlDropIndexesRequest(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, std::vector const& tables, + std::string const& indexName, CallbackType const& onFinish, int priority, + bool keepTracking); CallbackType _onFinish; ///< @note is reset when the request finishes }; diff --git a/src/replica/requests/SqlEnableDbRequest.cc b/src/replica/requests/SqlEnableDbRequest.cc index 061895e28..5cbe20b8d 100644 --- a/src/replica/requests/SqlEnableDbRequest.cc +++ b/src/replica/requests/SqlEnableDbRequest.cc @@ -22,38 +22,35 @@ // Class header #include "replica/requests/SqlEnableDbRequest.h" -// Qserv headers -#include "replica/services/ServiceProvider.h" - // LSST headers #include "lsst/log/Log.h" using namespace std; namespace { - LOG_LOGGER _log = LOG_GET("lsst.qserv.replica.SqlEnableDbRequest"); - +const uint64_t unlimitedMaxRows = 0; } // namespace namespace lsst::qserv::replica { -SqlEnableDbRequest::Ptr SqlEnableDbRequest::create(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, string const& worker, - std::string const& database, CallbackType const& onFinish, - int priority, bool keepTracking, - shared_ptr const& messenger) { - return Ptr(new SqlEnableDbRequest(serviceProvider, io_service, worker, database, onFinish, priority, - keepTracking, messenger)); +SqlEnableDbRequest::Ptr SqlEnableDbRequest::createAndStart(shared_ptr const& controller, + string const& workerName, + std::string const& database, + CallbackType const& onFinish, int priority, + bool keepTracking, string const& jobId, + unsigned int requestExpirationIvalSec) { + auto ptr = + Ptr(new SqlEnableDbRequest(controller, workerName, database, onFinish, priority, keepTracking)); + ptr->start(jobId, requestExpirationIvalSec); + return ptr; } -SqlEnableDbRequest::SqlEnableDbRequest(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, string const& worker, +SqlEnableDbRequest::SqlEnableDbRequest(shared_ptr const& controller, string const& workerName, std::string const& database, CallbackType const& onFinish, - int priority, bool keepTracking, - shared_ptr const& messenger) - : SqlRequest(serviceProvider, io_service, "SQL_ENABLE_DATABASE", worker, 0 /* maxRows */, priority, - keepTracking, messenger), + int priority, bool keepTracking) + : SqlRequest(controller, "SQL_ENABLE_DATABASE", workerName, ::unlimitedMaxRows, priority, + keepTracking), _onFinish(onFinish) { // Finish initializing the request body's content requestBody.set_type(ProtocolRequestSql::ENABLE_DATABASE); @@ -63,7 +60,6 @@ SqlEnableDbRequest::SqlEnableDbRequest(ServiceProvider::Ptr const& serviceProvid void SqlEnableDbRequest::notify(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "[" << ProtocolRequestSql_Type_Name(requestBody.type()) << "]"); - notifyDefaultImpl(lock, _onFinish); } diff --git a/src/replica/requests/SqlEnableDbRequest.h b/src/replica/requests/SqlEnableDbRequest.h index 541c8833d..446a1c4d8 100644 --- a/src/replica/requests/SqlEnableDbRequest.h +++ b/src/replica/requests/SqlEnableDbRequest.h @@ -29,6 +29,11 @@ // Qserv headers #include "replica/requests/SqlRequest.h" +// Forward declarations +namespace lsst::qserv::replica { +class Controller; +} // namespace lsst::qserv::replica + // This header declarations namespace lsst::qserv::replica { @@ -57,31 +62,27 @@ class SqlEnableDbRequest : public SqlRequest { * Static factory method is needed to prevent issue with the lifespan * and memory management of instances created otherwise (as values or via * low-level pointers). - * @param serviceProvider Is needed to access the Configuration and - * the Controller for communicating with the worker. - * @param io_service The BOOST ASIO communication end-point. - * @param worker An identifier of a worker node. + * + * Class-specific parameters are documented below: * @param database The name of an existing database to be enabled. - * @param onFinish The (optional) callback function to call upon completion of - * the request. - * @param priority The priority level of the request. - * @param keepTracking Keep tracking the request before it finishes or fails. - * @param messenger An interface for communicating with workers. + * + * @see The very base class Request for the description of the common parameters + * of all subclasses. + * * @return A pointer to the created object. */ - static Ptr create(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& database, CallbackType const& onFinish, - int priority, bool keepTracking, std::shared_ptr const& messenger); + static Ptr createAndStart(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, CallbackType const& onFinish = nullptr, + int priority = PRIORITY_NORMAL, bool keepTracking = true, + std::string const& jobId = "", unsigned int requestExpirationIvalSec = 0); protected: - /// @see Request::notify() void notify(replica::Lock const& lock) final; private: - /// @see SqlEnableDbRequest::create() - SqlEnableDbRequest(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& database, CallbackType const& onFinish, - int priority, bool keepTracking, std::shared_ptr const& messenger); + SqlEnableDbRequest(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, CallbackType const& onFinish, int priority, + bool keepTracking); CallbackType _onFinish; ///< @note is reset when the request finishes }; diff --git a/src/replica/requests/SqlGetIndexesRequest.cc b/src/replica/requests/SqlGetIndexesRequest.cc index 061e8fdd5..9eea59ed1 100644 --- a/src/replica/requests/SqlGetIndexesRequest.cc +++ b/src/replica/requests/SqlGetIndexesRequest.cc @@ -22,40 +22,33 @@ // Class header #include "replica/requests/SqlGetIndexesRequest.h" -// Qserv headers -#include "replica/services/ServiceProvider.h" - // LSST headers #include "lsst/log/Log.h" using namespace std; namespace { - LOG_LOGGER _log = LOG_GET("lsst.qserv.replica.SqlGetIndexesRequest"); - +const uint64_t unlimitedMaxRows = 0; } // namespace namespace lsst::qserv::replica { -SqlGetIndexesRequest::Ptr SqlGetIndexesRequest::create(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, - string const& worker, string const& database, - vector const& tables, - CallbackType const& onFinish, int priority, - bool keepTracking, - shared_ptr const& messenger) { - return Ptr(new SqlGetIndexesRequest(serviceProvider, io_service, worker, database, tables, onFinish, - priority, keepTracking, messenger)); +SqlGetIndexesRequest::Ptr SqlGetIndexesRequest::createAndStart( + shared_ptr const& controller, string const& workerName, string const& database, + vector const& tables, CallbackType const& onFinish, int priority, bool keepTracking, + string const& jobId, unsigned int requestExpirationIvalSec) { + auto ptr = Ptr(new SqlGetIndexesRequest(controller, workerName, database, tables, onFinish, priority, + keepTracking)); + ptr->start(jobId, requestExpirationIvalSec); + return ptr; } -SqlGetIndexesRequest::SqlGetIndexesRequest(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, string const& worker, +SqlGetIndexesRequest::SqlGetIndexesRequest(shared_ptr const& controller, string const& workerName, string const& database, vector const& tables, - CallbackType const& onFinish, int priority, bool keepTracking, - shared_ptr const& messenger) - : SqlRequest(serviceProvider, io_service, "SQL_GET_TABLE_INDEXES", worker, 0, /* maxRows */ - priority, keepTracking, messenger), + CallbackType const& onFinish, int priority, bool keepTracking) + : SqlRequest(controller, "SQL_GET_TABLE_INDEXES", workerName, ::unlimitedMaxRows, priority, + keepTracking), _onFinish(onFinish) { // Finish initializing the request body's content requestBody.set_type(ProtocolRequestSql::GET_TABLE_INDEX); @@ -70,7 +63,6 @@ SqlGetIndexesRequest::SqlGetIndexesRequest(ServiceProvider::Ptr const& servicePr void SqlGetIndexesRequest::notify(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "[" << ProtocolRequestSql_Type_Name(requestBody.type()) << "]"); - notifyDefaultImpl(lock, _onFinish); } diff --git a/src/replica/requests/SqlGetIndexesRequest.h b/src/replica/requests/SqlGetIndexesRequest.h index 836e1375d..a141831e5 100644 --- a/src/replica/requests/SqlGetIndexesRequest.h +++ b/src/replica/requests/SqlGetIndexesRequest.h @@ -33,6 +33,11 @@ #include "replica/requests/SqlRequest.h" #include "replica/util/Common.h" +// Forward declarations +namespace lsst::qserv::replica { +class Controller; +} // namespace lsst::qserv::replica + // This header declarations namespace lsst::qserv::replica { @@ -60,33 +65,28 @@ class SqlGetIndexesRequest : public SqlRequest { * and memory management of instances created otherwise (as values or via * low-level pointers). * - * @param serviceProvider Is needed to access the Configuration and - * the Controller for communicating with the worker. - * @param io_service The BOOST ASIO communication end-point. - * @param worker An identifier of a worker node. + * Class-specific parameters are documented below: * @param database The name of an existing database where the tables are residing. * @param tables The names of tables affected by the operation. - * @param onFinish (optional) A callback function to call upon completion of - * the request. - * @param priority A priority level of the request. - * @param keepTracking Keep tracking the request before it finishes or fails. - * @param messenger An interface for communicating with workers. + * + * @see The very base class Request for the description of the common parameters + * of all subclasses. * * @return A pointer to the created object. */ - static Ptr create(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& database, - std::vector const& tables, CallbackType const& onFinish, int priority, - bool keepTracking, std::shared_ptr const& messenger); + static Ptr createAndStart(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, std::vector const& tables, + CallbackType const& onFinish = nullptr, int priority = PRIORITY_NORMAL, + bool keepTracking = true, std::string const& jobId = "", + unsigned int requestExpirationIvalSec = 0); protected: void notify(replica::Lock const& lock) final; private: - SqlGetIndexesRequest(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& database, - std::vector const& tables, CallbackType const& onFinish, int priority, - bool keepTracking, std::shared_ptr const& messenger); + SqlGetIndexesRequest(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, std::vector const& tables, + CallbackType const& onFinish, int priority, bool keepTracking); CallbackType _onFinish; ///< @note is reset when the request finishes }; diff --git a/src/replica/requests/SqlGrantAccessRequest.cc b/src/replica/requests/SqlGrantAccessRequest.cc index a0e99c774..0cc2f5100 100644 --- a/src/replica/requests/SqlGrantAccessRequest.cc +++ b/src/replica/requests/SqlGrantAccessRequest.cc @@ -22,40 +22,33 @@ // Class header #include "replica/requests/SqlGrantAccessRequest.h" -// Qserv headers -#include "replica/services/ServiceProvider.h" - // LSST headers #include "lsst/log/Log.h" using namespace std; namespace { - LOG_LOGGER _log = LOG_GET("lsst.qserv.replica.SqlGrantAccessRequest"); - +const uint64_t unlimitedMaxRows = 0; } // namespace namespace lsst::qserv::replica { -SqlGrantAccessRequest::Ptr SqlGrantAccessRequest::create(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, - string const& worker, std::string const& database, - std::string const& user, - CallbackType const& onFinish, int priority, - bool keepTracking, - shared_ptr const& messenger) { - return Ptr(new SqlGrantAccessRequest(serviceProvider, io_service, worker, database, user, onFinish, - priority, keepTracking, messenger)); +SqlGrantAccessRequest::Ptr SqlGrantAccessRequest::createAndStart( + shared_ptr const& controller, string const& workerName, std::string const& database, + std::string const& user, CallbackType const& onFinish, int priority, bool keepTracking, + string const& jobId, unsigned int requestExpirationIvalSec) { + auto ptr = Ptr(new SqlGrantAccessRequest(controller, workerName, database, user, onFinish, priority, + keepTracking)); + ptr->start(jobId, requestExpirationIvalSec); + return ptr; } -SqlGrantAccessRequest::SqlGrantAccessRequest(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, string const& worker, - std::string const& database, std::string const& user, - CallbackType const& onFinish, int priority, bool keepTracking, - shared_ptr const& messenger) - : SqlRequest(serviceProvider, io_service, "SQL_GRANT_ACCESS", worker, 0 /* maxRows */, priority, - keepTracking, messenger), +SqlGrantAccessRequest::SqlGrantAccessRequest(shared_ptr const& controller, + string const& workerName, std::string const& database, + std::string const& user, CallbackType const& onFinish, + int priority, bool keepTracking) + : SqlRequest(controller, "SQL_GRANT_ACCESS", workerName, ::unlimitedMaxRows, priority, keepTracking), _onFinish(onFinish) { // Finish initializing the request body's content requestBody.set_type(ProtocolRequestSql::GRANT_ACCESS); @@ -66,7 +59,6 @@ SqlGrantAccessRequest::SqlGrantAccessRequest(ServiceProvider::Ptr const& service void SqlGrantAccessRequest::notify(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "[" << ProtocolRequestSql_Type_Name(requestBody.type()) << "]"); - notifyDefaultImpl(lock, _onFinish); } diff --git a/src/replica/requests/SqlGrantAccessRequest.h b/src/replica/requests/SqlGrantAccessRequest.h index 8a64d3b92..0068efa7f 100644 --- a/src/replica/requests/SqlGrantAccessRequest.h +++ b/src/replica/requests/SqlGrantAccessRequest.h @@ -29,6 +29,11 @@ // Qserv headers #include "replica/requests/SqlRequest.h" +// Forward declarations +namespace lsst::qserv::replica { +class Controller; +} // namespace lsst::qserv::replica + // This header declarations namespace lsst::qserv::replica { @@ -58,34 +63,29 @@ class SqlGrantAccessRequest : public SqlRequest { * Static factory method is needed to prevent issue with the lifespan * and memory management of instances created otherwise (as values or via * low-level pointers). - * @param serviceProvider Is needed to access the Configuration and - * the Controller for communicating with the worker. - * @param io_service The BOOST ASIO communication end-point. - * @param worker An identifier of a worker node. + * + * Class-specific parameters are documented below: * @param database The name of an existing database. * @param user The name of an existing database account to be affected by the operation. - * @param onFinish The (optional) callback function to call upon completion of - * the request. - * @param priority The priority level of the request. - * @param keepTracking Keep tracking the request before it finishes or fails. - * @param messenger An interface for communicating with workers. + * + * @see The very base class Request for the description of the common parameters + * of all subclasses. + * * @return A pointer to the created object. */ - static Ptr create(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& database, std::string const& user, - CallbackType const& onFinish, int priority, bool keepTracking, - std::shared_ptr const& messenger); + static Ptr createAndStart(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, std::string const& user, + CallbackType const& onFinish = nullptr, int priority = PRIORITY_NORMAL, + bool keepTracking = true, std::string const& jobId = "", + unsigned int requestExpirationIvalSec = 0); protected: - /// @see Request::notify() void notify(replica::Lock const& lock) final; private: - /// @see SqlGrantAccessRequest::create() - SqlGrantAccessRequest(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& database, std::string const& user, - CallbackType const& onFinish, int priority, bool keepTracking, - std::shared_ptr const& messenger); + SqlGrantAccessRequest(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, std::string const& user, CallbackType const& onFinish, + int priority, bool keepTracking); CallbackType _onFinish; ///< @note is reset when the request finishes }; diff --git a/src/replica/requests/SqlQueryRequest.cc b/src/replica/requests/SqlQueryRequest.cc index fabde8fe1..e62e4a91d 100644 --- a/src/replica/requests/SqlQueryRequest.cc +++ b/src/replica/requests/SqlQueryRequest.cc @@ -22,9 +22,6 @@ // Class header #include "replica/requests/SqlQueryRequest.h" -// Qserv headers -#include "replica/services/ServiceProvider.h" - // LSST headers #include "lsst/log/Log.h" @@ -38,23 +35,23 @@ LOG_LOGGER _log = LOG_GET("lsst.qserv.replica.SqlQueryRequest"); namespace lsst::qserv::replica { -SqlQueryRequest::Ptr SqlQueryRequest::create(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, string const& worker, - std::string const& query, std::string const& user, - std::string const& password, uint64_t maxRows, - CallbackType const& onFinish, int priority, bool keepTracking, - shared_ptr const& messenger) { - return Ptr(new SqlQueryRequest(serviceProvider, io_service, worker, query, user, password, maxRows, - onFinish, priority, keepTracking, messenger)); +SqlQueryRequest::Ptr SqlQueryRequest::createAndStart(shared_ptr const& controller, + string const& workerName, std::string const& query, + std::string const& user, std::string const& password, + uint64_t maxRows, CallbackType const& onFinish, + int priority, bool keepTracking, string const& jobId, + unsigned int requestExpirationIvalSec) { + auto ptr = Ptr(new SqlQueryRequest(controller, workerName, query, user, password, maxRows, onFinish, + priority, keepTracking)); + ptr->start(jobId, requestExpirationIvalSec); + return ptr; } -SqlQueryRequest::SqlQueryRequest(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, string const& worker, +SqlQueryRequest::SqlQueryRequest(shared_ptr const& controller, string const& workerName, std::string const& query, std::string const& user, std::string const& password, uint64_t maxRows, CallbackType const& onFinish, - int priority, bool keepTracking, shared_ptr const& messenger) - : SqlRequest(serviceProvider, io_service, "SQL_QUERY", worker, maxRows, priority, keepTracking, - messenger), + int priority, bool keepTracking) + : SqlRequest(controller, "SQL_QUERY", workerName, maxRows, priority, keepTracking), _onFinish(onFinish) { // Finish initializing the request body's content requestBody.set_type(ProtocolRequestSql::QUERY); @@ -66,7 +63,6 @@ SqlQueryRequest::SqlQueryRequest(ServiceProvider::Ptr const& serviceProvider, void SqlQueryRequest::notify(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "[" << ProtocolRequestSql_Type_Name(requestBody.type()) << "]"); - notifyDefaultImpl(lock, _onFinish); } diff --git a/src/replica/requests/SqlQueryRequest.h b/src/replica/requests/SqlQueryRequest.h index dfc34223e..a96b3803e 100644 --- a/src/replica/requests/SqlQueryRequest.h +++ b/src/replica/requests/SqlQueryRequest.h @@ -30,6 +30,11 @@ // Qserv headers #include "replica/requests/SqlRequest.h" +// Forward declarations +namespace lsst::qserv::replica { +class Controller; +} // namespace lsst::qserv::replica + // This header declarations namespace lsst::qserv::replica { @@ -60,40 +65,35 @@ class SqlQueryRequest : public SqlRequest { * Static factory method is needed to prevent issue with the lifespan * and memory management of instances created otherwise (as values or via * low-level pointers). - * @param serviceProvider Is needed to access the Configuration and - * the Controller for communicating with the worker. - * @param io_service The BOOST ASIO communication end-point. - * @param worker An identifier of a worker node. + * + * Class-specific parameters are documented below: * @param query The query to be executed. - * @param user The name of a database account for connecting to the database service. + * @param user The name of a database account for connecting to the database service. * @param password The database account password for connecting to the database service. - * @param maxRows The (optional) limit for the maximum number of rows to be returned with - * the request. Leaving the default value of the parameter to 0 will result in not imposing + * @param maxRows The limit for the maximum number of rows to be returned with + * the request. Setting a value of the parameter to 0 will result in not imposing * any explicit restrictions on a size of the result set. Note that other, resource-defined * restrictions will still apply. The later includes the maximum size of the Google Protobuf * objects, the amount of available memory, etc. - * @param onFinish The (optional) callback function to call upon completion of - * the request. - * @param priority The priority level of the request. - * @param keepTracking Keep tracking the request before it finishes or fails. - * @param messenger An interface for communicating with workers. + * + * @see The very base class Request for the description of the common parameters + * of all subclasses. + * * @return A pointer to the created object. */ - static Ptr create(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& query, std::string const& user, - std::string const& password, uint64_t maxRows, CallbackType const& onFinish, - int priority, bool keepTracking, std::shared_ptr const& messenger); + static Ptr createAndStart(std::shared_ptr const& controller, std::string const& workerName, + std::string const& query, std::string const& user, std::string const& password, + uint64_t maxRows, CallbackType const& onFinish = nullptr, + int priority = PRIORITY_NORMAL, bool keepTracking = true, + std::string const& jobId = "", unsigned int requestExpirationIvalSec = 0); protected: - /// @see Request::notify() void notify(replica::Lock const& lock) final; private: - /// @see SqlQueryRequest::create() - SqlQueryRequest(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& query, std::string const& user, - std::string const& password, uint64_t maxRows, CallbackType const& onFinish, int priority, - bool keepTracking, std::shared_ptr const& messenger); + SqlQueryRequest(std::shared_ptr const& controller, std::string const& workerName, + std::string const& query, std::string const& user, std::string const& password, + uint64_t maxRows, CallbackType const& onFinish, int priority, bool keepTracking); CallbackType _onFinish; ///< @note is reset when the request finishes }; diff --git a/src/replica/requests/SqlRemoveTablePartitionsRequest.cc b/src/replica/requests/SqlRemoveTablePartitionsRequest.cc index 2397d3adf..b0fb00dc1 100644 --- a/src/replica/requests/SqlRemoveTablePartitionsRequest.cc +++ b/src/replica/requests/SqlRemoveTablePartitionsRequest.cc @@ -22,37 +22,33 @@ // Class header #include "replica/requests/SqlRemoveTablePartitionsRequest.h" -// Qserv headers -#include "replica/services/ServiceProvider.h" - // LSST headers #include "lsst/log/Log.h" using namespace std; namespace { - LOG_LOGGER _log = LOG_GET("lsst.qserv.replica.SqlRemoveTablePartitionsRequest"); - +const uint64_t unlimitedMaxRows = 0; } // namespace namespace lsst::qserv::replica { -SqlRemoveTablePartitionsRequest::Ptr SqlRemoveTablePartitionsRequest::create( - ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - string const& worker, string const& database, vector const& tables, - CallbackType const& onFinish, int priority, bool keepTracking, - shared_ptr const& messenger) { - return Ptr(new SqlRemoveTablePartitionsRequest(serviceProvider, io_service, worker, database, tables, - onFinish, priority, keepTracking, messenger)); +SqlRemoveTablePartitionsRequest::Ptr SqlRemoveTablePartitionsRequest::createAndStart( + shared_ptr const& controller, string const& workerName, string const& database, + vector const& tables, CallbackType const& onFinish, int priority, bool keepTracking, + string const& jobId, unsigned int requestExpirationIvalSec) { + auto ptr = Ptr(new SqlRemoveTablePartitionsRequest(controller, workerName, database, tables, onFinish, + priority, keepTracking)); + ptr->start(jobId, requestExpirationIvalSec); + return ptr; } SqlRemoveTablePartitionsRequest::SqlRemoveTablePartitionsRequest( - ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - string const& worker, string const& database, vector const& tables, - CallbackType const& onFinish, int priority, bool keepTracking, shared_ptr const& messenger) - : SqlRequest(serviceProvider, io_service, "SQL_REMOVE_TABLE_PARTITIONING", worker, 0, /* maxRows */ - priority, keepTracking, messenger), + shared_ptr const& controller, string const& workerName, string const& database, + vector const& tables, CallbackType const& onFinish, int priority, bool keepTracking) + : SqlRequest(controller, "SQL_REMOVE_TABLE_PARTITIONING", workerName, ::unlimitedMaxRows, priority, + keepTracking), _onFinish(onFinish) { // Finish initializing the request body's content requestBody.set_type(ProtocolRequestSql::REMOVE_TABLE_PARTITIONING); @@ -67,7 +63,6 @@ SqlRemoveTablePartitionsRequest::SqlRemoveTablePartitionsRequest( void SqlRemoveTablePartitionsRequest::notify(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << "[" << ProtocolRequestSql_Type_Name(requestBody.type()) << "]"); - notifyDefaultImpl(lock, _onFinish); } diff --git a/src/replica/requests/SqlRemoveTablePartitionsRequest.h b/src/replica/requests/SqlRemoveTablePartitionsRequest.h index 41a437fcd..a3eee709f 100644 --- a/src/replica/requests/SqlRemoveTablePartitionsRequest.h +++ b/src/replica/requests/SqlRemoveTablePartitionsRequest.h @@ -30,6 +30,11 @@ // Qserv headers #include "replica/requests/SqlRequest.h" +// Forward declarations +namespace lsst::qserv::replica { +class Controller; +} // namespace lsst::qserv::replica + // This header declarations namespace lsst::qserv::replica { @@ -58,32 +63,30 @@ class SqlRemoveTablePartitionsRequest : public SqlRequest { * Static factory method is needed to prevent issue with the lifespan * and memory management of instances created otherwise (as values or via * low-level pointers). - * @param serviceProvider is needed to access the Configuration and the Controller - * for communicating with the worker - * @param io_service a communication end-point - * @param worker identifier of a worker node - * @param database the name of an existing database where the table is residing - * @param tables the names of tables affected by the operation - * @param onFinish (optional) callback function to call upon completion of the request - * @param priority priority level of the request - * @param keepTracking keep tracking the request before it finishes or fails - * @param messenger interface for communicating with workers + * + * Class-specific parameters are documented below: + * @param database The name of an existing database where the table is residing. + * @param tables The names of tables affected by the operation. + * + * @see The very base class Request for the description of the common parameters + * of all subclasses. + * * @return a pointer to the created object */ - static Ptr create(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& database, - std::vector const& tables, CallbackType const& onFinish, int priority, - bool keepTracking, std::shared_ptr const& messenger); + static Ptr createAndStart(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, std::vector const& tables, + CallbackType const& onFinish = nullptr, int priority = PRIORITY_NORMAL, + bool keepTracking = true, std::string const& jobId = "", + unsigned int requestExpirationIvalSec = 0); protected: void notify(replica::Lock const& lock) final; private: - SqlRemoveTablePartitionsRequest(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, std::string const& worker, - std::string const& database, std::vector const& tables, - CallbackType const& onFinish, int priority, bool keepTracking, - std::shared_ptr const& messenger); + SqlRemoveTablePartitionsRequest(std::shared_ptr const& controller, + std::string const& workerName, std::string const& database, + std::vector const& tables, CallbackType const& onFinish, + int priority, bool keepTracking); CallbackType _onFinish; ///< @note is reset when the request finishes }; diff --git a/src/replica/requests/SqlRequest.cc b/src/replica/requests/SqlRequest.cc index 0dfebb129..cc2d4881b 100644 --- a/src/replica/requests/SqlRequest.cc +++ b/src/replica/requests/SqlRequest.cc @@ -44,44 +44,35 @@ using namespace std; using namespace std::placeholders; namespace { - LOG_LOGGER _log = LOG_GET("lsst.qserv.replica.SqlRequest"); - +bool const allowDuplicateNo = false; +bool const disposeRequired = true; } // namespace namespace lsst::qserv::replica { void SqlRequest::extendedPrinter(Ptr const& ptr) { Request::defaultPrinter(ptr); - for (auto&& itr : ptr->responseData().queryResultSet) { auto&& scope = itr.first; auto&& resultSet = itr.second; - if (resultSet.hasResult) { string const caption = "RESULT SET [" + scope + "]"; string const indent = ""; - auto const table = resultSet.toColumnTable(caption, indent); - bool const topSeparator = false; bool const bottomSeparator = false; bool const repeatedHeader = false; - size_t const pageSize = 0; - table.print(cout, topSeparator, bottomSeparator, pageSize, repeatedHeader); } } } -SqlRequest::SqlRequest(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& requestName, string const& workerName, uint64_t maxRows, - int priority, bool keepTracking, shared_ptr const& messenger) - : RequestMessenger(serviceProvider, io_service, requestName, workerName, priority, keepTracking, - false, // allowDuplicate - true, // disposeRequired - messenger) { +SqlRequest::SqlRequest(shared_ptr const& controller, std::string const& requestName, + string const& workerName, uint64_t maxRows, int priority, bool keepTracking) + : RequestMessenger(controller, requestName, workerName, priority, keepTracking, ::allowDuplicateNo, + ::disposeRequired) { // Partial initialization of the request body's content. Other members // will be set in the request type-specific subclasses. requestBody.set_max_rows(maxRows); @@ -111,7 +102,6 @@ void SqlRequest::startImpl(replica::Lock const& lock) { // Serialize the Request message header and the request body into // the network buffer. - buffer()->resize(); ProtocolRequestHeader hdr; @@ -120,8 +110,7 @@ void SqlRequest::startImpl(replica::Lock const& lock) { hdr.set_queued_type(ProtocolQueuedRequestType::SQL); hdr.set_timeout(requestExpirationIvalSec()); hdr.set_priority(priority()); - hdr.set_instance_id(serviceProvider()->instanceId()); - + hdr.set_instance_id(controller()->serviceProvider()->instanceId()); buffer()->serialize(hdr); buffer()->serialize(requestBody); @@ -132,28 +121,24 @@ void SqlRequest::awaken(boost::system::error_code const& ec) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__); if (isAborted(ec)) return; - if (state() == State::FINISHED) return; replica::Lock lock(_mtx, context() + __func__); if (state() == State::FINISHED) return; // Serialize the Status message header and the status request's body into // the network buffer. - buffer()->resize(); ProtocolRequestHeader hdr; hdr.set_id(id()); hdr.set_type(ProtocolRequestHeader::REQUEST); - hdr.set_management_type(ProtocolManagementRequestType::REQUEST_STATUS); - hdr.set_instance_id(serviceProvider()->instanceId()); - + hdr.set_management_type(ProtocolManagementRequestType::REQUEST_TRACK); + hdr.set_instance_id(controller()->serviceProvider()->instanceId()); buffer()->serialize(hdr); - ProtocolRequestStatus statusRequestBody; + ProtocolRequestTrack statusRequestBody; statusRequestBody.set_id(id()); statusRequestBody.set_queued_type(ProtocolQueuedRequestType::SQL); - buffer()->serialize(statusRequestBody); _send(lock); @@ -162,7 +147,7 @@ void SqlRequest::awaken(boost::system::error_code const& ec) { void SqlRequest::_send(replica::Lock const& lock) { LOGS(_log, LOG_LVL_DEBUG, context() << __func__); auto self = shared_from_base(); - messenger()->send( + controller()->serviceProvider()->messenger()->send( workerName(), id(), priority(), buffer(), [self](string const& id, bool success, ProtocolResponseSql const& response) { self->_analyze(success, response); @@ -180,7 +165,6 @@ void SqlRequest::_analyze(bool success, ProtocolResponseSql const& response) { if (state() == State::FINISHED) return; replica::Lock lock(_mtx, context() + __func__); if (state() == State::FINISHED) return; - if (not success) { finish(lock, CLIENT_ERROR); return; diff --git a/src/replica/requests/SqlRequest.h b/src/replica/requests/SqlRequest.h index 14fca8c4a..a7b4dd343 100644 --- a/src/replica/requests/SqlRequest.h +++ b/src/replica/requests/SqlRequest.h @@ -37,7 +37,7 @@ // Forward declarations namespace lsst::qserv::replica { -class Messenger; +class Controller; } // namespace lsst::qserv::replica // This header declarations @@ -88,30 +88,22 @@ class SqlRequest : public RequestMessenger { protected: /** * Create a new request with specified parameters. - * @param serviceProvider is needed to access the Configuration and the Controller - * for communicating with the worker. - * @param io_service a communication end-point - * @param workerName identifier of a worker node - * @param maxRows (optional) limit for the maximum number of rows to be returned with the request. + * + * Class-specific parameters are documented below: + * @param maxRows The (optional) limit for the maximum number of rows to be returned with the request. * Leaving the default value of the parameter to 0 will result in not imposing any * explicit restrictions on a size of the result set. Note that other, resource-defined * restrictions will still apply. The later includes the maximum size of the Google Protobuf * objects, the amount of available memory, etc. - * @param priority priority level of the request - * @param keepTracking keep tracking the request before it finishes or fails - * @param messenger interface for communicating with workers + * + * @see The very base class Request for the description of the common parameters + * of all subclasses. */ - SqlRequest(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& requestName, std::string const& workerName, uint64_t maxRows, int priority, - bool keepTracking, std::shared_ptr const& messenger); + SqlRequest(std::shared_ptr const& controller, std::string const& requestName, + std::string const& workerName, uint64_t maxRows, int priority, bool keepTracking); - /// @see Request::startImpl() void startImpl(replica::Lock const& lock) final; - - /// @see Request::savePersistentState() void savePersistentState(replica::Lock const& lock) final; - - /// @see Request::awaken() void awaken(boost::system::error_code const& ec) final; /** diff --git a/src/replica/requests/SqlRowStatsRequest.cc b/src/replica/requests/SqlRowStatsRequest.cc index e800f9742..c16f872bc 100644 --- a/src/replica/requests/SqlRowStatsRequest.cc +++ b/src/replica/requests/SqlRowStatsRequest.cc @@ -34,23 +34,23 @@ const uint64_t unlimitedMaxRows = 0; namespace lsst::qserv::replica { -SqlRowStatsRequest::Ptr SqlRowStatsRequest::create(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, string const& worker, - string const& database, vector const& tables, - CallbackType const& onFinish, int priority, - bool keepTracking, - shared_ptr const& messenger) { - return Ptr(new SqlRowStatsRequest(serviceProvider, io_service, worker, database, tables, onFinish, - priority, keepTracking, messenger)); +SqlRowStatsRequest::Ptr SqlRowStatsRequest::createAndStart(shared_ptr const& controller, + string const& workerName, string const& database, + vector const& tables, + CallbackType const& onFinish, int priority, + bool keepTracking, string const& jobId, + unsigned int requestExpirationIvalSec) { + auto ptr = Ptr(new SqlRowStatsRequest(controller, workerName, database, tables, onFinish, priority, + keepTracking)); + ptr->start(jobId, requestExpirationIvalSec); + return ptr; } -SqlRowStatsRequest::SqlRowStatsRequest(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, string const& worker, +SqlRowStatsRequest::SqlRowStatsRequest(shared_ptr const& controller, string const& workerName, string const& database, vector const& tables, - CallbackType const& onFinish, int priority, bool keepTracking, - shared_ptr const& messenger) - : SqlRequest(serviceProvider, io_service, "SQL_TABLE_ROW_STATS", worker, ::unlimitedMaxRows, priority, - keepTracking, messenger), + CallbackType const& onFinish, int priority, bool keepTracking) + : SqlRequest(controller, "SQL_TABLE_ROW_STATS", workerName, ::unlimitedMaxRows, priority, + keepTracking), _onFinish(onFinish) { // Finish initializing the request body's content requestBody.set_type(ProtocolRequestSql::TABLE_ROW_STATS); diff --git a/src/replica/requests/SqlRowStatsRequest.h b/src/replica/requests/SqlRowStatsRequest.h index 590912222..e1a0001b9 100644 --- a/src/replica/requests/SqlRowStatsRequest.h +++ b/src/replica/requests/SqlRowStatsRequest.h @@ -33,6 +33,11 @@ #include "replica/requests/SqlRequest.h" #include "replica/util/Common.h" +// Forward declarations +namespace lsst::qserv::replica { +class Controller; +} // namespace lsst::qserv::replica + // This header declarations namespace lsst::qserv::replica { @@ -60,33 +65,28 @@ class SqlRowStatsRequest : public SqlRequest { * and memory management of instances created otherwise (as values or via * low-level pointers). * - * @param serviceProvider Is needed to access the Configuration and - * the Controller for communicating with the worker. - * @param io_service The BOOST ASIO communication end-point. - * @param worker An identifier of a worker node. + * Class-specific parameters are documented below: * @param database The name of an existing database where the tables are residing. * @param tables The names of tables affected by the operation. - * @param onFinish (optional) A callback function to call upon completion of - * the request. - * @param priority A priority level of the request. - * @param keepTracking Keep tracking the request before it finishes or fails. - * @param messenger An interface for communicating with workers. + * + * @see The very base class Request for the description of the common parameters + * of all subclasses. * * @return A pointer to the created object. */ - static Ptr create(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& database, - std::vector const& tables, CallbackType const& onFinish, int priority, - bool keepTracking, std::shared_ptr const& messenger); + static Ptr createAndStart(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, std::vector const& tables, + CallbackType const& onFinish = nullptr, int priority = PRIORITY_NORMAL, + bool keepTracking = true, std::string const& jobId = "", + unsigned int requestExpirationIvalSec = 0); protected: void notify(replica::Lock const& lock) final; private: - SqlRowStatsRequest(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& worker, std::string const& database, - std::vector const& tables, CallbackType const& onFinish, int priority, - bool keepTracking, std::shared_ptr const& messenger); + SqlRowStatsRequest(std::shared_ptr const& controller, std::string const& workerName, + std::string const& database, std::vector const& tables, + CallbackType const& onFinish, int priority, bool keepTracking); CallbackType _onFinish; ///< @note is reset when the request finishes }; diff --git a/src/replica/requests/StatusRequest.cc b/src/replica/requests/StatusRequest.cc index a0a28d230..237ef3716 100644 --- a/src/replica/requests/StatusRequest.cc +++ b/src/replica/requests/StatusRequest.cc @@ -22,158 +22,190 @@ // Class header #include "replica/requests/StatusRequest.h" -using namespace std; +// System headers +#include -namespace lsst::qserv::replica { +// Qserv headers +#include "replica/contr/Controller.h" +#include "replica/requests/Messenger.h" +#include "replica/services/DatabaseServices.h" +#include "replica/services/ServiceProvider.h" +#include "replica/util/ProtocolBuffer.h" -// --------------------------------------------------- -// --------- StatusReplicationRequestPolicy ---------- -// --------------------------------------------------- +// LSST headers +#include "lsst/log/Log.h" -char const* StatusReplicationRequestPolicy::requestName() { return "REQUEST_STATUS:REPLICA_CREATE"; } +using namespace std; -ProtocolQueuedRequestType StatusReplicationRequestPolicy::targetRequestType() { - return ProtocolQueuedRequestType::REPLICA_CREATE; -} +namespace { +LOG_LOGGER _log = LOG_GET("lsst.qserv.replica.StatusRequest"); +bool const allowDuplicateNo = false; +bool const disposeRequiredNo = false; +} // namespace -void StatusReplicationRequestPolicy::extractResponseData(ResponseMessageType const& msg, - ResponseDataType& data) { - data = ResponseDataType(&(msg.replica_info())); -} +namespace lsst::qserv::replica { -void StatusReplicationRequestPolicy::extractTargetRequestParams(ResponseMessageType const& msg, - TargetRequestParamsType& params) { - if (msg.has_request()) { - params = TargetRequestParamsType(msg.request()); +StatusRequest::Ptr StatusRequest::createAndStart(shared_ptr const& controller, + string const& workerName, string const& targetRequestId, + CallbackType const& onFinish, int priority, + bool keepTracking, string const& jobId, + unsigned int requestExpirationIvalSec) { + auto ptr = StatusRequest::Ptr( + new StatusRequest(controller, workerName, targetRequestId, onFinish, priority, keepTracking)); + ptr->start(jobId, requestExpirationIvalSec); + return ptr; +} + +StatusRequest::StatusRequest(shared_ptr const& controller, string const& workerName, + string const& targetRequestId, CallbackType const& onFinish, int priority, + bool keepTracking) + : RequestMessenger(controller, "REQUEST_STATUS", workerName, priority, keepTracking, + ::allowDuplicateNo, ::disposeRequiredNo), + _targetRequestId(targetRequestId), + _onFinish(onFinish) {} + +string StatusRequest::toString(bool extended) const { + ostringstream oss; + oss << Request::toString(extended) << " targetRequestId: " + targetRequestId() << "\n"; + if ((state() == State::FINISHED) && (extendedState() == ExtendedState::SUCCESS)) { + oss << " targetStatus: " << ProtocolStatus_Name(targetRequestStatus()) << "\n"; + oss << " targetStatusExt: " << ProtocolStatusExt_Name(targetRequestExtendedStatus()) << "\n"; + oss << " targetPerformance: " << targetRequestPerformance() << "\n"; + } else { + oss << " targetStatus: N/A\n"; + oss << " targetStatusExt: N/A\n"; + oss << " targetPerformance: N/A\n"; } + return oss.str(); } -// ---------------------------------------------- -// --------- StatusDeleteRequestPolicy ---------- -// ---------------------------------------------- - -char const* StatusDeleteRequestPolicy::requestName() { return "REQUEST_STATUS:REPLICA_DELETE"; } - -ProtocolQueuedRequestType StatusDeleteRequestPolicy::targetRequestType() { - return ProtocolQueuedRequestType::REPLICA_DELETE; +ProtocolStatus StatusRequest::targetRequestStatus() const { + _assertIsSucceeded(); + return _targetStatus; } -void StatusDeleteRequestPolicy::extractResponseData(ResponseMessageType const& msg, ResponseDataType& data) { - data = ResponseDataType(&(msg.replica_info())); +ProtocolStatusExt StatusRequest::targetRequestExtendedStatus() const { + _assertIsSucceeded(); + return _targetExtendedServerStatus; } -void StatusDeleteRequestPolicy::extractTargetRequestParams(ResponseMessageType const& msg, - TargetRequestParamsType& params) { - if (msg.has_request()) { - params = TargetRequestParamsType(msg.request()); - } +Performance const& StatusRequest::targetRequestPerformance() const { + _assertIsSucceeded(); + return _targetPerformance; } -// -------------------------------------------- -// --------- StatusFindRequestPolicy ---------- -// -------------------------------------------- +void StatusRequest::notify(replica::Lock const& lock) { notifyDefaultImpl(lock, _onFinish); } -char const* StatusFindRequestPolicy::requestName() { return "REQUEST_STATUS:REPLICA_FIND"; } +void StatusRequest::startImpl(replica::Lock const& lock) { + LOGS(_log, LOG_LVL_DEBUG, context() << __func__); -ProtocolQueuedRequestType StatusFindRequestPolicy::targetRequestType() { - return ProtocolQueuedRequestType::REPLICA_FIND; -} - -void StatusFindRequestPolicy::extractResponseData(ResponseMessageType const& msg, ResponseDataType& data) { - data = ReplicaInfo(&(msg.replica_info())); -} + // Serialize the Status message header and the request itself into + // the network buffer. + buffer()->resize(); -void StatusFindRequestPolicy::extractTargetRequestParams(ResponseMessageType const& msg, - TargetRequestParamsType& params) { - if (msg.has_request()) { - params = TargetRequestParamsType(msg.request()); - } -} + ProtocolRequestHeader hdr; + hdr.set_id(id()); + hdr.set_type(ProtocolRequestHeader::REQUEST); + hdr.set_management_type(ProtocolManagementRequestType::REQUEST_STOP); + hdr.set_instance_id(controller()->serviceProvider()->instanceId()); + buffer()->serialize(hdr); -// ----------------------------------------------- -// --------- StatusFindAllRequestPolicy ---------- -// ----------------------------------------------- + ProtocolRequestStatus message; + message.set_id(_targetRequestId); + buffer()->serialize(message); -char const* StatusFindAllRequestPolicy::requestName() { return "REQUEST_STATUS:REPLICA_FIND_ALL"; } - -ProtocolQueuedRequestType StatusFindAllRequestPolicy::targetRequestType() { - return ProtocolQueuedRequestType::REPLICA_FIND_ALL; + _send(lock); } -void StatusFindAllRequestPolicy::extractResponseData(ResponseMessageType const& msg, ResponseDataType& data) { - for (int num = msg.replica_info_many_size(), idx = 0; idx < num; ++idx) { - data.emplace_back(&(msg.replica_info_many(idx))); - } -} +void StatusRequest::awaken(boost::system::error_code const& ec) { + LOGS(_log, LOG_LVL_DEBUG, context() << __func__); + if (isAborted(ec)) return; + if (state() == State::FINISHED) return; + replica::Lock lock(_mtx, context() + __func__); + if (state() == State::FINISHED) return; -void StatusFindAllRequestPolicy::extractTargetRequestParams(ResponseMessageType const& msg, - TargetRequestParamsType& params) { - if (msg.has_request()) { - params = TargetRequestParamsType(msg.request()); - } + // Send the same message again. + _send(lock); } -// -------------------------------------------- -// --------- StatusEchoRequestPolicy ---------- -// -------------------------------------------- - -char const* StatusEchoRequestPolicy::requestName() { return "REQUEST_STATUS:TEST_ECHO"; } - -ProtocolQueuedRequestType StatusEchoRequestPolicy::targetRequestType() { - return ProtocolQueuedRequestType::TEST_ECHO; +void StatusRequest::_send(replica::Lock const& lock) { + controller()->serviceProvider()->messenger()->send( + workerName(), id(), priority(), buffer(), + [self = shared_from_base()](string const& id, bool success, + ProtocolResponseStatus const& response) { + self->_analyze(success, response); + }); } -void StatusEchoRequestPolicy::extractResponseData(ResponseMessageType const& msg, ResponseDataType& data) { - data = msg.data(); -} +void StatusRequest::_analyze(bool success, ProtocolResponseStatus message) { + LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << " success=" << (success ? "true" : "false")); -void StatusEchoRequestPolicy::extractTargetRequestParams(ResponseMessageType const& msg, - TargetRequestParamsType& params) { - if (msg.has_request()) { - params = TargetRequestParamsType(msg.request()); + // This method is called on behalf of an asynchronous callback fired + // upon a completion of the request within method _send() - the only + // client of _analyze(). So, we should take care of proper locking and watch + // for possible state transition which might occur while the async I/O was + // still in a progress. + if (state() == State::FINISHED) return; + replica::Lock lock(_mtx, context() + __func__); + if (state() == State::FINISHED) return; + if (not success) { + finish(lock, CLIENT_ERROR); + return; } -} -// ----------------------------------------------------- -// --------- StatusDirectorIndexRequestPolicy ---------- -// ----------------------------------------------------- + // Always get the latest status reported by the remote server + setExtendedServerStatus(lock, message.status_ext()); -char const* StatusDirectorIndexRequestPolicy::requestName() { return "REQUEST_STATUS:INDEX"; } + // Always update performance counters obtained from the worker service. + mutablePerformance().update(message.performance()); -ProtocolQueuedRequestType StatusDirectorIndexRequestPolicy::targetRequestType() { - return ProtocolQueuedRequestType::INDEX; -} - -void StatusDirectorIndexRequestPolicy::extractResponseData(ResponseMessageType const& msg, - ResponseDataType& data) { - data = msg.error(); -} - -void StatusDirectorIndexRequestPolicy::extractTargetRequestParams(ResponseMessageType const& msg, - TargetRequestParamsType& params) { - if (msg.has_request()) { - params = TargetRequestParamsType(msg.request()); + // Extract status of the target request if available + if (message.has_target_status()) { + _targetStatus = message.target_status(); + } + if (message.has_target_status_ext()) { + _targetExtendedServerStatus = message.target_status_ext(); + } + if (message.has_target_performance()) { + _targetPerformance.update(message.target_performance()); + } + switch (message.status()) { + case ProtocolStatus::SUCCESS: + finish(lock, SUCCESS); + break; + case ProtocolStatus::CREATED: + keepTrackingOrFinish(lock, SERVER_CREATED); + break; + case ProtocolStatus::QUEUED: + keepTrackingOrFinish(lock, SERVER_QUEUED); + break; + case ProtocolStatus::IN_PROGRESS: + keepTrackingOrFinish(lock, SERVER_IN_PROGRESS); + break; + case ProtocolStatus::IS_CANCELLING: + keepTrackingOrFinish(lock, SERVER_IS_CANCELLING); + break; + case ProtocolStatus::BAD: + finish(lock, SERVER_BAD); + break; + case ProtocolStatus::FAILED: + finish(lock, SERVER_ERROR); + break; + case ProtocolStatus::CANCELLED: + finish(lock, SERVER_CANCELLED); + break; + default: + throw logic_error("StatusRequest::" + string(__func__) + " unknown status '" + + ProtocolStatus_Name(message.status()) + "' received from server"); } } -// ------------------------------------------- -// --------- StatusSqlRequestPolicy ---------- -// ------------------------------------------- - -char const* StatusSqlRequestPolicy::requestName() { return "REQUEST_STATUS:SQL"; } - -ProtocolQueuedRequestType StatusSqlRequestPolicy::targetRequestType() { - return ProtocolQueuedRequestType::SQL; -} - -void StatusSqlRequestPolicy::extractResponseData(ResponseMessageType const& msg, ResponseDataType& data) { - data.set(msg); -} - -void StatusSqlRequestPolicy::extractTargetRequestParams(ResponseMessageType const& msg, - TargetRequestParamsType& params) { - if (msg.has_request()) { - params = TargetRequestParamsType(msg.request()); +void StatusRequest::_assertIsSucceeded() const { + if (state() != State::FINISHED) { + throw logic_error("StatusRequest::" + string(__func__) + " the status request hasn't finished yet"); + } + if (extendedState() != ExtendedState::SUCCESS) { + throw logic_error("StatusRequest::" + string(__func__) + " the status request has failed"); } } diff --git a/src/replica/requests/StatusRequest.h b/src/replica/requests/StatusRequest.h index f1b39a808..150f52cb8 100644 --- a/src/replica/requests/StatusRequest.h +++ b/src/replica/requests/StatusRequest.h @@ -21,16 +21,6 @@ #ifndef LSST_QSERV_REPLICA_STATUSREQUEST_H #define LSST_QSERV_REPLICA_STATUSREQUEST_H -/** - * This header declares a collection of the request status management request - * classes for the Controller-side Replication Framework. - * - * @see class StatusRequestReplicate - * @see class StatusRequestDelete - * @see class StatusRequestFind - * @see class StatusRequestFindAll - */ - // System headers #include #include @@ -39,333 +29,104 @@ // Qserv headers #include "replica/proto/protocol.pb.h" -#include "replica/requests/Messenger.h" #include "replica/requests/RequestMessenger.h" -#include "replica/requests/StatusRequestBase.h" -#include "replica/requests/SqlResultSet.h" -#include "replica/services/DatabaseServices.h" -#include "replica/services/ServiceProvider.h" #include "replica/util/Common.h" -#include "replica/util/ProtocolBuffer.h" -#include "replica/util/ReplicaInfo.h" +#include "replica/util/Performance.h" -// This header declarations +// Forward declarations namespace lsst::qserv::replica { +class Controller; +} // namespace lsst::qserv::replica -// ======================================================================== -// Customizations for specific request types require dedicated policies -// ======================================================================== - -class StatusReplicationRequestPolicy { -public: - using ResponseMessageType = ProtocolResponseReplicate; - using ResponseDataType = ReplicaInfo; - using TargetRequestParamsType = ReplicationRequestParams; - - static char const* requestName(); - static ProtocolQueuedRequestType targetRequestType(); - static void extractResponseData(ResponseMessageType const& msg, ResponseDataType& data); - static void extractTargetRequestParams(ResponseMessageType const& msg, TargetRequestParamsType& params); - - template - static void saveReplicaInfo(REQUEST_PTR const& request) { - request->serviceProvider()->databaseServices()->saveReplicaInfo(request->responseData()); - request->serviceProvider()->databaseServices()->updateRequestState( - *request, request->targetRequestId(), request->targetPerformance()); - } -}; - -class StatusDeleteRequestPolicy { -public: - using ResponseMessageType = ProtocolResponseDelete; - using ResponseDataType = ReplicaInfo; - using TargetRequestParamsType = DeleteRequestParams; - - static char const* requestName(); - static ProtocolQueuedRequestType targetRequestType(); - static void extractResponseData(ResponseMessageType const& msg, ResponseDataType& data); - static void extractTargetRequestParams(ResponseMessageType const& msg, TargetRequestParamsType& params); - - template - static void saveReplicaInfo(REQUEST_PTR const& request) { - request->serviceProvider()->databaseServices()->saveReplicaInfo(request->responseData()); - request->serviceProvider()->databaseServices()->updateRequestState( - *request, request->targetRequestId(), request->targetPerformance()); - } -}; - -class StatusFindRequestPolicy { -public: - using ResponseMessageType = ProtocolResponseFind; - using ResponseDataType = ReplicaInfo; - using TargetRequestParamsType = FindRequestParams; - - static char const* requestName(); - static ProtocolQueuedRequestType targetRequestType(); - static void extractResponseData(ResponseMessageType const& msg, ResponseDataType& data); - static void extractTargetRequestParams(ResponseMessageType const& msg, TargetRequestParamsType& params); - - template - static void saveReplicaInfo(REQUEST_PTR const& request) { - request->serviceProvider()->databaseServices()->saveReplicaInfo(request->responseData()); - request->serviceProvider()->databaseServices()->updateRequestState( - *request, request->targetRequestId(), request->targetPerformance()); - } -}; - -class StatusFindAllRequestPolicy { -public: - using ResponseMessageType = ProtocolResponseFindAll; - using ResponseDataType = ReplicaInfoCollection; - using TargetRequestParamsType = FindAllRequestParams; - - static char const* requestName(); - static ProtocolQueuedRequestType targetRequestType(); - static void extractResponseData(ResponseMessageType const& msg, ResponseDataType& data); - static void extractTargetRequestParams(ResponseMessageType const& msg, TargetRequestParamsType& params); - - template - static void saveReplicaInfo(REQUEST_PTR const& request) { - request->serviceProvider()->databaseServices()->saveReplicaInfoCollection( - request->workerName(), request->targetRequestParams().database, request->responseData()); - request->serviceProvider()->databaseServices()->updateRequestState( - *request, request->targetRequestId(), request->targetPerformance()); - } -}; - -class StatusEchoRequestPolicy { -public: - using ResponseMessageType = ProtocolResponseEcho; - using ResponseDataType = std::string; - using TargetRequestParamsType = EchoRequestParams; - - static char const* requestName(); - static ProtocolQueuedRequestType targetRequestType(); - static void extractResponseData(ResponseMessageType const& msg, ResponseDataType& data); - static void extractTargetRequestParams(ResponseMessageType const& msg, TargetRequestParamsType& params); - - template - static void saveReplicaInfo(REQUEST_PTR const& request) { - request->serviceProvider()->databaseServices()->updateRequestState( - *request, request->targetRequestId(), request->targetPerformance()); - } -}; - -/// @note This type of the management request for testing the target request won't -/// return any data even in case when the target request was found successfully -/// completed. An assumption here is that since the target requests of this -/// kind have no side effects then they could always be resubmited if needed. -/// The response object will contained the server error should the request failed -/// at a worker. -class StatusDirectorIndexRequestPolicy { -public: - using ResponseMessageType = ProtocolResponseDirectorIndex; - using ResponseDataType = std::string; - using TargetRequestParamsType = DirectorIndexRequestParams; - - static char const* requestName(); - static ProtocolQueuedRequestType targetRequestType(); - static void extractResponseData(ResponseMessageType const& msg, ResponseDataType& data); - static void extractTargetRequestParams(ResponseMessageType const& msg, TargetRequestParamsType& params); - - template - static void saveReplicaInfo(REQUEST_PTR const& request) { - request->serviceProvider()->databaseServices()->updateRequestState( - *request, request->targetRequestId(), request->targetPerformance()); - } -}; - -class StatusSqlRequestPolicy { -public: - using ResponseMessageType = ProtocolResponseSql; - using ResponseDataType = SqlResultSet; - using TargetRequestParamsType = SqlRequestParams; - - static char const* requestName(); - static ProtocolQueuedRequestType targetRequestType(); - static void extractResponseData(ResponseMessageType const& msg, ResponseDataType& data); - static void extractTargetRequestParams(ResponseMessageType const& msg, TargetRequestParamsType& params); - - template - static void saveReplicaInfo(REQUEST_PTR const& request) { - request->serviceProvider()->databaseServices()->updateRequestState( - *request, request->targetRequestId(), request->targetPerformance()); - } -}; +// This header declarations +namespace lsst::qserv::replica { /** - * Generic class StatusRequest extends its base class to allow further policy-based - * customization of specific requests. + * Class StatusRequest is used for checking a status of the previously submitted requests. */ -template -class StatusRequest : public StatusRequestBase { +class StatusRequest : public RequestMessenger { public: - typedef std::shared_ptr> Ptr; + typedef std::shared_ptr Ptr; /// The function type for notifications on the completion of the request typedef std::function CallbackType; + /** + * Create a new request with specified parameters. + * + * Static factory method is needed to prevent issue with the lifespan + * and memory management of instances created otherwise (as values or via + * low-level pointers). + * + * Class-specific parameters are documented below: + * @param targetRequestId An identifier of the target request whose remote status + * is going to be inspected. + * + * @see The very base class Request for the description of the common parameters + * of all subclasses. + * + * @return A pointer to the created object. + */ + static Ptr createAndStart(std::shared_ptr const& controller, std::string const& workerName, + std::string const& targetRequestId, CallbackType const& onFinish = nullptr, + int priority = PRIORITY_NORMAL, bool keepTracking = true, + std::string const& jobId = "", unsigned int requestExpirationIvalSec = 0); + StatusRequest() = delete; StatusRequest(StatusRequest const&) = delete; StatusRequest& operator=(StatusRequest const&) = delete; ~StatusRequest() final = default; - /// @return target request specific parameters - typename POLICY::TargetRequestParamsType const& targetRequestParams() const { - return _targetRequestParams; - } + std::string const& targetRequestId() const { return _targetRequestId; } - /** - * @return The request-specific extended data reported upon a successful - * completion of the request. - */ - typename POLICY::ResponseDataType const& responseData() const { return _responseData; } + // Status info on the target request (as reported by the worker) is only available after + // the status request is successfully completed. Otherwise std::logic_error is thrown. - /** - * Create a new request with specified parameters. - * - * Static factory method is needed to prevent issue with the lifespan - * and memory management of instances created otherwise (as values or via - * low-level pointers). - * @param serviceProvider a host of services for various communications - * @param workerName the identifier of a worker node (the one to be affected by the request) - * @param io_service network communication service - * @param targetRequestId an identifier of the target request whose remote status - * is going to be inspected - * @param onFinish an optional callback function to be called upon a completion of - * the request. - * @param priority priority level of the request - * @param keepTracking keep tracking the request before it finishes or fails - * @param messenger an interface for communicating with workers - * @return pointer to the created object - */ - static Ptr create(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& workerName, std::string const& targetRequestId, - CallbackType const& onFinish, int priority, bool keepTracking, - std::shared_ptr const& messenger) { - return StatusRequest::Ptr(new StatusRequest( - serviceProvider, io_service, POLICY::requestName(), workerName, targetRequestId, - POLICY::targetRequestType(), onFinish, priority, keepTracking, messenger)); - } + ProtocolStatus targetRequestStatus() const; + ProtocolStatusExt targetRequestExtendedStatus() const; + Performance const& targetRequestPerformance() const; - /** - * Make an extended print of the request which would include a result set. - * The method will also make a call to Request::defaultPrinter(). - * @param ptr An object to be printed. - */ - static void extendedPrinter(Ptr const& ptr) { - Request::defaultPrinter(ptr); - std::cout << ptr->responseData() << std::endl; - } + /// @see Request::toString() + std::string toString(bool extended = false) const override; protected: - void notify(replica::Lock const& lock) final { - notifyDefaultImpl>(lock, _onFinish); - } + void startImpl(replica::Lock const& lock) final; + void notify(replica::Lock const& lock) final; + void awaken(boost::system::error_code const& ec) final; +private: + StatusRequest(std::shared_ptr const& controller, std::string const& workerName, + std::string const& targetRequestId, CallbackType const& onFinish, int priority, + bool keepTracking); /** - * Initiate request-specific send. - * @note This method implements the corresponding virtual method defined - * by the base class. - * @param lock A lock on Request::_mtx must be acquired before calling this method. + * Send the serialized content of the buffer to a worker + * @param lock a lock on Request::_mtx must be acquired before calling + * this method */ - void send(replica::Lock const& lock) final { - auto self = shared_from_base>(); - messenger()->send( - workerName(), id(), priority(), buffer(), - [self](std::string const& id, bool success, - typename POLICY::ResponseMessageType const& response) { - if (success) - self->analyze(true, self->_parseResponse(response)); - else - self->analyze(false); - }); - } + void _send(replica::Lock const& lock); /** - * Initiate request-specific operation with the persistent state service - * to store replica status. - * @note This method implements the corresponding virtual method defined - * by the base class. + * Process the worker response to the requested operation. + * @param success 'true' indicates a successful response from a worker + * @param message worker response (if success) */ - void saveReplicaInfo() final { - auto const self = shared_from_base>(); - POLICY::saveReplicaInfo(self); - } - -private: - StatusRequest(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - char const* requestName, std::string const& workerName, std::string const& targetRequestId, - ProtocolQueuedRequestType targetRequestType, CallbackType const& onFinish, int priority, - bool keepTracking, std::shared_ptr const& messenger) - : StatusRequestBase(serviceProvider, io_service, requestName, workerName, targetRequestId, - targetRequestType, priority, keepTracking, messenger), - _onFinish(onFinish) {} + void _analyze(bool success, ProtocolResponseStatus message); - /** - * Parse request-specific reply. - * @param message A message to be parsed. - * @return The status of the operation reported by a server. - */ - ProtocolStatus _parseResponse(typename POLICY::ResponseMessageType const& message) { - // This lock must be acquired because the method is going to modify - // results of the request. Note that the operation doesn't care - // about the global state of the request (wether it's already finished - // or not) - replica::Lock lock(_mtx, context() + __func__); - - // Extract target request-specific parameters from the response if available. - POLICY::extractTargetRequestParams(message, _targetRequestParams); - - // Extract request-specific data from the response regardless of - // the completion status of the request. - POLICY::extractResponseData(message, _responseData); - - // Always get the latest status reported by the remote server. - setExtendedServerStatus(lock, message.status_ext()); - - // Always update performance counters obtained from the worker service. - mutablePerformance().update(message.performance()); - - // Set the optional performance of the target operation. - if (message.has_target_performance()) { - _targetPerformance.update(message.target_performance()); - } - - // Field 'status' of a type returned by the current method always - // be defined in all types of request-specific responses. - return message.status(); - } + /// Ensure the request is in a successful state. + /// @throw std::logic_error if the request is not in a successful state. + void _assertIsSucceeded() const; // Input parameters - + std::string const _targetRequestId; CallbackType _onFinish; - /// Request-specific parameters of the target request - typename POLICY::TargetRequestParamsType _targetRequestParams; - - /// Request-specific data - typename POLICY::ResponseDataType _responseData; + // Status of of the target request + ProtocolStatus _targetStatus; + ProtocolStatusExt _targetExtendedServerStatus; + Performance _targetPerformance; }; -typedef StatusRequest StatusReplicationRequest; -typedef StatusRequest StatusDeleteRequest; -typedef StatusRequest StatusFindRequest; -typedef StatusRequest StatusFindAllRequest; -typedef StatusRequest StatusEchoRequest; -typedef StatusRequest StatusDirectorIndexRequest; -typedef StatusRequest StatusSqlQueryRequest; -typedef StatusRequest StatusSqlCreateDbRequest; -typedef StatusRequest StatusSqlDeleteDbRequest; -typedef StatusRequest StatusSqlEnableDbRequest; -typedef StatusRequest StatusSqlDisableDbRequest; -typedef StatusRequest StatusSqlGrantAccessRequest; -typedef StatusRequest StatusSqlCreateTableRequest; -typedef StatusRequest StatusSqlDeleteTableRequest; -typedef StatusRequest StatusSqlRemoveTablePartitionsRequest; -typedef StatusRequest StatusSqlDeleteTablePartitionRequest; - } // namespace lsst::qserv::replica #endif // LSST_QSERV_REPLICA_STATUSREQUEST_H diff --git a/src/replica/requests/StatusRequestBase.cc b/src/replica/requests/StatusRequestBase.cc deleted file mode 100644 index 31e5aea09..000000000 --- a/src/replica/requests/StatusRequestBase.cc +++ /dev/null @@ -1,169 +0,0 @@ -/* - * LSST Data Management System - * - * This product includes software developed by the - * LSST Project (http://www.lsst.org/). - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the LSST License Statement and - * the GNU General Public License along with this program. If not, - * see . - */ - -// Class header -#include "replica/requests/StatusRequestBase.h" - -// System headers -#include -#include -#include - -// Third party headers -#include "boost/date_time/posix_time/posix_time.hpp" - -// Qserv headers -#include "replica/services/ServiceProvider.h" -#include "replica/util/ProtocolBuffer.h" - -// LSST headers -#include "lsst/log/Log.h" - -using namespace std; -using namespace std::placeholders; - -namespace { - -LOG_LOGGER _log = LOG_GET("lsst.qserv.replica.StatusRequest"); - -} // namespace - -namespace lsst::qserv::replica { - -StatusRequestBase::StatusRequestBase(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, char const* requestTypeName, - string const& workerName, string const& targetRequestId, - ProtocolQueuedRequestType targetRequestType, int priority, - bool keepTracking, shared_ptr const& messenger) - : RequestMessenger(serviceProvider, io_service, requestTypeName, workerName, priority, keepTracking, - false, // allowDuplicate - false, // disposeRequired - messenger), - _targetRequestId(targetRequestId), - _targetRequestType(targetRequestType) {} - -string StatusRequestBase::toString(bool extended) const { - ostringstream oss(Request::toString(extended)); - oss << " targetRequestId: " << targetRequestId() << "\n" - << " targetPerformance: " << targetPerformance() << "\n"; - return oss.str(); -} - -void StatusRequestBase::startImpl(replica::Lock const& lock) { - LOGS(_log, LOG_LVL_DEBUG, context() << __func__); - _sendImpl(lock); -} - -void StatusRequestBase::awaken(boost::system::error_code const& ec) { - LOGS(_log, LOG_LVL_DEBUG, context() << __func__); - - if (isAborted(ec)) return; - - if (state() == State::FINISHED) return; - replica::Lock lock(_mtx, context() + __func__); - if (state() == State::FINISHED) return; - - _sendImpl(lock); -} - -void StatusRequestBase::_sendImpl(replica::Lock const& lock) { - LOGS(_log, LOG_LVL_DEBUG, context() << __func__); - - // Serialize the Status message header and the request itself into - // the network buffer. - - buffer()->resize(); - - ProtocolRequestHeader hdr; - hdr.set_id(id()); - hdr.set_type(ProtocolRequestHeader::REQUEST); - hdr.set_management_type(ProtocolManagementRequestType::REQUEST_STATUS); - hdr.set_instance_id(serviceProvider()->instanceId()); - - buffer()->serialize(hdr); - - ProtocolRequestStatus message; - message.set_id(_targetRequestId); - message.set_queued_type(_targetRequestType); - - buffer()->serialize(message); - - send(lock); -} - -void StatusRequestBase::analyze(bool success, ProtocolStatus status) { - LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << " success=" << (success ? "true" : "false")); - - // This method is called on behalf of an asynchronous callback fired - // upon a completion of the request within method send() - the only - // client of analyze(). So, we should take care of proper locking and watch - // for possible state transition which might occur while the async I/O was - // still in a progress. - if (state() == State::FINISHED) return; - replica::Lock lock(_mtx, context() + __func__); - if (state() == State::FINISHED) return; - - if (not success) { - finish(lock, CLIENT_ERROR); - return; - } - - switch (status) { - case ProtocolStatus::SUCCESS: - saveReplicaInfo(); - finish(lock, SUCCESS); - break; - - case ProtocolStatus::CREATED: - keepTrackingOrFinish(lock, SERVER_CREATED); - break; - - case ProtocolStatus::QUEUED: - keepTrackingOrFinish(lock, SERVER_QUEUED); - break; - - case ProtocolStatus::IN_PROGRESS: - keepTrackingOrFinish(lock, SERVER_IN_PROGRESS); - break; - - case ProtocolStatus::IS_CANCELLING: - keepTrackingOrFinish(lock, SERVER_IS_CANCELLING); - break; - - case ProtocolStatus::BAD: - finish(lock, SERVER_BAD); - break; - - case ProtocolStatus::FAILED: - finish(lock, SERVER_ERROR); - break; - - case ProtocolStatus::CANCELLED: - finish(lock, SERVER_CANCELLED); - break; - - default: - throw logic_error("StatusRequestBase::" + string(__func__) + " unknown status '" + - ProtocolStatus_Name(status) + "' received from server"); - } -} - -} // namespace lsst::qserv::replica diff --git a/src/replica/requests/StatusRequestBase.h b/src/replica/requests/StatusRequestBase.h deleted file mode 100644 index 3b722f0fe..000000000 --- a/src/replica/requests/StatusRequestBase.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * LSST Data Management System - * - * This product includes software developed by the - * LSST Project (http://www.lsst.org/). - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the LSST License Statement and - * the GNU General Public License along with this program. If not, - * see . - */ -#ifndef LSST_QSERV_REPLICA_STATUSREQUESTBASE_H -#define LSST_QSERV_REPLICA_STATUSREQUESTBASE_H - -// System headers -#include -#include - -// Qserv headers -#include "replica/proto/protocol.pb.h" -#include "replica/requests/Messenger.h" -#include "replica/requests/RequestMessenger.h" -#include "replica/services/ServiceProvider.h" -#include "replica/util/Common.h" - -// This header declarations -namespace lsst::qserv::replica { - -/** - * Class StatusRequestBase represents the base class for a family of requests - * pulling a status of on-going operation. - */ -class StatusRequestBase : public RequestMessenger { -public: - typedef std::shared_ptr Ptr; - - StatusRequestBase() = delete; - StatusRequestBase(StatusRequestBase const&) = delete; - StatusRequestBase& operator=(StatusRequestBase const&) = delete; - - ~StatusRequestBase() override = default; - - /// @return an identifier of the target request - std::string const& targetRequestId() const { return _targetRequestId; } - - /// @return the performance info of the target operation (if available) - Performance const& targetPerformance() const { return _targetPerformance; } - - std::string toString(bool extended = false) const override; - -protected: - /** - * Construct the request. - * @param serviceProvider Services of the Replicaion framework. - * @param io_service Network communication services. - * @param requestName The name of a request. - * @param workerName The name of a worker node (the one to be affected by the request). - * @param targetRequestId An identifier of the target request whose remote status - * is going to be inspected. - * @param targetRequestType The type of a request affected by the operation. - * @param priority A priority level of a request. - * @param keepTracking Keep tracking the request before it finishes or fails. - * @param messenger A service for communicating with workers. - */ - StatusRequestBase(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - char const* requestName, std::string const& workerName, - std::string const& targetRequestId, ProtocolQueuedRequestType targetRequestType, - int priority, bool keepTracking, std::shared_ptr const& messenger); - - /// @see Request::startImpl() - void startImpl(replica::Lock const& lock) final; - - /// @see Request::awaken() - void awaken(boost::system::error_code const& ec) final; - - /** - * Initiate request-specific send. - * @param lock A lock on Request::_mtx must be acquired before calling this method. - */ - virtual void send(replica::Lock const& lock) = 0; - - /** - * Process the worker response to the requested operation. - * @param success 'true' indicates a successful response from a worker - * @param status a response from the worker service (only valid if success is 'true') - */ - void analyze(bool success, ProtocolStatus status = ProtocolStatus::FAILED); - - /** - * Initiate request-specific operation with the persistent state service - * to store replica status. - */ - virtual void saveReplicaInfo() = 0; - - /// The performance of the target operation (updated by subclasses) - Performance _targetPerformance; - -private: - /** - * Serialize request data into a network buffer and send the message to a worker. - * @param lock A lock on Request::_mtx must be acquired before calling this method. - */ - void _sendImpl(replica::Lock const& lock); - - // Input parameters - - std::string const _targetRequestId; - - ProtocolQueuedRequestType const _targetRequestType; -}; - -} // namespace lsst::qserv::replica - -#endif // LSST_QSERV_REPLICA_STATUSREQUESTBASE_H diff --git a/src/replica/requests/StopRequest.cc b/src/replica/requests/StopRequest.cc index b4418b0f6..21dadc1e2 100644 --- a/src/replica/requests/StopRequest.cc +++ b/src/replica/requests/StopRequest.cc @@ -22,156 +22,151 @@ // Class header #include "replica/requests/StopRequest.h" -using namespace std; - -namespace lsst::qserv::replica { +// Qserv headers +#include "replica/contr/Controller.h" +#include "replica/requests/Messenger.h" +#include "replica/services/DatabaseServices.h" +#include "replica/services/ServiceProvider.h" +#include "replica/util/ProtocolBuffer.h" -// ------------------------------------------------- -// --------- StopReplicationRequestPolicy ---------- -// ------------------------------------------------- +// LSST headers +#include "lsst/log/Log.h" -char const* StopReplicationRequestPolicy::requestName() { return "REQUEST_STOP:REPLICA_CREATE"; } +using namespace std; -ProtocolQueuedRequestType StopReplicationRequestPolicy::targetRequestType() { - return ProtocolQueuedRequestType::REPLICA_CREATE; -} +namespace { +LOG_LOGGER _log = LOG_GET("lsst.qserv.replica.StopRequest"); +bool const allowDuplicateNo = false; +bool const disposeRequiredNo = false; +} // namespace -void StopReplicationRequestPolicy::extractResponseData(ResponseMessageType const& msg, - ResponseDataType& data) { - data = ResponseDataType(&(msg.replica_info())); -} +namespace lsst::qserv::replica { -void StopReplicationRequestPolicy::extractTargetRequestParams(ResponseMessageType const& msg, - TargetRequestParamsType& params) { - if (msg.has_request()) { - params = TargetRequestParamsType(msg.request()); - } +StopRequest::Ptr StopRequest::createAndStart(shared_ptr const& controller, + string const& workerName, string const& targetRequestId, + CallbackType const& onFinish, int priority, bool keepTracking, + string const& jobId, unsigned int requestExpirationIvalSec) { + auto ptr = StopRequest::Ptr( + new StopRequest(controller, workerName, targetRequestId, onFinish, priority, keepTracking)); + ptr->start(jobId, requestExpirationIvalSec); + return ptr; } -// -------------------------------------------- -// --------- StopDeleteRequestPolicy ---------- -// -------------------------------------------- +StopRequest::StopRequest(shared_ptr const& controller, string const& workerName, + string const& targetRequestId, CallbackType const& onFinish, int priority, + bool keepTracking) + : RequestMessenger(controller, "REQUEST_STOP", workerName, priority, keepTracking, ::allowDuplicateNo, + ::disposeRequiredNo), + _targetRequestId(targetRequestId), + _onFinish(onFinish) {} -char const* StopDeleteRequestPolicy::requestName() { return "REQUEST_STOP:REPLICA_DELETE"; } - -ProtocolQueuedRequestType StopDeleteRequestPolicy::targetRequestType() { - return ProtocolQueuedRequestType::REPLICA_DELETE; +string StopRequest::toString(bool extended) const { + return Request::toString(extended) + " targetRequestId: " + targetRequestId() + "\n"; } -void StopDeleteRequestPolicy::extractResponseData(ResponseMessageType const& msg, ResponseDataType& data) { - data = ResponseDataType(&(msg.replica_info())); +list> StopRequest::extendedPersistentState() const { + list> result; + result.emplace_back("target_request_id", targetRequestId()); + return result; } -void StopDeleteRequestPolicy::extractTargetRequestParams(ResponseMessageType const& msg, - TargetRequestParamsType& params) { - if (msg.has_request()) { - params = TargetRequestParamsType(msg.request()); - } -} - -// ------------------------------------------ -// --------- StopFindRequestPolicy ---------- -// ------------------------------------------ - -char const* StopFindRequestPolicy::requestName() { return "REQUEST_STOP:REPLICA_FIND"; } +void StopRequest::notify(replica::Lock const& lock) { notifyDefaultImpl(lock, _onFinish); } -ProtocolQueuedRequestType StopFindRequestPolicy::targetRequestType() { - return ProtocolQueuedRequestType::REPLICA_FIND; +void StopRequest::savePersistentState(replica::Lock const& lock) { + controller()->serviceProvider()->databaseServices()->saveState(*this, performance(lock)); } -void StopFindRequestPolicy::extractResponseData(ResponseMessageType const& msg, ResponseDataType& data) { - data = ResponseDataType(&(msg.replica_info())); -} +void StopRequest::startImpl(replica::Lock const& lock) { + LOGS(_log, LOG_LVL_DEBUG, context() << __func__); -void StopFindRequestPolicy::extractTargetRequestParams(ResponseMessageType const& msg, - TargetRequestParamsType& params) { - if (msg.has_request()) { - params = TargetRequestParamsType(msg.request()); - } -} + // Serialize the Stop message header and the request itself into + // the network buffer. + buffer()->resize(); -// --------------------------------------------- -// --------- StopFindAllRequestPolicy ---------- -// --------------------------------------------- + ProtocolRequestHeader hdr; + hdr.set_id(id()); + hdr.set_type(ProtocolRequestHeader::REQUEST); + hdr.set_management_type(ProtocolManagementRequestType::REQUEST_STOP); + hdr.set_instance_id(controller()->serviceProvider()->instanceId()); + buffer()->serialize(hdr); -char const* StopFindAllRequestPolicy::requestName() { return "REQUEST_STOP:REPLICA_FIND_ALL"; } + ProtocolRequestStop message; + message.set_id(_targetRequestId); + buffer()->serialize(message); -ProtocolQueuedRequestType StopFindAllRequestPolicy::targetRequestType() { - return ProtocolQueuedRequestType::REPLICA_FIND_ALL; + _send(lock); } -void StopFindAllRequestPolicy::extractResponseData(ResponseMessageType const& msg, ResponseDataType& data) { - for (int num = msg.replica_info_many_size(), idx = 0; idx < num; ++idx) { - data.emplace_back(&(msg.replica_info_many(idx))); - } -} +void StopRequest::awaken(boost::system::error_code const& ec) { + LOGS(_log, LOG_LVL_DEBUG, context() << __func__); + if (isAborted(ec)) return; + if (state() == State::FINISHED) return; + replica::Lock lock(_mtx, context() + __func__); + if (state() == State::FINISHED) return; -void StopFindAllRequestPolicy::extractTargetRequestParams(ResponseMessageType const& msg, - TargetRequestParamsType& params) { - if (msg.has_request()) { - params = TargetRequestParamsType(msg.request()); - } + // Send the same message again. + _send(lock); } -// ------------------------------------------ -// --------- StopEchoRequestPolicy ---------- -// ------------------------------------------ - -char const* StopEchoRequestPolicy::requestName() { return "REQUEST_STOP:TEST_ECHO"; } - -ProtocolQueuedRequestType StopEchoRequestPolicy::targetRequestType() { - return ProtocolQueuedRequestType::TEST_ECHO; -} - -void StopEchoRequestPolicy::extractResponseData(ResponseMessageType const& msg, ResponseDataType& data) { - data = msg.data(); -} - -void StopEchoRequestPolicy::extractTargetRequestParams(ResponseMessageType const& msg, - TargetRequestParamsType& params) { - if (msg.has_request()) { - params = TargetRequestParamsType(msg.request()); - } -} - -// --------------------------------------------------- -// --------- StopDirectorIndexRequestPolicy ---------- -// --------------------------------------------------- - -char const* StopDirectorIndexRequestPolicy::requestName() { return "REQUEST_STOP:INDEX"; } - -ProtocolQueuedRequestType StopDirectorIndexRequestPolicy::targetRequestType() { - return ProtocolQueuedRequestType::INDEX; +void StopRequest::_send(replica::Lock const& lock) { + controller()->serviceProvider()->messenger()->send( + workerName(), id(), priority(), buffer(), + [self = shared_from_base()](string const& id, bool success, + ProtocolResponseStop const& response) { + self->_analyze(success, response); + }); } -void StopDirectorIndexRequestPolicy::extractResponseData(ResponseMessageType const& msg, - ResponseDataType& data) { - data = msg.error(); -} +void StopRequest::_analyze(bool success, ProtocolResponseStop message) { + LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << " success=" << (success ? "true" : "false")); -void StopDirectorIndexRequestPolicy::extractTargetRequestParams(ResponseMessageType const& msg, - TargetRequestParamsType& params) { - if (msg.has_request()) { - params = TargetRequestParamsType(msg.request()); + // This method is called on behalf of an asynchronous callback fired + // upon a completion of the request within method _send() - the only + // client of _analyze(). So, we should take care of proper locking and watch + // for possible state transition which might occur while the async I/O was + // still in a progress. + if (state() == State::FINISHED) return; + replica::Lock lock(_mtx, context() + __func__); + if (state() == State::FINISHED) return; + if (not success) { + finish(lock, CLIENT_ERROR); + return; } -} - -// ----------------------------------------- -// --------- StopSqlRequestPolicy ---------- -// ----------------------------------------- - -char const* StopSqlRequestPolicy::requestName() { return "REQUEST_STOP:SQL"; } - -ProtocolQueuedRequestType StopSqlRequestPolicy::targetRequestType() { return ProtocolQueuedRequestType::SQL; } - -void StopSqlRequestPolicy::extractResponseData(ResponseMessageType const& msg, ResponseDataType& data) { - data.set(msg); -} -void StopSqlRequestPolicy::extractTargetRequestParams(ResponseMessageType const& msg, - TargetRequestParamsType& params) { - if (msg.has_request()) { - params = TargetRequestParamsType(msg.request()); + // Always get the latest status reported by the remote server + setExtendedServerStatus(lock, message.status_ext()); + + // Always update performance counters obtained from the worker service. + mutablePerformance().update(message.performance()); + + switch (message.status()) { + case ProtocolStatus::SUCCESS: + finish(lock, SUCCESS); + break; + case ProtocolStatus::CREATED: + keepTrackingOrFinish(lock, SERVER_CREATED); + break; + case ProtocolStatus::QUEUED: + keepTrackingOrFinish(lock, SERVER_QUEUED); + break; + case ProtocolStatus::IN_PROGRESS: + keepTrackingOrFinish(lock, SERVER_IN_PROGRESS); + break; + case ProtocolStatus::IS_CANCELLING: + keepTrackingOrFinish(lock, SERVER_IS_CANCELLING); + break; + case ProtocolStatus::BAD: + finish(lock, SERVER_BAD); + break; + case ProtocolStatus::FAILED: + finish(lock, SERVER_ERROR); + break; + case ProtocolStatus::CANCELLED: + finish(lock, SERVER_CANCELLED); + break; + default: + throw logic_error("StopRequest::" + string(__func__) + " unknown status '" + + ProtocolStatus_Name(message.status()) + "' received from server"); } } diff --git a/src/replica/requests/StopRequest.h b/src/replica/requests/StopRequest.h index 1f06336dd..72ddbd6f1 100644 --- a/src/replica/requests/StopRequest.h +++ b/src/replica/requests/StopRequest.h @@ -21,17 +21,6 @@ #ifndef LSST_QSERV_REPLICA_STOPREQUEST_H #define LSST_QSERV_REPLICA_STOPREQUEST_H -/** - * This header declares a collection of classes representing various - * server-side request cancellation tools (requests) as a part of the - * Controller-side Replication Framework. - * - * @see class StopRequestReplicate - * @see class StopRequestDelete - * @see class StopRequestFind - * @see class StopRequestFindAll - */ - // System headers #include #include @@ -40,319 +29,86 @@ // Qserv headers #include "replica/proto/protocol.pb.h" -#include "replica/requests/Messenger.h" #include "replica/requests/RequestMessenger.h" -#include "replica/requests/StopRequestBase.h" -#include "replica/requests/SqlResultSet.h" -#include "replica/services/DatabaseServices.h" -#include "replica/services/ServiceProvider.h" #include "replica/util/Common.h" -#include "replica/util/ProtocolBuffer.h" -#include "replica/util/ReplicaInfo.h" -// This header declarations +// Forward declarations namespace lsst::qserv::replica { +class Controller; +} // namespace lsst::qserv::replica -// ======================================================================== -// Customizations for specific request types require dedicated policies -// ======================================================================== - -class StopReplicationRequestPolicy { -public: - using ResponseMessageType = ProtocolResponseReplicate; - using ResponseDataType = ReplicaInfo; - using TargetRequestParamsType = ReplicationRequestParams; - - static char const* requestName(); - static ProtocolQueuedRequestType targetRequestType(); - static void extractResponseData(ResponseMessageType const& msg, ResponseDataType& data); - static void extractTargetRequestParams(ResponseMessageType const& msg, TargetRequestParamsType& params); - - template - static void saveReplicaInfo(REQUEST_PTR const& request) { - request->serviceProvider()->databaseServices()->saveReplicaInfo(request->responseData()); - request->serviceProvider()->databaseServices()->updateRequestState( - *request, request->targetRequestId(), request->targetPerformance()); - } -}; - -class StopDeleteRequestPolicy { -public: - using ResponseMessageType = ProtocolResponseDelete; - using ResponseDataType = ReplicaInfo; - using TargetRequestParamsType = DeleteRequestParams; - - static char const* requestName(); - static ProtocolQueuedRequestType targetRequestType(); - static void extractResponseData(ResponseMessageType const& msg, ResponseDataType& data); - static void extractTargetRequestParams(ResponseMessageType const& msg, TargetRequestParamsType& params); - - template - static void saveReplicaInfo(REQUEST_PTR const& request) { - request->serviceProvider()->databaseServices()->saveReplicaInfo(request->responseData()); - request->serviceProvider()->databaseServices()->updateRequestState( - *request, request->targetRequestId(), request->targetPerformance()); - } -}; - -class StopFindRequestPolicy { -public: - using ResponseMessageType = ProtocolResponseFind; - using ResponseDataType = ReplicaInfo; - using TargetRequestParamsType = FindRequestParams; - - static char const* requestName(); - static ProtocolQueuedRequestType targetRequestType(); - static void extractResponseData(ResponseMessageType const& msg, ResponseDataType& data); - static void extractTargetRequestParams(ResponseMessageType const& msg, TargetRequestParamsType& params); - - template - static void saveReplicaInfo(REQUEST_PTR const& request) { - request->serviceProvider()->databaseServices()->saveReplicaInfo(request->responseData()); - request->serviceProvider()->databaseServices()->updateRequestState( - *request, request->targetRequestId(), request->targetPerformance()); - } -}; - -class StopFindAllRequestPolicy { -public: - using ResponseMessageType = ProtocolResponseFindAll; - using ResponseDataType = ReplicaInfoCollection; - using TargetRequestParamsType = FindAllRequestParams; - - static char const* requestName(); - static ProtocolQueuedRequestType targetRequestType(); - static void extractResponseData(ResponseMessageType const& msg, ResponseDataType& data); - static void extractTargetRequestParams(ResponseMessageType const& msg, TargetRequestParamsType& params); - - template - static void saveReplicaInfo(REQUEST_PTR const& request) { - request->serviceProvider()->databaseServices()->saveReplicaInfoCollection( - request->workerName(), request->targetRequestParams().database, request->responseData()); - request->serviceProvider()->databaseServices()->updateRequestState( - *request, request->targetRequestId(), request->targetPerformance()); - } -}; - -class StopEchoRequestPolicy { -public: - using ResponseMessageType = ProtocolResponseEcho; - using ResponseDataType = std::string; - using TargetRequestParamsType = EchoRequestParams; - - static char const* requestName(); - static ProtocolQueuedRequestType targetRequestType(); - static void extractResponseData(ResponseMessageType const& msg, ResponseDataType& data); - static void extractTargetRequestParams(ResponseMessageType const& msg, TargetRequestParamsType& params); - - template - static void saveReplicaInfo(REQUEST_PTR const& request) { - request->serviceProvider()->databaseServices()->updateRequestState( - *request, request->targetRequestId(), request->targetPerformance()); - } -}; - -/// @note This type of the management request for stopping the target request won't -/// return any data even in case when the target request was found successfully -/// completed. An assumption here is that since the target requests of this -/// kind have no side effects then they could always be resubmited if needed. -/// The response object will contained the server error should the request failed -/// at a worker. -class StopDirectorIndexRequestPolicy { -public: - using ResponseMessageType = ProtocolResponseDirectorIndex; - using ResponseDataType = std::string; - using TargetRequestParamsType = DirectorIndexRequestParams; - - static char const* requestName(); - static ProtocolQueuedRequestType targetRequestType(); - static void extractResponseData(ResponseMessageType const& msg, ResponseDataType& data); - static void extractTargetRequestParams(ResponseMessageType const& msg, TargetRequestParamsType& params); - - template - static void saveReplicaInfo(REQUEST_PTR const& request) { - request->serviceProvider()->databaseServices()->updateRequestState( - *request, request->targetRequestId(), request->targetPerformance()); - } -}; - -class StopSqlRequestPolicy { -public: - using ResponseMessageType = ProtocolResponseSql; - using ResponseDataType = SqlResultSet; - using TargetRequestParamsType = SqlRequestParams; - - static char const* requestName(); - static ProtocolQueuedRequestType targetRequestType(); - static void extractResponseData(ResponseMessageType const& msg, ResponseDataType& data); - static void extractTargetRequestParams(ResponseMessageType const& msg, TargetRequestParamsType& params); - - template - static void saveReplicaInfo(REQUEST_PTR const& request) { - request->serviceProvider()->databaseServices()->updateRequestState( - *request, request->targetRequestId(), request->targetPerformance()); - } -}; +// This header declarations +namespace lsst::qserv::replica { /** - * Generic class StopRequest extends its base class to allow further policy-based - * customization of specific requests. + * Class StopRequest is used for canceling the previously submitted requests. */ -template -class StopRequest : public StopRequestBase { +class StopRequest : public RequestMessenger { public: - typedef std::shared_ptr> Ptr; + typedef std::shared_ptr Ptr; /// The function type for notifications on the completion of the request typedef std::function CallbackType; - StopRequest() = delete; - StopRequest(StopRequest const&) = delete; - StopRequest& operator=(StopRequest const&) = delete; - - ~StopRequest() final = default; - - /// @return target request specific parameters - typename POLICY::TargetRequestParamsType const& targetRequestParams() const { - return _targetRequestParams; - } - - /** - * @return The request-specific extended data reported upon a successful - * completion of the request. - */ - typename POLICY::ResponseDataType const& responseData() const { return _responseData; } - /** * Create a new request with specified parameters. * * Static factory method is needed to prevent issue with the lifespan * and memory management of instances created otherwise (as values or via * low-level pointers). - * @param serviceProvider a host of services for various communications - * @param workerName the identifier of a worker node (the one to be affected by the request) - * @param io_service network communication service - * @param targetRequestId an identifier of the target request whose remote status - * is going to be inspected - * @param onFinish an optional callback function to be called upon a completion of - * the request. - * @param priority priority level of the request - * @param keepTracking keep tracking the request before it finishes or fails - * @param messenger an interface for communicating with workers - * @return A pointer to the created object. + * + * Class-specific parameters are documented below: + * @param targetRequestId An identifier of the target request to be stopped. + * + * @see The very base class Request for the description of the common parameters + * of all subclasses. + * + * @return A pointer to the created object. */ - static Ptr create(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - std::string const& workerName, std::string const& targetRequestId, - CallbackType const& onFinish, int priority, bool keepTracking, - std::shared_ptr const& messenger) { - return StopRequest::Ptr(new StopRequest( - serviceProvider, io_service, POLICY::requestName(), workerName, targetRequestId, - POLICY::targetRequestType(), onFinish, priority, keepTracking, messenger)); - } + static Ptr createAndStart(std::shared_ptr const& controller, std::string const& workerName, + std::string const& targetRequestId, CallbackType const& onFinish = nullptr, + int priority = PRIORITY_NORMAL, bool keepTracking = true, + std::string const& jobId = "", unsigned int requestExpirationIvalSec = 0); - /** - * Make an extended print of the request which would include a result set. - * The method will also make a call to Request::defaultPrinter(). - * @param ptr An object to be printed. - */ - static void extendedPrinter(Ptr const& ptr) { - Request::defaultPrinter(ptr); - std::cout << ptr->responseData() << std::endl; - } + StopRequest() = delete; + StopRequest(StopRequest const&) = delete; + StopRequest& operator=(StopRequest const&) = delete; -protected: - void notify(replica::Lock const& lock) final { notifyDefaultImpl>(lock, _onFinish); } + ~StopRequest() final = default; - void send(replica::Lock const& lock) final { - auto self = shared_from_base>(); - messenger()->send( - workerName(), id(), priority(), buffer(), - [self](std::string const& id, bool success, - typename POLICY::ResponseMessageType const& response) { - if (success) - self->analyze(true, self->_parseResponse(response)); - else - self->analyze(false); - }); - } + std::string const& targetRequestId() const { return _targetRequestId; } + std::list> extendedPersistentState() const override; + std::string toString(bool extended = false) const override; - void saveReplicaInfo() final { - auto const self = shared_from_base>(); - POLICY::saveReplicaInfo(self); - } +protected: + void startImpl(replica::Lock const& lock) final; + void notify(replica::Lock const& lock) final; + void savePersistentState(replica::Lock const& lock) final; + void awaken(boost::system::error_code const& ec) final; private: - StopRequest(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - char const* requestName, std::string const& workerName, std::string const& targetRequestId, - ProtocolQueuedRequestType targetRequestType, CallbackType const& onFinish, int priority, - bool keepTracking, std::shared_ptr const& messenger) - : StopRequestBase(serviceProvider, io_service, requestName, workerName, targetRequestId, - targetRequestType, priority, keepTracking, messenger), - _onFinish(onFinish) {} - + StopRequest(std::shared_ptr const& controller, std::string const& workerName, + std::string const& targetRequestId, CallbackType const& onFinish, int priority, + bool keepTracking); /** - * Parse request-specific reply. - * @param message A message to be parsed. - * @return The status of the operation reported by a server. + * Send the serialized content of the buffer to a worker + * @param lock a lock on Request::_mtx must be acquired before calling + * this method */ - ProtocolStatus _parseResponse(typename POLICY::ResponseMessageType const& message) { - // This lock must be acquired because the method is going to modify - // results of the request. Note that the operation doesn't care - // about the global state of the request (wether it's already finished - // or not). - replica::Lock lock(_mtx, context() + __func__); - - // Extract target request-specific parameters from the response if available. - POLICY::extractTargetRequestParams(message, _targetRequestParams); - - // Extract request-specific data from the response regardless of - // the completion status of the request. - POLICY::extractResponseData(message, _responseData); + void _send(replica::Lock const& lock); - // Always get the latest status reported by the remote server. - setExtendedServerStatus(lock, message.status_ext()); - - // Always update performance counters obtained from the worker service. - mutablePerformance().update(message.performance()); - - // Set the optional performance of the target operation. - if (message.has_target_performance()) { - _targetPerformance.update(message.target_performance()); - } - - // Field 'status' of a type returned by the current method always - // be defined in all types of request-specific responses. - return message.status(); - } + /** + * Process the worker response to the requested operation. + * @param success 'true' indicates a successful response from a worker + * @param message worker response (if success) + */ + void _analyze(bool success, ProtocolResponseStop message); // Input parameters - + std::string const _targetRequestId; CallbackType _onFinish; - - /// Request-specific parameters of the target request - typename POLICY::TargetRequestParamsType _targetRequestParams; - - /// Request-specific data - typename POLICY::ResponseDataType _responseData; }; -typedef StopRequest StopReplicationRequest; -typedef StopRequest StopDeleteRequest; -typedef StopRequest StopFindRequest; -typedef StopRequest StopFindAllRequest; -typedef StopRequest StopEchoRequest; -typedef StopRequest StopDirectorIndexRequest; -typedef StopRequest StopSqlQueryRequest; -typedef StopRequest StopSqlCreateDbRequest; -typedef StopRequest StopSqlDeleteDbRequest; -typedef StopRequest StopSqlEnableDbRequest; -typedef StopRequest StopSqlDisableDbRequest; -typedef StopRequest StopSqlGrantAccessRequest; -typedef StopRequest StopSqlCreateTableRequest; -typedef StopRequest StopSqlDeleteTableRequest; -typedef StopRequest StopSqlRemoveTablePartitionsRequest; -typedef StopRequest StopSqlDeleteTablePartitionRequest; - } // namespace lsst::qserv::replica #endif // LSST_QSERV_REPLICA_STOPREQUEST_H diff --git a/src/replica/requests/StopRequestBase.cc b/src/replica/requests/StopRequestBase.cc deleted file mode 100644 index af98582d0..000000000 --- a/src/replica/requests/StopRequestBase.cc +++ /dev/null @@ -1,181 +0,0 @@ -/* - * LSST Data Management System - * - * This product includes software developed by the - * LSST Project (http://www.lsst.org/). - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the LSST License Statement and - * the GNU General Public License along with this program. If not, - * see . - */ - -// Class header -#include "replica/requests/StopRequestBase.h" - -// System headers -#include -#include -#include - -// Third party headers -#include "boost/date_time/posix_time/posix_time.hpp" - -// Qserv headers -#include "replica/contr/Controller.h" -#include "replica/services/DatabaseServices.h" -#include "replica/services/ServiceProvider.h" -#include "replica/util/ProtocolBuffer.h" - -// LSST headers -#include "lsst/log/Log.h" - -using namespace std; -using namespace std::placeholders; - -namespace { - -LOG_LOGGER _log = LOG_GET("lsst.qserv.replica.StopRequest"); - -} // namespace - -namespace lsst::qserv::replica { - -StopRequestBase::StopRequestBase(ServiceProvider::Ptr const& serviceProvider, - boost::asio::io_service& io_service, char const* requestTypeName, - string const& workerName, string const& targetRequestId, - ProtocolQueuedRequestType targetRequestType, int priority, bool keepTracking, - shared_ptr const& messenger) - : RequestMessenger(serviceProvider, io_service, requestTypeName, workerName, priority, keepTracking, - false, // allowDuplicate - false, // disposeRequired - messenger), - _targetRequestId(targetRequestId), - _targetRequestType(targetRequestType) {} - -string StopRequestBase::toString(bool extended) const { - ostringstream oss(Request::toString(extended)); - oss << " targetRequestId: " << targetRequestId() << "\n" - << " targetPerformance: " << targetPerformance() << "\n"; - return oss.str(); -} - -void StopRequestBase::startImpl(replica::Lock const& lock) { - LOGS(_log, LOG_LVL_DEBUG, context() << __func__); - _sendImpl(lock); -} - -void StopRequestBase::awaken(boost::system::error_code const& ec) { - LOGS(_log, LOG_LVL_DEBUG, context() << __func__); - - if (isAborted(ec)) return; - - if (state() == State::FINISHED) return; - replica::Lock lock(_mtx, context() + __func__); - if (state() == State::FINISHED) return; - - _sendImpl(lock); -} - -void StopRequestBase::_sendImpl(replica::Lock const& lock) { - LOGS(_log, LOG_LVL_DEBUG, context() << __func__); - - // Serialize the Stop message header and the request itself into - // the network buffer. - - buffer()->resize(); - - ProtocolRequestHeader hdr; - hdr.set_id(id()); - hdr.set_type(ProtocolRequestHeader::REQUEST); - hdr.set_management_type(ProtocolManagementRequestType::REQUEST_STOP); - hdr.set_instance_id(serviceProvider()->instanceId()); - - buffer()->serialize(hdr); - - ProtocolRequestStop message; - message.set_id(_targetRequestId); - message.set_queued_type(_targetRequestType); - - buffer()->serialize(message); - - send(lock); -} - -void StopRequestBase::analyze(bool success, ProtocolStatus status) { - LOGS(_log, LOG_LVL_DEBUG, context() << __func__ << " success=" << (success ? "true" : "false")); - - // This method is called on behalf of an asynchronous callback fired - // upon a completion of the request within method send() - the only - // client of analyze(). So, we should take care of proper locking and watch - // for possible state transition which might occur while the async I/O was - // still in a progress. - if (state() == State::FINISHED) return; - replica::Lock lock(_mtx, context() + __func__); - if (state() == State::FINISHED) return; - - if (not success) { - finish(lock, CLIENT_ERROR); - return; - } - - switch (status) { - case ProtocolStatus::SUCCESS: - saveReplicaInfo(); - finish(lock, SUCCESS); - break; - - case ProtocolStatus::CREATED: - keepTrackingOrFinish(lock, SERVER_CREATED); - break; - - case ProtocolStatus::QUEUED: - keepTrackingOrFinish(lock, SERVER_QUEUED); - break; - - case ProtocolStatus::IN_PROGRESS: - keepTrackingOrFinish(lock, SERVER_IN_PROGRESS); - break; - - case ProtocolStatus::IS_CANCELLING: - keepTrackingOrFinish(lock, SERVER_IS_CANCELLING); - break; - - case ProtocolStatus::BAD: - finish(lock, SERVER_BAD); - break; - - case ProtocolStatus::FAILED: - finish(lock, SERVER_ERROR); - break; - - case ProtocolStatus::CANCELLED: - finish(lock, SERVER_CANCELLED); - break; - - default: - throw logic_error("StopRequestBase::" + string(__func__) + " unknown status '" + - ProtocolStatus_Name(status) + "' received from server"); - } -} - -void StopRequestBase::savePersistentState(replica::Lock const& lock) { - controller()->serviceProvider()->databaseServices()->saveState(*this, performance(lock)); -} - -list> StopRequestBase::extendedPersistentState() const { - list> result; - result.emplace_back("target_request_id", targetRequestId()); - return result; -} - -} // namespace lsst::qserv::replica diff --git a/src/replica/requests/StopRequestBase.h b/src/replica/requests/StopRequestBase.h deleted file mode 100644 index c3343f831..000000000 --- a/src/replica/requests/StopRequestBase.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * LSST Data Management System - * - * This product includes software developed by the - * LSST Project (http://www.lsst.org/). - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the LSST License Statement and - * the GNU General Public License along with this program. If not, - * see . - */ -#ifndef LSST_QSERV_REPLICA_STOPREQUESTBASE_H -#define LSST_QSERV_REPLICA_STOPREQUESTBASE_H - -// System headers - -#include -#include - -// Qserv headers -#include "replica/proto/protocol.pb.h" -#include "replica/requests/Messenger.h" -#include "replica/requests/RequestMessenger.h" -#include "replica/services/ServiceProvider.h" -#include "replica/util/Common.h" - -// This header declarations -namespace lsst::qserv::replica { - -/** - * Class StopRequestBase represents the base class for a family of requests - * stopping an on-going operation. - */ -class StopRequestBase : public RequestMessenger { -public: - typedef std::shared_ptr Ptr; - - StopRequestBase() = delete; - StopRequestBase(StopRequestBase const&) = delete; - StopRequestBase& operator=(StopRequestBase const&) = delete; - - ~StopRequestBase() override = default; - - /// @return an identifier of the target request - std::string const& targetRequestId() const { return _targetRequestId; } - - /// @return the performance info of the target operation (if available) - Performance const& targetPerformance() const { return _targetPerformance; } - - /// @see Request::extendedPersistentState() - std::list> extendedPersistentState() const override; - - std::string toString(bool extended = false) const override; - -protected: - /** - * Construct the request. - * @param serviceProvider a host of services for accessing Configuration, saving request's - * state in the database, etc. - * @param io_service communication services - * @param requestName the name of a request (used in reporting messages to the log stream, - * and when saving its state in the database) - * @param workerName the name of a worker node (the one to be affected by the request) - * @param targetRequestId an identifier of the target request whose remote status - * is going to be inspected - * @param targetRequestType the sub-type of the replication request (if applies for - * the general type above) - * @param priority priority level of the request - * @param keepTracking keep tracking the request before it finishes or fails - * @param messenger an interface for communicating with workers - */ - StopRequestBase(ServiceProvider::Ptr const& serviceProvider, boost::asio::io_service& io_service, - char const* requestName, std::string const& workerName, - std::string const& targetRequestId, ProtocolQueuedRequestType targetRequestType, - int priority, bool keepTracking, std::shared_ptr const& messenger); - - /// @see Request::startImpl() - void startImpl(replica::Lock const& lock) final; - - /// @see Request::awaken() - void awaken(boost::system::error_code const& ec) final; - - /** - * Initiate request-specific send. - * @param lock a lock on Request::_mtx must be acquired before calling this method - */ - virtual void send(replica::Lock const& lock) = 0; - - /** - * Process the worker response to the requested operation. - * @param success 'true' indicates a successful response from a worker - * @param status a response from the worker service (only valid if success is 'true') - */ - void analyze(bool success, ProtocolStatus status = ProtocolStatus::FAILED); - - /** - * Initiate request-specific operation with the persistent state - * service to store replica status. - */ - virtual void saveReplicaInfo() = 0; - - /// @see Request::savePersistentState() - void savePersistentState(replica::Lock const& lock) final; - - /// The performance of the target operation (this object is updated by subclasses) - Performance _targetPerformance; - -private: - /** - * Serialize request data into a network buffer and send the message to a worker - * @param lock a lock on Request::_mtx must be acquired before calling this method - */ - void _sendImpl(replica::Lock const& lock); - - // Input parameters - - std::string const _targetRequestId; - ProtocolQueuedRequestType const _targetRequestType; -}; - -} // namespace lsst::qserv::replica - -#endif // LSST_QSERV_REPLICA_STOPREQUESTBASE_H diff --git a/src/replica/worker/WorkerProcessor.cc b/src/replica/worker/WorkerProcessor.cc index c5b2cd913..d1ddca60f 100644 --- a/src/replica/worker/WorkerProcessor.cc +++ b/src/replica/worker/WorkerProcessor.cc @@ -405,6 +405,55 @@ void WorkerProcessor::enqueueForDirectorIndex(string const& id, int32_t priority } } +void WorkerProcessor::checkStatus(ProtocolRequestStatus const& request, ProtocolResponseStatus& response) { + replica::Lock lock(_mtx, _context(__func__)); + + // Still waiting in the queue? + WorkerRequest::Ptr targetRequestPtr; + for (auto ptr : _newRequests) { + if (ptr->id() == request.id()) { + targetRequestPtr = ptr; + break; + } + } + if (targetRequestPtr == nullptr) { + // Is it already being processed? + auto itrInProgress = _inProgressRequests.find(request.id()); + if (itrInProgress != _inProgressRequests.end()) { + targetRequestPtr = itrInProgress->second; + } + if (targetRequestPtr == nullptr) { + // Has it finished? + auto itrFinished = _finishedRequests.find(request.id()); + if (itrFinished != _finishedRequests.end()) { + targetRequestPtr = itrFinished->second; + } + // No such request? + if (targetRequestPtr == nullptr) { + response.set_status(ProtocolStatus::BAD); + response.set_status_ext(ProtocolStatusExt::INVALID_ID); + return; + } + } + } + response.set_status(ProtocolStatus::SUCCESS); + response.set_status_ext(ProtocolStatusExt::NONE); + response.set_target_status(targetRequestPtr->status()); + response.set_target_status_ext(targetRequestPtr->extendedStatus()); + response.set_allocated_target_performance(targetRequestPtr->performance().info().release()); +} + +void WorkerProcessor::dequeueOrCancel(ProtocolRequestStop const& request, ProtocolResponseStop& response) { + replica::Lock lock(_mtx, _context(__func__)); + if (_dequeueOrCancelImpl(lock, request.id()) == nullptr) { + response.set_status(ProtocolStatus::BAD); + response.set_status_ext(ProtocolStatusExt::INVALID_ID); + } else { + response.set_status(ProtocolStatus::SUCCESS); + response.set_status_ext(ProtocolStatusExt::NONE); + } +} + WorkerRequest::Ptr WorkerProcessor::_dequeueOrCancelImpl(replica::Lock const& lock, string const& id) { LOGS(_log, LOG_LVL_DEBUG, _context(__func__) << " id: " << id); @@ -491,7 +540,7 @@ WorkerRequest::Ptr WorkerProcessor::_dequeueOrCancelImpl(replica::Lock const& lo return WorkerRequest::Ptr(); } -WorkerRequest::Ptr WorkerProcessor::_checkStatusImpl(replica::Lock const& lock, string const& id) { +WorkerRequest::Ptr WorkerProcessor::_trackRequestImpl(replica::Lock const& lock, string const& id) { LOGS(_log, LOG_LVL_DEBUG, _context(__func__) << " id: " << id); // Still waiting in the queue? diff --git a/src/replica/worker/WorkerProcessor.h b/src/replica/worker/WorkerProcessor.h index e6dc75e22..4a01bbaa8 100644 --- a/src/replica/worker/WorkerProcessor.h +++ b/src/replica/worker/WorkerProcessor.h @@ -245,6 +245,11 @@ class WorkerProcessor : public std::enable_shared_from_this { response.set_status_ext(extendedStatus); } + /** + * Get a status of the request + */ + void checkStatus(ProtocolRequestStatus const& request, ProtocolResponseStatus& response); + /** * Dequeue replication request * @@ -253,42 +258,19 @@ class WorkerProcessor : public std::enable_shared_from_this { * to cancel processing will be made. If it has already processed this will * be reported. */ - template - void dequeueOrCancel(ProtocolRequestStop const& request, RESPONSE_MSG_TYPE& response) { - replica::Lock lock(_mtx, _context(__func__)); - - // Set this response unless an exact request (same type and identifier) - // will be found. - setDefaultResponse(response, ProtocolStatus::BAD, ProtocolStatusExt::INVALID_ID); - - if (WorkerRequest::Ptr const ptr = _dequeueOrCancelImpl(lock, request.id())) { - try { - // Set request-specific fields. Note exception handling for scenarios - // when request identifiers won't match actual types of requests - _setInfo(ptr, response); - - // The status field is present in all response types - response.set_status(ptr->status()); - response.set_status_ext(ptr->extendedStatus()); - - } catch (std::logic_error const& ex) { - ; - } - } - } + void dequeueOrCancel(ProtocolRequestStop const& request, ProtocolResponseStop& response); /** - * Return the status of an on-going replication request + * Return the tracking info on the on-going request */ template - void checkStatus(ProtocolRequestStatus const& request, RESPONSE_MSG_TYPE& response) { + void trackRequest(ProtocolRequestTrack const& request, RESPONSE_MSG_TYPE& response) { replica::Lock lock(_mtx, _context(__func__)); // Set this response unless an exact request (same type and identifier) // will be found. setDefaultResponse(response, ProtocolStatus::BAD, ProtocolStatusExt::INVALID_ID); - - if (WorkerRequest::Ptr const ptr = _checkStatusImpl(lock, request.id())) { + if (WorkerRequest::Ptr const ptr = _trackRequestImpl(lock, request.id())) { try { // Set request-specific fields. Note exception handling for scenarios // when request identifiers won't match actual types of requests @@ -297,7 +279,6 @@ class WorkerProcessor : public std::enable_shared_from_this { // The status field is present in all response types response.set_status(ptr->status()); response.set_status_ext(ptr->extendedStatus()); - } catch (std::logic_error const&) { ; } @@ -382,7 +363,7 @@ class WorkerProcessor : public std::enable_shared_from_this { * @return a valid reference to the request object (if found) * or a reference to nullptr otherwise. */ - WorkerRequest::Ptr _checkStatusImpl(replica::Lock const& lock, std::string const& id); + WorkerRequest::Ptr _trackRequestImpl(replica::Lock const& lock, std::string const& id); /** * Extract the extra data from the request and put diff --git a/src/replica/worker/WorkerServerConnection.cc b/src/replica/worker/WorkerServerConnection.cc index dffc33884..295a634d6 100644 --- a/src/replica/worker/WorkerServerConnection.cc +++ b/src/replica/worker/WorkerServerConnection.cc @@ -286,106 +286,76 @@ void WorkerServerConnection::_processManagementRequest(ProtocolRequestHeader con return; } switch (hdr.management_type()) { + case ProtocolManagementRequestType::REQUEST_STATUS: { + // Read the request body + ProtocolRequestStatus request; + if (not ::readMessage(context(), _socket, _bufferPtr, bytes, request)) return; + ProtocolResponseStatus response; + WorkerPerformance performance; + performance.setUpdateStart(); + if (_verifyInstance(hdr, response)) _processor->checkStatus(request, response); + performance.setUpdateFinish(); + response.set_allocated_performance(performance.info().release()); + _reply(hdr.id(), response); + break; + } case ProtocolManagementRequestType::REQUEST_STOP: { // Read the request body ProtocolRequestStop request; if (not ::readMessage(context(), _socket, _bufferPtr, bytes, request)) return; - - switch (request.queued_type()) { - case ProtocolQueuedRequestType::REPLICA_CREATE: { - ProtocolResponseReplicate response; - if (_verifyInstance(hdr, response)) _processor->dequeueOrCancel(request, response); - _reply(hdr.id(), response); - break; - } - case ProtocolQueuedRequestType::REPLICA_DELETE: { - ProtocolResponseDelete response; - if (_verifyInstance(hdr, response)) _processor->dequeueOrCancel(request, response); - _reply(hdr.id(), response); - break; - } - case ProtocolQueuedRequestType::REPLICA_FIND: { - ProtocolResponseFind response; - if (_verifyInstance(hdr, response)) _processor->dequeueOrCancel(request, response); - _reply(hdr.id(), response); - break; - } - case ProtocolQueuedRequestType::REPLICA_FIND_ALL: { - ProtocolResponseFindAll response; - if (_verifyInstance(hdr, response)) _processor->dequeueOrCancel(request, response); - _reply(hdr.id(), response); - break; - } - case ProtocolQueuedRequestType::TEST_ECHO: { - ProtocolResponseEcho response; - if (_verifyInstance(hdr, response)) _processor->dequeueOrCancel(request, response); - _reply(hdr.id(), response); - break; - } - case ProtocolQueuedRequestType::INDEX: { - ProtocolResponseDirectorIndex response; - if (_verifyInstance(hdr, response)) _processor->dequeueOrCancel(request, response); - _reply(hdr.id(), response); - break; - } - case ProtocolQueuedRequestType::SQL: { - ProtocolResponseSql response; - if (_verifyInstance(hdr, response)) _processor->dequeueOrCancel(request, response); - _reply(hdr.id(), response); - break; - } - default: - throw logic_error("WorkerServerConnection::" + string(__func__) + - " unhandled request type: '" + - ProtocolQueuedRequestType_Name(request.queued_type())); - } + ProtocolResponseStop response; + WorkerPerformance performance; + performance.setUpdateStart(); + if (_verifyInstance(hdr, response)) _processor->dequeueOrCancel(request, response); + performance.setUpdateFinish(); + response.set_allocated_performance(performance.info().release()); + _reply(hdr.id(), response); break; } - case ProtocolManagementRequestType::REQUEST_STATUS: { + case ProtocolManagementRequestType::REQUEST_TRACK: { // Read the request body - ProtocolRequestStatus request; + ProtocolRequestTrack request; if (not ::readMessage(context(), _socket, _bufferPtr, bytes, request)) return; - switch (request.queued_type()) { case ProtocolQueuedRequestType::REPLICA_CREATE: { ProtocolResponseReplicate response; - if (_verifyInstance(hdr, response)) _processor->checkStatus(request, response); + if (_verifyInstance(hdr, response)) _processor->trackRequest(request, response); _reply(hdr.id(), response); break; } case ProtocolQueuedRequestType::REPLICA_DELETE: { ProtocolResponseDelete response; - if (_verifyInstance(hdr, response)) _processor->checkStatus(request, response); + if (_verifyInstance(hdr, response)) _processor->trackRequest(request, response); _reply(hdr.id(), response); break; } case ProtocolQueuedRequestType::REPLICA_FIND: { ProtocolResponseFind response; - if (_verifyInstance(hdr, response)) _processor->checkStatus(request, response); + if (_verifyInstance(hdr, response)) _processor->trackRequest(request, response); _reply(hdr.id(), response); break; } case ProtocolQueuedRequestType::REPLICA_FIND_ALL: { ProtocolResponseFindAll response; - if (_verifyInstance(hdr, response)) _processor->checkStatus(request, response); + if (_verifyInstance(hdr, response)) _processor->trackRequest(request, response); _reply(hdr.id(), response); break; } case ProtocolQueuedRequestType::TEST_ECHO: { ProtocolResponseEcho response; - if (_verifyInstance(hdr, response)) _processor->checkStatus(request, response); + if (_verifyInstance(hdr, response)) _processor->trackRequest(request, response); _reply(hdr.id(), response); break; } case ProtocolQueuedRequestType::INDEX: { ProtocolResponseDirectorIndex response; - if (_verifyInstance(hdr, response)) _processor->checkStatus(request, response); + if (_verifyInstance(hdr, response)) _processor->trackRequest(request, response); _reply(hdr.id(), response); break; } case ProtocolQueuedRequestType::SQL: { ProtocolResponseSql response; - if (_verifyInstance(hdr, response)) _processor->checkStatus(request, response); + if (_verifyInstance(hdr, response)) _processor->trackRequest(request, response); _reply(hdr.id(), response); break; } @@ -400,7 +370,6 @@ void WorkerServerConnection::_processManagementRequest(ProtocolRequestHeader con // Read the request body ProtocolRequestDispose request; if (not ::readMessage(context(), _socket, _bufferPtr, bytes, request)) return; - ProtocolResponseDispose response; if (_verifyInstance(hdr, response)) { for (int i = 0; i < request.ids_size(); ++i) { diff --git a/src/replica/worker/WorkerServerConnection.h b/src/replica/worker/WorkerServerConnection.h index a50e90eb3..6c21e4998 100644 --- a/src/replica/worker/WorkerServerConnection.h +++ b/src/replica/worker/WorkerServerConnection.h @@ -204,6 +204,15 @@ class WorkerServerConnection : public std::enable_shared_from_thisinstanceId()) return true; + response.set_status(ProtocolStatus::BAD); + response.set_status_ext(ProtocolStatusExt::FOREIGN_INSTANCE); + return false; + } + /// The specialized version of the above defined template method for responses /// to the requests disposals. bool _verifyInstance(ProtocolRequestHeader const& hdr, ProtocolResponseDispose& response) const {