/*
 * 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, "."),
            // Utils.getVolatileMemoryAllocatorService("pmalloc"),
            // 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("-------------------");
    }
  }

}
