// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

#include "util/memusage-path-handlers.h"

#include <gperftools/malloc_extension.h>

#include "runtime/mem-tracker.h"
#include "util/common-metrics.h"
#include "util/mem-info.h"
#include "util/pretty-printer.h"

#include "common/names.h"

using namespace impala;
using namespace rapidjson;

/// A MemTracker tracks memory consumption and limits which will be displayed. This method
/// adds the mem_limit and the current memory consumption to the rapidjson document. Also,
/// it dumps all the additional mem trackers to the rapidjson document.
void AddMemTracker(MemTracker* mem_tracker,
    const Webserver::WebRequest& req, Document* document) {
  DCHECK(mem_tracker != NULL);
  Value mem_limit(PrettyPrinter::Print(mem_tracker->limit(), TUnit::BYTES).c_str(),
      document->GetAllocator());
  document->AddMember("mem_limit", mem_limit, document->GetAllocator());
  Value consumption(
      PrettyPrinter::Print(mem_tracker->consumption(), TUnit::BYTES).c_str(),
      document->GetAllocator());
  document->AddMember("consumption", consumption, document->GetAllocator());

  // Dump all mem trackers.
  Value detailed(mem_tracker->LogUsage(MemTracker::UNLIMITED_DEPTH).c_str(),
      document->GetAllocator());
  document->AddMember("detailed", detailed, document->GetAllocator());
}

/// Adds the following malloc data structures to the rapidjson document.
/// - Total inuse memory by application.
/// - Free memory(thread, central and page heap),
/// - Freelist of central cache, each class.
/// - Page heap freelist.
void AddTCmallocOverview(const Webserver::WebRequest& req, Document* document) {
  stringstream ss;
#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER)
  ss << "Memory tracking is not available with address or thread sanitizer builds.";
#else
  char buf[2048];
  MallocExtension::instance()->GetStats(buf, 2048);
  ss << string(buf);
#endif

  Value overview(ss.str().c_str(), document->GetAllocator());
  document->AddMember("overview", overview, document->GetAllocator());
}

/// Adds the system memory configuration to the rapidjson document.
void AddSystemInfo(const Webserver::WebRequest& req, Document* document) {
  Value systeminfo(MemInfo::DebugString().c_str(), document->GetAllocator());
  document->AddMember("systeminfo", systeminfo, document->GetAllocator());
}

/// A MetricGroup is a container for a set of metric. This method extracts and adds the
/// initialized JVM, buffer-pool and aggregated memory metrics to the rapidjson document
/// from the given MetricGroup.
void AddMetricGroup(MetricGroup* metric_group,
    const Webserver::WebRequest& req, Document* document) {
  if (metric_group != nullptr) {
    MetricGroup* aggregate_group = metric_group->FindChildGroup("memory");
    if (aggregate_group != nullptr) {
      Value json_metrics(kObjectType);
      aggregate_group->ToJson(false, document, &json_metrics);
      document->AddMember(
          "aggregate_metrics", json_metrics["metrics"], document->GetAllocator());
    }
    MetricGroup* jvm_group = metric_group->FindChildGroup("jvm");
    if (jvm_group != nullptr) {
      Value jvm(kObjectType);
      jvm_group->ToJson(false, document, &jvm);
      Value heap(kArrayType);
      Value non_heap(kArrayType);
      Value total(kArrayType);
      for (SizeType i = 0; i < jvm["metrics"].Size(); ++i) {
        if (strstr(jvm["metrics"][i]["name"].GetString(), "total") != nullptr) {
          total.PushBack(jvm["metrics"][i], document->GetAllocator());
        } else if (strstr(jvm["metrics"][i]["name"].GetString(), "non-heap") != nullptr) {
          non_heap.PushBack(jvm["metrics"][i], document->GetAllocator());
        } else if (strstr(jvm["metrics"][i]["name"].GetString(), "heap") != nullptr) {
          heap.PushBack(jvm["metrics"][i], document->GetAllocator());
        }
      }
      document->AddMember("jvm_total", total, document->GetAllocator());
      document->AddMember("jvm_heap", heap, document->GetAllocator());
      document->AddMember("jvm_non_heap", non_heap, document->GetAllocator());
    }
    MetricGroup* buffer_pool_group = metric_group->FindChildGroup("buffer-pool");
    if (buffer_pool_group != nullptr) {
      Value json_metrics(kObjectType);
      buffer_pool_group->ToJson(false, document, &json_metrics);
      document->AddMember(
          "buffer_pool", json_metrics["metrics"], document->GetAllocator());
    }
  }
}

void impala::AddMemUsageCallbacks(Webserver* webserver, MemTracker* mem_tracker,
    MetricGroup* metric_group) {
  if (mem_tracker != nullptr) {
    auto callback = [mem_tracker, metric_group]
        (const Webserver::WebRequest& req, Document* doc) {
      AddMemTracker(mem_tracker, req, doc);
      AddTCmallocOverview(req, doc);
      AddSystemInfo(req, doc);
      AddMetricGroup(metric_group, req, doc);
    };
    webserver->RegisterUrlCallback("/memz", "memz.tmpl", callback, true);
  } else {
    auto callback = [metric_group]
        (const Webserver::WebRequest& req, Document* doc) {
      AddTCmallocOverview(req, doc);
      AddSystemInfo(req, doc);
      AddMetricGroup(metric_group, req, doc);
    };
    webserver->RegisterUrlCallback("/memz", "memz.tmpl", callback, true);
  }
}
