// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

#include "runtime/thread_context.h"

#include <mutex>

#include "common/signal_handler.h"
#include "runtime/exec_env.h"
#include "runtime/query_context.h"
#include "runtime/runtime_state.h"
#include "runtime/workload_management/resource_context.h"

namespace doris {
class MemTracker;

bthread_key_t btls_key;

namespace {

void thread_context_deleter(void* data) {
    delete static_cast<ThreadContext*>(data);
}

} // namespace

void init_thread_context_btls_key() {
    static std::once_flag btls_key_once;
    std::call_once(btls_key_once,
                   []() { CHECK_EQ(0, bthread_key_create(&btls_key, thread_context_deleter)); });
}

void ThreadContext::attach_task(const std::shared_ptr<ResourceContext>& rc) {
    // will only attach_task at the beginning of the thread function, there should be no duplicate attach_task.
    DCHECK(resource_ctx_ == nullptr);
    // Validation of `rc` and its sub-objects is performed by the
    // AttachTask::init() / SwitchResourceContext constructor entry
    // points before any thread-local or signal mutation, so a thrown
    // FatalError does not leak thread-local handle counts or leave a
    // stale signal task id behind.
    resource_ctx_ = rc;
    thread_mem_tracker_mgr->attach_limiter_tracker(rc->memory_context()->mem_tracker(),
                                                   rc->workload_group());
    thread_mem_tracker_mgr->enable_wait_gc();
}

std::shared_ptr<ResourceContext> ThreadContext::_make_orphan_resource_ctx() {
    auto ctx = ResourceContext::create_shared();
    ctx->memory_context()->set_mem_tracker(ExecEnv::GetInstance()->orphan_mem_tracker());
    return ctx;
}

void AttachTask::init(const std::shared_ptr<ResourceContext>& rc) {
    // Validate the ResourceContext chain before mutating any thread-local
    // or signal state. If any link is null we throw immediately, so the
    // caller's stack-unwind sees a clean state (no thread-local handle is
    // acquired and no signal task id is set). Without these the previous
    // code would silently propagate a null mem_tracker into
    // ThreadMemTrackerMgr and crash much later inside the allocator.
    if (UNLIKELY(rc == nullptr)) {
        throw Exception(
                Status::FatalError("AttachTask::init: rc is null. signal_query_id={:x}-{:x}",
                                   signal::query_id_hi, signal::query_id_lo));
    }
    if (UNLIKELY(rc->memory_context() == nullptr)) {
        throw Exception(Status::FatalError(
                "AttachTask::init: rc->memory_context() is null. signal_query_id={:x}-{:x}",
                signal::query_id_hi, signal::query_id_lo));
    }
    if (UNLIKELY(rc->memory_context()->mem_tracker() == nullptr)) {
        throw Exception(Status::FatalError(
                "AttachTask::init: rc->memory_context()->mem_tracker() is null. "
                "ResourceContext was created but set_mem_tracker has not been called yet "
                "(likely a half-initialized QueryContext used before _init_query_mem_tracker). "
                "signal_query_id={:x}-{:x}",
                signal::query_id_hi, signal::query_id_lo));
    }
    if (UNLIKELY(rc->task_controller() == nullptr)) {
        throw Exception(Status::FatalError(
                "AttachTask::init: rc->task_controller() is null. signal_query_id={:x}-{:x}",
                signal::query_id_hi, signal::query_id_lo));
    }
    ThreadLocalHandle::create_thread_local_if_not_exits();
    signal::set_signal_task_id(rc->task_controller()->task_id());
    thread_context()->attach_task(rc);
}

AttachTask::AttachTask(const std::shared_ptr<ResourceContext>& rc) {
    init(rc);
}

AttachTask::AttachTask(const std::shared_ptr<MemTrackerLimiter>& mem_tracker) {
    // if parameter is `orphan_mem_tracker`, if you do not switch thraed mem tracker afterwards,
    // alloc or free memory from Allocator will fail DCHECK. unless you know for sure that
    // the thread will not alloc or free memory from Allocator later.
    //
    // Validate before constructing the ResourceContext: MemoryContext::set_mem_tracker()
    // immediately dereferences mem_tracker->limit(), so a null shared_ptr would
    // crash there before reaching init()'s diagnostics.
    if (UNLIKELY(mem_tracker == nullptr)) {
        throw Exception(Status::FatalError(
                "AttachTask(MemTrackerLimiter): mem_tracker is null. signal_query_id={:x}-{:x}",
                signal::query_id_hi, signal::query_id_lo));
    }
    std::shared_ptr<ResourceContext> rc = ResourceContext::create_shared();
    rc->memory_context()->set_mem_tracker(mem_tracker);
    init(rc);
}

AttachTask::AttachTask(RuntimeState* runtime_state) {
    // Walk the chain `runtime_state -> get_query_ctx() -> resource_ctx()`
    // step by step so that an unexpected null pinpoints exactly which link
    // failed instead of crashing with a generic NPE inside attach_task() or
    // even later inside the allocator.
    if (UNLIKELY(runtime_state == nullptr)) {
        throw Exception(Status::FatalError(
                "AttachTask(RuntimeState*): runtime_state is null. signal_query_id={:x}-{:x}",
                signal::query_id_hi, signal::query_id_lo));
    }
    if (UNLIKELY(runtime_state->get_query_ctx() == nullptr)) {
        throw Exception(Status::FatalError(
                "AttachTask(RuntimeState*): runtime_state->get_query_ctx() is null. "
                "signal_query_id={:x}-{:x}",
                signal::query_id_hi, signal::query_id_lo));
    }
    if (UNLIKELY(runtime_state->get_query_ctx()->resource_ctx() == nullptr)) {
        throw Exception(
                Status::FatalError("AttachTask(RuntimeState*): query_ctx->resource_ctx() is null. "
                                   "signal_query_id={:x}-{:x}",
                                   signal::query_id_hi, signal::query_id_lo));
    }
    signal::set_signal_is_nereids(runtime_state->is_nereids());
    init(runtime_state->get_query_ctx()->resource_ctx());
}

AttachTask::AttachTask(QueryContext* query_ctx) {
    if (UNLIKELY(query_ctx == nullptr)) {
        throw Exception(Status::FatalError(
                "AttachTask(QueryContext*): query_ctx is null. signal_query_id={:x}-{:x}",
                signal::query_id_hi, signal::query_id_lo));
    }
    init(query_ctx->resource_ctx());
}

AttachTask::~AttachTask() {
    signal::set_signal_task_id(TUniqueId());
    thread_context()->detach_task();
    ThreadLocalHandle::del_thread_local_if_count_is_zero();
}

SwitchResourceContext::SwitchResourceContext(const std::shared_ptr<ResourceContext>& rc) {
    DCHECK(rc != nullptr);
    // Validate the chain before mutating any thread-local or signal state,
    // symmetric to AttachTask::init(). Throwing after the thread-local
    // handle was acquired or the signal task id was set would skip this
    // object's destructor (because construction failed) and leak the
    // handle / leave a stale signal task id behind.
    if (UNLIKELY(rc == nullptr)) {
        throw Exception(
                Status::FatalError("SwitchResourceContext: rc is null. signal_query_id={:x}-{:x}",
                                   signal::query_id_hi, signal::query_id_lo));
    }
    if (UNLIKELY(rc->memory_context() == nullptr)) {
        throw Exception(Status::FatalError(
                "SwitchResourceContext: rc->memory_context() is null. signal_query_id={:x}-{:x}",
                signal::query_id_hi, signal::query_id_lo));
    }
    if (UNLIKELY(rc->memory_context()->mem_tracker() == nullptr)) {
        throw Exception(Status::FatalError(
                "SwitchResourceContext: rc->memory_context()->mem_tracker() is null. "
                "ResourceContext was switched in before _init_query_mem_tracker ran. "
                "signal_query_id={:x}-{:x}",
                signal::query_id_hi, signal::query_id_lo));
    }
    if (UNLIKELY(rc->task_controller() == nullptr)) {
        throw Exception(Status::FatalError(
                "SwitchResourceContext: rc->task_controller() is null. signal_query_id={:x}-{:x}",
                signal::query_id_hi, signal::query_id_lo));
    }
    doris::ThreadLocalHandle::create_thread_local_if_not_exits();
    DCHECK(thread_context()->is_attach_task());
    old_resource_ctx_ = thread_context()->resource_ctx();
    if (rc != old_resource_ctx_) {
        signal::set_signal_task_id(rc->task_controller()->task_id());
        thread_context()->resource_ctx_ = rc;
        thread_context()->thread_mem_tracker_mgr->attach_limiter_tracker(
                rc->memory_context()->mem_tracker(), rc->workload_group());
    }
}

SwitchResourceContext::~SwitchResourceContext() {
    if (old_resource_ctx_ != thread_context()->resource_ctx()) {
        DCHECK(old_resource_ctx_ != nullptr);
        signal::set_signal_task_id(old_resource_ctx_->task_controller()->task_id());
        thread_context()->resource_ctx_ = old_resource_ctx_;
        thread_context()->thread_mem_tracker_mgr->detach_limiter_tracker();
    }
    doris::ThreadLocalHandle::del_thread_local_if_count_is_zero();
}

SwitchThreadMemTrackerLimiter::SwitchThreadMemTrackerLimiter(
        const std::shared_ptr<doris::MemTrackerLimiter>& mem_tracker) {
    DCHECK(mem_tracker);
    // Third entry point that calls attach_limiter_tracker(). Without this
    // null guard a null mem_tracker silently propagates and the next
    // allocation on this thread would NPE deep inside the allocator. Throw
    // before acquiring the thread-local handle / doing any side effect so
    // the destructor (which is noexcept) never runs in a dirty state.
    if (UNLIKELY(mem_tracker == nullptr)) {
        throw Exception(Status::FatalError(
                "SwitchThreadMemTrackerLimiter: mem_tracker is null. signal_query_id={:x}-{:x}",
                signal::query_id_hi, signal::query_id_lo));
    }
    doris::ThreadLocalHandle::create_thread_local_if_not_exits();
    if (mem_tracker != thread_context()->thread_mem_tracker_mgr->limiter_mem_tracker_sptr()) {
        thread_context()->thread_mem_tracker_mgr->attach_limiter_tracker(mem_tracker);
        is_switched_ = true;
    }
}

SwitchThreadMemTrackerLimiter::~SwitchThreadMemTrackerLimiter() {
    if (is_switched_) {
        thread_context()->thread_mem_tracker_mgr->detach_limiter_tracker();
    }
    doris::ThreadLocalHandle::del_thread_local_if_count_is_zero();
}

AddThreadMemTrackerConsumer::AddThreadMemTrackerConsumer(MemTracker* mem_tracker) {
    ThreadLocalHandle::create_thread_local_if_not_exits();
    if (mem_tracker) {
        _need_pop = thread_context()->thread_mem_tracker_mgr->push_consumer_tracker(mem_tracker);
    }
}

AddThreadMemTrackerConsumer::AddThreadMemTrackerConsumer(
        const std::shared_ptr<MemTracker>& mem_tracker)
        : _mem_tracker(mem_tracker) {
    ThreadLocalHandle::create_thread_local_if_not_exits();
    if (_mem_tracker) {
        _need_pop =
                thread_context()->thread_mem_tracker_mgr->push_consumer_tracker(_mem_tracker.get());
    }
}

AddThreadMemTrackerConsumer::~AddThreadMemTrackerConsumer() {
    if (_need_pop) {
        thread_context()->thread_mem_tracker_mgr->pop_consumer_tracker();
    }
    ThreadLocalHandle::del_thread_local_if_count_is_zero();
}

} // namespace doris
