// Copyright 2016 The Bazel Authors. All rights reserved.
//
// Licensed 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.

package com.google.devtools.build.lib.actions;

import com.google.common.base.Splitter;
import com.google.common.io.Files;
import com.google.devtools.build.lib.util.ProcMeminfoParser;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.HashSet;
import java.util.Set;

/**
 * This class estimates the local host's resource capacity for Linux.
 */
public class LocalHostResourceManagerLinux {
  private static String cpuInfoContent = null;

  private static final Splitter NEWLINE_SPLITTER = Splitter.on('\n').omitEmptyStrings();
  private static final String CPU_INFO_FILE = "/proc/cpuinfo";
  private static final String MEM_INFO_FILE = "/proc/meminfo";

  private static int getLogicalCpuCount() throws IOException {
    String content = getCpuInfoContent();
    return getLogicalCpuCountHelper(content);
  }

  private static int getPhysicalCpuCount(int logicalCpuCount) throws IOException {
    String content = getCpuInfoContent();
    return getPhysicalCpuCountHelper(logicalCpuCount, content);
  }

  private static double getMemoryInMb() throws IOException {
    return getMemoryInMbHelper(MEM_INFO_FILE);
  }

  public static ResourceSet getLocalHostResources() {
    try {
      int logicalCpuCount = getLogicalCpuCount();
      int physicalCpuCount = getPhysicalCpuCount(logicalCpuCount);
      double ramMb = getMemoryInMb();

      boolean hyperthreading = (logicalCpuCount != physicalCpuCount);
      final double EFFECTIVE_CPUS_PER_HYPERTHREADED_CPU = 0.6;
      return ResourceSet.create(
          ramMb,
          logicalCpuCount * (hyperthreading ? EFFECTIVE_CPUS_PER_HYPERTHREADED_CPU : 1.0),
          1.0,
          Integer.MAX_VALUE);
    } catch (IOException | IllegalArgumentException e) {
      return null;
    }
  }

  private static String getCpuInfoContent() throws IOException {
    if (cpuInfoContent == null) {
      cpuInfoContent = readContent(CPU_INFO_FILE);
    }
    return cpuInfoContent;
  }

  private static String readContent(String filename) throws IOException {
    return Files.toString(new File(filename), Charset.defaultCharset());
  }

  /**
   * For testing purposes only. Do not use it.
   */
  public static int getLogicalCpuCountHelper(String content) throws IOException {
    int count = 0;
    Iterable<String> lines = NEWLINE_SPLITTER.split(content);
    for (String line : lines) {
      if (line.startsWith("processor")) {
        count++;
      }
    }
    if (count == 0) {
      throw new IllegalArgumentException("Can't get logical CPU count");
    }
    return count;
  }

  public static int getPhysicalCpuCountHelper(int logicalCpuCount, String content)
      throws IOException {
    // CPU count
    Iterable<String> lines = NEWLINE_SPLITTER.split(content);
    Set<String> uniq = new HashSet<>();
    for (String line : lines) {
      if (line.startsWith("physical id")) {
        uniq.add(line);
      }
    }
    int cpuCount = uniq.size();
    if (cpuCount == 0) {
      cpuCount = logicalCpuCount;
    }

    // core per CPU
    uniq = new HashSet<>();
    for (String line : lines) {
      if (line.startsWith("core id")) {
        uniq.add(line);
      }
    }
    int coresPerCpu = uniq.size();
    if (coresPerCpu == 0) {
      coresPerCpu = 1;
    }

    return cpuCount * coresPerCpu;
  }

  public static double getMemoryInMbHelper(String memInfoFileName) throws IOException {
    ProcMeminfoParser memInfo = new ProcMeminfoParser(memInfoFileName);
    double ramMb = ProcMeminfoParser.kbToMb(memInfo.getTotalKb());
    return ramMb;
  }
}
