// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <trace-reader/reader.h>

#include <fbl/string_printf.h>
#include <trace-engine/fields.h>

namespace trace {

TraceReader::TraceReader(RecordConsumer record_consumer,
                         ErrorHandler error_handler)
    : record_consumer_(fbl::move(record_consumer)),
      error_handler_(fbl::move(error_handler)) {
    RegisterProvider(0u, "");
}

bool TraceReader::ReadRecords(Chunk& chunk) {
    while (true) {
        if (!pending_header_ && !chunk.ReadUint64(&pending_header_))
            return true; // need more data

        auto size = RecordFields::RecordSize::Get<size_t>(pending_header_);
        if (size == 0) {
            ReportError("Unexpected record of size 0");
            return false; // fatal error
        }
        ZX_DEBUG_ASSERT(size <= RecordFields::kMaxRecordSizeWords);

        Chunk record;
        if (!chunk.ReadChunk(size - 1, &record))
            return true; // need more data to decode record

        auto type = RecordFields::Type::Get<RecordType>(pending_header_);
        switch (type) {
        case RecordType::kMetadata: {
            if (!ReadMetadataRecord(record, pending_header_)) {
                ReportError("Failed to read metadata record");
            }
            break;
        }
        case RecordType::kInitialization: {
            if (!ReadInitializationRecord(record, pending_header_)) {
                ReportError("Failed to read initialization record");
            }
            break;
        }
        case RecordType::kString: {
            if (!ReadStringRecord(record, pending_header_)) {
                ReportError("Failed to read string record");
            }
            break;
        }
        case RecordType::kThread: {
            if (!ReadThreadRecord(record, pending_header_)) {
                ReportError("Failed to read thread record");
            }
            break;
        }
        case RecordType::kEvent: {
            if (!ReadEventRecord(record, pending_header_)) {
                ReportError("Failed to read event record");
            }
            break;
        }
        case RecordType::kBlob: {
            void* ptr;
            if (!ReadBlobRecord(record, pending_header_, &ptr)) {
                ReportError("Failed to read blob record");
            }
            break;
        }
        case RecordType::kKernelObject: {
            if (!ReadKernelObjectRecord(record, pending_header_)) {
                ReportError("Failed to read kernel object record");
            }
            break;
        }
        case RecordType::kContextSwitch: {
            if (!ReadContextSwitchRecord(record, pending_header_)) {
                ReportError("Failed to read context switch record");
            }
            break;
        }
        case RecordType::kLog: {
            if (!ReadLogRecord(record, pending_header_)) {
                ReportError("Failed to read log record");
            }
            break;
        }
        default: {
            // Ignore unknown record types for forward compatibility.
            ReportError(fbl::StringPrintf(
                "Skipping record of unknown type %d", static_cast<uint32_t>(type)));
            break;
        }
        }
        pending_header_ = 0u;
    }
}

bool TraceReader::ReadMetadataRecord(Chunk& record, RecordHeader header) {
    auto type = MetadataRecordFields::MetadataType::Get<MetadataType>(header);

    switch (type) {
    case MetadataType::kProviderInfo: {
        auto id = ProviderInfoMetadataRecordFields::Id::Get<ProviderId>(header);
        auto name_length =
            ProviderInfoMetadataRecordFields::NameLength::Get<size_t>(header);
        fbl::StringPiece name_view;
        if (!record.ReadString(name_length, &name_view))
            return false;
        fbl::String name(name_view);

        RegisterProvider(id, name);
        record_consumer_(Record(Record::Metadata{
            MetadataContent(MetadataContent::ProviderInfo{id, name})}));
        break;
    }
    case MetadataType::kProviderSection: {
        auto id =
            ProviderSectionMetadataRecordFields::Id::Get<ProviderId>(header);

        SetCurrentProvider(id);
        record_consumer_(Record(
            Record::Metadata{MetadataContent(MetadataContent::ProviderSection{id})}));
        break;
    }
    case MetadataType::kProviderEvent: {
        auto id =
            ProviderEventMetadataRecordFields::Id::Get<ProviderId>(header);
        auto event = ProviderEventMetadataRecordFields::Event::Get<ProviderEventType>(header);
        switch (event) {
        case ProviderEventType::kBufferOverflow:
            record_consumer_(Record(
                Record::Metadata{MetadataContent(
                    MetadataContent::ProviderEvent{id, event})}));
            break;
        default:
            // Ignore unknown event types for forward compatibility.
            ReportError(fbl::StringPrintf(
                "Skipping provider event of unknown type %u",
                static_cast<unsigned>(event)));
            break;
        }
        break;
    }
    default: {
        // Ignore unknown metadata types for forward compatibility.
        ReportError(fbl::StringPrintf(
            "Skipping metadata of unknown type %d", static_cast<uint32_t>(type)));
        break;
    }
    }
    return true;
}

bool TraceReader::ReadInitializationRecord(Chunk& record, RecordHeader header) {
    trace_ticks_t ticks_per_second;
    if (!record.ReadUint64(&ticks_per_second) || !ticks_per_second)
        return false;

    record_consumer_(Record(Record::Initialization{ticks_per_second}));
    return true;
}

bool TraceReader::ReadStringRecord(Chunk& record, RecordHeader header) {
    auto index = StringRecordFields::StringIndex::Get<trace_string_index_t>(header);
    if (index < TRACE_ENCODED_STRING_REF_MIN_INDEX ||
        index > TRACE_ENCODED_STRING_REF_MAX_INDEX) {
        ReportError("Invalid string index");
        return false;
    }

    auto length = StringRecordFields::StringLength::Get<size_t>(header);
    fbl::StringPiece string_view;
    if (!record.ReadString(length, &string_view))
        return false;
    fbl::String string(string_view);

    RegisterString(index, string);
    record_consumer_(Record(Record::String{index, fbl::move(string)}));
    return true;
}

bool TraceReader::ReadThreadRecord(Chunk& record, RecordHeader header) {
    auto index = ThreadRecordFields::ThreadIndex::Get<trace_thread_index_t>(header);
    if (index < TRACE_ENCODED_THREAD_REF_MIN_INDEX ||
        index > TRACE_ENCODED_THREAD_REF_MAX_INDEX) {
        ReportError("Invalid thread index");
        return false;
    }

    zx_koid_t process_koid, thread_koid;
    if (!record.ReadUint64(&process_koid) ||
        !record.ReadUint64(&thread_koid))
        return false;

    ProcessThread process_thread(process_koid, thread_koid);
    RegisterThread(index, process_thread);
    record_consumer_(Record(Record::Thread{index, process_thread}));
    return true;
}

bool TraceReader::ReadEventRecord(Chunk& record, RecordHeader header) {
    auto type = EventRecordFields::EventType::Get<EventType>(header);
    auto argument_count = EventRecordFields::ArgumentCount::Get<size_t>(header);
    auto thread_ref = EventRecordFields::ThreadRef::Get<trace_encoded_thread_ref_t>(header);
    auto category_ref =
        EventRecordFields::CategoryStringRef::Get<trace_encoded_string_ref_t>(header);
    auto name_ref =
        EventRecordFields::NameStringRef::Get<trace_encoded_string_ref_t>(header);

    trace_ticks_t timestamp;
    ProcessThread process_thread;
    fbl::String category;
    fbl::String name;
    fbl::Vector<Argument> arguments;
    if (!record.ReadUint64(&timestamp) ||
        !DecodeThreadRef(record, thread_ref, &process_thread) ||
        !DecodeStringRef(record, category_ref, &category) ||
        !DecodeStringRef(record, name_ref, &name) ||
        !ReadArguments(record, argument_count, &arguments))
        return false;

    switch (type) {
    case EventType::kInstant: {
        uint64_t scope;
        if (!record.ReadUint64(&scope))
            return false;
        record_consumer_(Record(Record::Event{
            timestamp, process_thread, fbl::move(category), fbl::move(name),
            fbl::move(arguments),
            EventData(EventData::Instant{static_cast<EventScope>(scope)})}));
        break;
    }
    case EventType::kCounter: {
        trace_counter_id_t id;
        if (!record.ReadUint64(&id))
            return false;
        record_consumer_(Record(Record::Event{
            timestamp, process_thread, fbl::move(category), fbl::move(name),
            fbl::move(arguments), EventData(EventData::Counter{id})}));
        break;
    }
    case EventType::kDurationBegin: {
        record_consumer_(Record(Record::Event{
            timestamp, process_thread, fbl::move(category), fbl::move(name),
            fbl::move(arguments), EventData(EventData::DurationBegin{})}));
        break;
    }
    case EventType::kDurationEnd: {
        record_consumer_(Record(Record::Event{
            timestamp, process_thread, fbl::move(category), fbl::move(name),
            fbl::move(arguments), EventData(EventData::DurationEnd{})}));
        break;
    }
    case EventType::kAsyncBegin: {
        trace_async_id_t id;
        if (!record.ReadUint64(&id))
            return false;
        record_consumer_(Record(Record::Event{
            timestamp, process_thread, fbl::move(category), fbl::move(name),
            fbl::move(arguments), EventData(EventData::AsyncBegin{id})}));
        break;
    }
    case EventType::kAsyncInstant: {
        trace_async_id_t id;
        if (!record.ReadUint64(&id))
            return false;
        record_consumer_(Record(Record::Event{
            timestamp, process_thread, fbl::move(category), fbl::move(name),
            fbl::move(arguments), EventData(EventData::AsyncInstant{id})}));
        break;
    }
    case EventType::kAsyncEnd: {
        trace_async_id_t id;
        if (!record.ReadUint64(&id))
            return false;
        record_consumer_(Record(Record::Event{
            timestamp, process_thread, fbl::move(category), fbl::move(name),
            fbl::move(arguments), EventData(EventData::AsyncEnd{id})}));
        break;
    }
    case EventType::kFlowBegin: {
        trace_flow_id_t id;
        if (!record.ReadUint64(&id))
            return false;
        record_consumer_(Record(Record::Event{
            timestamp, process_thread, fbl::move(category), fbl::move(name),
            fbl::move(arguments), EventData(EventData::FlowBegin{id})}));
        break;
    }
    case EventType::kFlowStep: {
        trace_flow_id_t id;
        if (!record.ReadUint64(&id))
            return false;
        record_consumer_(Record(Record::Event{
            timestamp, process_thread, fbl::move(category), fbl::move(name),
            fbl::move(arguments), EventData(EventData::FlowStep{id})}));
        break;
    }
    case EventType::kFlowEnd: {
        trace_flow_id_t id;
        if (!record.ReadUint64(&id))
            return false;
        record_consumer_(Record(Record::Event{
            timestamp, process_thread, fbl::move(category), fbl::move(name),
            fbl::move(arguments), EventData(EventData::FlowEnd{id})}));
        break;
    }
    default: {
        // Ignore unknown event types for forward compatibility.
        ReportError(fbl::StringPrintf(
            "Skipping event of unknown type %d", static_cast<uint32_t>(type)));
        break;
    }
    }
    return true;
}

bool TraceReader::ReadBlobRecord(Chunk& record, RecordHeader header, void** out_blob) {
    auto blob_type =
        BlobRecordFields::BlobType::Get<trace_blob_type_t>(header);
    auto name_ref =
        BlobRecordFields::NameStringRef::Get<trace_encoded_string_ref_t>(header);
    auto blob_size =
        BlobRecordFields::BlobSize::Get<size_t>(header);
    fbl::String name;
    if (!DecodeStringRef(record, name_ref, &name))
        return false;
    const void* blob;
    auto blob_words = BytesToWords(blob_size);
    if (!record.ReadInPlace(blob_words, &blob))
        return false;

    record_consumer_(
        Record(Record::Blob{blob_type, name, blob, blob_size}));
    return true;
}

bool TraceReader::ReadKernelObjectRecord(Chunk& record, RecordHeader header) {
    auto object_type =
        KernelObjectRecordFields::ObjectType::Get<zx_obj_type_t>(header);
    auto name_ref =
        KernelObjectRecordFields::NameStringRef::Get<trace_encoded_string_ref_t>(header);
    auto argument_count =
        KernelObjectRecordFields::ArgumentCount::Get<size_t>(header);

    zx_koid_t koid;
    fbl::String name;
    fbl::Vector<Argument> arguments;
    if (!record.ReadUint64(&koid) ||
        !DecodeStringRef(record, name_ref, &name) ||
        !ReadArguments(record, argument_count, &arguments))
        return false;

    record_consumer_(
        Record(Record::KernelObject{koid, object_type, name, fbl::move(arguments)}));
    return true;
}

bool TraceReader::ReadContextSwitchRecord(Chunk& record, RecordHeader header) {
    auto cpu_number =
        ContextSwitchRecordFields::CpuNumber::Get<trace_cpu_number_t>(header);
    auto outgoing_thread_state =
        ContextSwitchRecordFields::OutgoingThreadState::Get<ThreadState>(header);
    auto outgoing_thread_priority =
        ContextSwitchRecordFields::OutgoingThreadPriority::Get<trace_thread_priority_t>(header);
    auto incoming_thread_priority =
        ContextSwitchRecordFields::IncomingThreadPriority::Get<trace_thread_priority_t>(header);
    auto outgoing_thread_ref =
        ContextSwitchRecordFields::OutgoingThreadRef::Get<trace_encoded_thread_ref_t>(
            header);
    auto incoming_thread_ref =
        ContextSwitchRecordFields::IncomingThreadRef::Get<trace_encoded_thread_ref_t>(
            header);

    trace_ticks_t timestamp;
    ProcessThread outgoing_thread;
    ProcessThread incoming_thread;
    if (!record.ReadUint64(&timestamp) ||
        !DecodeThreadRef(record, outgoing_thread_ref,
                         &outgoing_thread) ||
        !DecodeThreadRef(record, incoming_thread_ref, &incoming_thread))
        return false;

    record_consumer_(
        Record(Record::ContextSwitch{timestamp, cpu_number, outgoing_thread_state,
                                     outgoing_thread, incoming_thread,
                                     outgoing_thread_priority, incoming_thread_priority}));
    return true;
}

bool TraceReader::ReadLogRecord(Chunk& record, RecordHeader header) {
    auto log_message_length =
        LogRecordFields::LogMessageLength::Get<uint16_t>(header);

    if (log_message_length > LogRecordFields::kMaxMessageLength)
        return false;

    auto thread_ref = LogRecordFields::ThreadRef::Get<trace_encoded_thread_ref_t>(header);
    trace_ticks_t timestamp;
    ProcessThread process_thread;
    fbl::StringPiece log_message;
    if (!record.ReadUint64(&timestamp) ||
        !DecodeThreadRef(record, thread_ref, &process_thread) ||
        !record.ReadString(log_message_length, &log_message))
        return false;
    record_consumer_(
        Record(Record::Log{timestamp, process_thread, fbl::String(log_message)}));
    return true;
}

bool TraceReader::ReadArguments(Chunk& record,
                                size_t count,
                                fbl::Vector<Argument>* out_arguments) {
    while (count-- > 0) {
        ArgumentHeader header;
        if (!record.ReadUint64(&header)) {
            ReportError("Failed to read argument header");
            return false;
        }

        auto size = ArgumentFields::ArgumentSize::Get<size_t>(header);
        Chunk arg;
        if (!size || !record.ReadChunk(size - 1, &arg)) {
            ReportError("Invalid argument size");
            return false;
        }

        auto name_ref = ArgumentFields::NameRef::Get<trace_encoded_string_ref_t>(header);
        fbl::String name;
        if (!DecodeStringRef(arg, name_ref, &name)) {
            ReportError("Failed to read argument name");
            return false;
        }

        auto type = ArgumentFields::Type::Get<ArgumentType>(header);
        switch (type) {
        case ArgumentType::kNull: {
            out_arguments->push_back(Argument{fbl::move(name),
                                              ArgumentValue::MakeNull()});
            break;
        }
        case ArgumentType::kInt32: {
            auto value = Int32ArgumentFields::Value::Get<int32_t>(header);
            out_arguments->push_back(Argument{fbl::move(name),
                                              ArgumentValue::MakeInt32(value)});
            break;
        }
        case ArgumentType::kUint32: {
            auto value = Uint32ArgumentFields::Value::Get<uint32_t>(header);
            out_arguments->push_back(Argument{fbl::move(name),
                                              ArgumentValue::MakeUint32(value)});
            break;
        }
        case ArgumentType::kInt64: {
            int64_t value;
            if (!arg.ReadInt64(&value)) {
                ReportError("Failed to read int64 argument value");
                return false;
            }
            out_arguments->push_back(Argument{fbl::move(name),
                                              ArgumentValue::MakeInt64(value)});
            break;
        }
        case ArgumentType::kUint64: {
            uint64_t value;
            if (!arg.ReadUint64(&value)) {
                ReportError("Failed to read uint64 argument value");
                return false;
            }
            out_arguments->push_back(Argument{fbl::move(name),
                                              ArgumentValue::MakeUint64(value)});
            break;
        }
        case ArgumentType::kDouble: {
            double value;
            if (!arg.ReadDouble(&value)) {
                ReportError("Failed to read double argument value");
                return false;
            }
            out_arguments->push_back(Argument{fbl::move(name),
                                              ArgumentValue::MakeDouble(value)});
            break;
        }
        case ArgumentType::kString: {
            auto string_ref =
                StringArgumentFields::Index::Get<trace_encoded_string_ref_t>(header);
            fbl::String value;
            if (!DecodeStringRef(arg, string_ref, &value)) {
                ReportError("Failed to read string argument value");
                return false;
            }
            out_arguments->push_back(
                Argument{fbl::move(name),
                         ArgumentValue::MakeString(fbl::move(value))});
            break;
        }
        case ArgumentType::kPointer: {
            uint64_t value;
            if (!arg.ReadUint64(&value)) {
                ReportError("Failed to read pointer argument value");
                return false;
            }
            out_arguments->push_back(Argument{fbl::move(name),
                                              ArgumentValue::MakePointer(value)});
            break;
        }
        case ArgumentType::kKoid: {
            zx_koid_t value;
            if (!arg.ReadUint64(&value)) {
                ReportError("Failed to read koid argument value");
                return false;
            }
            out_arguments->push_back(Argument{fbl::move(name),
                                              ArgumentValue::MakeKoid(value)});
            break;
        }
        default: {
            // Ignore unknown argument types for forward compatibility.
            ReportError(fbl::StringPrintf(
                "Skipping argument of unknown type %d, argument name %s",
                static_cast<uint32_t>(type), name.c_str()));
            break;
        }
        }
    }
    return true;
}

fbl::String TraceReader::GetProviderName(ProviderId id) const {
    auto it = providers_.find(id);
    if (it != providers_.end())
        return it->name;
    return fbl::String();
}

void TraceReader::SetCurrentProvider(ProviderId id) {
    auto it = providers_.find(id);
    if (it != providers_.end()) {
        current_provider_ = &*it;
        return;
    }
    RegisterProvider(id, "");
}

void TraceReader::RegisterProvider(ProviderId id, fbl::String name) {
    auto provider = fbl::make_unique<ProviderInfo>();
    provider->id = id;
    provider->name = name;
    current_provider_ = provider.get();

    providers_.insert_or_replace(fbl::move(provider));
}

void TraceReader::RegisterString(trace_string_index_t index, fbl::String string) {
    ZX_DEBUG_ASSERT(index >= TRACE_ENCODED_STRING_REF_MIN_INDEX &&
                    index <= TRACE_ENCODED_STRING_REF_MAX_INDEX);

    auto entry = fbl::make_unique<StringTableEntry>(index, string);
    current_provider_->string_table.insert_or_replace(fbl::move(entry));
}

void TraceReader::RegisterThread(trace_thread_index_t index,
                                 const ProcessThread& process_thread) {
    ZX_DEBUG_ASSERT(index >= TRACE_ENCODED_THREAD_REF_MIN_INDEX &&
                    index <= TRACE_ENCODED_THREAD_REF_MAX_INDEX);

    auto entry = fbl::make_unique<ThreadTableEntry>(index, process_thread);
    current_provider_->thread_table.insert_or_replace(fbl::move(entry));
}

bool TraceReader::DecodeStringRef(Chunk& chunk,
                                  trace_encoded_string_ref_t string_ref,
                                  fbl::String* out_string) const {
    if (string_ref == TRACE_ENCODED_STRING_REF_EMPTY) {
        out_string->clear();
        return true;
    }

    if (string_ref & TRACE_ENCODED_STRING_REF_INLINE_FLAG) {
        size_t length = string_ref & TRACE_ENCODED_STRING_REF_LENGTH_MASK;
        fbl::StringPiece string_view;
        if (length > TRACE_ENCODED_STRING_REF_MAX_LENGTH ||
            !chunk.ReadString(length, &string_view)) {
            ReportError("Could not read inline string");
            return false;
        }
        *out_string = string_view;
        return true;
    }

    auto it = current_provider_->string_table.find(string_ref);
    if (it == current_provider_->string_table.end()) {
        ReportError("String ref not in table");
        return false;
    }
    *out_string = it->string;
    return true;
}

bool TraceReader::DecodeThreadRef(Chunk& chunk,
                                  trace_encoded_thread_ref_t thread_ref,
                                  ProcessThread* out_process_thread) const {
    if (thread_ref == TRACE_ENCODED_THREAD_REF_INLINE) {
        zx_koid_t process_koid, thread_koid;
        if (!chunk.ReadUint64(&process_koid) ||
            !chunk.ReadUint64(&thread_koid)) {
            ReportError("Could not read inline process and thread");
            return false;
        }
        *out_process_thread = ProcessThread(process_koid, thread_koid);
        return true;
    }

    auto it = current_provider_->thread_table.find(thread_ref);
    if (it == current_provider_->thread_table.end()) {
        ReportError("Thread ref not in table");
        return false;
    }
    *out_process_thread = it->process_thread;
    return true;
}

void TraceReader::ReportError(fbl::String error) const {
    if (error_handler_)
        error_handler_(fbl::move(error));
}

Chunk::Chunk()
    : current_(nullptr), end_(nullptr) {}

Chunk::Chunk(const uint64_t* begin, size_t num_words)
    : current_(begin), end_(current_ + num_words) {}

bool Chunk::ReadUint64(uint64_t* out_value) {
    if (current_ < end_) {
        *out_value = *current_++;
        return true;
    }
    return false;
}

bool Chunk::ReadInt64(int64_t* out_value) {
    if (current_ < end_) {
        *out_value = *reinterpret_cast<const int64_t*>(current_++);
        return true;
    }
    return false;
}

bool Chunk::ReadDouble(double* out_value) {
    if (current_ < end_) {
        *out_value = *reinterpret_cast<const double*>(current_++);
        return true;
    }
    return false;
}

bool Chunk::ReadChunk(size_t num_words, Chunk* out_chunk) {
    if (current_ + num_words > end_)
        return false;

    *out_chunk = Chunk(current_, num_words);
    current_ += num_words;
    return true;
}

bool Chunk::ReadString(size_t length, fbl::StringPiece* out_string) {
    auto num_words = BytesToWords(length);
    if (current_ + num_words > end_)
        return false;

    *out_string =
        fbl::StringPiece(reinterpret_cast<const char*>(current_), length);
    current_ += num_words;
    return true;
}

bool Chunk::ReadInPlace(size_t num_words, const void** out_ptr) {
    if (current_ + num_words > end_)
        return false;
    *out_ptr = current_;
    current_ += num_words;
    return true;
}

} // namespace trace
