// Copyright 2017 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.

#ifdef __Fuchsia__
#include <zircon/syscalls.h>
#endif

#include <lib/syslog/cpp/macros.h>

#include "buffer_reader.h"
#include "records.h"

namespace perfmon {

ReaderStatus BufferReader::Create(const std::string& name, const void* buffer, size_t buffer_size,
                                  std::unique_ptr<BufferReader>* out_reader) {
  auto header = reinterpret_cast<const BufferHeader*>(buffer);
  ReaderStatus status = AnalyzeHeader(header, buffer_size);
  if (status != ReaderStatus::kOk) {
    return status;
  }
  out_reader->reset(new BufferReader(name, buffer, header->capture_end));
  return ReaderStatus::kOk;
}

BufferReader::BufferReader(const std::string& name, const void* buffer, size_t capture_end)
    : name_(name),
      buffer_(reinterpret_cast<const uint8_t*>(buffer)),
      header_(reinterpret_cast<const BufferHeader*>(buffer)),
      next_record_(buffer_ + sizeof(*header_)),
      buffer_end_(buffer_ + capture_end),
      ticks_per_second_(header_->ticks_per_second) {}

ReaderStatus BufferReader::AnalyzeHeader(const BufferHeader* header, size_t buffer_size) {
  FX_VLOGS(2) << "Reading header, buffer version " << header->version << ", " << header->capture_end
              << " bytes";

  // TODO(dje): check magic

  uint32_t expected_version = perfmon::kBufferVersion;
  if (header->version != expected_version) {
    FX_LOGS(ERROR) << "Unsupported buffer version, got " << header->version << " instead of "
                   << expected_version;
    return ReaderStatus::kHeaderError;
  }

  if (header->capture_end > buffer_size) {
    FX_LOGS(ERROR) << "Bad trace data, end point beyond buffer";
    return ReaderStatus::kHeaderError;
  }
  if (header->capture_end < sizeof(*header)) {
    FX_LOGS(ERROR) << "Bad trace data, end point within header";
    return ReaderStatus::kHeaderError;
  }

#ifdef __Fuchsia__
  zx_ticks_t user_ticks_per_second = zx_ticks_per_second();
  if (header->ticks_per_second != user_ticks_per_second) {
    FX_LOGS(WARNING) << "Kernel and userspace are using different tracing"
                     << " timebases, tracks may be misaligned:"
                     << " kernel_ticks_per_second=" << header->ticks_per_second
                     << " user_ticks_per_second=" << user_ticks_per_second;
  }
#endif

  return ReaderStatus::kOk;
}

ReaderStatus BufferReader::ReadNextRecord(SampleRecord* record) {
  if (status_ != ReaderStatus::kOk)
    return status_;

  if (next_record_ >= buffer_end_) {
    return set_status(ReaderStatus::kNoMoreRecords);
  }

  const RecordHeader* hdr = reinterpret_cast<const RecordHeader*>(next_record_);
  if (next_record_ + sizeof(*hdr) > buffer_end_) {
    FX_LOGS(ERROR) << name_ << ": Bad trace data"
                   << ", no space for final record header";
    return set_status(ReaderStatus::kRecordError);
  }

  auto record_type = GetRecordType(hdr);
  auto record_size = GetRecordSize(hdr);
  if (record_size == 0) {
    FX_LOGS(ERROR) << name_
                   << ": Bad trace data, bad record type: " << static_cast<unsigned>(hdr->type);
    return set_status(ReaderStatus::kRecordError);
  }
  if (next_record_ + record_size > buffer_end_) {
    FX_LOGS(ERROR) << name_ << ": Bad trace data"
                   << ", no space for final record";
    return set_status(ReaderStatus::kRecordError);
  }

  // There can be millions of records. This is useful for small test runs,
  // but otherwise is too painful. The verbosity level is chosen to
  // recognize that.
  FX_VLOGS(10) << "ReadNextRecord: offset=" << (next_record_ - buffer_);

  switch (record_type) {
    case kRecordTypeTime:
      record->time = reinterpret_cast<const TimeRecord*>(next_record_);
      time_ = record->time->time;
      break;
    case kRecordTypeTick:
      record->tick = reinterpret_cast<const TickRecord*>(next_record_);
      break;
    case kRecordTypeCount:
      record->count = reinterpret_cast<const CountRecord*>(next_record_);
      break;
    case kRecordTypeValue:
      record->value = reinterpret_cast<const ValueRecord*>(next_record_);
      break;
    case kRecordTypePc:
      record->pc = reinterpret_cast<const PcRecord*>(next_record_);
      break;
    case kRecordTypeLastBranch:
      record->last_branch = reinterpret_cast<const LastBranchRecord*>(next_record_);
      break;
    default:
      // We shouldn't get here because RecordSize() should have returned
      // zero and we would have skipped to the next cpu.
      __UNREACHABLE;
  }

  last_record_ = next_record_;
  next_record_ += record_size;
  return ReaderStatus::kOk;
}

}  // namespace perfmon
