// 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, i, data_end);
    }
  }

  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
