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

package org.apache.mnemonic.examples;

import java.nio.ByteBuffer;
import java.util.Random;

import org.apache.mnemonic.VolatileMemAllocator;
import org.apache.mnemonic.CommonAllocator;
import org.apache.mnemonic.MemBufferHolder;
import org.apache.mnemonic.MemChunkHolder;
import org.apache.mnemonic.MemClustering;
import org.apache.mnemonic.Reclaim;
import org.apache.mnemonic.SysMemAllocator;
import org.apache.mnemonic.Utils;

import sun.misc.Unsafe;

/**
 * Main is the class of example.
 * 
 */
@SuppressWarnings("restriction")
public class Main {

  /**
   * Run a example code to demonstrate some basic functionalities.
   *
   * @param argv
   *          array of commandline parameters
   */
  public static void main(String[] argv) throws Exception {
    Random randomGenerator = new Random();

    /* Generate configuration for each node */
    /*
     * Currently only one node is supported due to the external native code
     * 'vmem' returns null for multiple 'vmem' allocator instantialization
     */
    MemClustering.NodeConfig ncs[] = new MemClustering.NodeConfig[] {
        new MemClustering.NodeConfig(new SysMemAllocator(1024 * 1024 * 20, true).disableActiveGC(),
            MemClustering.PerformanceLevel.FASTEST),

        // new MemClustering.NodeConfig(new
        // BigDataMemAllocator(1024*1024*20, ".",
        // true).disableActiveGC(),
        // MemClustering.PerformanceLevel.FAST),
        // new MemClustering.NodeConfig(new
        // BigDataMemAllocator(1024*1024*20, ".",
        // true).disableActiveGC(),
        // MemClustering.PerformanceLevel.NORMAL),
        new MemClustering.NodeConfig(
            new VolatileMemAllocator(Utils.getVolatileMemoryAllocatorService("vmem"), 1024 * 1024 * 20, "."),
            // 1024 * 1024 * 20, "./example.dat", true),
            MemClustering.PerformanceLevel.SLOW), };

    for (MemClustering.NodeConfig nc : ncs) {
      /**
       * set a reclaimer for memory buffers
       */
      nc.getAllocator().setBufferReclaimer(new Reclaim<ByteBuffer>() {
        @Override
        public boolean reclaim(ByteBuffer mres, Long sz) {
          System.out.println(String.format("Reclaim Memory Buffer: %X  Size: %s", System.identityHashCode(mres),
              null == sz ? "NULL" : sz.toString()));
          return false;
        }
      });
      /**
       * set a reclaimer for memory chunks
       */
      nc.getAllocator().setChunkReclaimer(new Reclaim<Long>() {
        @Override
        public boolean reclaim(Long mres, Long sz) {
          System.out
              .println(String.format("Reclaim Memory Chunk: %X  Size: %s", mres, null == sz ? "NULL" : sz.toString()));
          return false;
        }
      });
    }

    /* Deploy Memory Clustering */
    MemClustering mclst = new MemClustering(ncs);

    /**
     * Set event callback for allocator changing. this callback is used to trace
     * the event of spilling out of allocation when previous allocator is unable
     * to meet the allocation requirement so trying to switch to next allocator.
     */
    mclst.setAllocatorChange(new MemClustering.AllocatorChange() {
      @Override
      public void changed(MemClustering.PerformanceLevel lvl, CommonAllocator prevallocator,
          CommonAllocator tgtallocator) {
        System.out.println(String.format("AllocatorChanged: %s, %X -> %X", lvl.name(),
            System.identityHashCode(prevallocator), System.identityHashCode(tgtallocator)));
      }
    });

    /**
     * Set event callback for performance level changing. this callback is used
     * to trace the event of downgrading to low level performance allocation.
     */
    mclst.setPerformanceLevelChange(new MemClustering.PerformanceLevelChange() {
      @Override
      public void changed(MemClustering.PerformanceLevel prevlvl, MemClustering.PerformanceLevel lvl) {
        System.out.println(
            String.format("PerfLevelChanged: %s -> %s", null == prevlvl ? "NULL" : prevlvl.name(), lvl.name()));
      }
    });

    /**
     * Start to create a piece of memory resource backed ByteBuffer and then
     * automatically release it or manually release it every six objects.
     */
    System.out.println(Utils.ANSI_GREEN + "[[Demo Allocation, Auto Destruction "
        + "and Manual Destruction of Big Memory ByteBuffer.]]" + Utils.ANSI_RESET);
    MemBufferHolder<?> mbh;
    for (int idx = 1; idx <= 50; ++idx) {
      int size = randomGenerator.nextInt(1024 * 1024) + 1024 * 1024;
      mbh = mclst.createBuffer(size);
      if (null == mbh) {
        throw new OutOfMemoryError("Memory Cluster out of memory!");
      }
      for (int i = 0; i < size; i++) {
        /**
         * Manipulate the ByteBuffer backed by external memory resource. Note:
         * Do not assigned internal ByteBuffer object to any variable, only use
         * function get() to access it all time.
         */
        mbh.get().put((byte) randomGenerator.nextInt(255));
      }
      System.out.println(String.format("[Seq.%d] size %d - %d, (%s)", idx, size, mbh.get().capacity(),
          size == mbh.get().capacity() ? "Correct" : "Failed!!!"));
      if (idx % 6 == 0) {
        /**
         * Force to release memory resource of specified ByteBuffer object
         * immediately.
         */
        System.out.println(String.format("Manually destroy Buffer  at %X.", System.identityHashCode(mbh.get())));
        mbh.destroy();
      }
      System.out.println("-------------------");
    }
    // Utils.collectGarbage();

    /**
     * Start to create a piece of memory resource backed chunk and then
     * automatically release it or manually release it every six chunks.
     */
    System.out.println(Utils.ANSI_GREEN + "[[Demo Allocation, Auto Destruction "
        + "and Manual Destruction of Big Memory Chunk.]]" + Utils.ANSI_RESET);
    Unsafe unsafe = Utils.getUnsafe();
    MemChunkHolder<?> mch;
    for (int idx = 1; idx <= 50; ++idx) {
      int size = randomGenerator.nextInt(1024 * 1024) + 1024 * 1024;
      mch = mclst.createChunk(size);
      if (null == mch) {
        throw new OutOfMemoryError("Memory Cluster out of memory!");
      }
      // mch.cancelAutoReclaim();
      mch.resize(size - 10);
      System.out.printf("chunk size is %d \n", mch.getSize());
      for (int i = 0; i < mch.getSize(); i++) {
        /**
         * Manipulate the chunk data. Note: Do not assigned the internal memory
         * space to any variable, please always use function get() to access it
         * at all time.
         */
        unsafe.putByte(mch.get() + i, (byte) randomGenerator.nextInt(255));
      }
      System.out.println(String.format("[Seq.%d] size %d - %d at %X.", idx, size, mch.getSize(), mch.get()));
      if (idx % 6 == 0) {
        /**
         * Force to release memory resource of specified Chunk object
         * Immediately.
         */
        System.out.println(String.format("Manually destroy Chunk at %X.", mch.get()));
        mch.destroy();
      }
      System.out.println("-------------------");
    }
  }

}
