/*
 * Copyright (c) 2023 SAP SE. All rights reserved.
 * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

#include "precompiled.hpp"

#include "memory/allocation.hpp"
#include "runtime/java.hpp"
#include "runtime/globals.hpp"
#include "services/mallocLimit.hpp"
#include "services/nmtCommon.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/parseInteger.hpp"
#include "utilities/ostream.hpp"

MallocLimitSet MallocLimitHandler::_limits;
bool MallocLimitHandler::_have_limit = false;

static const char* const MODE_OOM = "oom";
static const char* const MODE_FATAL = "fatal";

static const char* mode_to_name(MallocLimitMode m) {
  switch (m) {
  case MallocLimitMode::trigger_fatal: return MODE_FATAL;
  case MallocLimitMode::trigger_oom: return MODE_OOM;
  default: ShouldNotReachHere();
  };
  return nullptr;
}

class ParserHelper {
  // Start, end of parsed string.
  const char* const _s;
  const char* const _end;
  // Current parse position.
  const char* _p;

public:
  ParserHelper(const char* s) : _s(s), _end(s + strlen(s)), _p(s) {}

  bool eof() const { return _p >= _end; }

  // Check if string at position matches a malloclimit_mode_t.
  // Advance position on match.
  bool match_mode_flag(MallocLimitMode* out) {
    if (eof()) {
      return false;
    }
    if (strncasecmp(_p, MODE_OOM, strlen(MODE_OOM)) == 0) {
      *out = MallocLimitMode::trigger_oom;
      _p += 3;
      return true;
    } else if (strncasecmp(_p, MODE_FATAL, strlen(MODE_FATAL)) == 0) {
      *out = MallocLimitMode::trigger_fatal;
      _p += 5;
      return true;
    }
    return false;
  }

  // Check if string at position matches a category name.
  // Advances position on match.
  bool match_category(MEMFLAGS* out) {
    if (eof()) {
      return false;
    }
    const char* end = strchr(_p, ':');
    if (end == nullptr) {
      end = _end;
    }
    stringStream ss;
    ss.print("%.*s", (int)(end - _p), _p);
    MEMFLAGS f = NMTUtil::string_to_flag(ss.base());
    if (f != mtNone) {
      *out = f;
      _p = end;
      return true;
    }
    return false;
  }

  // Check if string at position matches a memory size (e.g. "100", "100g" etc).
  // Advances position on match.
  bool match_size(size_t* out) {
    if (!eof()) {
      char* remainder = nullptr;
      if (parse_integer<size_t>(_p, &remainder, out)) {
        assert(remainder > _p && remainder <= _end, "sanity");
        _p = remainder;
        return true;
      }
    }
    return false;
  }

  // Check if char at pos matches c; return true and advance pos if so.
  bool match_char(char c) {
    if (!eof() && (*_p) == c) {
      _p ++;
      return true;
    }
    return false;
  }
};

MallocLimitSet::MallocLimitSet() {
  reset();
}

void MallocLimitSet::set_global_limit(size_t s, MallocLimitMode flag) {
  _glob.sz = s; _glob.mode = flag;
}

void MallocLimitSet::set_category_limit(MEMFLAGS f, size_t s, MallocLimitMode flag) {
  const int i = NMTUtil::flag_to_index(f);
  _cat[i].sz = s; _cat[i].mode = flag;
}

void MallocLimitSet::reset() {
  set_global_limit(0, MallocLimitMode::trigger_fatal);
  _glob.sz = 0; _glob.mode = MallocLimitMode::trigger_fatal;
  for (int i = 0; i < mt_number_of_types; i++) {
    set_category_limit(NMTUtil::index_to_flag(i), 0, MallocLimitMode::trigger_fatal);
  }
}

void MallocLimitSet::print_on(outputStream* st) const {
  static const char* flagnames[] = { MODE_FATAL, MODE_OOM };
  if (_glob.sz > 0) {
    st->print_cr("MallocLimit: total limit: " PROPERFMT " (%s)", PROPERFMTARGS(_glob.sz),
                 mode_to_name(_glob.mode));
  } else {
    for (int i = 0; i < mt_number_of_types; i++) {
      if (_cat[i].sz > 0) {
        st->print_cr("MallocLimit: category \"%s\" limit: " PROPERFMT " (%s)",
                     NMTUtil::flag_to_enum_name(NMTUtil::index_to_flag(i)),
                     PROPERFMTARGS(_cat[i].sz), mode_to_name(_cat[i].mode));
      }
    }
  }
}

bool MallocLimitSet::parse_malloclimit_option(const char* v, const char** err) {

#define BAIL_UNLESS(condition, errormessage) if (!(condition)) { *err = errormessage; return false; }

  // Global form:
  // MallocLimit=<size>[:flag]

  // Category-specific form:
  // MallocLimit=<category>:<size>[:flag][,<category>:<size>[:flag]...]

  reset();

  ParserHelper sst(v);

  BAIL_UNLESS(!sst.eof(), "Empty string");

  // Global form?
  if (sst.match_size(&_glob.sz)) {
    // Match optional mode flag (e.g. 1g:oom)
    if (!sst.eof()) {
      BAIL_UNLESS(sst.match_char(':'), "Expected colon");
      BAIL_UNLESS(sst.match_mode_flag(&_glob.mode), "Expected flag");
    }
  }
  // Category-specific form?
  else {
    while (!sst.eof()) {
      MEMFLAGS f;

      // Match category, followed by :
      BAIL_UNLESS(sst.match_category(&f), "Expected category name");
      BAIL_UNLESS(sst.match_char(':'), "Expected colon following category");

      malloclimit* const modified_limit = &_cat[NMTUtil::flag_to_index(f)];

      // Match size
      BAIL_UNLESS(sst.match_size(&modified_limit->sz), "Expected size");

      // Match optional flag
      if (!sst.eof() && sst.match_char(':')) {
        BAIL_UNLESS(sst.match_mode_flag(&modified_limit->mode), "Expected flag");
      }

      // More to come?
      if (!sst.eof()) {
        BAIL_UNLESS(sst.match_char(','), "Expected comma");
      }
    }
  }
  return true;
}

void MallocLimitHandler::initialize(const char* options) {
  _have_limit = false;
  if (options != nullptr && options[0] != '\0') {
    const char* err = nullptr;
    if (!_limits.parse_malloclimit_option(options, &err)) {
      vm_exit_during_initialization("Failed to parse MallocLimit", err);
    }
    _have_limit = true;
  }
}

void MallocLimitHandler::print_on(outputStream* st) {
  if (have_limit()) {
    _limits.print_on(st);
  } else {
    st->print_cr("MallocLimit: unset");
  }
}

