/*
 * 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.geode.internal.offheap;

import org.apache.geode.annotations.Immutable;
import org.apache.geode.internal.DSCODE;
import org.apache.geode.internal.cache.CachedDeserializableFactory;
import org.apache.geode.internal.cache.DiskId;
import org.apache.geode.internal.cache.EntryEventImpl;
import org.apache.geode.internal.cache.RegionEntryContext;
import org.apache.geode.internal.cache.Token;
import org.apache.geode.internal.cache.entries.DiskEntry;
import org.apache.geode.internal.cache.entries.OffHeapRegionEntry;
import org.apache.geode.internal.offheap.annotations.Released;
import org.apache.geode.internal.offheap.annotations.Retained;
import org.apache.geode.internal.offheap.annotations.Unretained;

/**
 * The class just has static methods that operate on instances of {@link OffHeapRegionEntry}. It
 * allows common code to be shared for all the classes we have that implement
 * {@link OffHeapRegionEntry}.
 *
 * @since Geode 1.0
 */
public class OffHeapRegionEntryHelper {

  protected static final long NULL_ADDRESS = 0L << 1;
  protected static final long INVALID_ADDRESS = 1L << 1;
  protected static final long LOCAL_INVALID_ADDRESS = 2L << 1;
  protected static final long DESTROYED_ADDRESS = 3L << 1;
  protected static final long REMOVED_PHASE1_ADDRESS = 4L << 1;
  protected static final long REMOVED_PHASE2_ADDRESS = 5L << 1;
  protected static final long END_OF_STREAM_ADDRESS = 6L << 1;
  protected static final long NOT_AVAILABLE_ADDRESS = 7L << 1;
  protected static final long TOMBSTONE_ADDRESS = 8L << 1;
  public static final int MAX_LENGTH_FOR_DATA_AS_ADDRESS = 8;

  @Immutable
  private static final Token[] addrToObj =
      new Token[] {null, Token.INVALID, Token.LOCAL_INVALID, Token.DESTROYED, Token.REMOVED_PHASE1,
          Token.REMOVED_PHASE2, Token.END_OF_STREAM, Token.NOT_AVAILABLE, Token.TOMBSTONE,};

  private static long objectToAddress(@Unretained Object v) {
    if (v instanceof StoredObject)
      return ((StoredObject) v).getAddress();
    if (v == null)
      return NULL_ADDRESS;
    if (v == Token.TOMBSTONE)
      return TOMBSTONE_ADDRESS;
    if (v == Token.INVALID)
      return INVALID_ADDRESS;
    if (v == Token.LOCAL_INVALID)
      return LOCAL_INVALID_ADDRESS;
    if (v == Token.DESTROYED)
      return DESTROYED_ADDRESS;
    if (v == Token.REMOVED_PHASE1)
      return REMOVED_PHASE1_ADDRESS;
    if (v == Token.REMOVED_PHASE2)
      return REMOVED_PHASE2_ADDRESS;
    if (v == Token.END_OF_STREAM)
      return END_OF_STREAM_ADDRESS;
    if (v == Token.NOT_AVAILABLE)
      return NOT_AVAILABLE_ADDRESS;
    throw new IllegalStateException("Can not convert " + v + " to an off heap address.");
  }

  /**
   * This method may release the object stored at ohAddress if the result needs to be decompressed
   * and the decompress parameter is true. This decompressed result will be on the heap.
   *
   * @param ohAddress OFF_HEAP_ADDRESS
   * @param decompress true if off-heap value should be decompressed before returning
   * @param context used for decompression
   * @return OFF_HEAP_OBJECT (sometimes)
   */
  @Unretained
  @Retained
  public static Object addressToObject(@Released @Retained long ohAddress, boolean decompress,
      RegionEntryContext context) {
    if (isOffHeap(ohAddress)) {
      @Unretained
      OffHeapStoredObject chunk = new OffHeapStoredObject(ohAddress);
      @Unretained
      Object result = chunk;
      if (decompress && chunk.isCompressed()) {
        try {
          // to fix bug 47982 need to:
          byte[] decompressedBytes = chunk.getDecompressedBytes(context);
          if (chunk.isSerialized()) {
            // return a VMCachedDeserializable with the decompressed serialized bytes since chunk is
            // serialized
            result = CachedDeserializableFactory.create(decompressedBytes, context.getCache());
          } else {
            // return a byte[] since chunk is not serialized
            result = decompressedBytes;
          }
        } finally {
          // decompress is only true when this method is called by _getValueRetain.
          // In that case the caller has already retained ohAddress because it thought
          // we would return it. But we have unwrapped it and are returning the decompressed
          // results.
          // So we need to release the chunk here.
          chunk.release();
        }
      }
      return result;
    } else if ((ohAddress & ENCODED_BIT) != 0) {
      TinyStoredObject daa = new TinyStoredObject(ohAddress);
      Object result = daa;
      if (decompress && daa.isCompressed()) {
        byte[] decompressedBytes = daa.getDecompressedBytes(context);
        if (daa.isSerialized()) {
          // return a VMCachedDeserializable with the decompressed serialized bytes since daa is
          // serialized
          result = CachedDeserializableFactory.create(decompressedBytes, context.getCache());
        } else {
          // return a byte[] since daa is not serialized
          result = decompressedBytes;
        }
      }
      return result;
    } else {
      return addrToObj[(int) ohAddress >> 1];
    }
  }

  public static int getSerializedLength(TinyStoredObject dataAsAddress) {
    final long ohAddress = dataAsAddress.getAddress();

    if ((ohAddress & ENCODED_BIT) != 0) {
      boolean isLong = (ohAddress & LONG_BIT) != 0;
      if (isLong) {
        return 9;
      } else {
        return (int) ((ohAddress & SIZE_MASK) >> SIZE_SHIFT);
      }
    } else {
      return 0;
    }
  }

  /*
   * This method is optimized for cases where if the caller wants to convert address to a Token
   * compared to addressToObject which would deserialize the value.
   */
  private static Token addressToToken(long ohAddress) {
    if (isOffHeap(ohAddress) || (ohAddress & ENCODED_BIT) != 0) {
      return Token.NOT_A_TOKEN;
    } else {
      return addrToObj[(int) ohAddress >> 1];
    }
  }

  private static void releaseAddress(@Released long ohAddress) {
    if (isOffHeap(ohAddress)) {
      OffHeapStoredObject.release(ohAddress);
    }
  }

  /**
   * The address in 're' will be @Released.
   */
  public static void releaseEntry(@Released OffHeapRegionEntry re) {
    if (re instanceof DiskEntry) {
      DiskId did = ((DiskEntry) re).getDiskId();
      if (did != null && did.isPendingAsync()) {
        synchronized (did) {
          // This may not be needed so remove this call if it causes problems.
          // We no longer need this entry to be written to disk so unschedule it
          // before we change its value to REMOVED_PHASE2.
          did.setPendingAsync(false);
          setValue(re, Token.REMOVED_PHASE2);
          return;
        }
      }
    }
    setValue(re, Token.REMOVED_PHASE2);
  }

  public static void releaseEntry(@Unretained OffHeapRegionEntry re,
      @Released StoredObject expectedValue) {
    long oldAddress = objectToAddress(expectedValue);
    final long newAddress = objectToAddress(Token.REMOVED_PHASE2);
    if (re.setAddress(oldAddress, newAddress)) {
      releaseAddress(oldAddress);
    } /*
       * else { if (!calledSetValue || re.getAddress() != newAddress) { expectedValue.release(); } }
       */
  }

  /**
   * This bit is set to indicate that this address has data encoded in it.
   */
  private static final long ENCODED_BIT = 1L;
  /**
   * This bit is set to indicate that the encoded data is serialized.
   */
  static final long SERIALIZED_BIT = 2L;
  /**
   * This bit is set to indicate that the encoded data is compressed.
   */
  static final long COMPRESSED_BIT = 4L;
  /**
   * This bit is set to indicate that the encoded data is a long whose value fits in 7 bytes.
   */
  private static final long LONG_BIT = 8L;
  /**
   * size is in the range 0..7 so we only need 3 bits.
   */
  private static final long SIZE_MASK = 0x70L;
  /**
   * number of bits to shift the size by.
   */
  private static final int SIZE_SHIFT = 4;
  // the msb of this byte is currently unused

  /**
   * Returns 0 if the data could not be encoded as an address.
   */
  public static long encodeDataAsAddress(byte[] v, boolean isSerialized, boolean isCompressed) {
    if (v.length < MAX_LENGTH_FOR_DATA_AS_ADDRESS) {
      long result = 0L;
      for (int i = 0; i < v.length; i++) {
        result |= v[i] & 0x00ff;
        result <<= 8;
      }
      result |= (v.length << SIZE_SHIFT) | ENCODED_BIT;
      if (isSerialized) {
        result |= SERIALIZED_BIT;
      }
      if (isCompressed) {
        result |= COMPRESSED_BIT;
      }
      return result;
    } else if (isSerialized && !isCompressed) {
      // Check for some special types that take more than 7 bytes to serialize
      // but that might be able to be inlined with less than 8 bytes.
      if (v[0] == DSCODE.LONG.toByte()) {
        // A long is currently always serialized as 8 bytes (9 if you include the dscode).
        // But many long values will actually be small enough for is to encode in 7 bytes.
        if ((v[1] == 0 && (v[2] & 0x80) == 0) || (v[1] == -1 && (v[2] & 0x80) != 0)) {
          // The long can be encoded as 7 bytes since the most signification byte
          // is simply an extension of the sign byte on the second most signification byte.
          long result = 0L;
          for (int i = 2; i < v.length; i++) {
            result |= v[i] & 0x00ff;
            result <<= 8;
          }
          result |= (7 << SIZE_SHIFT) | LONG_BIT | SERIALIZED_BIT | ENCODED_BIT;
          return result;
        }
      }
    }
    return 0L;
  }

  static Object decodeAddressToObject(long ohAddress) {
    byte[] bytes = decodeUncompressedAddressToBytes(ohAddress);

    boolean isSerialized = (ohAddress & SERIALIZED_BIT) != 0;
    if (isSerialized) {
      return EntryEventImpl.deserialize(bytes);
    } else {
      return bytes;
    }
  }

  static int decodeAddressToDataSize(long addr) {
    if ((addr & ENCODED_BIT) == 0) {
      throw new AssertionError("Invalid address: " + addr);
    }
    boolean isLong = (addr & LONG_BIT) != 0;
    if (isLong) {
      return 9;
    }
    return (int) ((addr & SIZE_MASK) >> SIZE_SHIFT);
  }

  /**
   * Returns the bytes encoded in the given address. Note that compressed addresses are not
   * supported by this method.
   *
   * @throws UnsupportedOperationException if the address has compressed data
   */
  static byte[] decodeUncompressedAddressToBytes(long addr) {
    if ((addr & COMPRESSED_BIT) != 0) {
      throw new AssertionError("Did not expect encoded address to be compressed");
    }
    return decodeAddressToRawBytes(addr);
  }

  /**
   * Returns the "raw" bytes that have been encoded in the given address. Note that if address is
   * compressed then the raw bytes are the compressed bytes.
   */
  static byte[] decodeAddressToRawBytes(long addr) {
    if ((addr & ENCODED_BIT) == 0) {
      throw new AssertionError("Invalid address: " + addr);
    }
    int size = (int) ((addr & SIZE_MASK) >> SIZE_SHIFT);
    boolean isLong = (addr & LONG_BIT) != 0;
    byte[] bytes;
    if (isLong) {
      bytes = new byte[9];
      bytes[0] = DSCODE.LONG.toByte();
      for (int i = 8; i >= 2; i--) {
        addr >>= 8;
        bytes[i] = (byte) (addr & 0x00ff);
      }
      if ((bytes[2] & 0x80) != 0) {
        bytes[1] = -1;
      } else {
        bytes[1] = 0;
      }
    } else {
      bytes = new byte[size];
      for (int i = size - 1; i >= 0; i--) {
        addr >>= 8;
        bytes[i] = (byte) (addr & 0x00ff);
      }
    }
    return bytes;
  }

  /**
   * The previous value at the address in 're' will be @Released and then the address in 're' will
   * be set to the @Unretained address of 'v'.
   */
  public static void setValue(@Released OffHeapRegionEntry re, @Unretained Object v) {
    // setValue is called when synced so I don't need to worry
    // about oldAddress being released by someone else.
    final long newAddress = objectToAddress(v);
    long oldAddress;
    do {
      oldAddress = re.getAddress();
    } while (!re.setAddress(oldAddress, newAddress));
    ReferenceCountHelper.setReferenceCountOwner(re);
    releaseAddress(oldAddress);
    ReferenceCountHelper.setReferenceCountOwner(null);
  }

  public static Token getValueAsToken(@Unretained OffHeapRegionEntry re) {
    return addressToToken(re.getAddress());
  }

  @Unretained
  public static Object _getValue(@Unretained OffHeapRegionEntry re) {
    return addressToObject(re.getAddress(), false, null); // no context needed so decompress is
                                                          // false
  }

  public static boolean isOffHeap(long addr) {
    if ((addr & ENCODED_BIT) != 0)
      return false;
    if (addr < 0)
      return true;
    addr >>= 1; // shift right 1 to convert to array index;
    return addr >= addrToObj.length;
  }

  /**
   * If the value stored at the location held in 're' is returned, then it will be Retained. If the
   * value returned is 're' decompressed into another off-heap location, then 're' will be
   * Unretained but the new, decompressed value will be Retained. Therefore, whichever is returned
   * (the value at the address in 're' or the decompressed value) it will have been Retained.
   *
   * @return possible OFF_HEAP_OBJECT (caller must release)
   */
  @Retained
  public static Object _getValueRetain(@Retained @Unretained OffHeapRegionEntry re,
      boolean decompress, RegionEntryContext context) {
    int retryCount = 0;
    @Retained
    long addr = re.getAddress();
    while (isOffHeap(addr)) {
      if (OffHeapStoredObject.retain(addr)) {
        @Unretained
        long addr2 = re.getAddress();
        if (addr != addr2) {
          retryCount = 0;
          OffHeapStoredObject.release(addr);
          // spin around and try again.
          addr = addr2;
        } else {
          return addressToObject(addr, decompress, context);
        }
      } else {
        // spin around and try again
        long addr2 = re.getAddress();
        retryCount++;
        if (retryCount > 100) {
          throw new IllegalStateException("retain failed addr=" + addr + " addr2=" + addr
              + " 100 times" + " history=" + ReferenceCountHelper.getFreeRefCountInfo(addr));
        }
        addr = addr2;
        // Since retain returned false our region entry should have a different
        // value in it. However the actual address could be the exact same one
        // because addr was released, then reallocated from the free list and set
        // back into this region entry. See bug 47782
      }
    }
    return addressToObject(addr, decompress, context);
  }



  public static boolean isSerialized(long address) {
    return (address & SERIALIZED_BIT) != 0;
  }

  public static boolean isCompressed(long address) {
    return (address & COMPRESSED_BIT) != 0;
  }

  private static final ThreadLocal<Object> clearNeedsToCheckForOffHeap = new ThreadLocal<Object>();

  public static boolean doesClearNeedToCheckForOffHeap() {
    return clearNeedsToCheckForOffHeap.get() != null;
  }

  public static void doWithOffHeapClear(Runnable r) {
    clearNeedsToCheckForOffHeap.set(Boolean.TRUE);
    try {
      r.run();
    } finally {
      clearNeedsToCheckForOffHeap.remove();
    }
  }
}
