// Copyright 2018 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 <inttypes.h>

#include <iterator>
#include <memory>
#include <utility>

#include <fbl/string_printf.h>
#include <trace-reader/reader_internal.h>

namespace trace {
namespace internal {

fbl::String BufferHeaderReader::Create(const void* header, size_t buffer_size,
                                       std::unique_ptr<BufferHeaderReader>* out_reader) {
  if (buffer_size < sizeof(trace_buffer_header)) {
    return "buffer too small for header";
  }
  auto hdr = reinterpret_cast<const trace_buffer_header*>(header);
  auto error = Validate(*hdr, buffer_size);
  if (error != "") {
    return error;
  }
  *out_reader = std::unique_ptr<BufferHeaderReader>(new BufferHeaderReader(hdr));
  return "";
}

BufferHeaderReader::BufferHeaderReader(const trace_buffer_header* header) : header_(header) {}

fbl::String BufferHeaderReader::Validate(const trace_buffer_header& header, size_t buffer_size) {
  if (header.magic != TRACE_BUFFER_HEADER_MAGIC) {
    return fbl::StringPrintf("bad magic: 0x%" PRIx64, header.magic);
  }
  if (header.version != TRACE_BUFFER_HEADER_V0) {
    return fbl::StringPrintf("bad version: %u", header.version);
  }

  if (buffer_size & 7u) {
    return fbl::StringPrintf("buffer size not multiple of 64-bit words: 0x%zx", buffer_size);
  }

  switch (header.buffering_mode) {
    case TRACE_BUFFERING_MODE_ONESHOT:
    case TRACE_BUFFERING_MODE_CIRCULAR:
    case TRACE_BUFFERING_MODE_STREAMING:
      break;
    default:
      return fbl::StringPrintf("bad buffering mode: %u", header.buffering_mode);
  }

  if (header.total_size != buffer_size) {
    return fbl::StringPrintf("bad total buffer size: 0x%" PRIx64, header.total_size);
  }

  auto rolling_buffer_size = header.rolling_buffer_size;
  auto durable_buffer_size = header.durable_buffer_size;

  if ((rolling_buffer_size & 7) != 0) {
    return fbl::StringPrintf("bad rolling buffer size: 0x%" PRIx64, rolling_buffer_size);
  }
  if ((durable_buffer_size & 7) != 0) {
    return fbl::StringPrintf("bad durable buffer size: 0x%" PRIx64, durable_buffer_size);
  }

  if (header.buffering_mode == TRACE_BUFFERING_MODE_ONESHOT) {
    if (rolling_buffer_size != buffer_size - sizeof(trace_buffer_header)) {
      return fbl::StringPrintf("bad rolling buffer size: 0x%" PRIx64, rolling_buffer_size);
    }
    if (durable_buffer_size != 0) {
      return fbl::StringPrintf("bad durable buffer size: 0x%" PRIx64, durable_buffer_size);
    }
  } else {
    if (rolling_buffer_size >= buffer_size / 2) {
      return fbl::StringPrintf("bad rolling buffer size: 0x%" PRIx64, rolling_buffer_size);
    }
    if (durable_buffer_size >= rolling_buffer_size) {
      return fbl::StringPrintf("bad durable buffer size: 0x%" PRIx64, durable_buffer_size);
    }
    if ((sizeof(trace_buffer_header) + durable_buffer_size + 2 * rolling_buffer_size) !=
        buffer_size) {
      return fbl::StringPrintf(
          "buffer sizes don't add up:"
          " 0x%" PRIx64 ", 0x%" PRIx64,
          durable_buffer_size, rolling_buffer_size);
    }
  }

  for (size_t i = 0; i < std::size(header.rolling_data_end); ++i) {
    auto data_end = header.rolling_data_end[i];
    if (data_end > rolling_buffer_size || (data_end & 7) != 0) {
      return fbl::StringPrintf("bad data end for buffer %zu: 0x%" PRIx64 " (size 0x%" PRIx64 ")", i,
                               data_end, rolling_buffer_size);
    }
  }

  auto durable_data_end = header.durable_data_end;
  if (durable_data_end > durable_buffer_size || (durable_data_end & 7) != 0) {
    return fbl::StringPrintf("bad durable_data_end: 0x%" PRIx64, durable_data_end);
  }

  return "";
}

TraceBufferReader::TraceBufferReader(ChunkConsumer chunk_consumer, ErrorHandler error_handler)
    : chunk_consumer_(std::move(chunk_consumer)), error_handler_(std::move(error_handler)) {}

bool TraceBufferReader::ReadChunks(const void* buffer, size_t buffer_size) {
  std::unique_ptr<BufferHeaderReader> header;
  auto error = BufferHeaderReader::Create(buffer, buffer_size, &header);
  if (error != "") {
    error_handler_(error);
    return false;
  }

  CallChunkConsumerIfNonEmpty(header->GetDurableBuffer(buffer), header->durable_data_end());

  // There's only two buffers, thus the earlier one is not the current one.
  // It's important to process them in chronological order on the off
  // chance that the earlier buffer provides a stringref or threadref
  // referenced by the later buffer.
  int later_buffer = header->GetBufferNumber(header->wrapped_count());
  int earlier_buffer = 0;
  if (header->wrapped_count() > 0)
    earlier_buffer = header->GetBufferNumber(header->wrapped_count() - 1);

  if (earlier_buffer != later_buffer) {
    CallChunkConsumerIfNonEmpty(header->GetRollingBuffer(buffer, earlier_buffer),
                                header->rolling_data_end(earlier_buffer));
  }

  CallChunkConsumerIfNonEmpty(header->GetRollingBuffer(buffer, later_buffer),
                              header->rolling_data_end(later_buffer));

  return true;
}

void TraceBufferReader::CallChunkConsumerIfNonEmpty(const void* ptr, size_t size) {
  if (size != 0) {
    auto word_size = sizeof(uint64_t);
    ZX_DEBUG_ASSERT((reinterpret_cast<uintptr_t>(ptr) & (word_size - 1)) == 0);
    ZX_DEBUG_ASSERT((size & (word_size - 1)) == 0);
    Chunk chunk(reinterpret_cast<const uint64_t*>(ptr), size / word_size);
    chunk_consumer_(chunk);
  }
}

}  // namespace internal
}  // namespace trace
