// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/metrics.h"

#include "vm/isolate.h"
#include "vm/json_stream.h"
#include "vm/native_entry.h"
#include "vm/runtime_entry.h"
#include "vm/object.h"
#include "vm/log.h"

namespace dart {

DEFINE_FLAG(bool, print_metrics, false,
            "Print metrics when isolates (and the VM) are shutdown.");

Metric* Metric::vm_list_head_ = NULL;

Metric::Metric()
    : isolate_(NULL),
      name_(NULL),
      description_(NULL),
      unit_(kCounter),
      value_(0),
      next_(NULL) {
}


void Metric::Init(Isolate* isolate,
                  const char* name,
                  const char* description,
                  Unit unit) {
  // Only called once.
  ASSERT(next_ == NULL);
  ASSERT(name != NULL);
  isolate_ = isolate;
  name_ = name;
  description_ = description;
  unit_ = unit;
  RegisterWithIsolate();
}


void Metric::Init(const char* name, const char* description, Unit unit) {
  // Only called once.
  ASSERT(next_ == NULL);
  ASSERT(name != NULL);
  name_ = name;
  description_ = description;
  unit_ = unit;
  RegisterWithVM();
}


Metric::~Metric() {
  // Only deregister metrics which had been registered. Metrics without a name
  // are from shallow copy isolates.
  if (name_ != NULL) {
    if (isolate_ == NULL) {
      DeregisterWithVM();
    } else {
      DeregisterWithIsolate();
    }
  }
}


static const char* UnitString(intptr_t unit) {
  switch (unit) {
    case Metric::kCounter: return "counter";
    case Metric::kByte: return "byte";
    default:
      UNREACHABLE();
  }
  UNREACHABLE();
  return NULL;
}


void Metric::PrintJSON(JSONStream* stream) {
  if (!FLAG_support_service) {
    return;
  }
  JSONObject obj(stream);
  obj.AddProperty("type", "Counter");
  obj.AddProperty("name", name_);
  obj.AddProperty("description", description_);
  obj.AddProperty("unit", UnitString(unit()));
  if (isolate_ == NULL) {
    obj.AddFixedServiceId("vm/metrics/%s", name_);
  } else {
    obj.AddFixedServiceId("metrics/native/%s", name_);
  }
  // TODO(johnmccutchan): Overflow?
  double value_as_double = static_cast<double>(Value());
  obj.AddProperty("value", value_as_double);
}


char* Metric::ValueToString(int64_t value, Unit unit) {
  Thread* thread = Thread::Current();
  ASSERT(thread != NULL);
  Zone* zone = thread->zone();
  ASSERT(zone != NULL);
  switch (unit) {
    case kCounter:
      return zone->PrintToString("%" Pd64 "", value);
    case kByte: {
      const char* scaled_suffix = "b";
      double scaled_value = static_cast<double>(value);
      if (value > KB) {
        scaled_suffix = "kb";
        scaled_value /= KB;
      } else if (value > MB) {
        scaled_suffix = "mb";
        scaled_value /= MB;
      } else if (value > GB) {
        scaled_suffix = "gb";
        scaled_value /= GB;
      }
      return zone->PrintToString("%.3f %s (%" Pd64 ")",
                                 scaled_value,
                                 scaled_suffix,
                                 value);
    }
    default:
      UNREACHABLE();
      return NULL;
  }
}


char* Metric::ToString() {
  Thread* thread = Thread::Current();
  ASSERT(thread != NULL);
  Zone* zone = thread->zone();
  ASSERT(zone != NULL);
  return zone->PrintToString("%s %s", name(), ValueToString(value(), unit()));
}


bool Metric::NameExists(Metric* head, const char* name) {
  ASSERT(name != NULL);
  while (head != NULL) {
    const char* metric_name = head->name();
    ASSERT(metric_name != NULL);
    if (strcmp(metric_name, name) == 0) {
      return true;
    }
    head = head->next();
  }
  return false;
}



void Metric::RegisterWithIsolate() {
  ASSERT(isolate_ != NULL);
  ASSERT(next_ == NULL);
  // No duplicate names allowed.
  ASSERT(!NameExists(isolate_->metrics_list_head(), name()));
  Metric* head = isolate_->metrics_list_head();
  if (head != NULL) {
    set_next(head);
  }
  isolate_->set_metrics_list_head(this);
}


void Metric::DeregisterWithIsolate() {
  Metric* head = isolate_->metrics_list_head();
  ASSERT(head != NULL);
  // Handle head of list case.
  if (head == this) {
    isolate_->set_metrics_list_head(next());
    set_next(NULL);
    return;
  }
  Metric* previous = NULL;
  while (true) {
    previous = head;
    ASSERT(previous != NULL);
    head = head->next();
    if (head == NULL) {
      break;
    }
    if (head == this) {
      // Remove this from list.
      previous->set_next(head->next());
      set_next(NULL);
      return;
    }
    ASSERT(head != NULL);
  }
  UNREACHABLE();
}


void Metric::RegisterWithVM() {
  ASSERT(isolate_ == NULL);
  ASSERT(next_ == NULL);
  // No duplicate names allowed.
  ASSERT(!NameExists(vm_list_head_, name()));
  Metric* head = vm_list_head_;
  if (head != NULL) {
    set_next(head);
  }
  vm_list_head_ = this;
}


void Metric::DeregisterWithVM() {
  ASSERT(isolate_ == NULL);
  Metric* head = vm_list_head_;
  if (head == NULL) {
    return;
  }
  // Handle head of list case.
  if (head == this) {
    vm_list_head_ = next();
    set_next(NULL);
    return;
  }
  Metric* previous = NULL;
  while (true) {
    previous = head;
    ASSERT(previous != NULL);
    head = head->next();
    if (head == NULL) {
      break;
    }
    if (head == this) {
      // Remove this from list.
      previous->set_next(head->next());
      set_next(NULL);
      return;
    }
    ASSERT(head != NULL);
  }
  UNREACHABLE();
}


int64_t MetricHeapOldUsed::Value() const {
  ASSERT(isolate() == Isolate::Current());
  return isolate()->heap()->UsedInWords(Heap::kOld) * kWordSize;
}


int64_t MetricHeapOldCapacity::Value() const {
  ASSERT(isolate() == Isolate::Current());
  return isolate()->heap()->CapacityInWords(Heap::kOld) * kWordSize;
}


int64_t MetricHeapOldExternal::Value() const {
  ASSERT(isolate() == Isolate::Current());
  return isolate()->heap()->ExternalInWords(Heap::kOld) * kWordSize;
}


int64_t MetricHeapNewUsed::Value() const {
  ASSERT(isolate() == Isolate::Current());
  return isolate()->heap()->UsedInWords(Heap::kNew) * kWordSize;
}


int64_t MetricHeapNewCapacity::Value() const {
  ASSERT(isolate() == Isolate::Current());
  return isolate()->heap()->CapacityInWords(Heap::kNew) * kWordSize;
}


int64_t MetricHeapNewExternal::Value() const {
  ASSERT(isolate() == Isolate::Current());
  return isolate()->heap()->ExternalInWords(Heap::kNew) * kWordSize;
}


int64_t MetricHeapUsed::Value() const {
  ASSERT(isolate() == Isolate::Current());
  return isolate()->heap()->UsedInWords(Heap::kNew) * kWordSize +
         isolate()->heap()->UsedInWords(Heap::kOld) * kWordSize;
}

int64_t MetricIsolateCount::Value() const {
  return Isolate::IsolateListLength();
}

#define VM_METRIC_VARIABLE(type, variable, name, unit)                         \
  static type vm_metric_##variable##_;
  VM_METRIC_LIST(VM_METRIC_VARIABLE);
#undef VM_METRIC_VARIABLE


void Metric::InitOnce() {
#define VM_METRIC_INIT(type, variable, name, unit)                             \
  vm_metric_##variable##_.Init(name, NULL, Metric::unit);
  VM_METRIC_LIST(VM_METRIC_INIT);
#undef VM_METRIC_INIT
}

void Metric::Cleanup() {
  if (FLAG_print_metrics) {
    // Create a zone to allocate temporary strings in.
    StackZone sz(Thread::Current());
    OS::Print("Printing metrics for VM\n");
    Metric* current = Metric::vm_head();
    while (current != NULL) {
      OS::Print("%s\n", current->ToString());
      current = current->next();
    }
    OS::Print("\n");
  }
}


MaxMetric::MaxMetric()
    : Metric() {
  set_value(kMinInt64);
}


void MaxMetric::SetValue(int64_t new_value) {
  if (new_value > value()) {
    set_value(new_value);
  }
}


MinMetric::MinMetric()
    : Metric() {
  set_value(kMaxInt64);
}


void MinMetric::SetValue(int64_t new_value) {
  if (new_value < value()) {
    set_value(new_value);
  }
}

}  // namespace dart
