patch 421 dbms scheduler to master
This commit is contained in:
		| @ -74,120 +74,149 @@ int ObDBMSSchedJobExecutor::run_dbms_sched_job( | |||||||
|   } else { |   } else { | ||||||
|     CK (job_info.valid()); |     CK (job_info.valid()); | ||||||
|     CK ((job_info.get_what().length() != 0) || (job_info.get_program_name().length() != 0)); |     CK ((job_info.get_what().length() != 0) || (job_info.get_program_name().length() != 0)); | ||||||
|     if (job_info.get_what().length() != 0) { // action |     if (OB_SUCC(ret)) { | ||||||
|       if (job_info.is_oracle_tenant_) { |       if (job_info.get_what().length() != 0) { // action | ||||||
|         OZ (what.append_fmt("BEGIN %.*s; END;", |         if (job_info.is_oracle_tenant_) { | ||||||
|             job_info.get_what().length(), job_info.get_what().ptr())); |           OZ (what.append_fmt("BEGIN %.*s; END;", | ||||||
|       } else { |               job_info.get_what().length(), job_info.get_what().ptr())); | ||||||
|         //mysql mode not support anonymous block |         } else { | ||||||
|         OZ (what.append_fmt("CALL %.*s;", |           //mysql mode not support anonymous block | ||||||
|             job_info.get_what().length(), job_info.get_what().ptr())); |           OZ (what.append_fmt("CALL %.*s;", | ||||||
|       } |               job_info.get_what().length(), job_info.get_what().ptr())); | ||||||
|     } else { // program |         } | ||||||
|       ObSqlString sql; |       } else { // program | ||||||
|       ObString program_action; |         ObSqlString sql; | ||||||
|       uint64_t number_of_argument = 0; |         ObString program_action; | ||||||
|       OZ (sql.assign_fmt("select program_action, number_of_argument from %s where program_name = \'%.*s\'", |         uint64_t number_of_argument = 0; | ||||||
|         OB_ALL_TENANT_SCHEDULER_PROGRAM_TNAME, |         OZ (sql.assign_fmt("select program_action, number_of_argument from %s where program_name = \'%.*s\'", | ||||||
|         job_info.get_program_name().length(), |           OB_ALL_TENANT_SCHEDULER_PROGRAM_TNAME, | ||||||
|         job_info.get_program_name().ptr())); |           job_info.get_program_name().length(), | ||||||
|       SMART_VAR(ObMySQLProxy::MySQLResult, result) { |           job_info.get_program_name().ptr())); | ||||||
|         if (OB_FAIL(sql_proxy_->read(result, tenant_id, sql.ptr()))) { |         SMART_VAR(ObMySQLProxy::MySQLResult, result) { | ||||||
|           LOG_WARN("execute query failed", K(ret), K(sql), K(tenant_id), K(job_info.get_program_name().ptr()), K(job_info.get_job_name().ptr())); |           if (OB_FAIL(sql_proxy_->read(result, tenant_id, sql.ptr()))) { | ||||||
|         } else if (OB_NOT_NULL(result.get_result())) { |             LOG_WARN("execute query failed", K(ret), K(sql), K(tenant_id), K(job_info.get_program_name().ptr()), K(job_info.get_job_name().ptr())); | ||||||
|           if (OB_SUCCESS == (ret = result.get_result()->next())) { |           } else if (OB_ISNULL(result.get_result())) { | ||||||
|             EXTRACT_VARCHAR_FIELD_MYSQL_SKIP_RET(*(result.get_result()), "program_action", program_action); |             ret = OB_ERR_UNEXPECTED; | ||||||
|             EXTRACT_INT_FIELD_MYSQL_SKIP_RET(*(result.get_result()), "number_of_argument", number_of_argument, uint64_t); |             LOG_WARN("failed to get result", K(ret), K(tenant_id), K(job_info.get_job_name().ptr()), K(job_info.get_program_name().ptr())); | ||||||
|             if (OB_SUCC(ret) && (result.get_result()->next()) != OB_ITER_END) { |  | ||||||
|               LOG_ERROR("got more than one row for dbms sched program!", K(ret), K(tenant_id), K(job_info.get_job_name().ptr()), K(job_info.get_program_name().ptr())); |  | ||||||
|               ret = OB_ERR_UNEXPECTED; |  | ||||||
|             } |  | ||||||
|           } else if (OB_ITER_END == ret) { |  | ||||||
|             LOG_INFO("program not exists, may delete alreay!", K(ret), K(tenant_id), K(job_info.get_program_name().ptr()), K(job_info.get_program_name().ptr())); |  | ||||||
|             ret = OB_SUCCESS; |  | ||||||
|           } else { |           } else { | ||||||
|             LOG_WARN("failed to get next", K(ret), K(tenant_id), K(job_info.get_job_name().ptr()), K(job_info.get_program_name().ptr())); |             if (OB_SUCCESS == (ret = result.get_result()->next())) { | ||||||
|  |               EXTRACT_VARCHAR_FIELD_MYSQL_SKIP_RET(*(result.get_result()), "program_action", program_action); | ||||||
|  |               EXTRACT_INT_FIELD_MYSQL_SKIP_RET(*(result.get_result()), "number_of_argument", number_of_argument, uint64_t); | ||||||
|  |               if (OB_SUCC(ret)) { | ||||||
|  |                 int tmp_ret = result.get_result()->next(); | ||||||
|  |                 if (OB_SUCCESS == tmp_ret) { | ||||||
|  |                   ret = OB_ERR_UNEXPECTED; | ||||||
|  |                   LOG_ERROR("got more than one row for dbms sched program!", K(ret), K(tenant_id), K(job_info.get_job_name().ptr()), K(job_info.get_program_name().ptr())); | ||||||
|  |                 } else if (tmp_ret != OB_ITER_END) { | ||||||
|  |                   ret = tmp_ret; | ||||||
|  |                   LOG_WARN("got next row for dbms sched program failed", K(ret), K(tenant_id), K(job_info.get_job_name().ptr()), K(job_info.get_program_name().ptr())); | ||||||
|  |                 } | ||||||
|  |               } | ||||||
|  |             } else if (OB_ITER_END == ret) { | ||||||
|  |               LOG_INFO("program not exists, may delete alreay!", K(ret), K(tenant_id), K(job_info.get_program_name().ptr()), K(job_info.get_program_name().ptr())); | ||||||
|  |               ret = OB_SUCCESS; | ||||||
|  |             } else { | ||||||
|  |               LOG_WARN("failed to get next", K(ret), K(tenant_id), K(job_info.get_job_name().ptr()), K(job_info.get_program_name().ptr())); | ||||||
|  |             } | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|       } |         OZ (what.append_fmt("BEGIN %.*s(", | ||||||
|       OZ (what.append_fmt("BEGIN %.*s(", |           program_action.length(), program_action.ptr())); | ||||||
|         program_action.length(), program_action.ptr())); |         if (OB_SUCC(ret) && (0 != number_of_argument)) { | ||||||
|       if (OB_SUCC(ret) && (0 != number_of_argument)) { |           ObString argument_value; | ||||||
|         ObString argument_value; |           for (int i = 1; OB_SUCC(ret) && i <= number_of_argument; i++) { | ||||||
|         for (int i = 1; OB_SUCC(ret) && i <= number_of_argument; i++) { |             argument_value.reset(); | ||||||
|           argument_value.reset(); |             OZ (sql.assign_fmt("select default_value from %s where program_name = \'%.*s\' and job_name = \'%.*s\' and argument_position = %d and is_for_default = 0", | ||||||
|           OZ (sql.assign_fmt("select default_value from %s where program_name = \'%.*s\' and job_name = \'%.*s\' and argument_position = %d and is_for_default = 0", |               OB_ALL_TENANT_SCHEDULER_PROGRAM_ARGUMENT_TNAME, | ||||||
|             OB_ALL_TENANT_SCHEDULER_PROGRAM_ARGUMENT_TNAME, |               job_info.get_program_name().length(), | ||||||
|             job_info.get_program_name().length(), |               job_info.get_program_name().ptr(), | ||||||
|             job_info.get_program_name().ptr(), |               job_info.get_job_name().length(), | ||||||
|             job_info.get_job_name().length(), |               job_info.get_job_name().ptr(), | ||||||
|             job_info.get_job_name().ptr(), |               i)); | ||||||
|             i)); |             SMART_VAR(ObMySQLProxy::MySQLResult, result) { | ||||||
|           SMART_VAR(ObMySQLProxy::MySQLResult, result) { |               if (OB_FAIL(sql_proxy_->read(result, tenant_id, sql.ptr()))) { | ||||||
|             if (OB_FAIL(sql_proxy_->read(result, tenant_id, sql.ptr()))) { |                 LOG_WARN("execute query failed", K(ret), K(sql), K(result.get_result()), K(tenant_id), K(job_info.get_job_name().ptr())); | ||||||
|               LOG_WARN("execute query failed", K(ret), K(sql), K(result.get_result()), K(tenant_id), K(job_info.get_job_name().ptr())); |               } else if (OB_ISNULL(result.get_result())) { | ||||||
|             } else if (OB_NOT_NULL(result.get_result())) { |                 ret = OB_ERR_UNEXPECTED; | ||||||
|               if (OB_SUCCESS == (ret = result.get_result()->next())) { |                 LOG_WARN("failed to get result", K(ret), K(tenant_id), K(job_info.get_job_name().ptr())); | ||||||
|                 EXTRACT_VARCHAR_FIELD_MYSQL_SKIP_RET(*(result.get_result()), "default_value", argument_value); |               } else { | ||||||
|                 if (OB_SUCC(ret) && (result.get_result()->next()) != OB_ITER_END) { |                 if (OB_SUCCESS == (ret = result.get_result()->next())) { | ||||||
|                   LOG_ERROR("got more than one row for argument!", K(ret), K(tenant_id), K(job_info.get_job_name().ptr()), K(job_info.get_program_name().ptr())); |                   EXTRACT_VARCHAR_FIELD_MYSQL_SKIP_RET(*(result.get_result()), "default_value", argument_value); | ||||||
|                   ret = OB_ERR_UNEXPECTED; |                   if (OB_SUCC(ret)) { | ||||||
|                 } |                     int tmp_ret = result.get_result()->next(); | ||||||
|               } else if (OB_ITER_END == ret) { |                     if (OB_SUCCESS == tmp_ret) { | ||||||
|                 LOG_INFO("job argument not exists, use default"); |                       ret = OB_ERR_UNEXPECTED; | ||||||
|                 ret = OB_SUCCESS; |                       LOG_ERROR("got more than one row for argument!", K(ret), K(tenant_id), K(job_info.get_job_name().ptr()), K(job_info.get_program_name().ptr())); | ||||||
|                 OZ (sql.assign_fmt("select default_value from %s where program_name = \'%.*s\' and job_name = \'%s\' and argument_position = %d and is_for_default = 1", |                     } else if (tmp_ret != OB_ITER_END) { | ||||||
|                   OB_ALL_TENANT_SCHEDULER_PROGRAM_ARGUMENT_TNAME, |                       ret = tmp_ret; | ||||||
|                   job_info.get_program_name().length(), |                       LOG_WARN("got next row for argument failed", K(ret), K(tenant_id), K(job_info.get_job_name().ptr()), K(job_info.get_program_name().ptr())); | ||||||
|                   job_info.get_program_name().ptr(), |  | ||||||
|                   "default", |  | ||||||
|                   i)); |  | ||||||
|                 SMART_VAR(ObMySQLProxy::MySQLResult, tmp_result) { |  | ||||||
|                   if (OB_FAIL(sql_proxy_->read(tmp_result, tenant_id, sql.ptr()))) { |  | ||||||
|                     LOG_WARN("execute query failed", K(ret), K(sql), K(tenant_id), K(job_info.get_job_name().ptr())); |  | ||||||
|                   } else if (OB_NOT_NULL(tmp_result.get_result())) { |  | ||||||
|                     if (OB_SUCCESS == (ret = tmp_result.get_result()->next())) { |  | ||||||
|                       EXTRACT_VARCHAR_FIELD_MYSQL_SKIP_RET(*(tmp_result.get_result()), "default_value", argument_value); |  | ||||||
|                       if (OB_SUCC(ret) && (tmp_result.get_result()->next()) != OB_ITER_END) { |  | ||||||
|                         LOG_ERROR("got more than one row for argument!", K(ret), K(tenant_id), K(job_info.get_job_name().ptr()), K(job_info.get_program_name().ptr())); |  | ||||||
|                         ret = OB_ERR_UNEXPECTED; |  | ||||||
|                       } |  | ||||||
|                     } else if (OB_ITER_END == ret) { |  | ||||||
|                       LOG_ERROR("program default argument not exists", K(sql.ptr()), K(job_info.get_program_name().ptr())); |  | ||||||
|                     } else { |  | ||||||
|                       LOG_WARN("failed to get next", K(ret), K(tenant_id), K(job_info.get_job_name().ptr())); |  | ||||||
|                     } |                     } | ||||||
|                   } |                   } | ||||||
|  |                 } else if (OB_ITER_END == ret) { | ||||||
|  |                   LOG_INFO("job argument not exists, use default"); | ||||||
|  |                   ret = OB_SUCCESS; | ||||||
|  |                   OZ (sql.assign_fmt("select default_value from %s where program_name = \'%.*s\' and job_name = \'%s\' and argument_position = %d and is_for_default = 1", | ||||||
|  |                     OB_ALL_TENANT_SCHEDULER_PROGRAM_ARGUMENT_TNAME, | ||||||
|  |                     job_info.get_program_name().length(), | ||||||
|  |                     job_info.get_program_name().ptr(), | ||||||
|  |                     "default", | ||||||
|  |                     i)); | ||||||
|  |                   SMART_VAR(ObMySQLProxy::MySQLResult, tmp_result) { | ||||||
|  |                     if (OB_FAIL(sql_proxy_->read(tmp_result, tenant_id, sql.ptr()))) { | ||||||
|  |                       LOG_WARN("execute query failed", K(ret), K(sql), K(tenant_id), K(job_info.get_job_name().ptr())); | ||||||
|  |                     } else if (OB_ISNULL(tmp_result.get_result())) { | ||||||
|  |                       ret = OB_ERR_UNEXPECTED; | ||||||
|  |                       LOG_WARN("failed to get result", K(ret), K(tenant_id), K(job_info.get_job_name().ptr())); | ||||||
|  |                     } else { | ||||||
|  |                       if (OB_SUCCESS == (ret = tmp_result.get_result()->next())) { | ||||||
|  |                         EXTRACT_VARCHAR_FIELD_MYSQL_SKIP_RET(*(tmp_result.get_result()), "default_value", argument_value); | ||||||
|  |                         if (OB_SUCC(ret)) { | ||||||
|  |                           int tmp_ret = tmp_result.get_result()->next(); | ||||||
|  |                           if (OB_SUCCESS == tmp_ret) { | ||||||
|  |                             ret = OB_ERR_UNEXPECTED; | ||||||
|  |                             LOG_ERROR("got more than one row for argument!", K(ret), K(tenant_id), K(job_info.get_job_name().ptr()), K(job_info.get_program_name().ptr())); | ||||||
|  |                           } else if (tmp_ret != OB_ITER_END) { | ||||||
|  |                             ret = tmp_ret; | ||||||
|  |                             LOG_WARN("got next row for argument failed", K(ret), K(tenant_id), K(job_info.get_job_name().ptr()), K(job_info.get_program_name().ptr())); | ||||||
|  |                           } | ||||||
|  |                         } | ||||||
|  |                       } else if (OB_ITER_END == ret) { | ||||||
|  |                         LOG_ERROR("program default argument not exists", K(sql.ptr()), K(job_info.get_program_name().ptr())); | ||||||
|  |                       } else { | ||||||
|  |                         LOG_WARN("failed to get next", K(ret), K(tenant_id), K(job_info.get_job_name().ptr())); | ||||||
|  |                       } | ||||||
|  |                     } | ||||||
|  |                   } | ||||||
|  |                   ret = OB_SUCCESS; | ||||||
|  |                 } else { | ||||||
|  |                   LOG_WARN("failed to get next", K(ret), K(tenant_id), K(job_info.get_job_name().ptr())); | ||||||
|                 } |                 } | ||||||
|                 ret = OB_SUCCESS; |  | ||||||
|               } else { |  | ||||||
|                 LOG_WARN("failed to get next", K(ret), K(tenant_id), K(job_info.get_job_name().ptr())); |  | ||||||
|               } |               } | ||||||
|             } |             } | ||||||
|  |             if (i == 1) { | ||||||
|  |               OZ (what.append_fmt("\'%.*s\'", argument_value.length(), argument_value.ptr())); | ||||||
|  |             } else { | ||||||
|  |               OZ (what.append_fmt(",\'%.*s\'", argument_value.length(), argument_value.ptr())); | ||||||
|  |             } | ||||||
|           } |           } | ||||||
|           if (i == 1) { |           OZ (what.append_fmt("); END;")); | ||||||
|             OZ (what.append_fmt("\'%.*s\'", argument_value.length(), argument_value.ptr())); |         } else { | ||||||
|           } else { |           LOG_ERROR("number_of_argument not exist or not right", K(ret), K(number_of_argument)); | ||||||
|             OZ (what.append_fmt(",\'%.*s\'", argument_value.length(), argument_value.ptr())); |  | ||||||
|           } |  | ||||||
|         } |         } | ||||||
|         OZ (what.append_fmt("); END;")); |  | ||||||
|       } else { |  | ||||||
|         LOG_ERROR("number_of_argument not exist or not right", K(ret), K(number_of_argument)); |  | ||||||
|       } |       } | ||||||
|     } |       if (job_info.is_oracle_tenant_) { | ||||||
|     if (job_info.is_oracle_tenant_) { |         ObOracleSqlProxy oracle_proxy(*(static_cast<ObMySQLProxy *>(sql_proxy_))); | ||||||
|       ObOracleSqlProxy oracle_proxy(*(static_cast<ObMySQLProxy *>(sql_proxy_))); |         CK (OB_NOT_NULL(pool = static_cast<ObInnerSQLConnectionPool *>(oracle_proxy.get_pool()))); | ||||||
|       CK (OB_NOT_NULL(pool = static_cast<ObInnerSQLConnectionPool *>(oracle_proxy.get_pool()))); |         OZ (ObDBMSSchedJobUtils::init_env(job_info, *session_info)); | ||||||
|       OZ (ObDBMSSchedJobUtils::init_env(job_info, *session_info)); |         OZ (pool->acquire_spi_conn(session_info, conn)); | ||||||
|       OZ (pool->acquire_spi_conn(session_info, conn)); |         OZ (conn->execute_write(tenant_id, what.string().ptr(), affected_rows)); | ||||||
|       OZ (conn->execute_write(tenant_id, what.string().ptr(), affected_rows)); |         if (OB_NOT_NULL(conn)) { | ||||||
|       if (OB_NOT_NULL(conn)) { |           sql_proxy_->close(conn, ret); | ||||||
|         sql_proxy_->close(conn, ret); |         } | ||||||
|  |       } else {//mysql mode need use mysql proxy | ||||||
|  |         OZ (ObDBMSSchedJobUtils::init_env(job_info, *session_info)); | ||||||
|  |         OZ (sql_proxy_->write(tenant_id, what.string().ptr(), affected_rows)); | ||||||
|       } |       } | ||||||
|     } else {//mysql mode need use mysql proxy |  | ||||||
|       OZ (ObDBMSSchedJobUtils::init_env(job_info, *session_info)); |  | ||||||
|       OZ (sql_proxy_->write(tenant_id, what.string().ptr(), affected_rows)); |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   if (NULL != session_info) { |   if (NULL != session_info) { | ||||||
| @ -211,7 +240,6 @@ int ObDBMSSchedJobExecutor::run_dbms_sched_job(uint64_t tenant_id, bool is_oracl | |||||||
|   OZ (table_operator_.get_dbms_sched_job_info(tenant_id, is_oracle_tenant, job_id, job_name, allocator, job_info)); |   OZ (table_operator_.get_dbms_sched_job_info(tenant_id, is_oracle_tenant, job_id, job_name, allocator, job_info)); | ||||||
|  |  | ||||||
|   if (OB_SUCC(ret)) { |   if (OB_SUCC(ret)) { | ||||||
|     OZ (table_operator_.update_for_start(tenant_id, job_info)); |  | ||||||
|  |  | ||||||
|     OZ (run_dbms_sched_job(tenant_id, job_info)); |     OZ (run_dbms_sched_job(tenant_id, job_info)); | ||||||
|  |  | ||||||
|  | |||||||
| @ -29,6 +29,8 @@ | |||||||
| #include "observer/ob_server_struct.h" | #include "observer/ob_server_struct.h" | ||||||
| #include "rootserver/ob_root_service.h" | #include "rootserver/ob_root_service.h" | ||||||
|  |  | ||||||
|  | #define TO_TS(second) (1000000L * second) | ||||||
|  |  | ||||||
| namespace oceanbase | namespace oceanbase | ||||||
| { | { | ||||||
| using namespace common; | using namespace common; | ||||||
| @ -48,26 +50,20 @@ int ObDBMSSchedJobTask::init() | |||||||
|   if (inited_) { |   if (inited_) { | ||||||
|     ret = OB_INIT_TWICE; |     ret = OB_INIT_TWICE; | ||||||
|     LOG_WARN("init twice", K(ret), K(inited_)); |     LOG_WARN("init twice", K(ret), K(inited_)); | ||||||
|   } else if (OB_FAIL(timer_.init())) { |  | ||||||
|     LOG_WARN("fail to init timer", K(ret)); |  | ||||||
|   } else { |   } else { | ||||||
|     inited_ = true; |     inited_ = true; | ||||||
|   } |   } | ||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| int ObDBMSSchedJobTask::start(dbms_job::ObDBMSJobQueue *ready_queue) | int ObDBMSSchedJobTask::start(ObVSliceAlloc *allocator) | ||||||
| { | { | ||||||
|   int ret = OB_SUCCESS; |   int ret = OB_SUCCESS; | ||||||
|   if (!inited_) { |   if (!inited_) { | ||||||
|     ret = OB_NOT_INIT; |     ret = OB_NOT_INIT; | ||||||
|     LOG_WARN("dbms sched job task not inited", K(ret), K(inited_)); |     LOG_WARN("dbms sched job task not inited", K(ret), K(inited_)); | ||||||
|   } else if (OB_ISNULL(ready_queue)) { |  | ||||||
|     ret = OB_ERR_UNEXPECTED; |  | ||||||
|     LOG_WARN("NULL ptr", K(ret), K(ready_queue)); |  | ||||||
|   } |   } | ||||||
|   ready_queue_ = ready_queue; |   allocator_ = allocator; | ||||||
|   OZ (timer_.start()); |  | ||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -78,12 +74,15 @@ int ObDBMSSchedJobTask::stop() | |||||||
|     ret = OB_NOT_INIT; |     ret = OB_NOT_INIT; | ||||||
|     LOG_WARN("dbms sched job task not inited", K(ret), K(inited_)); |     LOG_WARN("dbms sched job task not inited", K(ret), K(inited_)); | ||||||
|   } else { |   } else { | ||||||
|     timer_.cancel(*this); |     if (allocator_ != NULL) { | ||||||
|     timer_.stop(); |       for (WaitVectorIterator iter = wait_vector_.begin(); | ||||||
|     timer_.wait(); |               OB_SUCC(ret) && iter != wait_vector_.end(); ++iter) { | ||||||
|  |         ObDBMSSchedJobKey *job_key = *iter; | ||||||
|  |         allocator_->free(job_key); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|     wait_vector_.clear(); |     wait_vector_.clear(); | ||||||
|     job_key_ = NULL; |     allocator_ = NULL; | ||||||
|     ready_queue_ = NULL; |  | ||||||
|   } |   } | ||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
| @ -94,50 +93,10 @@ int ObDBMSSchedJobTask::destroy() | |||||||
|   if (!inited_) { |   if (!inited_) { | ||||||
|     ret = OB_NOT_INIT; |     ret = OB_NOT_INIT; | ||||||
|     LOG_WARN("scheduler task not inited", K(ret), K(inited_)); |     LOG_WARN("scheduler task not inited", K(ret), K(inited_)); | ||||||
|   } else { |  | ||||||
|     timer_.destroy(); |  | ||||||
|   } |   } | ||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| void ObDBMSSchedJobTask::runTimerTask() |  | ||||||
| { |  | ||||||
|   int ret = OB_SUCCESS; |  | ||||||
|   ObSpinLockGuard guard(lock_); |  | ||||||
|   if (!inited_) { |  | ||||||
|     ret = OB_NOT_INIT; |  | ||||||
|     LOG_WARN("dbms sched job task not init", K(ret), K(inited_)); |  | ||||||
|   } else if (OB_ISNULL(job_key_) |  | ||||||
|           || OB_ISNULL(ready_queue_)) { |  | ||||||
|     ret = OB_ERR_UNEXPECTED; |  | ||||||
|     LOG_WARN("null ptr", K(ret), K(job_key_), K(ready_queue_)); |  | ||||||
|   } else if (OB_FAIL(ready_queue_->push(job_key_, 0))) { |  | ||||||
|     LOG_WARN("fail to push ready job to queue", K(ret), K(*job_key_)); |  | ||||||
|   } else { |  | ||||||
|     job_key_ = NULL; |  | ||||||
|     if (wait_vector_.count() > 0) { |  | ||||||
|       job_key_ = wait_vector_[0]; |  | ||||||
|       if (OB_FAIL(wait_vector_.remove(wait_vector_.begin()))) { |  | ||||||
|         job_key_ = NULL; |  | ||||||
|         LOG_WARN("fail to remove job_id from sorted vector", K(ret)); |  | ||||||
|       } else if (OB_ISNULL(job_key_)) { |  | ||||||
|         ret = OB_ERR_UNEXPECTED; |  | ||||||
|         LOG_WARN("NULL ptr", K(ret), K(job_key_)); |  | ||||||
|       } else if (OB_FAIL(timer_.schedule(*this, job_key_->get_adjust_delay()))) { |  | ||||||
|         LOG_WARN("fail to schedule task", K(ret), K(*job_key_)); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   LOG_DEBUG("JobKEYS INFO HEADER ==== ", KPC(job_key_), K(wait_vector_.count())); |  | ||||||
|   int i = 0; |  | ||||||
|   for (WaitVectorIterator iter = wait_vector_.begin(); |  | ||||||
|           OB_SUCC(ret) && iter != wait_vector_.end(); ++iter, ++i) { |  | ||||||
|     ObDBMSSchedJobKey *job = *iter; |  | ||||||
|     LOG_DEBUG("JobKEYS INFO ELEMENT ====", K(i), KPC(job)); |  | ||||||
|   } |  | ||||||
|   return; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int ObDBMSSchedJobTask::scheduler(ObDBMSSchedJobKey *job_key) | int ObDBMSSchedJobTask::scheduler(ObDBMSSchedJobKey *job_key) | ||||||
| { | { | ||||||
|   int ret = OB_SUCCESS; |   int ret = OB_SUCCESS; | ||||||
| @ -146,12 +105,10 @@ int ObDBMSSchedJobTask::scheduler(ObDBMSSchedJobKey *job_key) | |||||||
|     LOG_WARN("dbms sched job task not init", K(ret)); |     LOG_WARN("dbms sched job task not init", K(ret)); | ||||||
|   } else if (OB_ISNULL(job_key)) { |   } else if (OB_ISNULL(job_key)) { | ||||||
|     ret = OB_ERR_UNEXPECTED; |     ret = OB_ERR_UNEXPECTED; | ||||||
|     LOG_WARN("NULL ptr for job id", K(ret), KPC(job_key)); |     LOG_WARN("NULL ptr for job id", K(ret)); | ||||||
|   } else if (!job_key->is_valid()) { |   } else if (!job_key->is_valid()) { | ||||||
|     ret = OB_ERR_UNEXPECTED; |     ret = OB_ERR_UNEXPECTED; | ||||||
|     LOG_WARN("job id is invalid", K(ret), KPC(job_key)); |     LOG_WARN("job id is invalid", K(ret), KPC(job_key)); | ||||||
|   } else if (0 == job_key->get_delay()) { |  | ||||||
|     OZ (immediately(job_key), KPC(job_key)); |  | ||||||
|   } else { |   } else { | ||||||
|     OZ (add_new_job(job_key), KPC(job_key)); |     OZ (add_new_job(job_key), KPC(job_key)); | ||||||
|   } |   } | ||||||
| @ -169,40 +126,19 @@ int ObDBMSSchedJobTask::add_new_job(ObDBMSSchedJobKey *new_job_key) | |||||||
|     ret = OB_ERR_UNEXPECTED; |     ret = OB_ERR_UNEXPECTED; | ||||||
|     LOG_WARN("NULL ptr", K(ret), KPC(new_job_key)); |     LOG_WARN("NULL ptr", K(ret), KPC(new_job_key)); | ||||||
|   } else { |   } else { | ||||||
|     ObSpinLockGuard guard(lock_); |     WaitVectorIterator iter; | ||||||
|     if (OB_ISNULL(job_key_)) { |     ObDBMSSchedJobKey *replace_job_key = NULL; | ||||||
|       job_key_ = new_job_key; |     OZ (wait_vector_.replace(new_job_key, iter, compare_job_key, equal_job_key, replace_job_key)); | ||||||
|       OZ (timer_.schedule(*this, job_key_->get_delay())); |  | ||||||
|     } else if (new_job_key->get_execute_at() >= job_key_->get_execute_at()) { |  | ||||||
|       WaitVectorIterator iter; |  | ||||||
|       ObDBMSSchedJobKey *replace_job_key = NULL; |  | ||||||
|       OZ (wait_vector_.replace(new_job_key, iter, compare_job_key, equal_job_key, replace_job_key)); |  | ||||||
|     } else { |  | ||||||
|       WaitVectorIterator iter; |  | ||||||
|       OX (timer_.cancel(*this)); |  | ||||||
|       OZ (wait_vector_.insert(job_key_, iter, compare_job_key)); |  | ||||||
|       OX (job_key_ = new_job_key); |  | ||||||
|       OZ (timer_.schedule(*this, job_key_->get_delay())); |  | ||||||
|     } |  | ||||||
|   } |   } | ||||||
|   return ret; |   /* | ||||||
| } |   LOG_DEBUG("JobKEYS INFO HEADER ==== ", KPC(new_job_key), K(wait_vector_.count())); | ||||||
|  |   int i = 0; | ||||||
| int ObDBMSSchedJobTask::immediately(ObDBMSSchedJobKey *job_key) |   for (WaitVectorIterator iter = wait_vector_.begin(); | ||||||
| { |           OB_SUCC(ret) && iter != wait_vector_.end(); ++iter, ++i) { | ||||||
|   int ret = OB_SUCCESS; |     ObDBMSSchedJobKey *job = *iter; | ||||||
|   if (!inited_) { |     LOG_DEBUG("JobKEYS INFO ELEMENT ====", K(i), KPC(job)); | ||||||
|     ret = OB_NOT_INIT; |  | ||||||
|     LOG_WARN("dbms sched job not init", K(ret), K(inited_)); |  | ||||||
|   } else if (OB_ISNULL(job_key) || OB_ISNULL(ready_queue_)) { |  | ||||||
|     ret = OB_ERR_UNEXPECTED; |  | ||||||
|     LOG_WARN("NULL ptr", K(ret), K(job_key), K(ready_queue_)); |  | ||||||
|   } else { |  | ||||||
|     ObSpinLockGuard guard(lock_); |  | ||||||
|     if (OB_FAIL(ready_queue_->push(job_key, 0))) { |  | ||||||
|       LOG_WARN("fail to push ready job to queue", K(ret), K(*job_key)); |  | ||||||
|     } |  | ||||||
|   } |   } | ||||||
|  |   */ | ||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -258,8 +194,6 @@ int ObDBMSSchedJobMaster::init(ObUnitManager *unit_mgr, | |||||||
|           ) { |           ) { | ||||||
|     ret = OB_ERR_UNEXPECTED; |     ret = OB_ERR_UNEXPECTED; | ||||||
|     LOG_WARN("null ptr", K(ret), K(unit_mgr), K(sql_client), K(schema_service)); |     LOG_WARN("null ptr", K(ret), K(unit_mgr), K(sql_client), K(schema_service)); | ||||||
|   } else if (FALSE_IT(ready_queue_.set_limit(MAX_READY_JOBS_CAPACITY))) { |  | ||||||
|     // do-nothing |  | ||||||
|   } else if (OB_FAIL(scheduler_task_.init())) { |   } else if (OB_FAIL(scheduler_task_.init())) { | ||||||
|     LOG_WARN("fail to init ready queue", K(ret)); |     LOG_WARN("fail to init ready queue", K(ret)); | ||||||
|   } else if (OB_FAIL(scheduler_thread_.init(1, 1))) { |   } else if (OB_FAIL(scheduler_thread_.init(1, 1))) { | ||||||
| @ -293,7 +227,7 @@ int ObDBMSSchedJobMaster::start() | |||||||
|     // alreay running , do nothing ... |     // alreay running , do nothing ... | ||||||
|   } else if (OB_FAIL(scheduler_thread_.push(static_cast<void *>(this)))) { |   } else if (OB_FAIL(scheduler_thread_.push(static_cast<void *>(this)))) { | ||||||
|     LOG_WARN("fail to start scheduler thread", K(ret)); |     LOG_WARN("fail to start scheduler thread", K(ret)); | ||||||
|   } else if (OB_FAIL(scheduler_task_.start(&ready_queue_))) { |   } else if (OB_FAIL(scheduler_task_.start(&allocator_))) { | ||||||
|     LOG_WARN("fail to start ready queue", K(ret)); |     LOG_WARN("fail to start ready queue", K(ret)); | ||||||
|   } |   } | ||||||
|   LOG_INFO("dbms sched job master started", K(ret)); |   LOG_INFO("dbms sched job master started", K(ret)); | ||||||
| @ -308,13 +242,52 @@ int ObDBMSSchedJobMaster::stop() | |||||||
|     sleep(1); |     sleep(1); | ||||||
|   } |   } | ||||||
|   scheduler_task_.stop(); |   scheduler_task_.stop(); | ||||||
|   ready_queue_.clear(); |  | ||||||
|   alive_jobs_.clear(); |   alive_jobs_.clear(); | ||||||
|   stoped_ = false; |   stoped_ = false; | ||||||
|   LOG_INFO("dbms sched job master stoped", K(ret)); |   LOG_INFO("dbms sched job master stoped", K(ret)); | ||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | int64_t ObDBMSSchedJobMaster::calc_next_date(ObDBMSSchedJobInfo &job_info) | ||||||
|  | { | ||||||
|  |   int64_t next_date = 0; | ||||||
|  |   const int64_t now = ObTimeUtility::current_time(); | ||||||
|  |   if (job_info.get_interval_ts() == 0) { | ||||||
|  |     next_date = 64060560000000000; | ||||||
|  |   } else { | ||||||
|  |     int64_t N = (now - job_info.get_start_date()) / job_info.get_interval_ts(); | ||||||
|  |     next_date = job_info.get_start_date() + (N + 1) * job_info.get_interval_ts(); | ||||||
|  |   } | ||||||
|  |   return next_date; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int64_t ObDBMSSchedJobMaster::run_job(ObDBMSSchedJobInfo &job_info, ObDBMSSchedJobKey *job_key, int64_t next_date) | ||||||
|  | { | ||||||
|  |   int ret = OB_SUCCESS; | ||||||
|  |   ObAddr execute_addr; | ||||||
|  |   if (OB_FAIL((get_execute_addr(job_info, execute_addr)))) { | ||||||
|  |     LOG_WARN("failed to get execute addr, retry soon", K(ret), K(job_info)); | ||||||
|  |   } else if (ObTimeUtility::current_time() > job_info.get_end_date()) { | ||||||
|  |     LOG_INFO("job reach end date, not running", K(job_info)); | ||||||
|  |   } else if (OB_FAIL(table_operator_.update_for_start(job_info.get_tenant_id(), job_info, next_date))) { | ||||||
|  |     LOG_WARN("failed to update for start", K(ret), K(job_info), KPC(job_key)); | ||||||
|  |   } else if (OB_FAIL(job_rpc_proxy_->run_dbms_sched_job(job_key->get_tenant_id(), | ||||||
|  |       job_key->is_oracle_tenant(), | ||||||
|  |       job_key->get_job_id(), | ||||||
|  |       job_key->get_job_name(), | ||||||
|  |       execute_addr, | ||||||
|  |       self_addr_))) { | ||||||
|  |     LOG_WARN("failed to run dbms sched job", K(ret), K(job_info), KPC(job_key)); | ||||||
|  |     if (is_server_down_error(ret)) { | ||||||
|  |       int tmp = OB_SUCCESS; | ||||||
|  |       if (OB_SUCCESS != (tmp = table_operator_.update_for_end(job_info.get_tenant_id(), job_info, 0, "send job rpc failed"))) { | ||||||
|  |         LOG_WARN("update for end failed for send rpc failed job", K(tmp), K(job_info), KPC(job_key)); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
| int ObDBMSSchedJobMaster::scheduler() | int ObDBMSSchedJobMaster::scheduler() | ||||||
| { | { | ||||||
|   int ret = OB_SUCCESS; |   int ret = OB_SUCCESS; | ||||||
| @ -331,30 +304,31 @@ int ObDBMSSchedJobMaster::scheduler() | |||||||
|     lib::set_thread_name("DBMS_SCHEDULER"); |     lib::set_thread_name("DBMS_SCHEDULER"); | ||||||
|     while (OB_SUCC(ret) && !stoped_) { |     while (OB_SUCC(ret) && !stoped_) { | ||||||
|       ObLink* ptr = NULL; |       ObLink* ptr = NULL; | ||||||
|       int64_t timeout = MIN_SCHEDULER_INTERVAL; |  | ||||||
|       ObDBMSSchedJobKey *job_key = NULL; |       ObDBMSSchedJobKey *job_key = NULL; | ||||||
|       if (REACH_TIME_INTERVAL(MIN_SCHEDULER_INTERVAL)) { |       int tmp_ret = OB_SUCCESS; | ||||||
|         int tmp_ret = OB_SUCCESS; |       if (REACH_TIME_INTERVAL(CHECK_NEW_INTERVAL)) { | ||||||
|         if (OB_SUCCESS != (tmp_ret = check_all_tenants())) { |         if (OB_SUCCESS != (tmp_ret = check_all_tenants())) { | ||||||
|           LOG_WARN("fail to check all tenants", K(tmp_ret)); |           LOG_WARN("fail to check all tenants", K(tmp_ret)); | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|       if (OB_FAIL(ready_queue_.pop(ptr, timeout))) { |       if (scheduler_task_.wait_vector().count() == 0) { | ||||||
|         if (OB_ENTRY_NOT_EXIST == ret) { |         ob_usleep(MIN_SCHEDULER_INTERVAL); | ||||||
|           LOG_INFO("dbms sched job master wait timeout, no entry", K(ret)); |       } else if (OB_ISNULL(job_key = scheduler_task_.wait_vector()[0]) || !job_key->is_valid()) { | ||||||
|           ret = OB_SUCCESS; |  | ||||||
|         } else { |  | ||||||
|           LOG_ERROR("fail to pop dbms sched job ready queue", K(ret), K(timeout)); |  | ||||||
|         } |  | ||||||
|       } else if (OB_ISNULL(job_key = static_cast<ObDBMSSchedJobKey *>(ptr)) || !job_key->is_valid()) { |  | ||||||
|         ret = OB_ERR_UNEXPECTED; |         ret = OB_ERR_UNEXPECTED; | ||||||
|         LOG_ERROR("unexpected error, invalid job key found in ready queue!", K(ret), KPC(job_key)); |         LOG_ERROR("unexpected error, invalid job key found in ready queue!", K(ret), KPC(job_key)); | ||||||
|       } else { |       } else { | ||||||
|         int tmp_ret = OB_SUCCESS; |         int64_t delay = job_key->get_execute_at() - ObTimeUtility::current_time(); | ||||||
|         if (OB_SUCCESS != (tmp_ret = scheduler_job(job_key))) { |         if (delay > MIN_SCHEDULER_INTERVAL) { | ||||||
|           LOG_WARN("fail to scheduler single dbms sched job", K(ret), K(tmp_ret), KPC(job_key)); |           ob_usleep(MIN_SCHEDULER_INTERVAL); | ||||||
|         } else { |         } else { | ||||||
|           LOG_INFO("success to scheduler single dbms sched job", K(ret), K(tmp_ret), KPC(job_key)); |           ob_usleep(max(0, delay)); | ||||||
|  |           if (OB_SUCCESS != (tmp_ret = scheduler_task_.wait_vector().remove(scheduler_task_.wait_vector().begin()))) { | ||||||
|  |             LOG_WARN("fail to remove job_id from sorted vector", K(ret)); | ||||||
|  |           } else if (OB_SUCCESS != (tmp_ret = scheduler_job(job_key))) { | ||||||
|  |             LOG_WARN("fail to scheduler single dbms sched job", K(ret), K(tmp_ret)); | ||||||
|  |           } else { | ||||||
|  |             LOG_INFO("success to scheduler single dbms sched job", K(ret), K(tmp_ret)); | ||||||
|  |           } | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| @ -375,7 +349,7 @@ int ObDBMSSchedJobMaster::scheduler_job(ObDBMSSchedJobKey *job_key) | |||||||
|   CK (OB_LIKELY(inited_)); |   CK (OB_LIKELY(inited_)); | ||||||
|   CK (OB_NOT_NULL(job_key)); |   CK (OB_NOT_NULL(job_key)); | ||||||
|   CK (OB_LIKELY(job_key->is_valid())); |   CK (OB_LIKELY(job_key->is_valid())); | ||||||
|  |   JobIdByTenant job_id_by_tenant(job_key->get_tenant_id(), job_key->get_job_id()); | ||||||
|   if (OB_FAIL(ret)) { |   if (OB_FAIL(ret)) { | ||||||
|     LOG_WARN("fail to scheduler job", K(ret), KPC(job_key)); |     LOG_WARN("fail to scheduler job", K(ret), KPC(job_key)); | ||||||
|   } else { |   } else { | ||||||
| @ -383,78 +357,118 @@ int ObDBMSSchedJobMaster::scheduler_job(ObDBMSSchedJobKey *job_key) | |||||||
|     OZ (table_operator_.get_dbms_sched_job_info( |     OZ (table_operator_.get_dbms_sched_job_info( | ||||||
|       job_key->get_tenant_id(), job_key->is_oracle_tenant(), job_key->get_job_id(), job_key->get_job_name(), allocator, job_info)); |       job_key->get_tenant_id(), job_key->is_oracle_tenant(), job_key->get_job_id(), job_key->get_job_name(), allocator, job_info)); | ||||||
|  |  | ||||||
|     if (OB_FAIL(ret) || !job_info.valid()) { |     const int64_t now = ObTimeUtility::current_time(); | ||||||
|       int tmp = alive_jobs_.erase_refactored(job_key->get_job_id_with_tenant()); |     int64_t next_check_date = now + MIN_SCHEDULER_INTERVAL; | ||||||
|       if (tmp != OB_SUCCESS) { |     if (OB_FAIL(ret) || !job_info.valid() || job_info.is_disabled() || job_info.is_broken()) { | ||||||
|         LOG_ERROR("failed delete invalid job from hash set", K(tmp), K(ret), K(job_info), KPC(job_key)); |       free_job_key(job_key); | ||||||
|  |       job_key = NULL; | ||||||
|  |     } else if (job_info.is_running()) { | ||||||
|  |       LOG_INFO("job is running now, retry later", K(job_info)); | ||||||
|  |       if (now > job_info.get_this_date() + TO_TS(job_info.get_max_run_duration())) { | ||||||
|  |         if (OB_FAIL(table_operator_.update_for_end(job_info.get_tenant_id(), job_info, 0, "check job timeout"))) { | ||||||
|  |           LOG_WARN("update for end failed for timeout job", K(ret)); | ||||||
|  |         } else { | ||||||
|  |           LOG_WARN("job is timeout, force update for end", K(job_info), K(now)); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } else if (now > job_info.get_end_date()) { | ||||||
|  |       int tmp = OB_SUCCESS; | ||||||
|  |       if (OB_SUCCESS != (tmp = table_operator_.update_for_end(job_info.get_tenant_id(), job_info, 0, "check expired job"))) { | ||||||
|  |         LOG_WARN("update for end failed for auto drop job", K(tmp), K(job_info)); | ||||||
|       } else { |       } else { | ||||||
|         LOG_INFO("delete invalid job from hash set", K(tmp), K(ret), K(job_info), KPC(job_key)); |         LOG_WARN("update for end for expired job", K(job_info), K(now)); | ||||||
|       } |       } | ||||||
|       allocator_.free(job_key); // sql proxy error |       free_job_key(job_key); | ||||||
|     } else{ |       job_key = NULL; | ||||||
|       bool ignore_nextdate = false; |     } else if (now < job_info.get_next_date()) { | ||||||
|       if (!job_key->is_check() && !job_info.is_running() && !job_info.is_broken() && !job_info.is_disabled()) { |         next_check_date = min(job_info.get_next_date(), now + CHECK_NEW_INTERVAL); | ||||||
|         bool can_running = false; |     } else { | ||||||
|         OZ (table_operator_.check_job_can_running(job_info.get_tenant_id(), can_running)); |       bool can_running = false; | ||||||
|         if (OB_SUCC(ret) && can_running) { |       if (OB_FAIL(table_operator_.check_job_can_running(job_info.get_tenant_id(), alive_jobs_.size(), can_running))) { | ||||||
|           OZ (get_execute_addr(job_info, execute_addr)); |         LOG_WARN("failed to check job can running, retry later", K(ret)); | ||||||
|           OZ (table_operator_.update_for_start( |       } else if (!can_running) { | ||||||
|             job_info.get_tenant_id(), job_info)); |         LOG_INFO("job concurrency reach limit, retry later", K(ret), K(job_info), K(can_running)); | ||||||
|           OZ (job_rpc_proxy_->run_dbms_sched_job( |       } else if (now > job_info.get_next_date() + TO_TS(job_info.get_max_run_duration())) { | ||||||
|             job_key->get_tenant_id(), job_key->is_oracle_tenant(), job_key->get_job_id(), job_key->get_job_name(), execute_addr, self_addr_)); |         LOG_WARN("job maybe missed, ignore it", K(now), K(job_info)); | ||||||
|  |         int64_t new_next_date = calc_next_date(job_info); | ||||||
|  |         int tmp = OB_SUCCESS; | ||||||
|  |         if (OB_SUCCESS != (tmp = table_operator_.update_for_end(job_info.get_tenant_id(), job_info, 0, "check job missed"))) { | ||||||
|  |           LOG_WARN("update for end failed for missed job", K(tmp)); | ||||||
|  |         } else if (OB_SUCCESS != (tmp = table_operator_.update_next_date(job_info.get_tenant_id(), job_info, new_next_date))){ | ||||||
|  |           LOG_WARN("update next date failed", K(tmp), K(job_info)); | ||||||
|         } else { |         } else { | ||||||
|           LOG_INFO("avoid duplicate job", K(ret), K(job_info), K(can_running)); |           next_check_date = min(new_next_date, now + CHECK_NEW_INTERVAL); | ||||||
|         } |         } | ||||||
|         ignore_nextdate = true; |       } else { | ||||||
|       } |         int64_t new_next_date = calc_next_date(job_info); | ||||||
|       int tmp_ret = OB_SUCCESS; |         if (OB_FAIL(run_job(job_info, job_key, new_next_date))) { | ||||||
|       // always add job to queue. we need this to check job status changes. |           LOG_WARN("failed to run job", K(ret), K(job_info), KPC(job_key)); | ||||||
|       if (OB_SUCCESS != (tmp_ret = register_job(job_info, job_key, ignore_nextdate))) { |  | ||||||
|         LOG_WARN("failed to register job to job queue", K(tmp_ret), K(job_info)); |  | ||||||
|         int tmp = alive_jobs_.erase_refactored(job_info.get_job_id_with_tenant()); |  | ||||||
|         if (tmp != OB_SUCCESS) { |  | ||||||
|           LOG_ERROR("failed delete invalid job from hash set", K(tmp), K(job_info)); |  | ||||||
|         } else { |         } else { | ||||||
|           LOG_WARN("delete register failed job from hash set", K(job_info)); |           next_check_date = min(new_next_date, now + CHECK_NEW_INTERVAL); | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |     int tmp = OB_SUCCESS; | ||||||
|  |     if (OB_NOT_NULL(job_key) && OB_SUCCESS != (tmp = register_job(job_key, next_check_date))) { | ||||||
|  |       LOG_WARN("failed to register job", K(tmp), K(job_info)); | ||||||
|  |       free_job_key(job_key); | ||||||
|  |       job_key = NULL; | ||||||
|  |     } | ||||||
|   } |   } | ||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| int ObDBMSSchedJobMaster::destroy() | int ObDBMSSchedJobMaster::destroy() | ||||||
| { | { | ||||||
|   ready_queue_.destroy(); |  | ||||||
|   scheduler_task_.destroy(); |   scheduler_task_.destroy(); | ||||||
|   scheduler_thread_.destroy(); |   scheduler_thread_.destroy(); | ||||||
|   allocator_.clear(); |   allocator_.destroy(); | ||||||
|   return OB_SUCCESS; |   return OB_SUCCESS; | ||||||
| } | } | ||||||
|  |  | ||||||
| int ObDBMSSchedJobMaster::alloc_job_key( | int ObDBMSSchedJobMaster::alloc_job_key( | ||||||
|   ObDBMSSchedJobKey *&job_key, |   ObDBMSSchedJobKey *&job_key, | ||||||
|   uint64_t tenant_id, bool is_oracle_tenant, uint64_t job_id, const ObString &job_name, |   uint64_t tenant_id, bool is_oracle_tenant, uint64_t job_id, const ObString &job_name) | ||||||
|   uint64_t execute_at, uint64_t delay, |  | ||||||
|   bool check_job) |  | ||||||
| { | { | ||||||
|   int ret = OB_SUCCESS; |   int ret = OB_SUCCESS; | ||||||
|   ObSpinLockGuard guard(lock_); |  | ||||||
|   void *ptr = NULL; |   void *ptr = NULL; | ||||||
|   job_key = NULL; |   job_key = NULL; | ||||||
|   if (OB_ISNULL(ptr = allocator_.alloc(sizeof(ObDBMSSchedJobKey)))) { |   if (OB_ISNULL(ptr = allocator_.alloc(sizeof(ObDBMSSchedJobKey)))) { | ||||||
|     ret = OB_ALLOCATE_MEMORY_FAILED; |     ret = OB_ALLOCATE_MEMORY_FAILED; | ||||||
|     LOG_WARN("fail to alloc memory", K(ret), K(ptr)); |     LOG_WARN("fail to alloc memory", K(ret), K(ptr)); | ||||||
|   } else if (OB_ISNULL(job_key = |   } else if (OB_ISNULL(job_key = | ||||||
|     new(ptr)ObDBMSSchedJobKey(tenant_id, is_oracle_tenant, job_id, job_name, |     new(ptr)ObDBMSSchedJobKey(tenant_id, is_oracle_tenant, job_id, job_name))) { | ||||||
|                          execute_at, delay, |  | ||||||
|                          check_job))) { |  | ||||||
|     ret = OB_ERR_UNEXPECTED; |     ret = OB_ERR_UNEXPECTED; | ||||||
|     LOG_WARN("fail to init scheduler job id", K(ret), K(tenant_id)); |     LOG_WARN("fail to init scheduler job id", K(ret), K(tenant_id)); | ||||||
|  |   } else { | ||||||
|  |     JobIdByTenant job_id_by_tenant; | ||||||
|  |     job_id_by_tenant.set_tenant_id(tenant_id); | ||||||
|  |     job_id_by_tenant.set_job_id(job_id); | ||||||
|  |     if (OB_FAIL(alive_jobs_.set_refactored(job_id_by_tenant))) { | ||||||
|  |       LOG_WARN("faile to add job to alive_jobs", K(ret), K(tenant_id), K(job_id)); | ||||||
|  |       allocator_.free(job_key); | ||||||
|  |       job_key = NULL; | ||||||
|  |     } | ||||||
|   } |   } | ||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void ObDBMSSchedJobMaster::free_job_key(ObDBMSSchedJobKey *&job_key) | ||||||
|  | { | ||||||
|  |   int ret = OB_SUCCESS; | ||||||
|  |   if (OB_ISNULL(job_key)) { | ||||||
|  |     ret = OB_INVALID_ARGUMENT; | ||||||
|  |     LOG_WARN("job_key is null", K(ret)); | ||||||
|  |   } else { | ||||||
|  |     JobIdByTenant job_id_by_tenant; | ||||||
|  |     job_id_by_tenant.set_tenant_id(job_key->get_tenant_id()); | ||||||
|  |     job_id_by_tenant.set_job_id(job_key->get_job_id()); | ||||||
|  |     OZ (alive_jobs_.erase_refactored(job_id_by_tenant)); | ||||||
|  |     allocator_.free(job_key); | ||||||
|  |     job_key = NULL; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
| int ObDBMSSchedJobMaster::get_execute_addr(ObDBMSSchedJobInfo &job_info, ObAddr &execute_addr) | int ObDBMSSchedJobMaster::get_execute_addr(ObDBMSSchedJobInfo &job_info, ObAddr &execute_addr) | ||||||
| { | { | ||||||
|   int ret = OB_SUCCESS; |   int ret = OB_SUCCESS; | ||||||
| @ -520,7 +534,7 @@ int ObDBMSSchedJobMaster::server_random_pick(int64_t tenant_id, ObString &pick_z | |||||||
|     bool is_alive = false; |     bool is_alive = false; | ||||||
|     bool is_active = false; |     bool is_active = false; | ||||||
|     bool on_server = false; |     bool on_server = false; | ||||||
|     int64_t pos = rand_.get(0,255) % total_server.count(); |     int64_t pos = rand_.get(0,65536) % total_server.count(); | ||||||
|     int64_t cnt = 0; |     int64_t cnt = 0; | ||||||
|     do { |     do { | ||||||
|       pos = (pos + 1) % total_server.count(); |       pos = (pos + 1) % total_server.count(); | ||||||
| @ -566,7 +580,27 @@ int ObDBMSSchedJobMaster::check_all_tenants() | |||||||
|       const ObTenantSchema *tenant_schema = NULL; |       const ObTenantSchema *tenant_schema = NULL; | ||||||
|       OZ (schema_guard.get_tenant_info(tenant_ids.at(i), tenant_schema)); |       OZ (schema_guard.get_tenant_info(tenant_ids.at(i), tenant_schema)); | ||||||
|       CK (OB_NOT_NULL(tenant_schema)); |       CK (OB_NOT_NULL(tenant_schema)); | ||||||
|       if (OB_SUCC(ret)) { |       int64_t tenant_id = tenant_ids.at(i); | ||||||
|  |       bool is_tenant_standby = false; | ||||||
|  |       if (OB_FAIL(ret)) { | ||||||
|  |       } else if (OB_FAIL(ObAllTenantInfoProxy::is_standby_tenant(GCTX.sql_proxy_, tenant_id, is_tenant_standby))) { | ||||||
|  |         LOG_WARN("check is standby tenant failed", K(ret), K(tenant_id)); | ||||||
|  |       } else if (is_tenant_standby) { | ||||||
|  |         LOG_INFO("tenant is standby, not check new jobs, and remove exist jobs", K(tenant_id)); | ||||||
|  |         for (ObDBMSSchedJobTask::WaitVectorIterator iter = scheduler_task_.wait_vector().begin(); | ||||||
|  |                 OB_SUCC(ret) && iter != scheduler_task_.wait_vector().end(); ++iter) { | ||||||
|  |           ObDBMSSchedJobKey *job_key = *iter; | ||||||
|  |           if (OB_NOT_NULL(job_key) && tenant_id == job_key->get_tenant_id()) { | ||||||
|  |             if (OB_FAIL(scheduler_task_.wait_vector().remove(iter))) { | ||||||
|  |               LOG_WARN("failed to remove job key from wait vector", K(ret), KPC(job_key)); | ||||||
|  |             } else { | ||||||
|  |               LOG_INFO("remove job key", KPC(job_key)); | ||||||
|  |               iter--; | ||||||
|  |               free_job_key(job_key); | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       } else { | ||||||
|         uint64_t data_version = 0; |         uint64_t data_version = 0; | ||||||
|         if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_ids.at(i), data_version))) { |         if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_ids.at(i), data_version))) { | ||||||
|           LOG_WARN("fail to get tenant data version", KR(ret), K(data_version)); |           LOG_WARN("fail to get tenant data version", KR(ret), K(data_version)); | ||||||
| @ -599,84 +633,54 @@ int ObDBMSSchedJobMaster::register_new_jobs(uint64_t tenant_id, bool is_oracle_t | |||||||
| { | { | ||||||
|   int ret = OB_SUCCESS; |   int ret = OB_SUCCESS; | ||||||
|   ObDBMSSchedJobInfo job_info; |   ObDBMSSchedJobInfo job_info; | ||||||
|  |   JobIdByTenant job_id_by_tenant; | ||||||
|   for (int64_t i = 0; OB_SUCC(ret) && i < job_infos.count(); i++) { |   for (int64_t i = 0; OB_SUCC(ret) && i < job_infos.count(); i++) { | ||||||
|     job_info = job_infos.at(i); |     job_info = job_infos.at(i); | ||||||
|     if (job_info.valid()) { |     if (job_info.valid() && !job_info.is_disabled() && !job_info.is_broken()) { | ||||||
|       int tmp = alive_jobs_.exist_refactored(job_info.get_job_id_with_tenant()); |       job_id_by_tenant.set_tenant_id(job_info.get_tenant_id()); | ||||||
|  |       job_id_by_tenant.set_job_id(job_info.get_job_id()); | ||||||
|  |       int tmp = alive_jobs_.exist_refactored(job_id_by_tenant); | ||||||
|       if (OB_HASH_EXIST == tmp) { |       if (OB_HASH_EXIST == tmp) { | ||||||
|         // do nothing ... |         // do nothing ... | ||||||
|       } else if (OB_HASH_NOT_EXIST) { |         LOG_DEBUG("job exist", K(alive_jobs_), K(job_id_by_tenant)); | ||||||
|         OZ (register_job(job_info)); |       } else if (OB_HASH_NOT_EXIST == tmp) { | ||||||
|         OZ (alive_jobs_.set_refactored(job_info.get_job_id_with_tenant())); |         ObDBMSSchedJobKey *job_key = NULL; | ||||||
|  |         if (OB_FAIL(alloc_job_key( | ||||||
|  |           job_key, | ||||||
|  |           job_info.get_tenant_id(), | ||||||
|  |           job_info.is_oracle_tenant(), | ||||||
|  |           job_info.get_job_id(), | ||||||
|  |           job_info.get_job_name()))) { | ||||||
|  |           LOG_WARN("failed to alloc job key", K(ret), K(job_info)); | ||||||
|  |         } else if (OB_FAIL(register_job(job_key, ObTimeUtility::current_time()))) { | ||||||
|  |           LOG_WARN("failed to register job", K(ret), K(job_info)); | ||||||
|  |           free_job_key(job_key); | ||||||
|  |           job_key = NULL; | ||||||
|  |         } | ||||||
|         LOG_INFO("register new job", K(ret), K(tenant_id), K(job_info)); |         LOG_INFO("register new job", K(ret), K(tenant_id), K(job_info)); | ||||||
|       } else { |       } else { | ||||||
|         LOG_ERROR("dbms sched job master check job exist failed", K(ret), K(job_info)); |         LOG_ERROR("dbms sched job master check job exist failed", K(tmp), K(job_info)); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| int ObDBMSSchedJobMaster::register_job( | int ObDBMSSchedJobMaster::register_job(ObDBMSSchedJobKey *job_key, int64_t next_date) | ||||||
|   ObDBMSSchedJobInfo &job_info, ObDBMSSchedJobKey *job_key, bool ignore_nextdate) |  | ||||||
| { | { | ||||||
|   int ret = OB_SUCCESS; |   int ret = OB_SUCCESS; | ||||||
|  |   if (OB_ISNULL(job_key)) { | ||||||
|   int64_t execute_at = -1; |     ret = OB_INVALID_ARGUMENT; | ||||||
|   int64_t delay = -1; |     LOG_WARN("job key is null", K(ret)); | ||||||
|   bool check_job = false; |   } else if (next_date == 0) { | ||||||
|   int64_t now = ObTimeUtility::current_time(); |     ret = OB_INVALID_ARGUMENT; | ||||||
|  |     LOG_WARN("next date should not be 0", K(ret), KPC(job_key), K(next_date)); | ||||||
|   CK (OB_LIKELY(inited_)); |  | ||||||
|   CK (job_info.valid()); |  | ||||||
|   OZ (table_operator_.check_job_timeout(job_info)); |  | ||||||
|   OZ (table_operator_.check_auto_drop(job_info)); |  | ||||||
|   if (OB_FAIL(ret)) { |  | ||||||
|   } else if (job_info.is_broken() || job_info.is_disabled()) { |  | ||||||
|     execute_at = now + MIN_SCHEDULER_INTERVAL; |  | ||||||
|     delay = MIN_SCHEDULER_INTERVAL; // every MIN_SCHEDULER_INTERVAL check job status |  | ||||||
|     check_job = true; |  | ||||||
|   } else { |   } else { | ||||||
|     OZ (table_operator_.calc_execute_at(job_info, execute_at, delay, ignore_nextdate)); |     job_key->set_execute_at(next_date); | ||||||
|     if (OB_FAIL(ret) || delay < 0) { |     if (OB_FAIL(scheduler_task_.scheduler(job_key))) { | ||||||
|       ret = OB_SUCCESS; |       LOG_WARN("failed to scheduler job", K(ret), KPC(job_key)); | ||||||
|       execute_at = now + MIN_SCHEDULER_INTERVAL; |  | ||||||
|       delay = MIN_SCHEDULER_INTERVAL; |  | ||||||
|       check_job = true; |  | ||||||
|     } else if (delay > MIN_SCHEDULER_INTERVAL) { |  | ||||||
|       // job may run later, but we need check job update. |  | ||||||
|       execute_at = now + MIN_SCHEDULER_INTERVAL; |  | ||||||
|       delay = MIN_SCHEDULER_INTERVAL; |  | ||||||
|       check_job = true; |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   if (OB_FAIL(ret)) { |  | ||||||
|   } else if (OB_ISNULL(job_key)) { |  | ||||||
|     OZ (alloc_job_key( |  | ||||||
|       job_key, |  | ||||||
|       job_info.get_tenant_id(), |  | ||||||
|       job_info.is_oracle_tenant(), |  | ||||||
|       job_info.get_job_id(), |  | ||||||
|       job_info.get_job_name(), |  | ||||||
|       execute_at, |  | ||||||
|       delay, |  | ||||||
|       check_job)); |  | ||||||
|     CK (OB_NOT_NULL(job_key)); |  | ||||||
|     CK (job_key->is_valid()); |  | ||||||
|   } else { |  | ||||||
|     CK (job_key->get_tenant_id() == job_info.get_tenant_id()); |  | ||||||
|     CK (job_key->get_job_id() == job_info.get_job_id()); |  | ||||||
|     CK (job_key->get_job_name() == job_info.get_job_name()); |  | ||||||
|     OX (job_key->set_execute_at(execute_at)); |  | ||||||
|     OX (job_key->set_delay(delay)); |  | ||||||
|     OX (job_key->set_check_job(check_job)); |  | ||||||
|   } |  | ||||||
|   OZ (scheduler_task_.scheduler(job_key)); |  | ||||||
|   if (OB_FAIL(ret) && OB_NOT_NULL(job_key)) { |  | ||||||
|     allocator_.free(job_key); |  | ||||||
|   } |  | ||||||
|   LOG_INFO("register dbms sched job", K(ret), K(job_info), KPC(job_key), K(ignore_nextdate)); |  | ||||||
|  |  | ||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
| @ -51,16 +51,11 @@ class ObDBMSSchedJobKey : public common::ObLink | |||||||
| { | { | ||||||
| public: | public: | ||||||
|   ObDBMSSchedJobKey( |   ObDBMSSchedJobKey( | ||||||
|     uint64_t tenant_id, bool is_oracle_tenant, uint64_t job_id, const common::ObString &job_name, |     uint64_t tenant_id, bool is_oracle_tenant, uint64_t job_id, const common::ObString &job_name) | ||||||
|     uint64_t execute_at, uint64_t delay, |  | ||||||
|     bool check_job) |  | ||||||
|   : tenant_id_(tenant_id), |   : tenant_id_(tenant_id), | ||||||
|     is_oracle_tenant_(is_oracle_tenant), |     is_oracle_tenant_(is_oracle_tenant), | ||||||
|     job_id_(job_id), |     job_id_(job_id), | ||||||
|     job_name_(), |     job_name_() { | ||||||
|     execute_at_(execute_at), |  | ||||||
|     delay_(delay), |  | ||||||
|     check_job_(check_job) { |  | ||||||
|       job_name_.assign_buffer(job_name_buf_, JOB_NAME_MAX_SIZE); |       job_name_.assign_buffer(job_name_buf_, JOB_NAME_MAX_SIZE); | ||||||
|       job_name_.write(job_name.ptr(), job_name.length()); |       job_name_.write(job_name.ptr(), job_name.length()); | ||||||
|     } |     } | ||||||
| @ -73,18 +68,9 @@ public: | |||||||
|   OB_INLINE uint64_t get_job_id() const { return job_id_; } |   OB_INLINE uint64_t get_job_id() const { return job_id_; } | ||||||
|   OB_INLINE common::ObString &get_job_name() { return job_name_; } |   OB_INLINE common::ObString &get_job_name() { return job_name_; } | ||||||
|   OB_INLINE uint64_t get_execute_at() const { return execute_at_;} |   OB_INLINE uint64_t get_execute_at() const { return execute_at_;} | ||||||
|   OB_INLINE uint64_t get_delay() const { return delay_; } |  | ||||||
|  |  | ||||||
|   OB_INLINE bool is_check() { return check_job_; } |  | ||||||
|  |  | ||||||
|   OB_INLINE void set_tenant_id(uint64_t tenant_id) { tenant_id_ = tenant_id; } |   OB_INLINE void set_tenant_id(uint64_t tenant_id) { tenant_id_ = tenant_id; } | ||||||
|   OB_INLINE void set_job_id(uint64_t job_id) { job_id_ = job_id; } |   OB_INLINE void set_job_id(uint64_t job_id) { job_id_ = job_id; } | ||||||
|  |  | ||||||
|   OB_INLINE void set_execute_at(uint64_t execute_at) { execute_at_ = execute_at; } |   OB_INLINE void set_execute_at(uint64_t execute_at) { execute_at_ = execute_at; } | ||||||
|   OB_INLINE void set_delay(uint64_t delay) { delay_ = delay; } |  | ||||||
|  |  | ||||||
|   OB_INLINE void set_check_job(bool check_job) { check_job_ = check_job; } |  | ||||||
|  |  | ||||||
|   OB_INLINE uint64_t get_adjust_delay() const |   OB_INLINE uint64_t get_adjust_delay() const | ||||||
|   { |   { | ||||||
|     uint64_t now = ObTimeUtility::current_time(); |     uint64_t now = ObTimeUtility::current_time(); | ||||||
| @ -103,9 +89,7 @@ public: | |||||||
|     K_(is_oracle_tenant), |     K_(is_oracle_tenant), | ||||||
|     K_(job_id), |     K_(job_id), | ||||||
|     K_(job_name), |     K_(job_name), | ||||||
|     K_(execute_at), |     K_(execute_at)); | ||||||
|     K_(delay), |  | ||||||
|     K_(check_job)); |  | ||||||
|  |  | ||||||
| private: | private: | ||||||
|   uint64_t tenant_id_; |   uint64_t tenant_id_; | ||||||
| @ -114,12 +98,9 @@ private: | |||||||
|   char job_name_buf_[JOB_NAME_MAX_SIZE]; |   char job_name_buf_[JOB_NAME_MAX_SIZE]; | ||||||
|   common::ObString job_name_; |   common::ObString job_name_; | ||||||
|   uint64_t execute_at_; |   uint64_t execute_at_; | ||||||
|   uint64_t delay_; |  | ||||||
|  |  | ||||||
|   bool check_job_; // for check job update ... |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| class ObDBMSSchedJobTask : public ObTimerTask | class ObDBMSSchedJobTask | ||||||
| { | { | ||||||
| public: | public: | ||||||
|   typedef common::ObSortedVector<ObDBMSSchedJobKey *> WaitVector; |   typedef common::ObSortedVector<ObDBMSSchedJobKey *> WaitVector; | ||||||
| @ -127,23 +108,19 @@ public: | |||||||
|  |  | ||||||
|   ObDBMSSchedJobTask() |   ObDBMSSchedJobTask() | ||||||
|     : inited_(false), |     : inited_(false), | ||||||
|       job_key_(NULL), |       allocator_(NULL), | ||||||
|       ready_queue_(NULL), |       wait_vector_(0, NULL, ObModIds::VECTOR) {} | ||||||
|       wait_vector_(0, NULL, ObModIds::VECTOR), |  | ||||||
|       lock_(common::ObLatchIds::DBMS_SCHEDULER_TASK_LOCK) {} |  | ||||||
|  |  | ||||||
|   virtual ~ObDBMSSchedJobTask() {} |   virtual ~ObDBMSSchedJobTask() {} | ||||||
|  |  | ||||||
|   int init(); |   int init(); | ||||||
|   int start(dbms_job::ObDBMSJobQueue *ready_queue); |   int start(common::ObVSliceAlloc *allocator); | ||||||
|   int stop(); |   int stop(); | ||||||
|   int destroy(); |   int destroy(); | ||||||
|  |  | ||||||
|   void runTimerTask(); |  | ||||||
|  |  | ||||||
|   int scheduler(ObDBMSSchedJobKey *job_key); |   int scheduler(ObDBMSSchedJobKey *job_key); | ||||||
|   int add_new_job(ObDBMSSchedJobKey *job_key); |   int add_new_job(ObDBMSSchedJobKey *job_key); | ||||||
|   int immediately(ObDBMSSchedJobKey *job_key); |   WaitVector &wait_vector() { return wait_vector_; } | ||||||
|  |  | ||||||
|   inline static bool compare_job_key( |   inline static bool compare_job_key( | ||||||
|     const ObDBMSSchedJobKey *lhs, const ObDBMSSchedJobKey *rhs); |     const ObDBMSSchedJobKey *lhs, const ObDBMSSchedJobKey *rhs); | ||||||
| @ -152,13 +129,8 @@ public: | |||||||
|  |  | ||||||
| private: | private: | ||||||
|   bool inited_; |   bool inited_; | ||||||
|   ObDBMSSchedJobKey *job_key_; |   common::ObVSliceAlloc *allocator_; | ||||||
|   dbms_job::ObDBMSJobQueue *ready_queue_; |  | ||||||
|   WaitVector wait_vector_; |   WaitVector wait_vector_; | ||||||
|  |  | ||||||
|   ObSpinLock lock_; |  | ||||||
|   ObTimer timer_; |  | ||||||
|  |  | ||||||
| private: | private: | ||||||
|   DISALLOW_COPY_AND_ASSIGN(ObDBMSSchedJobTask); |   DISALLOW_COPY_AND_ASSIGN(ObDBMSSchedJobTask); | ||||||
| }; | }; | ||||||
| @ -175,11 +147,54 @@ public: | |||||||
|       schema_service_(NULL), |       schema_service_(NULL), | ||||||
|       job_rpc_proxy_(NULL), |       job_rpc_proxy_(NULL), | ||||||
|       self_addr_(), |       self_addr_(), | ||||||
|       lock_(common::ObLatchIds::DBMS_SCHEDULER_MASTER_LOCK), |       allocator_(ObMemAttr(OB_SERVER_TENANT_ID, "DbmsScheduler"), OB_MALLOC_NORMAL_BLOCK_SIZE, block_alloc_), | ||||||
|       alive_jobs_() {} |       alive_jobs_() {} | ||||||
|  |  | ||||||
|   virtual ~ObDBMSSchedJobMaster() { alive_jobs_.destroy(); }; |   virtual ~ObDBMSSchedJobMaster() { alive_jobs_.destroy(); }; | ||||||
|  |  | ||||||
|  |   class JobIdByTenant | ||||||
|  |   { | ||||||
|  |   public: | ||||||
|  |     JobIdByTenant() | ||||||
|  |         : tenant_id_(OB_INVALID_TENANT_ID), | ||||||
|  |           job_id_(OB_INVALID_ID) {} | ||||||
|  |     JobIdByTenant(const int64_t tenant_id, const int64_t job_id) | ||||||
|  |       : tenant_id_(tenant_id), | ||||||
|  |         job_id_(job_id) {} | ||||||
|  |     ~JobIdByTenant() {} | ||||||
|  |     bool operator ==(const JobIdByTenant &other) const | ||||||
|  |     { | ||||||
|  |       return tenant_id_ == other.tenant_id_ && job_id_ == other.job_id_; | ||||||
|  |     } | ||||||
|  |     bool operator !=(const JobIdByTenant &other) const | ||||||
|  |     { | ||||||
|  |       return !(*this == other); | ||||||
|  |     } | ||||||
|  |     uint64_t hash() const | ||||||
|  |     { | ||||||
|  |       uint64_t hash_val = 0; | ||||||
|  |  | ||||||
|  |       hash_val = murmurhash(&tenant_id_, sizeof(tenant_id_), hash_val); | ||||||
|  |       hash_val = murmurhash(&job_id_, sizeof(job_id_), hash_val); | ||||||
|  |  | ||||||
|  |       return hash_val; | ||||||
|  |     } | ||||||
|  |     int hash(uint64_t &hash_val) const | ||||||
|  |     { | ||||||
|  |       hash_val = hash(); | ||||||
|  |       return OB_SUCCESS; | ||||||
|  |     } | ||||||
|  |     void set_tenant_id(int64_t tenant_id) { tenant_id_ = tenant_id; } | ||||||
|  |     void set_job_id(int64_t job_id) { job_id_ = job_id; } | ||||||
|  |     int64_t get_tenant_id() { return tenant_id_; } | ||||||
|  |     int64_t get_job_id() { return job_id_; } | ||||||
|  |     TO_STRING_KV(K_(tenant_id), | ||||||
|  |       K_(job_id)); | ||||||
|  |   private: | ||||||
|  |     int64_t tenant_id_; | ||||||
|  |     int64_t job_id_; | ||||||
|  |   }; | ||||||
|  |  | ||||||
|   static ObDBMSSchedJobMaster &get_instance(); |   static ObDBMSSchedJobMaster &get_instance(); | ||||||
|  |  | ||||||
|   bool is_inited() { return inited_; } |   bool is_inited() { return inited_; } | ||||||
| @ -195,23 +210,23 @@ public: | |||||||
|  |  | ||||||
|   int alloc_job_key( |   int alloc_job_key( | ||||||
|     ObDBMSSchedJobKey *&job_key, |     ObDBMSSchedJobKey *&job_key, | ||||||
|     uint64_t tenant_id, bool is_oracle_tenant, uint64_t job_id, const common::ObString &job_name, |     uint64_t tenant_id, bool is_oracle_tenant, uint64_t job_id, const common::ObString &job_name); | ||||||
|     uint64_t execute_at, uint64_t delay, |   void free_job_key(ObDBMSSchedJobKey *&job_key); | ||||||
|     bool check_job = false); |  | ||||||
|  |  | ||||||
|   int server_random_pick(int64_t tenant_id, common::ObString &pick_zone, ObAddr &server); |   int server_random_pick(int64_t tenant_id, common::ObString &pick_zone, ObAddr &server); | ||||||
|   int get_execute_addr(ObDBMSSchedJobInfo &job_info, common::ObAddr &execute_addr); |   int get_execute_addr(ObDBMSSchedJobInfo &job_info, common::ObAddr &execute_addr); | ||||||
|  |  | ||||||
|   int check_all_tenants(); |   int check_all_tenants(); | ||||||
|   int check_new_jobs(uint64_t tenant_id, bool is_oracle_tenant); |   int check_new_jobs(uint64_t tenant_id, bool is_oracle_tenant); | ||||||
|   int register_new_jobs(uint64_t tenant_id, bool is_oracle_tenant, ObIArray<ObDBMSSchedJobInfo> &job_infos); |   int register_new_jobs(uint64_t tenant_id, bool is_oracle_tenant, ObIArray<ObDBMSSchedJobInfo> &job_infos); | ||||||
|   int register_job(ObDBMSSchedJobInfo &job_info, ObDBMSSchedJobKey *job_key = NULL, bool ignore_nextdate = false); |   int register_job(ObDBMSSchedJobKey *job_key, int64_t next_date); | ||||||
|  |  | ||||||
|   int scheduler_job(ObDBMSSchedJobKey *job_key); |   int scheduler_job(ObDBMSSchedJobKey *job_key); | ||||||
|  |   int64_t calc_next_date(ObDBMSSchedJobInfo &job_info); | ||||||
|  |   int64_t run_job(ObDBMSSchedJobInfo &job_info, ObDBMSSchedJobKey *job_key, int64_t next_date); | ||||||
|  |  | ||||||
| private: | private: | ||||||
|   const static int MAX_READY_JOBS_CAPACITY = 1024 * 1024; |   const static int MAX_READY_JOBS_CAPACITY = 1024 * 1024; | ||||||
|   const static int MIN_SCHEDULER_INTERVAL = 20 * 1000 * 1000; |   const static int MIN_SCHEDULER_INTERVAL = 1 * 1000 * 1000; | ||||||
|  |   const static int CHECK_NEW_INTERVAL = 20 * 1000 * 1000; | ||||||
|  |  | ||||||
|   bool inited_; |   bool inited_; | ||||||
|   bool stoped_; |   bool stoped_; | ||||||
| @ -225,15 +240,14 @@ private: | |||||||
|   obrpc::ObDBMSSchedJobRpcProxy *job_rpc_proxy_; |   obrpc::ObDBMSSchedJobRpcProxy *job_rpc_proxy_; | ||||||
|  |  | ||||||
|   common::ObAddr self_addr_; |   common::ObAddr self_addr_; | ||||||
|   dbms_job::ObDBMSJobQueue ready_queue_; |  | ||||||
|   ObDBMSSchedJobTask scheduler_task_; |   ObDBMSSchedJobTask scheduler_task_; | ||||||
|   ObDBMSSchedJobThread scheduler_thread_; |   ObDBMSSchedJobThread scheduler_thread_; | ||||||
|   ObDBMSSchedTableOperator table_operator_; |   ObDBMSSchedTableOperator table_operator_; | ||||||
|  |  | ||||||
|   common::ObSpinLock lock_; |   common::ObBlockAllocMgr block_alloc_; | ||||||
|   common::ObArenaAllocator allocator_; |   common::ObVSliceAlloc allocator_; | ||||||
|  |  | ||||||
|   common::hash::ObHashSet<uint64_t> alive_jobs_; |   common::hash::ObHashSet<JobIdByTenant> alive_jobs_; | ||||||
|  |  | ||||||
| private: | private: | ||||||
|   DISALLOW_COPY_AND_ASSIGN(ObDBMSSchedJobMaster); |   DISALLOW_COPY_AND_ASSIGN(ObDBMSSchedJobMaster); | ||||||
|  | |||||||
| @ -49,7 +49,6 @@ public: | |||||||
|   { |   { | ||||||
|     return common::is_valid_tenant_id(tenant_id_) |     return common::is_valid_tenant_id(tenant_id_) | ||||||
|         && job_id_ != common::OB_INVALID_ID |         && job_id_ != common::OB_INVALID_ID | ||||||
|         && !job_name_.empty() |  | ||||||
|         && server_addr_.is_valid() |         && server_addr_.is_valid() | ||||||
|         && master_addr_.is_valid(); |         && master_addr_.is_valid(); | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -145,6 +145,9 @@ public: | |||||||
|   int64_t  get_last_modify() { return last_modify_; } |   int64_t  get_last_modify() { return last_modify_; } | ||||||
|   int64_t  get_interval_ts() { return interval_ts_; } |   int64_t  get_interval_ts() { return interval_ts_; } | ||||||
|   int64_t  get_max_run_duration() { return (max_run_duration_ == 0) ? 30 : max_run_duration_ ; } // 30s by default |   int64_t  get_max_run_duration() { return (max_run_duration_ == 0) ? 30 : max_run_duration_ ; } // 30s by default | ||||||
|  |   int64_t  get_start_date() { return start_date_; } | ||||||
|  |   int64_t  get_end_date() { return end_date_; } | ||||||
|  |   int64_t  get_auto_drop() { return auto_drop_; } | ||||||
|  |  | ||||||
|   bool is_broken() { return 0x1 == (flag_ & 0x1); } |   bool is_broken() { return 0x1 == (flag_ & 0x1); } | ||||||
|   bool is_running(){ return this_date_ != 0; } |   bool is_running(){ return this_date_ != 0; } | ||||||
|  | |||||||
| @ -34,7 +34,6 @@ | |||||||
| #include "share/schema/ob_multi_version_schema_service.h" | #include "share/schema/ob_multi_version_schema_service.h" | ||||||
| #include "storage/mview/ob_mview_sched_job_utils.h" | #include "storage/mview/ob_mview_sched_job_utils.h" | ||||||
|  |  | ||||||
| #define TO_TS(second) 1000000L * second |  | ||||||
|  |  | ||||||
| namespace oceanbase | namespace oceanbase | ||||||
| { | { | ||||||
| @ -48,8 +47,8 @@ using namespace storage; | |||||||
| namespace dbms_scheduler | namespace dbms_scheduler | ||||||
| { | { | ||||||
|  |  | ||||||
| int ObDBMSSchedTableOperator::update_for_start( | int ObDBMSSchedTableOperator::update_next_date( | ||||||
|   uint64_t tenant_id, ObDBMSSchedJobInfo &job_info, bool update_nextdate) |   uint64_t tenant_id, ObDBMSSchedJobInfo &job_info, int64_t next_date) | ||||||
| { | { | ||||||
|   int ret = OB_SUCCESS; |   int ret = OB_SUCCESS; | ||||||
|  |  | ||||||
| @ -57,50 +56,67 @@ int ObDBMSSchedTableOperator::update_for_start( | |||||||
|   ObSqlString sql; |   ObSqlString sql; | ||||||
|   int64_t affected_rows = 0; |   int64_t affected_rows = 0; | ||||||
|   const int64_t now = ObTimeUtility::current_time(); |   const int64_t now = ObTimeUtility::current_time(); | ||||||
|   int64_t delay = 0; |  | ||||||
|   int64_t dummy_execute_at = 0; |  | ||||||
|  |  | ||||||
|   CK (OB_NOT_NULL(sql_proxy_)); |   CK (OB_NOT_NULL(sql_proxy_)); | ||||||
|   CK (OB_LIKELY(tenant_id != OB_INVALID_ID)); |   CK (OB_LIKELY(tenant_id != OB_INVALID_ID)); | ||||||
|   CK (OB_LIKELY(job_info.job_ != OB_INVALID_ID)); |   CK (OB_LIKELY(job_info.job_ != OB_INVALID_ID)); | ||||||
|  |  | ||||||
|   OZ (calc_execute_at( |   OZ (dml.add_gmt_modified(now)); | ||||||
|     job_info, (update_nextdate ? job_info.next_date_ : dummy_execute_at), delay, true)); |   OZ (dml.add_pk_column("tenant_id", ObSchemaUtils::get_extract_tenant_id(tenant_id, tenant_id))); | ||||||
|  |   OZ (dml.add_pk_column("job", job_info.job_)); | ||||||
|  |   OZ (dml.add_pk_column("job_name", job_info.job_name_)); | ||||||
|  |   OZ (dml.add_time_column("next_date", next_date)); | ||||||
|  |   OZ (dml.splice_update_sql(OB_ALL_TENANT_SCHEDULER_JOB_TNAME, sql)); | ||||||
|  |   OZ (sql_proxy_->write(tenant_id, sql.ptr(), affected_rows)); | ||||||
|  |   return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | int ObDBMSSchedTableOperator::update_for_start( | ||||||
|  |   uint64_t tenant_id, ObDBMSSchedJobInfo &job_info, int64_t next_date) | ||||||
|  | { | ||||||
|  |   int ret = OB_SUCCESS; | ||||||
|  |  | ||||||
|  |   ObDMLSqlSplicer dml; | ||||||
|  |   ObSqlString sql; | ||||||
|  |   int64_t affected_rows = 0; | ||||||
|  |   const int64_t now = ObTimeUtility::current_time(); | ||||||
|  |  | ||||||
|  |   CK (OB_NOT_NULL(sql_proxy_)); | ||||||
|  |   CK (OB_LIKELY(tenant_id != OB_INVALID_ID)); | ||||||
|  |   CK (OB_LIKELY(job_info.job_ != OB_INVALID_ID)); | ||||||
|  |  | ||||||
|   OX (job_info.this_date_ = now); |   OX (job_info.this_date_ = now); | ||||||
|   OZ (dml.add_gmt_modified(now)); |   OZ (dml.add_gmt_modified(now)); | ||||||
|   OZ (dml.add_pk_column("tenant_id", ObSchemaUtils::get_extract_tenant_id(tenant_id, tenant_id))); |   OZ (dml.add_pk_column("tenant_id", ObSchemaUtils::get_extract_tenant_id(tenant_id, tenant_id))); | ||||||
|   OZ (dml.add_pk_column("job", job_info.job_)); |   OZ (dml.add_pk_column("job", job_info.job_)); | ||||||
|  |   OZ (dml.add_pk_column("job_name", job_info.job_name_)); | ||||||
|   OZ (dml.add_time_column("this_date", job_info.this_date_)); |   OZ (dml.add_time_column("this_date", job_info.this_date_)); | ||||||
|  |   OZ (dml.add_time_column("next_date", next_date)); | ||||||
|   OZ (dml.add_column("state", "SCHEDULED")); |   OZ (dml.add_column("state", "SCHEDULED")); | ||||||
|   OZ (dml.splice_update_sql(OB_ALL_TENANT_SCHEDULER_JOB_TNAME, sql)); |   OZ (dml.splice_update_sql(OB_ALL_TENANT_SCHEDULER_JOB_TNAME, sql)); | ||||||
|  |   OZ (sql.append_fmt(" and this_date is null")); | ||||||
|   OZ (sql_proxy_->write(tenant_id, sql.ptr(), affected_rows)); |   OZ (sql_proxy_->write(tenant_id, sql.ptr(), affected_rows)); | ||||||
|  |   CK (affected_rows == 1); | ||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| int ObDBMSSchedTableOperator::update_nextdate( | int ObDBMSSchedTableOperator::seperate_job_id_from_name(ObString &job_name, int64_t &job_id) | ||||||
|   uint64_t tenant_id, ObDBMSSchedJobInfo &job_info) |  | ||||||
| { | { | ||||||
|   int ret = OB_SUCCESS; |   int ret = OB_SUCCESS; | ||||||
|  |   const char* prefix = "JOB$_"; | ||||||
|   ObDMLSqlSplicer dml; |   job_id = 0; | ||||||
|   ObSqlString sql; |   if (job_name.prefix_match(prefix)) { | ||||||
|   int64_t affected_rows = 0; |     char nptr[JOB_NAME_MAX_SIZE]; | ||||||
|   const int64_t now = ObTimeUtility::current_time(); |     char *endptr = NULL; | ||||||
|  |     snprintf(nptr, JOB_NAME_MAX_SIZE, "%.*s", job_name.length(), job_name.ptr()); | ||||||
|   CK (OB_NOT_NULL(sql_proxy_)); |     job_id = strtoll(nptr + strlen(prefix), &endptr, 10); | ||||||
|   CK (OB_LIKELY(tenant_id != OB_INVALID_ID)); |     if (job_id <= 0) { | ||||||
|   CK (OB_LIKELY(job_info.job_ != OB_INVALID_ID)); |       LOG_WARN("job_id is not right", K(job_name), K(nptr), K(job_id)); | ||||||
|  |     } else if (*endptr != '\0' || job_id <= JOB_ID_OFFSET) { | ||||||
|   OZ (dml.add_gmt_modified(now)); |       job_id = 0; // use job_info.job_ when job_id is not formal | ||||||
|   OZ (dml.add_pk_column("tenant_id", ObSchemaUtils::get_extract_tenant_id(tenant_id, tenant_id))); |     } | ||||||
|   OZ (dml.add_pk_column("job", job_info.job_)); |   } | ||||||
|   OZ (dml.add_column("interval_ts", job_info.interval_ts_)); |  | ||||||
|   OZ (dml.add_time_column("next_date", job_info.next_date_)); |  | ||||||
|   OZ (dml.splice_update_sql(OB_ALL_TENANT_SCHEDULER_JOB_TNAME, sql)); |  | ||||||
|   OZ (sql_proxy_->write(tenant_id, sql.ptr(), affected_rows)); |  | ||||||
|  |  | ||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -117,8 +133,6 @@ int ObDBMSSchedTableOperator::update_for_end( | |||||||
|   ObSqlString sql2; |   ObSqlString sql2; | ||||||
|   int64_t affected_rows = 0; |   int64_t affected_rows = 0; | ||||||
|   const int64_t now = ObTimeUtility::current_time(); |   const int64_t now = ObTimeUtility::current_time(); | ||||||
|   int64_t next_date; |  | ||||||
|   int64_t delay; |  | ||||||
|  |  | ||||||
|   UNUSED(errmsg); |   UNUSED(errmsg); | ||||||
|  |  | ||||||
| @ -161,12 +175,13 @@ int ObDBMSSchedTableOperator::update_for_end( | |||||||
|       OZ (dml1.add_column("state", "COMPLETED")); |       OZ (dml1.add_column("state", "COMPLETED")); | ||||||
|       OZ (dml1.add_column("enabled", job_info.enabled_)); |       OZ (dml1.add_column("enabled", job_info.enabled_)); | ||||||
|     } |     } | ||||||
|     CK (job_info.this_date_ > 0); |     CK (job_info.this_date_ > 0 || !errmsg.empty()); | ||||||
|     OX (job_info.total_ += (now - job_info.this_date_)); |     OX (job_info.total_ += (job_info.this_date_ > 0 ? now - job_info.this_date_ : 0)); | ||||||
|     OZ (dml1.add_gmt_modified(now)); |     OZ (dml1.add_gmt_modified(now)); | ||||||
|     OZ (dml1.add_pk_column("tenant_id", |     OZ (dml1.add_pk_column("tenant_id", | ||||||
|           ObSchemaUtils::get_extract_tenant_id(tenant_id, tenant_id))); |           ObSchemaUtils::get_extract_tenant_id(tenant_id, tenant_id))); | ||||||
|     OZ (dml1.add_pk_column("job", job_info.job_)); |     OZ (dml1.add_pk_column("job", job_info.job_)); | ||||||
|  |     OZ (dml1.add_pk_column("job_name", job_info.job_name_)); | ||||||
|     OZ (dml1.add_column(true, "this_date")); |     OZ (dml1.add_column(true, "this_date")); | ||||||
|     OZ (dml1.add_time_column("last_date", job_info.this_date_)); |     OZ (dml1.add_time_column("last_date", job_info.this_date_)); | ||||||
|     OZ (dml1.add_time_column("next_date", job_info.next_date_)); |     OZ (dml1.add_time_column("next_date", job_info.next_date_)); | ||||||
| @ -196,7 +211,12 @@ int ObDBMSSchedTableOperator::update_for_end( | |||||||
|     OZ (dml2.add_gmt_create(now)); |     OZ (dml2.add_gmt_create(now)); | ||||||
|     OZ (dml2.add_gmt_modified(now)); |     OZ (dml2.add_gmt_modified(now)); | ||||||
|     OZ (dml2.add_pk_column("tenant_id", ObSchemaUtils::get_extract_tenant_id(tenant_id, tenant_id))); |     OZ (dml2.add_pk_column("tenant_id", ObSchemaUtils::get_extract_tenant_id(tenant_id, tenant_id))); | ||||||
|     OZ (dml2.add_pk_column("job", job_info.job_)); |     int64_t job_id = 0; | ||||||
|  |     OZ (seperate_job_id_from_name(job_info.get_job_name(), job_id)); | ||||||
|  |     if (job_id <= 0) { | ||||||
|  |       job_id = job_info.get_job_id(); | ||||||
|  |     } | ||||||
|  |     OZ (dml2.add_pk_column("job", job_id)); | ||||||
|     OZ (dml2.add_time_column("time", now)); |     OZ (dml2.add_time_column("time", now)); | ||||||
|     OZ (dml2.add_column("code", err)); |     OZ (dml2.add_column("code", err)); | ||||||
|     OZ (dml2.add_column( |     OZ (dml2.add_column( | ||||||
| @ -225,32 +245,7 @@ int ObDBMSSchedTableOperator::update_for_end( | |||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| int ObDBMSSchedTableOperator::check_job_timeout(ObDBMSSchedJobInfo &job_info) | int ObDBMSSchedTableOperator::check_job_can_running(int64_t tenant_id, int64_t alive_job_count, bool &can_running) | ||||||
| { |  | ||||||
|   int ret = OB_SUCCESS; |  | ||||||
|   if ((!job_info.is_running()) || (job_info.get_max_run_duration() == 0)) { |  | ||||||
|     //not running or not set timeout |  | ||||||
|   } else if (ObTimeUtility::current_time() > (job_info.get_this_date() + TO_TS(job_info.get_max_run_duration()))) { |  | ||||||
|     OZ(update_for_end(job_info.get_tenant_id(), job_info, 0, "check job timeout")); |  | ||||||
|     LOG_WARN("job is timeout, force update for end", K(job_info), K(ObTimeUtility::current_time())); |  | ||||||
|   } |  | ||||||
|   return ret; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int ObDBMSSchedTableOperator::check_auto_drop(ObDBMSSchedJobInfo &job_info) |  | ||||||
| { |  | ||||||
|   int ret = OB_SUCCESS; |  | ||||||
|   if (job_info.is_running()) { |  | ||||||
|     // running job not check |  | ||||||
|   } else if (ObTimeUtility::current_time() > (job_info.end_date_) && |  | ||||||
|              (true == job_info.auto_drop_)) { |  | ||||||
|     OZ(update_for_end(job_info.get_tenant_id(), job_info, 0, "check auto drop expired job")); |  | ||||||
|     LOG_WARN("auto drop miss out job", K(job_info), K(ObTimeUtility::current_time())); |  | ||||||
|   } |  | ||||||
|   return ret; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int ObDBMSSchedTableOperator::check_job_can_running(int64_t tenant_id, bool &can_running) |  | ||||||
| { | { | ||||||
|   int ret = OB_SUCCESS; |   int ret = OB_SUCCESS; | ||||||
|   uint64_t job_queue_processor = 0; |   uint64_t job_queue_processor = 0; | ||||||
| @ -263,33 +258,40 @@ int ObDBMSSchedTableOperator::check_job_can_running(int64_t tenant_id, bool &can | |||||||
|   CK (tenant_config.is_valid()); |   CK (tenant_config.is_valid()); | ||||||
|   OX (job_queue_processor = tenant_config->job_queue_processes); |   OX (job_queue_processor = tenant_config->job_queue_processes); | ||||||
|   // found current running job count |   // found current running job count | ||||||
|   OZ (sql.append_fmt("select count(*) from %s where this_date is not null", OB_ALL_TENANT_SCHEDULER_JOB_TNAME)); |   if (OB_FAIL(ret)) { | ||||||
|  |   } else if (alive_job_count <= job_queue_processor) { | ||||||
|  |     can_running = true; | ||||||
|  |   } else { | ||||||
|  |     OZ (sql.append_fmt("select count(*) from %s where this_date is not null", OB_ALL_TENANT_SCHEDULER_JOB_TNAME)); | ||||||
|  |  | ||||||
|   CK (OB_NOT_NULL(GCTX.schema_service_)); |     CK (OB_NOT_NULL(GCTX.schema_service_)); | ||||||
|   OZ (GCTX.schema_service_->get_tenant_schema_guard(tenant_id, guard)); |     OZ (GCTX.schema_service_->get_tenant_schema_guard(tenant_id, guard)); | ||||||
|   OZ (guard.check_tenant_is_restore(tenant_id, is_restore)); |     OZ (guard.check_tenant_is_restore(tenant_id, is_restore)); | ||||||
|  |  | ||||||
|   // job can not run in standy cluster and restore. |     // job can not run in standy cluster and restore. | ||||||
|   if (OB_SUCC(ret) && job_queue_processor > 0 |     if (OB_SUCC(ret) && job_queue_processor > 0 | ||||||
|       && !GCTX.is_standby_cluster() |         && !is_restore) { | ||||||
|       && !is_restore) { |       SMART_VAR(ObMySQLProxy::MySQLResult, result) { | ||||||
|     SMART_VAR(ObMySQLProxy::MySQLResult, result) { |         if (OB_FAIL(sql_proxy_->read(result, tenant_id, sql.ptr()))) { | ||||||
|       if (OB_FAIL(sql_proxy_->read(result, tenant_id, sql.ptr()))) { |           LOG_WARN("execute query failed", K(ret), K(sql), K(tenant_id)); | ||||||
|         LOG_WARN("execute query failed", K(ret), K(sql), K(tenant_id)); |         } else if (OB_ISNULL(result.get_result())) { | ||||||
|       } else if (OB_NOT_NULL(result.get_result())) { |           ret = OB_ERR_UNEXPECTED; | ||||||
|         if (OB_SUCCESS == (ret = result.get_result()->next())) { |           LOG_WARN("get result failed", K(ret), K(sql), K(tenant_id)); | ||||||
|           int64_t int_value = 0; |  | ||||||
|           if (OB_FAIL(result.get_result()->get_int(static_cast<const int64_t>(0), int_value))) { |  | ||||||
|             LOG_WARN("failed to get column in row. ", K(ret)); |  | ||||||
|           } else { |  | ||||||
|             job_running_cnt = static_cast<uint64_t>(int_value); |  | ||||||
|           } |  | ||||||
|         } else { |         } else { | ||||||
|           LOG_WARN("failed to calc all running job, no row return", K(ret)); |           if (OB_SUCCESS == (ret = result.get_result()->next())) { | ||||||
|  |             int64_t int_value = 0; | ||||||
|  |             if (OB_FAIL(result.get_result()->get_int(static_cast<const int64_t>(0), int_value))) { | ||||||
|  |               LOG_WARN("failed to get column in row. ", K(ret)); | ||||||
|  |             } else { | ||||||
|  |               job_running_cnt = static_cast<uint64_t>(int_value); | ||||||
|  |             } | ||||||
|  |           } else { | ||||||
|  |             LOG_WARN("failed to calc all running job, no row return", K(ret)); | ||||||
|  |           } | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|  |       OX (can_running = (job_queue_processor > job_running_cnt)); | ||||||
|     } |     } | ||||||
|     OX (can_running = (job_queue_processor > job_running_cnt)); |  | ||||||
|   } |   } | ||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
| @ -399,16 +401,24 @@ int ObDBMSSchedTableOperator::get_dbms_sched_job_info( | |||||||
|     SMART_VAR(ObMySQLProxy::MySQLResult, result) { |     SMART_VAR(ObMySQLProxy::MySQLResult, result) { | ||||||
|       if (OB_FAIL(sql_proxy_->read(result, tenant_id, sql.ptr()))) { |       if (OB_FAIL(sql_proxy_->read(result, tenant_id, sql.ptr()))) { | ||||||
|         LOG_WARN("execute query failed", K(ret), K(sql), K(tenant_id), K(job_id)); |         LOG_WARN("execute query failed", K(ret), K(sql), K(tenant_id), K(job_id)); | ||||||
|       } else if (OB_NOT_NULL(result.get_result())) { |       } else if (OB_ISNULL(result.get_result())) { | ||||||
|  |         ret = OB_ERR_UNEXPECTED; | ||||||
|  |         LOG_WARN("failed to get result", K(ret), K(tenant_id), K(job_id)); | ||||||
|  |       } else { | ||||||
|         if (OB_SUCCESS == (ret = result.get_result()->next())) { |         if (OB_SUCCESS == (ret = result.get_result()->next())) { | ||||||
|           OZ (extract_info(*(result.get_result()), tenant_id, is_oracle_tenant, allocator, job_info)); |           OZ (extract_info(*(result.get_result()), tenant_id, is_oracle_tenant, allocator, job_info)); | ||||||
|           if (OB_SUCC(ret) && (result.get_result()->next()) != OB_ITER_END) { |           if (OB_SUCC(ret)) { | ||||||
|             LOG_ERROR("got more than one row for dbms sched job!", K(ret), K(tenant_id), K(job_id)); |             int tmp_ret = result.get_result()->next(); | ||||||
|             ret = OB_ERR_UNEXPECTED; |             if (OB_SUCCESS == tmp_ret) { | ||||||
|  |               ret = OB_ERR_UNEXPECTED; | ||||||
|  |               LOG_ERROR("got more than one row for dbms sched job!", K(ret), K(tenant_id), K(job_id)); | ||||||
|  |             } else if (tmp_ret != OB_ITER_END) { | ||||||
|  |               ret = tmp_ret; | ||||||
|  |               LOG_ERROR("got next row for dbms sched job failed", K(ret), K(tenant_id), K(job_id)); | ||||||
|  |             } | ||||||
|           } |           } | ||||||
|         } else if (OB_ITER_END == ret) { |         } else if (OB_ITER_END == ret) { | ||||||
|           LOG_INFO("job not exists, may delete alreay!", K(ret), K(tenant_id), K(job_id)); |           LOG_WARN("job not exists, may delete alreay!", K(ret), K(tenant_id), K(job_id)); | ||||||
|           ret = OB_SUCCESS; // job not exist, do nothing ... |  | ||||||
|         } else { |         } else { | ||||||
|           LOG_WARN("failed to get next", K(ret), K(tenant_id), K(job_id)); |           LOG_WARN("failed to get next", K(ret), K(tenant_id), K(job_id)); | ||||||
|         } |         } | ||||||
| @ -437,7 +447,10 @@ int ObDBMSSchedTableOperator::get_dbms_sched_job_infos_in_tenant( | |||||||
|     SMART_VAR(ObMySQLProxy::MySQLResult, result) { |     SMART_VAR(ObMySQLProxy::MySQLResult, result) { | ||||||
|       if (OB_FAIL(sql_proxy_->read(result, tenant_id, sql.ptr()))) { |       if (OB_FAIL(sql_proxy_->read(result, tenant_id, sql.ptr()))) { | ||||||
|         LOG_WARN("execute query failed", K(ret), K(sql), K(tenant_id)); |         LOG_WARN("execute query failed", K(ret), K(sql), K(tenant_id)); | ||||||
|       } else if (OB_NOT_NULL(result.get_result())) { |       } else if (OB_ISNULL(result.get_result())) { | ||||||
|  |         ret = OB_ERR_UNEXPECTED; | ||||||
|  |         LOG_WARN("get result failed", K(ret), K(sql), K(tenant_id)); | ||||||
|  |       } else { | ||||||
|         do { |         do { | ||||||
|           if (OB_FAIL(result.get_result()->next())) { |           if (OB_FAIL(result.get_result()->next())) { | ||||||
|             LOG_INFO("failed to get result", K(ret)); |             LOG_INFO("failed to get result", K(ret)); | ||||||
| @ -492,12 +505,21 @@ int ObDBMSSchedTableOperator::get_dbms_sched_job_class_info( | |||||||
|     SMART_VAR(ObMySQLProxy::MySQLResult, result) { |     SMART_VAR(ObMySQLProxy::MySQLResult, result) { | ||||||
|       if (OB_FAIL(sql_proxy_->read(result, tenant_id, sql.ptr()))) { |       if (OB_FAIL(sql_proxy_->read(result, tenant_id, sql.ptr()))) { | ||||||
|         LOG_WARN("execute query failed", K(ret), K(sql), K(tenant_id), K(job_class_name)); |         LOG_WARN("execute query failed", K(ret), K(sql), K(tenant_id), K(job_class_name)); | ||||||
|       } else if (OB_NOT_NULL(result.get_result())) { |       } else if (OB_ISNULL(result.get_result())) { | ||||||
|  |         ret = OB_ERR_UNEXPECTED; | ||||||
|  |         LOG_WARN("get result failed", K(ret), K(sql), K(tenant_id), K(job_class_name)); | ||||||
|  |       } else { | ||||||
|         if (OB_SUCCESS == (ret = result.get_result()->next())) { |         if (OB_SUCCESS == (ret = result.get_result()->next())) { | ||||||
|           OZ (extract_job_class_info(*(result.get_result()), tenant_id, is_oracle_tenant, allocator, job_class_info)); |           OZ (extract_job_class_info(*(result.get_result()), tenant_id, is_oracle_tenant, allocator, job_class_info)); | ||||||
|           if (OB_SUCC(ret) && (result.get_result()->next()) != OB_ITER_END) { |           if (OB_SUCC(ret)) { | ||||||
|             LOG_ERROR("got more than one row for dbms sched job class!", K(ret), K(tenant_id), K(job_class_name)); |             int tmp_ret = result.get_result()->next(); | ||||||
|             ret = OB_ERR_UNEXPECTED; |             if (OB_SUCCESS == tmp_ret) { | ||||||
|  |               ret = OB_ERR_UNEXPECTED; | ||||||
|  |               LOG_ERROR("got more than one row for dbms sched job class!", K(ret), K(tenant_id), K(job_class_name)); | ||||||
|  |             } else if (tmp_ret != OB_ITER_END) { | ||||||
|  |               ret = tmp_ret; | ||||||
|  |               LOG_ERROR("got next row for dbms sched job class failed", K(ret), K(tenant_id), K(job_class_name)); | ||||||
|  |             } | ||||||
|           } |           } | ||||||
|         } else if (OB_ITER_END == ret) { |         } else if (OB_ITER_END == ret) { | ||||||
|           LOG_INFO("job_class_name not exists, may delete alreay!", K(ret), K(tenant_id), K(job_class_name)); |           LOG_INFO("job_class_name not exists, may delete alreay!", K(ret), K(tenant_id), K(job_class_name)); | ||||||
| @ -511,96 +533,6 @@ int ObDBMSSchedTableOperator::get_dbms_sched_job_class_info( | |||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| int ObDBMSSchedTableOperator::calc_execute_at( |  | ||||||
|   ObDBMSSchedJobInfo &job_info, int64_t &execute_at, int64_t &delay, bool ignore_nextdate) |  | ||||||
| { |  | ||||||
|   int ret = OB_SUCCESS; |  | ||||||
|  |  | ||||||
|   ObString &interval = job_info.get_interval(); |  | ||||||
|  |  | ||||||
|   const int64_t now = ObTimeUtility::current_time(); |  | ||||||
|   int64_t last_sub_next = |  | ||||||
|     (job_info.get_last_modify() / 1000 / 1000) - (job_info.get_next_date() / 1000/ 1000); |  | ||||||
|   if (job_info.get_next_date() != 0 && (!ignore_nextdate || job_info.get_next_date() != execute_at)) { |  | ||||||
|     if (job_info.get_next_date() > now) { |  | ||||||
|       execute_at = job_info.get_next_date(); |  | ||||||
|       delay = job_info.get_next_date() - now; |  | ||||||
|     } else if (now - job_info.get_next_date() < TO_TS(job_info.get_max_run_duration())) { |  | ||||||
|       LOG_WARN("job maybe missed, retry it", K(now), K(job_info), K(execute_at), K(delay), K(ignore_nextdate), K(lbt())); |  | ||||||
|       execute_at = now; |  | ||||||
|       delay = 0; |  | ||||||
|     } else if (last_sub_next < 5 && last_sub_next >= -5) { |  | ||||||
|       LOG_WARN("job maybe missed, retry it", K(last_sub_next), K(now), K(job_info), K(execute_at), K(delay), K(ignore_nextdate), K(lbt())); |  | ||||||
|       execute_at = now; |  | ||||||
|       delay = 0; |  | ||||||
|     } else { |  | ||||||
|       LOG_WARN("job maybe missed, ignore it", K(last_sub_next), K(now), K(job_info), K(execute_at), K(delay), K(ignore_nextdate), K(lbt())); |  | ||||||
|       OZ(update_for_end(job_info.get_tenant_id(), job_info, 0, "check job missed")); |  | ||||||
|       delay = -1; |  | ||||||
|     } |  | ||||||
|   } else { |  | ||||||
|     delay = -1; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   if (delay < 0 && (job_info.get_interval_ts() != 0 |  | ||||||
|                     || (!interval.empty() && (0 != interval.case_compare("null"))))) { |  | ||||||
|     ObSqlString sql; |  | ||||||
|     common::ObISQLClient *sql_proxy = sql_proxy_; |  | ||||||
|     ObOracleSqlProxy oracle_proxy(*(static_cast<ObMySQLProxy *>(sql_proxy_))); |  | ||||||
|     // NOTE: we need utc timestamp. |  | ||||||
|     if (lib::is_mysql_mode()) { |  | ||||||
|       OZ (sql.append_fmt("select utc_timestamp() from dual;")); |  | ||||||
|     } else { |  | ||||||
|       OZ (sql.append_fmt( |  | ||||||
|         "select cast(to_timestamp(sys_extract_utc(to_timestamp(sysdate))) as date) from dual;")); |  | ||||||
|       sql_proxy = &oracle_proxy; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     SMART_VAR(ObMySQLProxy::MySQLResult, result) { |  | ||||||
|       if (OB_FAIL(sql_proxy->read(result, job_info.get_tenant_id(), sql.ptr()))) { |  | ||||||
|         LOG_WARN("execute query failed", K(ret), K(sql), K(job_info)); |  | ||||||
|       } else if (OB_NOT_NULL(result.get_result())) { |  | ||||||
|         if (OB_FAIL(result.get_result()->next())) { |  | ||||||
|           LOG_WARN("failed to get result", K(ret)); |  | ||||||
|         } else { |  | ||||||
|           int64_t sysdate = 0; |  | ||||||
|           int64_t col_idx = 0; |  | ||||||
|           OZ (result.get_result()->get_datetime(col_idx, sysdate)); |  | ||||||
|           if (OB_SUCC(ret) && job_info.is_date_expression_job_class()) { |  | ||||||
|             int64_t next_date_utc_ts = 0; |  | ||||||
|             if (OB_FAIL(ObMViewSchedJobUtils::calc_date_expression(job_info, next_date_utc_ts))) { |  | ||||||
|               LOG_WARN("failed to calc date expression", KR(ret), K(job_info)); |  | ||||||
|             } else { |  | ||||||
|               job_info.interval_ts_ = next_date_utc_ts - sysdate; |  | ||||||
|             } |  | ||||||
|           } |  | ||||||
|           if (OB_SUCC(ret)) { |  | ||||||
|             execute_at = sysdate + job_info.get_interval_ts(); |  | ||||||
|           } |  | ||||||
|           if (OB_FAIL(ret)) { |  | ||||||
|           } else if (job_info.get_next_date() > execute_at) { |  | ||||||
|             execute_at = job_info.get_next_date(); |  | ||||||
|             delay = execute_at - sysdate; |  | ||||||
|           } else { |  | ||||||
|             delay = execute_at - sysdate; |  | ||||||
|           } |  | ||||||
|           if (OB_SUCC(ret)) { |  | ||||||
|             OX (job_info.next_date_ = execute_at); |  | ||||||
|             OZ (update_nextdate(job_info.get_tenant_id(), job_info)); |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     LOG_INFO("repeat job update nextdate", K(job_info), K(execute_at), K(delay), K(ignore_nextdate)); |  | ||||||
|   } else if (delay < 0 && job_info.get_interval_ts() == 0) { |  | ||||||
|     OX (job_info.next_date_ = 64060560000000000); // 4000-01-01 |  | ||||||
|     OZ (update_nextdate(job_info.get_tenant_id(), job_info)); |  | ||||||
|     LOG_INFO("once job update nextdate", K(job_info), K(execute_at), K(delay), K(ignore_nextdate)); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return ret; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int ObDBMSSchedTableOperator::register_default_job_class(uint64_t tenant_id) | int ObDBMSSchedTableOperator::register_default_job_class(uint64_t tenant_id) | ||||||
| { | { | ||||||
|   int ret = OB_SUCCESS; |   int ret = OB_SUCCESS; | ||||||
|  | |||||||
| @ -46,14 +46,20 @@ class ObDBMSSchedTableOperator | |||||||
| public: | public: | ||||||
|   ObDBMSSchedTableOperator() : sql_proxy_(NULL) {} |   ObDBMSSchedTableOperator() : sql_proxy_(NULL) {} | ||||||
|   virtual ~ObDBMSSchedTableOperator() {}; |   virtual ~ObDBMSSchedTableOperator() {}; | ||||||
|  |   static constexpr int64_t JOB_NAME_MAX_SIZE = 128; | ||||||
|  |   static const int64_t JOB_ID_OFFSET = (1LL<<50); | ||||||
|  |  | ||||||
|   int init(common::ObISQLClient *sql_proxy) { sql_proxy_ = sql_proxy; return common::OB_SUCCESS; } |   int init(common::ObISQLClient *sql_proxy) { sql_proxy_ = sql_proxy; return common::OB_SUCCESS; } | ||||||
|  |  | ||||||
|  |   int update_next_date( | ||||||
|  |     uint64_t tenant_id, ObDBMSSchedJobInfo &job_info, int64_t next_date); | ||||||
|  |  | ||||||
|   int update_for_start( |   int update_for_start( | ||||||
|     uint64_t tenant_id, ObDBMSSchedJobInfo &job_info, bool update_nextdate = true); |     uint64_t tenant_id, ObDBMSSchedJobInfo &job_info, int64_t next_date); | ||||||
|   int update_for_end( |   int update_for_end( | ||||||
|     uint64_t tenant_id, ObDBMSSchedJobInfo &job_info, int err, const common::ObString &errmsg); |     uint64_t tenant_id, ObDBMSSchedJobInfo &job_info, int err, const common::ObString &errmsg); | ||||||
|   int update_nextdate(uint64_t tenant_id, ObDBMSSchedJobInfo &job_info); |  | ||||||
|  |   int seperate_job_id_from_name(common::ObString &job_name, int64_t &job_id); | ||||||
|  |  | ||||||
|   int get_dbms_sched_job_info( |   int get_dbms_sched_job_info( | ||||||
|     uint64_t tenant_id, bool is_oracle_tenant, uint64_t job_id, const common::ObString &job_name, |     uint64_t tenant_id, bool is_oracle_tenant, uint64_t job_id, const common::ObString &job_name, | ||||||
| @ -73,14 +79,7 @@ public: | |||||||
|     sqlclient::ObMySQLResult &result, int64_t tenant_id, bool is_oracle_tenant, |     sqlclient::ObMySQLResult &result, int64_t tenant_id, bool is_oracle_tenant, | ||||||
|     ObIAllocator &allocator, ObDBMSSchedJobClassInfo &job_class_info); |     ObIAllocator &allocator, ObDBMSSchedJobClassInfo &job_class_info); | ||||||
|  |  | ||||||
|   int calc_execute_at( |   int check_job_can_running(int64_t tenant_id, int64_t alive_job_count, bool &can_running); | ||||||
|     ObDBMSSchedJobInfo &job_info, int64_t &execute_at, int64_t &delay, bool ignore_nextdate = false); |  | ||||||
|  |  | ||||||
|   int check_job_can_running(int64_t tenant_id, bool &can_running); |  | ||||||
|  |  | ||||||
|   int check_job_timeout(ObDBMSSchedJobInfo &job_info); |  | ||||||
|  |  | ||||||
|   int check_auto_drop(ObDBMSSchedJobInfo &job_info); |  | ||||||
|  |  | ||||||
|   int register_default_job_class(uint64_t tenant_id); |   int register_default_job_class(uint64_t tenant_id); | ||||||
|   int purge_run_detail_histroy(uint64_t tenant_id); |   int purge_run_detail_histroy(uint64_t tenant_id); | ||||||
|  | |||||||
| @ -1517,7 +1517,7 @@ int ObInnerTableSchema::dba_scheduler_windows_schema(ObTableSchema &table_schema | |||||||
|   table_schema.set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset())); |   table_schema.set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset())); | ||||||
|  |  | ||||||
|   if (OB_SUCC(ret)) { |   if (OB_SUCC(ret)) { | ||||||
|     if (OB_FAIL(table_schema.set_view_definition(R"__(SELECT     CAST(T.POWNER AS CHAR(128)) AS OWNER,     CAST(T.JOB_NAME AS CHAR(128)) AS WINDOW_NAME,     CAST(NULL AS CHAR(128)) AS RESOURCE_PLAN,     CAST(NULL AS CHAR(4000)) AS SCHEDULE_OWNER,     CAST(NULL AS CHAR(4000)) AS SCHEDULE_NAME,     CAST(NULL AS CHAR(8)) AS SCHEDULE_TYPE,     CAST(T.START_DATE AS DATETIME(6)) AS START_DATE,     CAST(T.REPEAT_INTERVAL AS CHAR(4000)) AS REPEAT_INTERVAL,     CAST(T.END_DATE AS DATETIME(6)) AS END_DATE,     CAST(T.MAX_RUN_DURATION AS SIGNED) AS DURATION,     CAST(NULL AS CHAR(4)) AS WINDOW_PRIORITY,     CAST(T.NEXT_DATE AS DATETIME(6)) AS NEXT_RUN_DATE,     CAST(T.LAST_DATE AS DATETIME(6)) AS LAST_START_DATE,     CAST(T.ENABLED AS CHAR(5)) AS ENABLED,     CAST(NULL AS CHAR(5)) AS ACTIVE,     CAST(NULL AS DATETIME(6)) AS MANUAL_OPEN_TIME,     CAST(NULL AS SIGNED) AS MANUAL_DURATION,     CAST(T.COMMENTS AS CHAR(4000)) AS COMMENTS   FROM oceanbase.__all_tenant_scheduler_job T WHERE T.JOB_NAME in ('MONDAY_WINDOW',     'TUESDAY_WINDOW', 'WEDNESDAY_WINDOW', 'THURSDAY_WINDOW', 'FRIDAY_WINDOW', 'SATURDAY_WINDOW', 'SUNDAY_WINDOW')   )__"))) { |     if (OB_FAIL(table_schema.set_view_definition(R"__(SELECT     CAST(T.POWNER AS CHAR(128)) AS OWNER,     CAST(T.JOB_NAME AS CHAR(128)) AS WINDOW_NAME,     CAST(NULL AS CHAR(128)) AS RESOURCE_PLAN,     CAST(NULL AS CHAR(4000)) AS SCHEDULE_OWNER,     CAST(NULL AS CHAR(4000)) AS SCHEDULE_NAME,     CAST(NULL AS CHAR(8)) AS SCHEDULE_TYPE,     CAST(T.START_DATE AS DATETIME(6)) AS START_DATE,     CAST(T.REPEAT_INTERVAL AS CHAR(4000)) AS REPEAT_INTERVAL,     CAST(T.END_DATE AS DATETIME(6)) AS END_DATE,     CAST(T.MAX_RUN_DURATION AS SIGNED) AS DURATION,     CAST(NULL AS CHAR(4)) AS WINDOW_PRIORITY,     CAST(T.NEXT_DATE AS DATETIME(6)) AS NEXT_RUN_DATE,     CAST(T.LAST_DATE AS DATETIME(6)) AS LAST_START_DATE,     CAST(T.ENABLED AS CHAR(5)) AS ENABLED,     CAST(NULL AS CHAR(5)) AS ACTIVE,     CAST(NULL AS DATETIME(6)) AS MANUAL_OPEN_TIME,     CAST(NULL AS SIGNED) AS MANUAL_DURATION,     CAST(T.COMMENTS AS CHAR(4000)) AS COMMENTS   FROM oceanbase.__all_tenant_scheduler_job T WHERE T.JOB > 0 and T.JOB_NAME in ('MONDAY_WINDOW',     'TUESDAY_WINDOW', 'WEDNESDAY_WINDOW', 'THURSDAY_WINDOW', 'FRIDAY_WINDOW', 'SATURDAY_WINDOW', 'SUNDAY_WINDOW')   )__"))) { | ||||||
|       LOG_ERROR("fail to set view_definition", K(ret)); |       LOG_ERROR("fail to set view_definition", K(ret)); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -26512,7 +26512,7 @@ def_table_schema( | |||||||
|     CAST(NULL AS DATETIME(6)) AS MANUAL_OPEN_TIME, |     CAST(NULL AS DATETIME(6)) AS MANUAL_OPEN_TIME, | ||||||
|     CAST(NULL AS SIGNED) AS MANUAL_DURATION, |     CAST(NULL AS SIGNED) AS MANUAL_DURATION, | ||||||
|     CAST(T.COMMENTS AS CHAR(4000)) AS COMMENTS |     CAST(T.COMMENTS AS CHAR(4000)) AS COMMENTS | ||||||
|   FROM oceanbase.__all_tenant_scheduler_job T WHERE T.JOB_NAME in ('MONDAY_WINDOW', |   FROM oceanbase.__all_tenant_scheduler_job T WHERE T.JOB > 0 and T.JOB_NAME in ('MONDAY_WINDOW', | ||||||
|     'TUESDAY_WINDOW', 'WEDNESDAY_WINDOW', 'THURSDAY_WINDOW', 'FRIDAY_WINDOW', 'SATURDAY_WINDOW', 'SUNDAY_WINDOW') |     'TUESDAY_WINDOW', 'WEDNESDAY_WINDOW', 'THURSDAY_WINDOW', 'FRIDAY_WINDOW', 'SATURDAY_WINDOW', 'SUNDAY_WINDOW') | ||||||
|   """.replace("\n", " ") |   """.replace("\n", " ") | ||||||
| ) | ) | ||||||
|  | |||||||
| @ -1147,6 +1147,44 @@ int ObUpgradeFor4200Processor::post_upgrade_for_heartbeat_and_server_zone_op_ser | |||||||
|  |  | ||||||
| /* =========== 4200 upgrade processor end ============= */ | /* =========== 4200 upgrade processor end ============= */ | ||||||
|  |  | ||||||
|  | int ObUpgradeFor4211Processor::post_upgrade() | ||||||
|  | { | ||||||
|  |   int ret = OB_SUCCESS; | ||||||
|  |   if (OB_FAIL(check_inner_stat())) { | ||||||
|  |     LOG_WARN("fail to check inner stat", KR(ret)); | ||||||
|  |   } else if (OB_FAIL(post_upgrade_for_dbms_scheduler())) { | ||||||
|  |     LOG_WARN("post for upgrade dbms scheduler failed", K(ret)); | ||||||
|  |   } | ||||||
|  |   return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int ObUpgradeFor4211Processor::post_upgrade_for_dbms_scheduler() | ||||||
|  | { | ||||||
|  |   int ret = OB_SUCCESS; | ||||||
|  |   ObSqlString sql; | ||||||
|  |   int64_t affected_rows = 0; | ||||||
|  |   bool is_tenant_standby = false; | ||||||
|  |   if (sql_proxy_ == NULL) { | ||||||
|  |     ret = OB_ERR_UNEXPECTED; | ||||||
|  |     LOG_WARN("sql_proxy is null", K(ret), K(tenant_id_)); | ||||||
|  |   } else if (OB_FAIL(ObAllTenantInfoProxy::is_standby_tenant(sql_proxy_, tenant_id_, is_tenant_standby))) { | ||||||
|  |     LOG_WARN("check is standby tenant failed", K(ret), K(tenant_id_)); | ||||||
|  |   } else if (is_tenant_standby) { | ||||||
|  |     LOG_INFO("tenant is standby, ignore", K(tenant_id_)); | ||||||
|  |   } else { | ||||||
|  |     OZ (sql.append_fmt( | ||||||
|  |                     "insert ignore into %s " | ||||||
|  |                     "(tenant_id,job_name,job,lowner,powner,cowner,next_date,`interval#`,flag) " | ||||||
|  |                     "select tenant_id, job_name,0,lowner,powner,cowner,next_date,`interval#`,flag from %s where job != 0", | ||||||
|  |                     OB_ALL_TENANT_SCHEDULER_JOB_TNAME, | ||||||
|  |                     OB_ALL_TENANT_SCHEDULER_JOB_TNAME)); // if has new colomn, use default value | ||||||
|  |     OZ (sql_proxy_->write(tenant_id_, sql.ptr(), affected_rows)); | ||||||
|  |     LOG_INFO("insert job_id=0 rows finished for dbms_scheduler old jobs", K(ret), K(tenant_id_), K(affected_rows)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return ret; | ||||||
|  | } | ||||||
|  | /* =========== 4211 upgrade processor end ============= */ | ||||||
|  |  | ||||||
| /* =========== special upgrade processor end   ============= */ | /* =========== special upgrade processor end   ============= */ | ||||||
| } // end share | } // end share | ||||||
|  | |||||||
| @ -210,7 +210,17 @@ private: | |||||||
| }; | }; | ||||||
|  |  | ||||||
| DEF_SIMPLE_UPGRARD_PROCESSER(4, 2, 1, 0) | DEF_SIMPLE_UPGRARD_PROCESSER(4, 2, 1, 0) | ||||||
| DEF_SIMPLE_UPGRARD_PROCESSER(4, 2, 1, 1) | class ObUpgradeFor4211Processor : public ObBaseUpgradeProcessor | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |   ObUpgradeFor4211Processor() : ObBaseUpgradeProcessor() {} | ||||||
|  |   virtual ~ObUpgradeFor4211Processor() {} | ||||||
|  |   virtual int pre_upgrade() override { return common::OB_SUCCESS; } | ||||||
|  |   virtual int post_upgrade() override; | ||||||
|  | private: | ||||||
|  |   int post_upgrade_for_dbms_scheduler(); | ||||||
|  |  | ||||||
|  | }; | ||||||
| DEF_SIMPLE_UPGRARD_PROCESSER(4, 2, 1, 2) | DEF_SIMPLE_UPGRARD_PROCESSER(4, 2, 1, 2) | ||||||
| DEF_SIMPLE_UPGRARD_PROCESSER(4, 2, 2, 0) | DEF_SIMPLE_UPGRARD_PROCESSER(4, 2, 2, 0) | ||||||
| DEF_SIMPLE_UPGRARD_PROCESSER(4, 3, 0, 0) | DEF_SIMPLE_UPGRARD_PROCESSER(4, 3, 0, 0) | ||||||
|  | |||||||
| @ -1394,7 +1394,7 @@ DEF_INT(connection_control_max_connection_delay, OB_TENANT_PARAMETER, "214748364 | |||||||
| DEF_BOOL(ob_proxy_readonly_transaction_routing_policy, OB_TENANT_PARAMETER, "false", | DEF_BOOL(ob_proxy_readonly_transaction_routing_policy, OB_TENANT_PARAMETER, "false", | ||||||
|          "Proxy route policy for readonly sql: whether regard begining read only stmts as in transaction", |          "Proxy route policy for readonly sql: whether regard begining read only stmts as in transaction", | ||||||
|          ObParameterAttr(Section::OBSERVER, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE)); |          ObParameterAttr(Section::OBSERVER, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE)); | ||||||
| DEF_INT(job_queue_processes, OB_TENANT_PARAMETER, "1000", "[0,1000]", | DEF_INT(job_queue_processes, OB_TENANT_PARAMETER, "1000", "[0,16384]", | ||||||
|         "specifies the maximum number of job slaves per instance that can be created " |         "specifies the maximum number of job slaves per instance that can be created " | ||||||
|         "for the execution of DBMS_JOB jobs and Oracle Scheduler (DBMS_SCHEDULER) jobs.", |         "for the execution of DBMS_JOB jobs and Oracle Scheduler (DBMS_SCHEDULER) jobs.", | ||||||
|         ObParameterAttr(Section::OBSERVER, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE)); |         ObParameterAttr(Section::OBSERVER, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE)); | ||||||
|  | |||||||
| @ -100,21 +100,39 @@ int ObDbmsStatsMaintenanceWindow::get_stats_maintenance_window_jobs_sql(const Ob | |||||||
|       } else if (OB_UNLIKELY(start_usec == -1 || job_action.empty())) { |       } else if (OB_UNLIKELY(start_usec == -1 || job_action.empty())) { | ||||||
|         ret = OB_ERR_UNEXPECTED; |         ret = OB_ERR_UNEXPECTED; | ||||||
|         LOG_WARN("get unexpected error", K(ret), K(start_usec), K(job_action)); |         LOG_WARN("get unexpected error", K(ret), K(start_usec), K(job_action)); | ||||||
|       } else if (OB_FAIL(get_stat_window_job_sql(is_oracle_mode, |  | ||||||
|                                                  tenant_id, |  | ||||||
|                                                  job_id++, |  | ||||||
|                                                  windows_name[i], |  | ||||||
|                                                  exec_env, |  | ||||||
|                                                  start_usec, |  | ||||||
|                                                  job_action, |  | ||||||
|                                                  tmp_sql))) { |  | ||||||
|         LOG_WARN("failed to get stat window job sql", K(ret)); |  | ||||||
|       } else if (OB_FAIL(raw_sql.append_fmt("%s(%s)", (i == 0 ? "" : ","), tmp_sql.ptr()))) { |  | ||||||
|         LOG_WARN("failed to append sql", K(ret)); |  | ||||||
|       } else { |       } else { | ||||||
|         ++ expected_affected_rows; |         if (OB_FAIL(get_stat_window_job_sql(is_oracle_mode, | ||||||
|         tmp_sql.reset(); |                                                   tenant_id, | ||||||
|         job_action.reset(); |                                                   job_id++, | ||||||
|  |                                                   windows_name[i], | ||||||
|  |                                                   exec_env, | ||||||
|  |                                                   start_usec, | ||||||
|  |                                                   job_action, | ||||||
|  |                                                   tmp_sql))) { | ||||||
|  |           LOG_WARN("failed to get stat window job sql", K(ret)); | ||||||
|  |         } else if (OB_FAIL(raw_sql.append_fmt("%s(%s)", (i == 0 ? "" : ","), tmp_sql.ptr()))) { | ||||||
|  |           LOG_WARN("failed to append sql", K(ret)); | ||||||
|  |         } else { | ||||||
|  |           ++ expected_affected_rows; | ||||||
|  |           tmp_sql.reset(); | ||||||
|  |           job_action.reset(); | ||||||
|  |           if (OB_FAIL(get_stat_window_job_sql(is_oracle_mode, | ||||||
|  |                                                     tenant_id, | ||||||
|  |                                                     0, | ||||||
|  |                                                     windows_name[i], | ||||||
|  |                                                     exec_env, | ||||||
|  |                                                     start_usec, | ||||||
|  |                                                     job_action, | ||||||
|  |                                                     tmp_sql))) { | ||||||
|  |             LOG_WARN("failed to get stat window job sql", K(ret)); | ||||||
|  |           } else if (OB_FAIL(raw_sql.append_fmt("%s(%s)", ",", tmp_sql.ptr()))) { | ||||||
|  |             LOG_WARN("failed to append sql", K(ret)); | ||||||
|  |           } else { | ||||||
|  |             ++ expected_affected_rows; | ||||||
|  |             tmp_sql.reset(); | ||||||
|  |             job_action.reset(); | ||||||
|  |           } | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     if (OB_SUCC(ret)) { |     if (OB_SUCC(ret)) { | ||||||
| @ -127,7 +145,17 @@ int ObDbmsStatsMaintenanceWindow::get_stats_maintenance_window_jobs_sql(const Ob | |||||||
|       } else { |       } else { | ||||||
|          ++ expected_affected_rows; |          ++ expected_affected_rows; | ||||||
|          tmp_sql.reset(); |          tmp_sql.reset(); | ||||||
|  |         if (OB_FAIL(get_stats_history_manager_job_sql(is_oracle_mode, tenant_id, | ||||||
|  |                                                       0, exec_env, tmp_sql))) { | ||||||
|  |           LOG_WARN("failed to get stats history manager job sql", K(ret)); | ||||||
|  |         } else if (OB_FAIL(raw_sql.append_fmt(", (%s)", tmp_sql.ptr()))) { | ||||||
|  |           LOG_WARN("failed to append sql", K(ret)); | ||||||
|  |         } else { | ||||||
|  |           ++ expected_affected_rows; | ||||||
|  |           tmp_sql.reset(); | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       //set dummy guard job |       //set dummy guard job | ||||||
|       if (OB_FAIL(ret)) { |       if (OB_FAIL(ret)) { | ||||||
|       } else if (OB_FAIL(get_dummy_guard_job_sql(tenant_id, job_id, tmp_sql))) { |       } else if (OB_FAIL(get_dummy_guard_job_sql(tenant_id, job_id, tmp_sql))) { | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 obdev
					obdev