/*
 * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2020 SAP SE. 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/metaspace/counters.hpp"
#include "memory/metaspace/freeBlocks.hpp"
//#define LOG_PLEASE
#include "metaspaceGtestCommon.hpp"

using metaspace::FreeBlocks;
using metaspace::SizeCounter;

#define CHECK_CONTENT(fb, num_blocks_expected, word_size_expected) \
{ \
  if (word_size_expected > 0) { \
    EXPECT_FALSE(fb.is_empty()); \
  } else { \
    EXPECT_TRUE(fb.is_empty()); \
  } \
  EXPECT_EQ(fb.total_size(), (size_t)word_size_expected); \
  EXPECT_EQ(fb.count(), (int)num_blocks_expected); \
}

class FreeBlocksTest {

  FeederBuffer _fb;
  FreeBlocks _freeblocks;

  // random generator for block feeding
  RandSizeGenerator _rgen_feeding;

  // random generator for allocations (and, hence, deallocations)
  RandSizeGenerator _rgen_allocations;

  SizeCounter _allocated_words;

  struct allocation_t {
    allocation_t* next;
    size_t word_size;
    MetaWord* p;
  };

  // Array of the same size as the pool max capacity; holds the allocated elements.
  allocation_t* _allocations;

  int _num_allocs;
  int _num_deallocs;
  int _num_feeds;

  bool feed_some() {
    size_t word_size = _rgen_feeding.get();
    MetaWord* p = _fb.get(word_size);
    if (p != NULL) {
      _freeblocks.add_block(p, word_size);
      return true;
    }
    return false;
  }

  bool deallocate_top() {

    allocation_t* a = _allocations;
    if (a != NULL) {
      _allocations = a->next;
      check_marked_range(a->p, a->word_size);
      _freeblocks.add_block(a->p, a->word_size);
      delete a;
      DEBUG_ONLY(_freeblocks.verify();)
      return true;
    }
    return false;
  }

  void deallocate_all() {
    while (deallocate_top());
  }

  bool allocate() {

    size_t word_size = MAX2(_rgen_allocations.get(), _freeblocks.MinWordSize);
    MetaWord* p = _freeblocks.remove_block(word_size);
    if (p != NULL) {
      _allocated_words.increment_by(word_size);
      allocation_t* a = new allocation_t;
      a->p = p; a->word_size = word_size;
      a->next = _allocations;
      _allocations = a;
      DEBUG_ONLY(_freeblocks.verify();)
      mark_range(p, word_size);
      return true;
    }
    return false;
  }

  void test_all_marked_ranges() {
    for (allocation_t* a = _allocations; a != NULL; a = a->next) {
      check_marked_range(a->p, a->word_size);
    }
  }

  void test_loop() {
    // We loop and in each iteration execute one of three operations:
    // - allocation from fbl
    // - deallocation to fbl of a previously allocated block
    // - feeding a new larger block into the fbl (mimicks chunk retiring)
    // When we have fed all large blocks into the fbl (feedbuffer empty), we
    //  switch to draining the fbl completely (only allocs)
    bool forcefeed = false;
    bool draining = false;
    bool stop = false;
    int iter = 25000; // safety stop
    while (!stop && iter > 0) {
      iter --;
      int surprise = (int)os::random() % 10;
      if (!draining && (surprise >= 7 || forcefeed)) {
        forcefeed = false;
        if (feed_some()) {
          _num_feeds++;
        } else {
          // We fed all input memory into the fbl. Now lets proceed until the fbl is drained.
          draining = true;
        }
      } else if (!draining && surprise < 1) {
        deallocate_top();
        _num_deallocs++;
      } else {
        if (allocate()) {
          _num_allocs++;
        } else {
          if (draining) {
            stop = _freeblocks.total_size() < 512;
          } else {
            forcefeed = true;
          }
        }
      }
      if ((iter % 1000) == 0) {
        DEBUG_ONLY(_freeblocks.verify();)
        test_all_marked_ranges();
        LOG("a %d (" SIZE_FORMAT "), d %d, f %d", _num_allocs, _allocated_words.get(), _num_deallocs, _num_feeds);
#ifdef LOG_PLEASE
        _freeblocks.print(tty, true);
        tty->cr();
#endif
      }
    }

    // Drain

  }

public:

  FreeBlocksTest(size_t avg_alloc_size) :
    _fb(512 * K), _freeblocks(),
    _rgen_feeding(128, 4096),
    _rgen_allocations(avg_alloc_size / 4, avg_alloc_size * 2, 0.01f, avg_alloc_size / 3, avg_alloc_size * 30),
    _allocations(NULL),
    _num_allocs(0),
    _num_deallocs(0),
    _num_feeds(0)
  {
    CHECK_CONTENT(_freeblocks, 0, 0);
    // some initial feeding
    _freeblocks.add_block(_fb.get(1024), 1024);
    CHECK_CONTENT(_freeblocks, 1, 1024);
  }

  ~FreeBlocksTest() {
    deallocate_all();
  }

  static void test_small_allocations() {
    FreeBlocksTest test(10);
    test.test_loop();
  }

  static void test_medium_allocations() {
    FreeBlocksTest test(30);
    test.test_loop();
  }

  static void test_large_allocations() {
    FreeBlocksTest test(150);
    test.test_loop();
  }

};

TEST_VM(metaspace, freeblocks_basics) {

  FreeBlocks fbl;
  MetaWord tmp[1024];
  CHECK_CONTENT(fbl, 0, 0);

  fbl.add_block(tmp, 1024);
  DEBUG_ONLY(fbl.verify();)
  ASSERT_FALSE(fbl.is_empty());
  CHECK_CONTENT(fbl, 1, 1024);

  MetaWord* p = fbl.remove_block(1024);
  EXPECT_EQ(p, tmp);
  DEBUG_ONLY(fbl.verify();)
  CHECK_CONTENT(fbl, 0, 0);

}

TEST_VM(metaspace, freeblocks_small) {
  FreeBlocksTest::test_small_allocations();
}

TEST_VM(metaspace, freeblocks_medium) {
  FreeBlocksTest::test_medium_allocations();
}

TEST_VM(metaspace, freeblocks_large) {
  FreeBlocksTest::test_large_allocations();
}

