patch 421 dbms scheduler to master
This commit is contained in:
		| @ -74,120 +74,149 @@ int ObDBMSSchedJobExecutor::run_dbms_sched_job( | ||||
|   } else { | ||||
|     CK (job_info.valid()); | ||||
|     CK ((job_info.get_what().length() != 0) || (job_info.get_program_name().length() != 0)); | ||||
|     if (job_info.get_what().length() != 0) { // action | ||||
|       if (job_info.is_oracle_tenant_) { | ||||
|         OZ (what.append_fmt("BEGIN %.*s; END;", | ||||
|             job_info.get_what().length(), job_info.get_what().ptr())); | ||||
|       } else { | ||||
|         //mysql mode not support anonymous block | ||||
|         OZ (what.append_fmt("CALL %.*s;", | ||||
|             job_info.get_what().length(), job_info.get_what().ptr())); | ||||
|       } | ||||
|     } else { // program | ||||
|       ObSqlString sql; | ||||
|       ObString program_action; | ||||
|       uint64_t number_of_argument = 0; | ||||
|       OZ (sql.assign_fmt("select program_action, number_of_argument from %s where program_name = \'%.*s\'", | ||||
|         OB_ALL_TENANT_SCHEDULER_PROGRAM_TNAME, | ||||
|         job_info.get_program_name().length(), | ||||
|         job_info.get_program_name().ptr())); | ||||
|       SMART_VAR(ObMySQLProxy::MySQLResult, result) { | ||||
|         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_info.get_program_name().ptr()), K(job_info.get_job_name().ptr())); | ||||
|         } else if (OB_NOT_NULL(result.get_result())) { | ||||
|           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) && (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; | ||||
|     if (OB_SUCC(ret)) { | ||||
|       if (job_info.get_what().length() != 0) { // action | ||||
|         if (job_info.is_oracle_tenant_) { | ||||
|           OZ (what.append_fmt("BEGIN %.*s; END;", | ||||
|               job_info.get_what().length(), job_info.get_what().ptr())); | ||||
|         } else { | ||||
|           //mysql mode not support anonymous block | ||||
|           OZ (what.append_fmt("CALL %.*s;", | ||||
|               job_info.get_what().length(), job_info.get_what().ptr())); | ||||
|         } | ||||
|       } else { // program | ||||
|         ObSqlString sql; | ||||
|         ObString program_action; | ||||
|         uint64_t number_of_argument = 0; | ||||
|         OZ (sql.assign_fmt("select program_action, number_of_argument from %s where program_name = \'%.*s\'", | ||||
|           OB_ALL_TENANT_SCHEDULER_PROGRAM_TNAME, | ||||
|           job_info.get_program_name().length(), | ||||
|           job_info.get_program_name().ptr())); | ||||
|         SMART_VAR(ObMySQLProxy::MySQLResult, result) { | ||||
|           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_info.get_program_name().ptr()), K(job_info.get_job_name().ptr())); | ||||
|           } else if (OB_ISNULL(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()), 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()), 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(", | ||||
|         program_action.length(), program_action.ptr())); | ||||
|       if (OB_SUCC(ret) && (0 != number_of_argument)) { | ||||
|         ObString argument_value; | ||||
|         for (int i = 1; OB_SUCC(ret) && i <= number_of_argument; i++) { | ||||
|           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", | ||||
|             OB_ALL_TENANT_SCHEDULER_PROGRAM_ARGUMENT_TNAME, | ||||
|             job_info.get_program_name().length(), | ||||
|             job_info.get_program_name().ptr(), | ||||
|             job_info.get_job_name().length(), | ||||
|             job_info.get_job_name().ptr(), | ||||
|             i)); | ||||
|           SMART_VAR(ObMySQLProxy::MySQLResult, result) { | ||||
|             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())); | ||||
|             } else if (OB_NOT_NULL(result.get_result())) { | ||||
|               if (OB_SUCCESS == (ret = result.get_result()->next())) { | ||||
|                 EXTRACT_VARCHAR_FIELD_MYSQL_SKIP_RET(*(result.get_result()), "default_value", argument_value); | ||||
|                 if (OB_SUCC(ret) && (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_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_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())); | ||||
|         OZ (what.append_fmt("BEGIN %.*s(", | ||||
|           program_action.length(), program_action.ptr())); | ||||
|         if (OB_SUCC(ret) && (0 != number_of_argument)) { | ||||
|           ObString argument_value; | ||||
|           for (int i = 1; OB_SUCC(ret) && i <= number_of_argument; i++) { | ||||
|             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", | ||||
|               OB_ALL_TENANT_SCHEDULER_PROGRAM_ARGUMENT_TNAME, | ||||
|               job_info.get_program_name().length(), | ||||
|               job_info.get_program_name().ptr(), | ||||
|               job_info.get_job_name().length(), | ||||
|               job_info.get_job_name().ptr(), | ||||
|               i)); | ||||
|             SMART_VAR(ObMySQLProxy::MySQLResult, result) { | ||||
|               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())); | ||||
|               } else if (OB_ISNULL(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 = result.get_result()->next())) { | ||||
|                   EXTRACT_VARCHAR_FIELD_MYSQL_SKIP_RET(*(result.get_result()), "default_value", argument_value); | ||||
|                   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 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_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("\'%.*s\'", argument_value.length(), argument_value.ptr())); | ||||
|           } else { | ||||
|             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)); | ||||
|         } | ||||
|         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_) { | ||||
|       ObOracleSqlProxy oracle_proxy(*(static_cast<ObMySQLProxy *>(sql_proxy_))); | ||||
|       CK (OB_NOT_NULL(pool = static_cast<ObInnerSQLConnectionPool *>(oracle_proxy.get_pool()))); | ||||
|       OZ (ObDBMSSchedJobUtils::init_env(job_info, *session_info)); | ||||
|       OZ (pool->acquire_spi_conn(session_info, conn)); | ||||
|       OZ (conn->execute_write(tenant_id, what.string().ptr(), affected_rows)); | ||||
|       if (OB_NOT_NULL(conn)) { | ||||
|         sql_proxy_->close(conn, ret); | ||||
|       if (job_info.is_oracle_tenant_) { | ||||
|         ObOracleSqlProxy oracle_proxy(*(static_cast<ObMySQLProxy *>(sql_proxy_))); | ||||
|         CK (OB_NOT_NULL(pool = static_cast<ObInnerSQLConnectionPool *>(oracle_proxy.get_pool()))); | ||||
|         OZ (ObDBMSSchedJobUtils::init_env(job_info, *session_info)); | ||||
|         OZ (pool->acquire_spi_conn(session_info, conn)); | ||||
|         OZ (conn->execute_write(tenant_id, what.string().ptr(), affected_rows)); | ||||
|         if (OB_NOT_NULL(conn)) { | ||||
|           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) { | ||||
| @ -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)); | ||||
|  | ||||
|   if (OB_SUCC(ret)) { | ||||
|     OZ (table_operator_.update_for_start(tenant_id, job_info)); | ||||
|  | ||||
|     OZ (run_dbms_sched_job(tenant_id, job_info)); | ||||
|  | ||||
|  | ||||
| @ -29,6 +29,8 @@ | ||||
| #include "observer/ob_server_struct.h" | ||||
| #include "rootserver/ob_root_service.h" | ||||
|  | ||||
| #define TO_TS(second) (1000000L * second) | ||||
|  | ||||
| namespace oceanbase | ||||
| { | ||||
| using namespace common; | ||||
| @ -48,26 +50,20 @@ int ObDBMSSchedJobTask::init() | ||||
|   if (inited_) { | ||||
|     ret = OB_INIT_TWICE; | ||||
|     LOG_WARN("init twice", K(ret), K(inited_)); | ||||
|   } else if (OB_FAIL(timer_.init())) { | ||||
|     LOG_WARN("fail to init timer", K(ret)); | ||||
|   } else { | ||||
|     inited_ = true; | ||||
|   } | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| int ObDBMSSchedJobTask::start(dbms_job::ObDBMSJobQueue *ready_queue) | ||||
| int ObDBMSSchedJobTask::start(ObVSliceAlloc *allocator) | ||||
| { | ||||
|   int ret = OB_SUCCESS; | ||||
|   if (!inited_) { | ||||
|     ret = OB_NOT_INIT; | ||||
|     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; | ||||
|   OZ (timer_.start()); | ||||
|   allocator_ = allocator; | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| @ -78,12 +74,15 @@ int ObDBMSSchedJobTask::stop() | ||||
|     ret = OB_NOT_INIT; | ||||
|     LOG_WARN("dbms sched job task not inited", K(ret), K(inited_)); | ||||
|   } else { | ||||
|     timer_.cancel(*this); | ||||
|     timer_.stop(); | ||||
|     timer_.wait(); | ||||
|     if (allocator_ != NULL) { | ||||
|       for (WaitVectorIterator iter = wait_vector_.begin(); | ||||
|               OB_SUCC(ret) && iter != wait_vector_.end(); ++iter) { | ||||
|         ObDBMSSchedJobKey *job_key = *iter; | ||||
|         allocator_->free(job_key); | ||||
|       } | ||||
|     } | ||||
|     wait_vector_.clear(); | ||||
|     job_key_ = NULL; | ||||
|     ready_queue_ = NULL; | ||||
|     allocator_ = NULL; | ||||
|   } | ||||
|   return ret; | ||||
| } | ||||
| @ -94,50 +93,10 @@ int ObDBMSSchedJobTask::destroy() | ||||
|   if (!inited_) { | ||||
|     ret = OB_NOT_INIT; | ||||
|     LOG_WARN("scheduler task not inited", K(ret), K(inited_)); | ||||
|   } else { | ||||
|     timer_.destroy(); | ||||
|   } | ||||
|   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 ret = OB_SUCCESS; | ||||
| @ -146,12 +105,10 @@ int ObDBMSSchedJobTask::scheduler(ObDBMSSchedJobKey *job_key) | ||||
|     LOG_WARN("dbms sched job task not init", K(ret)); | ||||
|   } else if (OB_ISNULL(job_key)) { | ||||
|     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()) { | ||||
|     ret = OB_ERR_UNEXPECTED; | ||||
|     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 { | ||||
|     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; | ||||
|     LOG_WARN("NULL ptr", K(ret), KPC(new_job_key)); | ||||
|   } else { | ||||
|     ObSpinLockGuard guard(lock_); | ||||
|     if (OB_ISNULL(job_key_)) { | ||||
|       job_key_ = new_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())); | ||||
|     } | ||||
|     WaitVectorIterator iter; | ||||
|     ObDBMSSchedJobKey *replace_job_key = NULL; | ||||
|     OZ (wait_vector_.replace(new_job_key, iter, compare_job_key, equal_job_key, replace_job_key)); | ||||
|   } | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| int ObDBMSSchedJobTask::immediately(ObDBMSSchedJobKey *job_key) | ||||
| { | ||||
|   int ret = OB_SUCCESS; | ||||
|   if (!inited_) { | ||||
|     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)); | ||||
|     } | ||||
|   /* | ||||
|   LOG_DEBUG("JobKEYS INFO HEADER ==== ", KPC(new_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 ret; | ||||
| } | ||||
|  | ||||
| @ -258,8 +194,6 @@ int ObDBMSSchedJobMaster::init(ObUnitManager *unit_mgr, | ||||
|           ) { | ||||
|     ret = OB_ERR_UNEXPECTED; | ||||
|     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())) { | ||||
|     LOG_WARN("fail to init ready queue", K(ret)); | ||||
|   } else if (OB_FAIL(scheduler_thread_.init(1, 1))) { | ||||
| @ -293,7 +227,7 @@ int ObDBMSSchedJobMaster::start() | ||||
|     // alreay running , do nothing ... | ||||
|   } else if (OB_FAIL(scheduler_thread_.push(static_cast<void *>(this)))) { | ||||
|     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_INFO("dbms sched job master started", K(ret)); | ||||
| @ -308,13 +242,52 @@ int ObDBMSSchedJobMaster::stop() | ||||
|     sleep(1); | ||||
|   } | ||||
|   scheduler_task_.stop(); | ||||
|   ready_queue_.clear(); | ||||
|   alive_jobs_.clear(); | ||||
|   stoped_ = false; | ||||
|   LOG_INFO("dbms sched job master stoped", K(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 ret = OB_SUCCESS; | ||||
| @ -331,30 +304,31 @@ int ObDBMSSchedJobMaster::scheduler() | ||||
|     lib::set_thread_name("DBMS_SCHEDULER"); | ||||
|     while (OB_SUCC(ret) && !stoped_) { | ||||
|       ObLink* ptr = NULL; | ||||
|       int64_t timeout = MIN_SCHEDULER_INTERVAL; | ||||
|       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())) { | ||||
|           LOG_WARN("fail to check all tenants", K(tmp_ret)); | ||||
|         } | ||||
|       } | ||||
|       if (OB_FAIL(ready_queue_.pop(ptr, timeout))) { | ||||
|         if (OB_ENTRY_NOT_EXIST == ret) { | ||||
|           LOG_INFO("dbms sched job master wait timeout, no entry", K(ret)); | ||||
|           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()) { | ||||
|       if (scheduler_task_.wait_vector().count() == 0) { | ||||
|         ob_usleep(MIN_SCHEDULER_INTERVAL); | ||||
|       } else if (OB_ISNULL(job_key = scheduler_task_.wait_vector()[0]) || !job_key->is_valid()) { | ||||
|         ret = OB_ERR_UNEXPECTED; | ||||
|         LOG_ERROR("unexpected error, invalid job key found in ready queue!", K(ret), KPC(job_key)); | ||||
|       } else { | ||||
|         int tmp_ret = OB_SUCCESS; | ||||
|         if (OB_SUCCESS != (tmp_ret = scheduler_job(job_key))) { | ||||
|           LOG_WARN("fail to scheduler single dbms sched job", K(ret), K(tmp_ret), KPC(job_key)); | ||||
|         int64_t delay = job_key->get_execute_at() - ObTimeUtility::current_time(); | ||||
|         if (delay > MIN_SCHEDULER_INTERVAL) { | ||||
|           ob_usleep(MIN_SCHEDULER_INTERVAL); | ||||
|         } 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_NOT_NULL(job_key)); | ||||
|   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)) { | ||||
|     LOG_WARN("fail to scheduler job", K(ret), KPC(job_key)); | ||||
|   } else { | ||||
| @ -383,78 +357,118 @@ int ObDBMSSchedJobMaster::scheduler_job(ObDBMSSchedJobKey *job_key) | ||||
|     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)); | ||||
|  | ||||
|     if (OB_FAIL(ret) || !job_info.valid()) { | ||||
|       int tmp = alive_jobs_.erase_refactored(job_key->get_job_id_with_tenant()); | ||||
|       if (tmp != OB_SUCCESS) { | ||||
|         LOG_ERROR("failed delete invalid job from hash set", K(tmp), K(ret), K(job_info), KPC(job_key)); | ||||
|     const int64_t now = ObTimeUtility::current_time(); | ||||
|     int64_t next_check_date = now + MIN_SCHEDULER_INTERVAL; | ||||
|     if (OB_FAIL(ret) || !job_info.valid() || job_info.is_disabled() || job_info.is_broken()) { | ||||
|       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 { | ||||
|         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 | ||||
|     } else{ | ||||
|       bool ignore_nextdate = false; | ||||
|       if (!job_key->is_check() && !job_info.is_running() && !job_info.is_broken() && !job_info.is_disabled()) { | ||||
|         bool can_running = false; | ||||
|         OZ (table_operator_.check_job_can_running(job_info.get_tenant_id(), can_running)); | ||||
|         if (OB_SUCC(ret) && can_running) { | ||||
|           OZ (get_execute_addr(job_info, execute_addr)); | ||||
|           OZ (table_operator_.update_for_start( | ||||
|             job_info.get_tenant_id(), job_info)); | ||||
|           OZ (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_)); | ||||
|       free_job_key(job_key); | ||||
|       job_key = NULL; | ||||
|     } else if (now < job_info.get_next_date()) { | ||||
|         next_check_date = min(job_info.get_next_date(), now + CHECK_NEW_INTERVAL); | ||||
|     } else { | ||||
|       bool can_running = false; | ||||
|       if (OB_FAIL(table_operator_.check_job_can_running(job_info.get_tenant_id(), alive_jobs_.size(), can_running))) { | ||||
|         LOG_WARN("failed to check job can running, retry later", K(ret)); | ||||
|       } else if (!can_running) { | ||||
|         LOG_INFO("job concurrency reach limit, retry later", K(ret), K(job_info), K(can_running)); | ||||
|       } else if (now > job_info.get_next_date() + TO_TS(job_info.get_max_run_duration())) { | ||||
|         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 { | ||||
|           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; | ||||
|       } | ||||
|       int tmp_ret = OB_SUCCESS; | ||||
|       // always add job to queue. we need this to check job status changes. | ||||
|       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 { | ||||
|         int64_t new_next_date = calc_next_date(job_info); | ||||
|         if (OB_FAIL(run_job(job_info, job_key, new_next_date))) { | ||||
|           LOG_WARN("failed to run job", K(ret), K(job_info), KPC(job_key)); | ||||
|         } 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; | ||||
| } | ||||
|  | ||||
| int ObDBMSSchedJobMaster::destroy() | ||||
| { | ||||
|   ready_queue_.destroy(); | ||||
|   scheduler_task_.destroy(); | ||||
|   scheduler_thread_.destroy(); | ||||
|   allocator_.clear(); | ||||
|   allocator_.destroy(); | ||||
|   return OB_SUCCESS; | ||||
| } | ||||
|  | ||||
| int ObDBMSSchedJobMaster::alloc_job_key( | ||||
|   ObDBMSSchedJobKey *&job_key, | ||||
|   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) | ||||
|   uint64_t tenant_id, bool is_oracle_tenant, uint64_t job_id, const ObString &job_name) | ||||
| { | ||||
|   int ret = OB_SUCCESS; | ||||
|   ObSpinLockGuard guard(lock_); | ||||
|   void *ptr = NULL; | ||||
|   job_key = NULL; | ||||
|   if (OB_ISNULL(ptr = allocator_.alloc(sizeof(ObDBMSSchedJobKey)))) { | ||||
|     ret = OB_ALLOCATE_MEMORY_FAILED; | ||||
|     LOG_WARN("fail to alloc memory", K(ret), K(ptr)); | ||||
|   } else if (OB_ISNULL(job_key = | ||||
|     new(ptr)ObDBMSSchedJobKey(tenant_id, is_oracle_tenant, job_id, job_name, | ||||
|                          execute_at, delay, | ||||
|                          check_job))) { | ||||
|     new(ptr)ObDBMSSchedJobKey(tenant_id, is_oracle_tenant, job_id, job_name))) { | ||||
|     ret = OB_ERR_UNEXPECTED; | ||||
|     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; | ||||
| } | ||||
|  | ||||
| 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 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_active = 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; | ||||
|     do { | ||||
|       pos = (pos + 1) % total_server.count(); | ||||
| @ -566,7 +580,27 @@ int ObDBMSSchedJobMaster::check_all_tenants() | ||||
|       const ObTenantSchema *tenant_schema = NULL; | ||||
|       OZ (schema_guard.get_tenant_info(tenant_ids.at(i), 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; | ||||
|         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)); | ||||
| @ -599,84 +633,54 @@ int ObDBMSSchedJobMaster::register_new_jobs(uint64_t tenant_id, bool is_oracle_t | ||||
| { | ||||
|   int ret = OB_SUCCESS; | ||||
|   ObDBMSSchedJobInfo job_info; | ||||
|   JobIdByTenant job_id_by_tenant; | ||||
|   for (int64_t i = 0; OB_SUCC(ret) && i < job_infos.count(); i++) { | ||||
|     job_info = job_infos.at(i); | ||||
|     if (job_info.valid()) { | ||||
|       int tmp = alive_jobs_.exist_refactored(job_info.get_job_id_with_tenant()); | ||||
|     if (job_info.valid() && !job_info.is_disabled() && !job_info.is_broken()) { | ||||
|       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) { | ||||
|         // do nothing ... | ||||
|       } else if (OB_HASH_NOT_EXIST) { | ||||
|         OZ (register_job(job_info)); | ||||
|         OZ (alive_jobs_.set_refactored(job_info.get_job_id_with_tenant())); | ||||
|         LOG_DEBUG("job exist", K(alive_jobs_), K(job_id_by_tenant)); | ||||
|       } else if (OB_HASH_NOT_EXIST == tmp) { | ||||
|         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)); | ||||
|       } 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; | ||||
| } | ||||
|  | ||||
| int ObDBMSSchedJobMaster::register_job( | ||||
|   ObDBMSSchedJobInfo &job_info, ObDBMSSchedJobKey *job_key, bool ignore_nextdate) | ||||
| int ObDBMSSchedJobMaster::register_job(ObDBMSSchedJobKey *job_key, int64_t next_date) | ||||
| { | ||||
|   int ret = OB_SUCCESS; | ||||
|  | ||||
|   int64_t execute_at = -1; | ||||
|   int64_t delay = -1; | ||||
|   bool check_job = false; | ||||
|   int64_t now = ObTimeUtility::current_time(); | ||||
|  | ||||
|   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; | ||||
|   if (OB_ISNULL(job_key)) { | ||||
|     ret = OB_INVALID_ARGUMENT; | ||||
|     LOG_WARN("job key is null", K(ret)); | ||||
|   } else if (next_date == 0) { | ||||
|     ret = OB_INVALID_ARGUMENT; | ||||
|     LOG_WARN("next date should not be 0", K(ret), KPC(job_key), K(next_date)); | ||||
|   } else { | ||||
|     OZ (table_operator_.calc_execute_at(job_info, execute_at, delay, ignore_nextdate)); | ||||
|     if (OB_FAIL(ret) || delay < 0) { | ||||
|       ret = OB_SUCCESS; | ||||
|       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; | ||||
|     job_key->set_execute_at(next_date); | ||||
|     if (OB_FAIL(scheduler_task_.scheduler(job_key))) { | ||||
|       LOG_WARN("failed to scheduler job", K(ret), KPC(job_key)); | ||||
|     } | ||||
|   } | ||||
|   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; | ||||
| } | ||||
|  | ||||
|  | ||||
| @ -51,16 +51,11 @@ class ObDBMSSchedJobKey : public common::ObLink | ||||
| { | ||||
| public: | ||||
|   ObDBMSSchedJobKey( | ||||
|     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) | ||||
|     uint64_t tenant_id, bool is_oracle_tenant, uint64_t job_id, const common::ObString &job_name) | ||||
|   : tenant_id_(tenant_id), | ||||
|     is_oracle_tenant_(is_oracle_tenant), | ||||
|     job_id_(job_id), | ||||
|     job_name_(), | ||||
|     execute_at_(execute_at), | ||||
|     delay_(delay), | ||||
|     check_job_(check_job) { | ||||
|     job_name_() { | ||||
|       job_name_.assign_buffer(job_name_buf_, JOB_NAME_MAX_SIZE); | ||||
|       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 common::ObString &get_job_name() { return job_name_; } | ||||
|   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_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_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 | ||||
|   { | ||||
|     uint64_t now = ObTimeUtility::current_time(); | ||||
| @ -103,9 +89,7 @@ public: | ||||
|     K_(is_oracle_tenant), | ||||
|     K_(job_id), | ||||
|     K_(job_name), | ||||
|     K_(execute_at), | ||||
|     K_(delay), | ||||
|     K_(check_job)); | ||||
|     K_(execute_at)); | ||||
|  | ||||
| private: | ||||
|   uint64_t tenant_id_; | ||||
| @ -114,12 +98,9 @@ private: | ||||
|   char job_name_buf_[JOB_NAME_MAX_SIZE]; | ||||
|   common::ObString job_name_; | ||||
|   uint64_t execute_at_; | ||||
|   uint64_t delay_; | ||||
|  | ||||
|   bool check_job_; // for check job update ... | ||||
| }; | ||||
|  | ||||
| class ObDBMSSchedJobTask : public ObTimerTask | ||||
| class ObDBMSSchedJobTask | ||||
| { | ||||
| public: | ||||
|   typedef common::ObSortedVector<ObDBMSSchedJobKey *> WaitVector; | ||||
| @ -127,23 +108,19 @@ public: | ||||
|  | ||||
|   ObDBMSSchedJobTask() | ||||
|     : inited_(false), | ||||
|       job_key_(NULL), | ||||
|       ready_queue_(NULL), | ||||
|       wait_vector_(0, NULL, ObModIds::VECTOR), | ||||
|       lock_(common::ObLatchIds::DBMS_SCHEDULER_TASK_LOCK) {} | ||||
|       allocator_(NULL), | ||||
|       wait_vector_(0, NULL, ObModIds::VECTOR) {} | ||||
|  | ||||
|   virtual ~ObDBMSSchedJobTask() {} | ||||
|  | ||||
|   int init(); | ||||
|   int start(dbms_job::ObDBMSJobQueue *ready_queue); | ||||
|   int start(common::ObVSliceAlloc *allocator); | ||||
|   int stop(); | ||||
|   int destroy(); | ||||
|  | ||||
|   void runTimerTask(); | ||||
|  | ||||
|   int scheduler(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( | ||||
|     const ObDBMSSchedJobKey *lhs, const ObDBMSSchedJobKey *rhs); | ||||
| @ -152,13 +129,8 @@ public: | ||||
|  | ||||
| private: | ||||
|   bool inited_; | ||||
|   ObDBMSSchedJobKey *job_key_; | ||||
|   dbms_job::ObDBMSJobQueue *ready_queue_; | ||||
|   common::ObVSliceAlloc *allocator_; | ||||
|   WaitVector wait_vector_; | ||||
|  | ||||
|   ObSpinLock lock_; | ||||
|   ObTimer timer_; | ||||
|  | ||||
| private: | ||||
|   DISALLOW_COPY_AND_ASSIGN(ObDBMSSchedJobTask); | ||||
| }; | ||||
| @ -175,11 +147,54 @@ public: | ||||
|       schema_service_(NULL), | ||||
|       job_rpc_proxy_(NULL), | ||||
|       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_() {} | ||||
|  | ||||
|   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(); | ||||
|  | ||||
|   bool is_inited() { return inited_; } | ||||
| @ -195,23 +210,23 @@ public: | ||||
|  | ||||
|   int alloc_job_key( | ||||
|     ObDBMSSchedJobKey *&job_key, | ||||
|     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 = false); | ||||
|  | ||||
|     uint64_t tenant_id, bool is_oracle_tenant, uint64_t job_id, const common::ObString &job_name); | ||||
|   void free_job_key(ObDBMSSchedJobKey *&job_key); | ||||
|   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 check_all_tenants(); | ||||
|   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_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); | ||||
|   int64_t calc_next_date(ObDBMSSchedJobInfo &job_info); | ||||
|   int64_t run_job(ObDBMSSchedJobInfo &job_info, ObDBMSSchedJobKey *job_key, int64_t next_date); | ||||
|  | ||||
| private: | ||||
|   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 stoped_; | ||||
| @ -225,15 +240,14 @@ private: | ||||
|   obrpc::ObDBMSSchedJobRpcProxy *job_rpc_proxy_; | ||||
|  | ||||
|   common::ObAddr self_addr_; | ||||
|   dbms_job::ObDBMSJobQueue ready_queue_; | ||||
|   ObDBMSSchedJobTask scheduler_task_; | ||||
|   ObDBMSSchedJobThread scheduler_thread_; | ||||
|   ObDBMSSchedTableOperator table_operator_; | ||||
|  | ||||
|   common::ObSpinLock lock_; | ||||
|   common::ObArenaAllocator allocator_; | ||||
|   common::ObBlockAllocMgr block_alloc_; | ||||
|   common::ObVSliceAlloc allocator_; | ||||
|  | ||||
|   common::hash::ObHashSet<uint64_t> alive_jobs_; | ||||
|   common::hash::ObHashSet<JobIdByTenant> alive_jobs_; | ||||
|  | ||||
| private: | ||||
|   DISALLOW_COPY_AND_ASSIGN(ObDBMSSchedJobMaster); | ||||
|  | ||||
| @ -49,7 +49,6 @@ public: | ||||
|   { | ||||
|     return common::is_valid_tenant_id(tenant_id_) | ||||
|         && job_id_ != common::OB_INVALID_ID | ||||
|         && !job_name_.empty() | ||||
|         && server_addr_.is_valid() | ||||
|         && master_addr_.is_valid(); | ||||
|   } | ||||
|  | ||||
| @ -145,6 +145,9 @@ public: | ||||
|   int64_t  get_last_modify() { return last_modify_; } | ||||
|   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_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_running(){ return this_date_ != 0; } | ||||
|  | ||||
| @ -34,7 +34,6 @@ | ||||
| #include "share/schema/ob_multi_version_schema_service.h" | ||||
| #include "storage/mview/ob_mview_sched_job_utils.h" | ||||
|  | ||||
| #define TO_TS(second) 1000000L * second | ||||
|  | ||||
| namespace oceanbase | ||||
| { | ||||
| @ -48,8 +47,8 @@ using namespace storage; | ||||
| namespace dbms_scheduler | ||||
| { | ||||
|  | ||||
| int ObDBMSSchedTableOperator::update_for_start( | ||||
|   uint64_t tenant_id, ObDBMSSchedJobInfo &job_info, bool update_nextdate) | ||||
| int ObDBMSSchedTableOperator::update_next_date( | ||||
|   uint64_t tenant_id, ObDBMSSchedJobInfo &job_info, int64_t next_date) | ||||
| { | ||||
|   int ret = OB_SUCCESS; | ||||
|  | ||||
| @ -57,50 +56,67 @@ int ObDBMSSchedTableOperator::update_for_start( | ||||
|   ObSqlString sql; | ||||
|   int64_t affected_rows = 0; | ||||
|   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_LIKELY(tenant_id != OB_INVALID_ID)); | ||||
|   CK (OB_LIKELY(job_info.job_ != OB_INVALID_ID)); | ||||
|  | ||||
|   OZ (calc_execute_at( | ||||
|     job_info, (update_nextdate ? job_info.next_date_ : dummy_execute_at), delay, true)); | ||||
|   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("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); | ||||
|   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("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("next_date", next_date)); | ||||
|   OZ (dml.add_column("state", "SCHEDULED")); | ||||
|   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)); | ||||
|  | ||||
|   CK (affected_rows == 1); | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| int ObDBMSSchedTableOperator::update_nextdate( | ||||
|   uint64_t tenant_id, ObDBMSSchedJobInfo &job_info) | ||||
| int ObDBMSSchedTableOperator::seperate_job_id_from_name(ObString &job_name, int64_t &job_id) | ||||
| { | ||||
|   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)); | ||||
|  | ||||
|   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("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)); | ||||
|  | ||||
|   const char* prefix = "JOB$_"; | ||||
|   job_id = 0; | ||||
|   if (job_name.prefix_match(prefix)) { | ||||
|     char nptr[JOB_NAME_MAX_SIZE]; | ||||
|     char *endptr = NULL; | ||||
|     snprintf(nptr, JOB_NAME_MAX_SIZE, "%.*s", job_name.length(), job_name.ptr()); | ||||
|     job_id = strtoll(nptr + strlen(prefix), &endptr, 10); | ||||
|     if (job_id <= 0) { | ||||
|       LOG_WARN("job_id is not right", K(job_name), K(nptr), K(job_id)); | ||||
|     } else if (*endptr != '\0' || job_id <= JOB_ID_OFFSET) { | ||||
|       job_id = 0; // use job_info.job_ when job_id is not formal | ||||
|     } | ||||
|   } | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| @ -117,8 +133,6 @@ int ObDBMSSchedTableOperator::update_for_end( | ||||
|   ObSqlString sql2; | ||||
|   int64_t affected_rows = 0; | ||||
|   const int64_t now = ObTimeUtility::current_time(); | ||||
|   int64_t next_date; | ||||
|   int64_t delay; | ||||
|  | ||||
|   UNUSED(errmsg); | ||||
|  | ||||
| @ -161,12 +175,13 @@ int ObDBMSSchedTableOperator::update_for_end( | ||||
|       OZ (dml1.add_column("state", "COMPLETED")); | ||||
|       OZ (dml1.add_column("enabled", job_info.enabled_)); | ||||
|     } | ||||
|     CK (job_info.this_date_ > 0); | ||||
|     OX (job_info.total_ += (now - job_info.this_date_)); | ||||
|     CK (job_info.this_date_ > 0 || !errmsg.empty()); | ||||
|     OX (job_info.total_ += (job_info.this_date_ > 0 ? now - job_info.this_date_ : 0)); | ||||
|     OZ (dml1.add_gmt_modified(now)); | ||||
|     OZ (dml1.add_pk_column("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_name", job_info.job_name_)); | ||||
|     OZ (dml1.add_column(true, "this_date")); | ||||
|     OZ (dml1.add_time_column("last_date", job_info.this_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_modified(now)); | ||||
|     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_column("code", err)); | ||||
|     OZ (dml2.add_column( | ||||
| @ -225,32 +245,7 @@ int ObDBMSSchedTableOperator::update_for_end( | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| int ObDBMSSchedTableOperator::check_job_timeout(ObDBMSSchedJobInfo &job_info) | ||||
| { | ||||
|   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 ObDBMSSchedTableOperator::check_job_can_running(int64_t tenant_id, int64_t alive_job_count, bool &can_running) | ||||
| { | ||||
|   int ret = OB_SUCCESS; | ||||
|   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()); | ||||
|   OX (job_queue_processor = tenant_config->job_queue_processes); | ||||
|   // 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_)); | ||||
|   OZ (GCTX.schema_service_->get_tenant_schema_guard(tenant_id, guard)); | ||||
|   OZ (guard.check_tenant_is_restore(tenant_id, is_restore)); | ||||
|     CK (OB_NOT_NULL(GCTX.schema_service_)); | ||||
|     OZ (GCTX.schema_service_->get_tenant_schema_guard(tenant_id, guard)); | ||||
|     OZ (guard.check_tenant_is_restore(tenant_id, is_restore)); | ||||
|  | ||||
|   // job can not run in standy cluster and restore. | ||||
|   if (OB_SUCC(ret) && job_queue_processor > 0 | ||||
|       && !GCTX.is_standby_cluster() | ||||
|       && !is_restore) { | ||||
|     SMART_VAR(ObMySQLProxy::MySQLResult, result) { | ||||
|       if (OB_FAIL(sql_proxy_->read(result, tenant_id, sql.ptr()))) { | ||||
|         LOG_WARN("execute query failed", K(ret), K(sql), K(tenant_id)); | ||||
|       } else if (OB_NOT_NULL(result.get_result())) { | ||||
|         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); | ||||
|           } | ||||
|     // job can not run in standy cluster and restore. | ||||
|     if (OB_SUCC(ret) && job_queue_processor > 0 | ||||
|         && !is_restore) { | ||||
|       SMART_VAR(ObMySQLProxy::MySQLResult, result) { | ||||
|         if (OB_FAIL(sql_proxy_->read(result, tenant_id, sql.ptr()))) { | ||||
|           LOG_WARN("execute query failed", K(ret), K(sql), K(tenant_id)); | ||||
|         } else if (OB_ISNULL(result.get_result())) { | ||||
|           ret = OB_ERR_UNEXPECTED; | ||||
|           LOG_WARN("get result failed", K(ret), K(sql), K(tenant_id)); | ||||
|         } 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; | ||||
| } | ||||
| @ -399,16 +401,24 @@ int ObDBMSSchedTableOperator::get_dbms_sched_job_info( | ||||
|     SMART_VAR(ObMySQLProxy::MySQLResult, result) { | ||||
|       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)); | ||||
|       } 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())) { | ||||
|           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) { | ||||
|             LOG_ERROR("got more than one row for dbms sched job!", K(ret), K(tenant_id), K(job_id)); | ||||
|             ret = OB_ERR_UNEXPECTED; | ||||
|           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 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) { | ||||
|           LOG_INFO("job not exists, may delete alreay!", K(ret), K(tenant_id), K(job_id)); | ||||
|           ret = OB_SUCCESS; // job not exist, do nothing ... | ||||
|           LOG_WARN("job not exists, may delete alreay!", K(ret), K(tenant_id), K(job_id)); | ||||
|         } else { | ||||
|           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) { | ||||
|       if (OB_FAIL(sql_proxy_->read(result, tenant_id, sql.ptr()))) { | ||||
|         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 { | ||||
|           if (OB_FAIL(result.get_result()->next())) { | ||||
|             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) { | ||||
|       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)); | ||||
|       } 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())) { | ||||
|           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) { | ||||
|             LOG_ERROR("got more than one row for dbms sched job class!", K(ret), K(tenant_id), K(job_class_name)); | ||||
|             ret = OB_ERR_UNEXPECTED; | ||||
|           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 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) { | ||||
|           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; | ||||
| } | ||||
|  | ||||
| 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 ret = OB_SUCCESS; | ||||
|  | ||||
| @ -46,14 +46,20 @@ class ObDBMSSchedTableOperator | ||||
| public: | ||||
|   ObDBMSSchedTableOperator() : sql_proxy_(NULL) {} | ||||
|   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 update_next_date( | ||||
|     uint64_t tenant_id, ObDBMSSchedJobInfo &job_info, int64_t next_date); | ||||
|  | ||||
|   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( | ||||
|     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( | ||||
|     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, | ||||
|     ObIAllocator &allocator, ObDBMSSchedJobClassInfo &job_class_info); | ||||
|  | ||||
|   int calc_execute_at( | ||||
|     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 check_job_can_running(int64_t tenant_id, int64_t alive_job_count, bool &can_running); | ||||
|  | ||||
|   int register_default_job_class(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())); | ||||
|  | ||||
|   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)); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @ -26512,7 +26512,7 @@ def_table_schema( | ||||
|     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', | ||||
|   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') | ||||
|   """.replace("\n", " ") | ||||
| ) | ||||
|  | ||||
| @ -1147,6 +1147,44 @@ int ObUpgradeFor4200Processor::post_upgrade_for_heartbeat_and_server_zone_op_ser | ||||
|  | ||||
| /* =========== 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   ============= */ | ||||
| } // end share | ||||
|  | ||||
| @ -210,7 +210,17 @@ private: | ||||
| }; | ||||
|  | ||||
| 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, 2, 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", | ||||
|          "Proxy route policy for readonly sql: whether regard begining read only stmts as in transaction", | ||||
|          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 " | ||||
|         "for the execution of DBMS_JOB jobs and Oracle Scheduler (DBMS_SCHEDULER) jobs.", | ||||
|         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())) { | ||||
|         ret = OB_ERR_UNEXPECTED; | ||||
|         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 { | ||||
|         ++ expected_affected_rows; | ||||
|         tmp_sql.reset(); | ||||
|         job_action.reset(); | ||||
|         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 { | ||||
|           ++ 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)) { | ||||
| @ -127,7 +145,17 @@ int ObDbmsStatsMaintenanceWindow::get_stats_maintenance_window_jobs_sql(const Ob | ||||
|       } else { | ||||
|          ++ expected_affected_rows; | ||||
|          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 | ||||
|       if (OB_FAIL(ret)) { | ||||
|       } else if (OB_FAIL(get_dummy_guard_job_sql(tenant_id, job_id, tmp_sql))) { | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 obdev
					obdev