// 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 "counter.h"

#include <fcntl.h>

#include <base/eintr_wrapper.h>
#include <base/logging.h>
#include "metrics_library.h"

namespace chromeos_metrics {

// TaggedCounter::Record implementation.
void TaggedCounter::Record::Init(int32 tag, int32 count) {
  tag_ = tag;
  count_ = (count > 0) ? count : 0;
}

void TaggedCounter::Record::Add(int32 count) {
  if (count <= 0)
    return;

  // Saturates on positive overflow.
  int64 new_count = static_cast<int64>(count_) + static_cast<int64>(count);
  if (new_count > kint32max)
    count_ = kint32max;
  else
    count_ = static_cast<int32>(new_count);
}

// TaggedCounter implementation.
TaggedCounter::TaggedCounter()
    : reporter_(NULL),
      reporter_handle_(NULL),
      record_state_(kRecordInvalid) {}

TaggedCounter::~TaggedCounter() {}

void TaggedCounter::Init(const char* filename,
                         Reporter reporter, void* reporter_handle) {
  DCHECK(filename);
  filename_ = filename;
  reporter_ = reporter;
  reporter_handle_ = reporter_handle;
  record_state_ = kRecordInvalid;
}

void TaggedCounter::Update(int32 tag, int32 count) {
  UpdateInternal(tag,
                 count,
                 false);  // No flush.
}

void TaggedCounter::Flush() {
  UpdateInternal(0,  // tag
                 0,  // count
                 true);  // Do flush.
}

void TaggedCounter::UpdateInternal(int32 tag, int32 count, bool flush) {
  if (flush) {
    // Flushing but record is null, so nothing to do.
    if (record_state_ == kRecordNull)
      return;
  } else {
    // If there's no new data and the last record in the aggregation
    // file is with the same tag, there's nothing to do.
    if (count <= 0 && record_state_ == kRecordValid && record_.tag() == tag)
      return;
  }

  DLOG(INFO) << "tag: " << tag << " count: " << count << " flush: " << flush;
  DCHECK(!filename_.empty());

  // NOTE: The assumption is that this TaggedCounter object is the
  // sole owner of the persistent storage file so no locking is
  // necessary.
  int fd = HANDLE_EINTR(open(filename_.c_str(),
                             O_RDWR | O_CREAT, S_IRUSR | S_IWUSR));
  if (fd < 0) {
    PLOG(WARNING) << "Unable to open the persistent counter file";
    return;
  }

  ReadRecord(fd);
  ReportRecord(tag, flush);
  UpdateRecord(tag, count, flush);
  WriteRecord(fd);

  HANDLE_EINTR(close(fd));
}

void TaggedCounter::ReadRecord(int fd) {
  if (record_state_ != kRecordInvalid)
    return;

  if (HANDLE_EINTR(read(fd, &record_, sizeof(record_))) == sizeof(record_)) {
    if (record_.count() >= 0) {
      record_state_ = kRecordValid;
      return;
    }
    // This shouldn't happen normally unless somebody messed with the
    // persistent storage file.
    NOTREACHED();
    record_state_ = kRecordNullDirty;
    return;
  }
  record_state_ = kRecordNull;
}

void TaggedCounter::ReportRecord(int32 tag, bool flush) {
  // If no valid record, there's nothing to report.
  if (record_state_ != kRecordValid) {
    DCHECK_EQ(record_state_, kRecordNull);
    return;
  }

  // If the current record has the same tag as the new tag, it's not
  // ready to be reported yet.
  if (!flush && record_.tag() == tag)
    return;

  if (reporter_) {
    reporter_(reporter_handle_, record_.tag(), record_.count());
  }
  record_state_ = kRecordNullDirty;
}

void TaggedCounter::UpdateRecord(int32 tag, int32 count, bool flush) {
  if (flush) {
    DCHECK(record_state_ == kRecordNull || record_state_ == kRecordNullDirty);
    return;
  }

  switch (record_state_) {
    case kRecordNull:
    case kRecordNullDirty:
      // Current record is null, starting a new record.
      record_.Init(tag, count);
      record_state_ = kRecordValidDirty;
      break;

    case kRecordValid:
      // If there's an existing record for the current tag,
      // accumulates the counts.
      DCHECK_EQ(record_.tag(), tag);
      if (count > 0) {
        record_.Add(count);
        record_state_ = kRecordValidDirty;
      }
      break;

    default:
      NOTREACHED();
  }
}

void TaggedCounter::WriteRecord(int fd) {
  switch (record_state_) {
    case kRecordNullDirty:
      // Truncates the aggregation file to discard the record.
      PLOG_IF(WARNING, HANDLE_EINTR(ftruncate(fd, 0)) != 0);
      record_state_ = kRecordNull;
      break;

    case kRecordValidDirty:
      // Updates the accumulator record in the file if there's new data.
      PLOG_IF(WARNING, HANDLE_EINTR(lseek(fd, 0, SEEK_SET)) != 0);
      PLOG_IF(WARNING,
              HANDLE_EINTR(write(fd, &record_, sizeof(record_))) !=
              sizeof(record_));
      record_state_ = kRecordValid;
      break;

    case kRecordNull:
    case kRecordValid:
      // Nothing to do.
      break;

    default:
      NOTREACHED();
  }
}

MetricsLibraryInterface* TaggedCounterReporter::metrics_lib_ = NULL;

TaggedCounterReporter::TaggedCounterReporter()
    : tagged_counter_(new TaggedCounter()),
      min_(0),
      max_(0),
      buckets_(0) {
}

TaggedCounterReporter::~TaggedCounterReporter() {
}

void TaggedCounterReporter::Init(const char* filename,
                                 const char* histogram_name,
                                 int min,
                                 int max,
                                 int buckets) {
  tagged_counter_->Init(filename, Report, this);
  histogram_name_ = histogram_name;
  min_ = min;
  max_ = max;
  buckets_ = buckets;
  CHECK(min_ >= 0);
  CHECK(max_ > min_);
  CHECK(buckets_ > 0);
}

void TaggedCounterReporter::Report(void* handle, int32 tag, int32 count) {
  TaggedCounterReporter* this_reporter =
      reinterpret_cast<TaggedCounterReporter*>(handle);
  DLOG(INFO) << "received metric: " << this_reporter->histogram_name_
             << " " << count << " " << this_reporter->min_ << " "
             << this_reporter->max_ << " " << this_reporter->buckets_;
  CHECK(metrics_lib_ != NULL);
  CHECK(this_reporter->buckets_ > 0);
  metrics_lib_->SendToUMA(this_reporter->histogram_name_,
                          count,
                          this_reporter->min_,
                          this_reporter->max_,
                          this_reporter->buckets_);
}

FrequencyCounter::FrequencyCounter() : cycle_duration_(1) {
}

FrequencyCounter::~FrequencyCounter() {
}

void FrequencyCounter::Init(TaggedCounterInterface* tagged_counter,
                            time_t cycle_duration) {
  tagged_counter_.reset(tagged_counter);
  DCHECK(cycle_duration > 0);
  cycle_duration_ = cycle_duration;
}

void FrequencyCounter::UpdateInternal(int32 count, time_t now) {
  DCHECK(tagged_counter_.get() != NULL);
  tagged_counter_->Update(GetCycleNumber(now), count);
}

int32 FrequencyCounter::GetCycleNumber(time_t now) {
  return now / cycle_duration_;
}

}  // namespace chromeos_metrics
