/*=========================================================================
 * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
 * This product is protected by U.S. and international copyright
 * and intellectual property laws. Pivotal products are covered by
 * one or more patents listed at http://www.pivotal.io/patents.
 *=========================================================================
 */
package com.gemstone.gemfire.internal.cache;
// DO NOT modify this class. It was generated from LeafRegionEntry.cpp
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
import com.gemstone.gemfire.internal.offheap.OffHeapRegionEntryHelper;
import com.gemstone.gemfire.internal.offheap.annotations.Released;
import com.gemstone.gemfire.internal.offheap.annotations.Retained;
import com.gemstone.gemfire.internal.offheap.annotations.Unretained;
import com.gemstone.gemfire.internal.util.concurrent.CustomEntryConcurrentHashMap.HashEntry;
// macros whose definition changes this class:
// disk: DISK
// lru: LRU
// stats: STATS
// versioned: VERSIONED
// offheap: OFFHEAP
// One of the following key macros must be defined:
// key object: KEY_OBJECT
// key int: KEY_INT
// key long: KEY_LONG
// key uuid: KEY_UUID
// key string1: KEY_STRING1
// key string2: KEY_STRING2
/**
 * Do not modify this class. It was generated.
 * Instead modify LeafRegionEntry.cpp and then run
 * bin/generateRegionEntryClasses.sh from the directory
 * that contains your build.xml.
 */
public class VMThinRegionEntryOffHeapStringKey1 extends VMThinRegionEntryOffHeap {
  public VMThinRegionEntryOffHeapStringKey1 (RegionEntryContext context, String key,
      @Retained
      Object value
      , boolean byteEncode
      ) {
    super(context,
          value
        );
    // DO NOT modify this class. It was generated from LeafRegionEntry.cpp
    // caller has already confirmed that key.length <= MAX_INLINE_STRING_KEY
    long tmpBits1 = 0L;
    if (byteEncode) {
      for (int i=key.length()-1; i >= 0; i--) {
        // Note: we know each byte is <= 0x7f so the "& 0xff" is not needed. But I added it in to keep findbugs happy.
        tmpBits1 |= (byte)key.charAt(i) & 0xff;
        tmpBits1 <<= 8;
      }
      tmpBits1 |= 1<<6;
    } else {
      for (int i=key.length()-1; i >= 0; i--) {
        tmpBits1 |= key.charAt(i);
        tmpBits1 <<= 16;
      }
    }
    tmpBits1 |= key.length();
    this.bits1 = tmpBits1;
  }
  // DO NOT modify this class. It was generated from LeafRegionEntry.cpp
  // common code
  protected int hash;
  private HashEntry<Object, Object> next;
  @SuppressWarnings("unused")
  private volatile long lastModified;
  private static final AtomicLongFieldUpdater<VMThinRegionEntryOffHeapStringKey1> lastModifiedUpdater
    = AtomicLongFieldUpdater.newUpdater(VMThinRegionEntryOffHeapStringKey1.class, "lastModified");
  /**
   * All access done using ohAddrUpdater so it is used even though the compiler can not tell it is.
   */
  @SuppressWarnings("unused")
  @Retained @Released private volatile long ohAddress;
  /**
   * I needed to add this because I wanted clear to call setValue which normally can only be called while the re is synced.
   * But if I sync in that code it causes a lock ordering deadlock with the disk regions because they also get a rw lock in clear.
   * Some hardware platforms do not support CAS on a long. If gemfire is run on one of those the AtomicLongFieldUpdater does a sync
   * on the re and we will once again be deadlocked.
   * I don't know if we support any of the hardware platforms that do not have a 64bit CAS. If we do then we can expect deadlocks
   * on disk regions.
   */
  private final static AtomicLongFieldUpdater<VMThinRegionEntryOffHeapStringKey1> ohAddrUpdater = AtomicLongFieldUpdater.newUpdater(VMThinRegionEntryOffHeapStringKey1.class, "ohAddress");
  @Override
  public Token getValueAsToken() {
    return OffHeapRegionEntryHelper.getValueAsToken(this);
  }
  @Override
  protected Object getValueField() {
    return OffHeapRegionEntryHelper._getValue(this);
  }
  // DO NOT modify this class. It was generated from LeafRegionEntry.cpp
  @Override
  @Unretained
  protected void setValueField(@Unretained Object v) {
    OffHeapRegionEntryHelper.setValue(this, v);
  }
  @Override
  @Retained
  public Object _getValueRetain(RegionEntryContext context, boolean decompress) {
    return OffHeapRegionEntryHelper._getValueRetain(this, decompress, context);
  }
  @Override
  public long getAddress() {
    return ohAddrUpdater.get(this);
  }
  @Override
  public boolean setAddress(long expectedAddr, long newAddr) {
    return ohAddrUpdater.compareAndSet(this, expectedAddr, newAddr);
  }
  @Override
  @Released
  public void release() {
    OffHeapRegionEntryHelper.releaseEntry(this);
  }
  @Override
  public void returnToPool() {
    // Deadcoded for now; never was working
//    if (this instanceof VMThinRegionEntryLongKey) {
//      factory.returnToPool((VMThinRegionEntryLongKey)this);
//    }
  }
  protected long getlastModifiedField() {
    return lastModifiedUpdater.get(this);
  }
  protected boolean compareAndSetLastModifiedField(long expectedValue, long newValue) {
    return lastModifiedUpdater.compareAndSet(this, expectedValue, newValue);
  }
  /**
   * @see HashEntry#getEntryHash()
   */
  public final int getEntryHash() {
    return this.hash;
  }
  protected void setEntryHash(int v) {
    this.hash = v;
  }
  /**
   * @see HashEntry#getNextEntry()
   */
  public final HashEntry<Object, Object> getNextEntry() {
    return this.next;
  }
  /**
   * @see HashEntry#setNextEntry
   */
  public final void setNextEntry(final HashEntry<Object, Object> n) {
    this.next = n;
  }
  // DO NOT modify this class. It was generated from LeafRegionEntry.cpp
  // key code
  private final long bits1;
  private int getKeyLength() {
    return (int) (this.bits1 & 0x003fL);
  }
  private int getEncoding() {
    // 0 means encoded as char
    // 1 means encoded as bytes that are all <= 0x7f;
    return (int) (this.bits1 >> 6) & 0x03;
  }
  @Override
  public final Object getKey() {
    int keylen = getKeyLength();
    char[] chars = new char[keylen];
    long tmpBits1 = this.bits1;
    if (getEncoding() == 1) {
      for (int i=0; i < keylen; i++) {
        tmpBits1 >>= 8;
      chars[i] = (char) (tmpBits1 & 0x00ff);
      }
    } else {
      for (int i=0; i < keylen; i++) {
        tmpBits1 >>= 16;
        chars[i] = (char) (tmpBits1 & 0x00FFff);
      }
    }
    return new String(chars);
  }
  // DO NOT modify this class. It was generated from LeafRegionEntry.cpp
  @Override
  public boolean isKeyEqual(Object k) {
    if (k instanceof String) {
      String str = (String)k;
      int keylen = getKeyLength();
      if (str.length() == keylen) {
        long tmpBits1 = this.bits1;
        if (getEncoding() == 1) {
          for (int i=0; i < keylen; i++) {
            tmpBits1 >>= 8;
            char c = (char) (tmpBits1 & 0x00ff);
            if (str.charAt(i) != c) {
              return false;
            }
          }
        } else {
          for (int i=0; i < keylen; i++) {
            tmpBits1 >>= 16;
            char c = (char) (tmpBits1 & 0x00FFff);
            if (str.charAt(i) != c) {
              return false;
            }
          }
        }
        return true;
      }
    }
    return false;
  }
  // DO NOT modify this class. It was generated from LeafRegionEntry.cpp
}
