// 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.

#pragma once

#include <string>

#include <glog/logging.h>

#include "common/status.h"
#include "util/metrics-fwd.h"

namespace impala {
  class MallocUtil {
  public:
    // Gets the MallocUtil singleton. Always a non-nullptr.
    static MallocUtil* GetInstance();

    // Initialize the settings for the malloc implementation. This should be called once
    // at startup. Since backend tests may call this repeatedly, any additional calls
    // are ignored.
    virtual Status Init(int64_t process_memory_limit) = 0;

    // Malloc implementations that retain extra memory usually provide a way to manually
    // free excess memory. This should try to free the specified amount of excess
    // memory.
    virtual void ReleaseMemoryToSystem(int64_t bytes_to_free) {}

    // Gets a human readable description of malloc state / statistics
    virtual std::string GetTextDescription() const = 0;

    // The name of the malloc implementation
    virtual std::string GetName() const = 0;

    // Add malloc implementation specific metrics in the provided metrics group.
    virtual Status RegisterMemoryMetrics(MetricGroup* metrics) = 0;

    // Get the metric for used memory. This can only be called after initialization.
    // This must be non-null for all malloc implementations.
    virtual IntGauge* GetUsedBytesMetric(bool include_overhead) const = 0;

    // Get the metric for the malloc implementation's overhead. This can only be
    // called after initialization. This will return null if the malloc
    // implementation does not have an overhead metric.
    virtual IntGauge* GetOverheadBytesMetric() const = 0;

    // Get information about the malloc implementation's support for huge pages.
    // MADVISE_COMPATIBLE - It is permissible to use madvise() with MADV_HUGEPAGE
    //   on properly aligned large buffers to use huge pages. The malloc
    //   implementation does not split them up or decommit them in smaller chunks.
    //   A malloc implementation that immediately frees memory (e.g. Gperftools
    //   TCMalloc's aggressive decommit mode) can guarantee this.
    // MADVISE_INCOMPATIBLE - The malloc implementation can't guarantee that it
    //   will operate properly with huge pages. It may break up huge pages. This
    //   is true for most malloc implementations that retain memory without
    //   explicit huge page support.
    // MADVISE_UNNECESSARY - The malloc implementation uses huge pages natively.
    //   Callers should not use madvise() with MADV_HUGEPAGE themselves, because
    //   the malloc implementation is already doing this. If the malloc implementation
    //   retains memory, it does so in a way that is aware of huge pages.
    // This can only be called after initialization.
    enum class HugePageSupport {
      MADVISE_COMPATIBLE,
      MADVISE_INCOMPATIBLE,
      MADVISE_UNNECESSARY
    };
    virtual HugePageSupport GetHugePageSupport() const = 0;
    friend std::ostream& operator<<(std::ostream& os, const HugePageSupport& h);

    // Profiler interfaces
    // This will need to evolve as other malloc implementations are added. Right now,
    // this only needs to handle Gperftools TCMalloc and the sanitizers. To simplify
    // implementations that don't support profiling, these default to returning false
    // and DCHECKing if any are used.
    //
    // Currently, all the different types of profiling return a binary structure for
    // use with the pprof utility. These are the current types of profiling:
    // Heap profiling: profile all allocations for a period of time. The call pattern
    //    is HeapProfilerStart(), wait for some samples to be collected,
    //    GetHeapProfile(), then HeapProfilerStop().
    // Heap growth stacks: return stacks for allocations that caused the address space
    //    to grow.
    // CPU profiling: send a signal and sample stacks. The call pattern is
    //    CPUProfileStart(), wait for some samples to be collected, then
    //    CPUProfileStop(). This writes the profile to a temporary file that can be
    //    read back.

    virtual bool SupportsHeapProfiling() const { return false; }
    virtual void HeapProfilerStart(const std::string& tmp_prof_file_name) {
      DCHECK(false);
    }
    virtual void HeapProfilerStop() { DCHECK(false); }
    // Returns a binary heap profile. The returned pointer is a '\0'-terminated
    // string allocated using malloc() and should be free()-ed as soon as the
    // caller does not need it anymore.
    virtual char* GetHeapProfile() {
      DCHECK(false);
      return nullptr;
    }

    virtual bool SupportsHeapGrowthStacks() const {
      return false;
    }
    virtual void GetHeapGrowthStacks(std::string* heap_growth_stacks) {
      DCHECK(false);
    }

    virtual bool SupportsCPUProfiling() const { return false; }
    virtual void CPUProfilerStart(const std::string& tmp_prof_file_name) {
      DCHECK(false);
    }
    virtual void CPUProfilerStop() {
      DCHECK(false);
    }
  protected:
    // Restrict access to the constructor / destructor to protect the singleton.
    MallocUtil() = default;
    ~MallocUtil() = default;
  private:
    DISALLOW_COPY_AND_ASSIGN(MallocUtil);
  };
} // namespace impala
