// Copyright (c) 2010 The Chromium OS 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 "window_manager/profiler.h"

#include <cstring>
#include <stack>

#include <sys/time.h>
#include <stdio.h>

#include "base/file_path.h"
#include "base/file_util.h"
#include "base/hash_tables.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/time.h"
#include "window_manager/profiler_data.h"

namespace window_manager {

using base::TimeTicks;
using file_util::CloseFile;
using file_util::OpenFile;

//
// Static constants and functions
//
static inline int64_t Now() {
  return TimeTicks::Now().ToInternalValue();
}

//
// Marker definition
//
Marker::Marker(Profiler* profiler, const char* name)
    : profiler_(profiler),
      symbol_id_(0) {
  symbol_id_ = profiler->AddSymbol(name);
}

void Marker::Tap() {
  profiler_->AddSample(symbol_id_, Now(), profiler::MARK_FLAG_TAP);
}

void Marker::Begin() {
  profiler_->AddSample(symbol_id_, Now(), profiler::MARK_FLAG_BEGIN);
}

void Marker::End() {
  profiler_->AddSample(symbol_id_, Now(), profiler::MARK_FLAG_END);
}

//
// DynamicMarker definition
//
DynamicMarker::DynamicMarker()
    : profiler_(NULL) {
}

unsigned int DynamicMarker::GetSymbolId(const char* name) {
  if (symbol_table_.find(name) == symbol_table_.end()) {
    unsigned int symbol_id =  profiler_->AddSymbol(name);
    symbol_table_[name] = symbol_id;
    return symbol_id;
  } else {
    return symbol_table_[name];
  }
}

void DynamicMarker::Tap(const char* name) {
  profiler_->AddSample(GetSymbolId(name), Now(), profiler::MARK_FLAG_TAP);
}

void DynamicMarker::Begin(const char* name) {
  unsigned int symbol_id = GetSymbolId(name);
  recent_symbol_ids_.push(symbol_id);
  profiler_->AddSample(symbol_id, Now(), profiler::MARK_FLAG_BEGIN);
}

void DynamicMarker::End() {
  unsigned int symbol_id = recent_symbol_ids_.top();
  profiler_->AddSample(symbol_id, Now(), profiler::MARK_FLAG_END);
  recent_symbol_ids_.pop();
}

//
// Profiler definition
//
Profiler::Profiler()
    : profiler_writer_(NULL),
      status_(STATUS_STOP),
      max_num_symbols_(0),
      max_num_samples_(0),
      num_symbols_(0),
      num_samples_(0),
      symbols_(NULL),
      samples_(NULL) {
}

Profiler::~Profiler() {
  Stop();
}

void Profiler::Start(ProfilerWriter* profiler_writer,
                     unsigned int max_num_symbols,
                     unsigned int max_num_samples) {
  if (status_ != STATUS_STOP) {
    LOG(WARNING) << "the profiler has already started";
  } else if (profiler_writer == NULL) {
    LOG(WARNING) << "profiler writer cannot be NULL";
  } else if (max_num_symbols == 0 || max_num_samples == 0) {
    LOG(WARNING) << "the maximum # of symbols and samples must > 0";
  } else {
    profiler_writer_ = profiler_writer;
    max_num_symbols_ = max_num_symbols;
    max_num_samples_ = max_num_samples;
    status_ = STATUS_RUN;

    symbols_.reset(new profiler::Symbol[max_num_symbols_]);
    samples_.reset(new profiler::Sample[max_num_samples_]);

    memset(symbols_.get(), 0, sizeof(symbols_[0]) * max_num_symbols_);
    memset(samples_.get(), 0, sizeof(samples_[0]) * max_num_samples_);
  }
}

void Profiler::Pause() {
  if (status_ == STATUS_RUN) {
    status_ = STATUS_SUSPEND;
    Flush();
  }
}

void Profiler::Resume() {
  if (status_ == STATUS_SUSPEND) {
    status_ = STATUS_RUN;
  }
}

void Profiler::Stop() {
  if (status_ == STATUS_STOP) {
    LOG(WARNING) << "the profiler was not started";
    return;
  }
  Flush();
  max_num_symbols_ = 0;
  max_num_samples_ = 0;
  symbols_.reset(NULL);
  samples_.reset(NULL);
  status_ = STATUS_STOP;
}

void Profiler::Flush() {
  if (status_ != STATUS_STOP && num_samples_ != 0) {
    profiler_writer_->Update(*this);
    num_samples_ = 0;
  }
}

unsigned int Profiler::AddSymbol(const char* name) {
  if (status_ == STATUS_STOP || num_symbols_ == max_num_symbols_) {
    return max_num_symbols_;
  }
  const int kBufferSize = sizeof(symbols_[num_symbols_].name);
  strncpy(symbols_[num_symbols_].name, name, kBufferSize - 1);
  symbols_[num_symbols_].name[kBufferSize - 1] = '\0';

  return num_symbols_++;
}

void Profiler::AddSample(unsigned int symbol_id, int64_t time,
                         profiler::MarkFlag flag) {
  if (status_ != STATUS_RUN) {
    return;
  }
  if (symbol_id >= num_symbols_) {
    LOG(WARNING) << "symbol id provided exceeds number of symbols";
    return;
  }
  samples_[num_samples_].symbol_id = symbol_id;
  samples_[num_samples_].flag = flag;
  samples_[num_samples_].time = time;
  if (++num_samples_ == max_num_samples_) {
    Flush();
  }
}

//
// ProfilerWriter definition
//
ProfilerWriter::ProfilerWriter(FilePath file_path)
    : num_written_samples_(0),
      num_written_symbols_(0),
      file_path_(file_path) {
}

void ProfilerWriter::Update(const Profiler& profiler) {
  FILE* fp = NULL;
  if (num_written_samples_ == 0) {
    fp = OpenFile(file_path_, "wb");
  } else {
    fp = OpenFile(file_path_, "r+b");
  }

  if (fp == NULL) {
    LOG(WARNING) << "cannot open profile for writing";
    return;
  }

  num_written_samples_ += profiler.num_samples_;

  // overwrite header
  size_t result = 0;
  result = fwrite(&profiler.max_num_symbols_,
                  sizeof(profiler.max_num_symbols_), 1, fp);

  DCHECK_EQ(result, static_cast<size_t>(1));
  result = fwrite(&profiler.num_symbols_,
                  sizeof(profiler.num_symbols_), 1, fp);
  DCHECK_EQ(result, static_cast<size_t>(1));
  result = fwrite(&num_written_samples_, sizeof(num_written_samples_), 1, fp);
  DCHECK_EQ(result, static_cast<size_t>(1));

  if (num_written_symbols_ != profiler.num_symbols_) {
    // overwrite symbols
    result = fwrite(profiler.symbols_.get(), sizeof(profiler.symbols_[0]),
                    profiler.max_num_symbols_, fp);
    DCHECK_EQ(result, profiler.max_num_symbols_);
    num_written_symbols_ = profiler.num_symbols_;
  }

  // append samples
  fseek(fp, 0, SEEK_END);
  result = fwrite(profiler.samples_.get(), sizeof(profiler.samples_[0]),
                  profiler.num_samples_, fp);
  DCHECK_EQ(result, profiler.num_samples_);

  CloseFile(fp);
}

}  // namespace window_manager
