// Copyright 2016 the V8 project 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 "src/libplatform/tracing/trace-buffer.h"

namespace v8 {
namespace platform {
namespace tracing {

TraceBufferRingBuffer::TraceBufferRingBuffer(size_t max_chunks,
                                             TraceWriter* trace_writer)
    : max_chunks_(max_chunks) {
  trace_writer_.reset(trace_writer);
  chunks_.resize(max_chunks);
}

TraceBufferRingBuffer::~TraceBufferRingBuffer() {}

TraceObject* TraceBufferRingBuffer::AddTraceEvent(uint64_t* handle) {
  base::LockGuard<base::Mutex> guard(&mutex_);
  if (is_empty_ || chunks_[chunk_index_]->IsFull()) {
    chunk_index_ = is_empty_ ? 0 : NextChunkIndex(chunk_index_);
    is_empty_ = false;
    auto& chunk = chunks_[chunk_index_];
    if (chunk) {
      chunk->Reset(current_chunk_seq_++);
    } else {
      chunk.reset(new TraceBufferChunk(current_chunk_seq_++));
    }
  }
  auto& chunk = chunks_[chunk_index_];
  size_t event_index;
  TraceObject* trace_object = chunk->AddTraceEvent(&event_index);
  *handle = MakeHandle(chunk_index_, chunk->seq(), event_index);
  return trace_object;
}

TraceObject* TraceBufferRingBuffer::GetEventByHandle(uint64_t handle) {
  base::LockGuard<base::Mutex> guard(&mutex_);
  size_t chunk_index, event_index;
  uint32_t chunk_seq;
  ExtractHandle(handle, &chunk_index, &chunk_seq, &event_index);
  if (chunk_index >= chunks_.size()) return nullptr;
  auto& chunk = chunks_[chunk_index];
  if (!chunk || chunk->seq() != chunk_seq) return nullptr;
  return chunk->GetEventAt(event_index);
}

bool TraceBufferRingBuffer::Flush() {
  base::LockGuard<base::Mutex> guard(&mutex_);
  // This flushes all the traces stored in the buffer.
  if (!is_empty_) {
    for (size_t i = NextChunkIndex(chunk_index_);; i = NextChunkIndex(i)) {
      if (auto& chunk = chunks_[i]) {
        for (size_t j = 0; j < chunk->size(); ++j) {
          trace_writer_->AppendTraceEvent(chunk->GetEventAt(j));
        }
      }
      if (i == chunk_index_) break;
    }
  }
  trace_writer_->Flush();
  // This resets the trace buffer.
  is_empty_ = true;
  return true;
}

uint64_t TraceBufferRingBuffer::MakeHandle(size_t chunk_index,
                                           uint32_t chunk_seq,
                                           size_t event_index) const {
  return static_cast<uint64_t>(chunk_seq) * Capacity() +
         chunk_index * TraceBufferChunk::kChunkSize + event_index;
}

void TraceBufferRingBuffer::ExtractHandle(uint64_t handle, size_t* chunk_index,
                                          uint32_t* chunk_seq,
                                          size_t* event_index) const {
  *chunk_seq = static_cast<uint32_t>(handle / Capacity());
  size_t indices = handle % Capacity();
  *chunk_index = indices / TraceBufferChunk::kChunkSize;
  *event_index = indices % TraceBufferChunk::kChunkSize;
}

size_t TraceBufferRingBuffer::NextChunkIndex(size_t index) const {
  if (++index >= max_chunks_) index = 0;
  return index;
}

TraceBufferChunk::TraceBufferChunk(uint32_t seq) : seq_(seq) {}

void TraceBufferChunk::Reset(uint32_t new_seq) {
  next_free_ = 0;
  seq_ = new_seq;
}

TraceObject* TraceBufferChunk::AddTraceEvent(size_t* event_index) {
  *event_index = next_free_++;
  return &chunk_[*event_index];
}

TraceBuffer* TraceBuffer::CreateTraceBufferRingBuffer(
    size_t max_chunks, TraceWriter* trace_writer) {
  return new TraceBufferRingBuffer(max_chunks, trace_writer);
}

}  // namespace tracing
}  // namespace platform
}  // namespace v8
