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

/**
 * EntryExpiryTask represents a timeout event for a region entry.
 */

import java.util.concurrent.locks.Lock;

import org.apache.logging.log4j.Logger;

import org.apache.geode.annotations.internal.MutableForTesting;
import org.apache.geode.cache.CacheException;
import org.apache.geode.cache.EntryDestroyedException;
import org.apache.geode.cache.EntryNotFoundException;
import org.apache.geode.cache.ExpirationAction;
import org.apache.geode.cache.ExpirationAttributes;
import org.apache.geode.cache.Operation;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.TimeoutException;
import org.apache.geode.distributed.internal.DistributionConfig;
import org.apache.geode.internal.InternalStatisticsDisabledException;
import org.apache.geode.internal.lang.SystemPropertyHelper;
import org.apache.geode.internal.logging.LogService;
import org.apache.geode.internal.offheap.annotations.Released;

public class EntryExpiryTask extends ExpiryTask {

  private static final Logger logger = LogService.getLogger();
  /**
   * The region entry we are working with
   */
  private RegionEntry re; // not final so cancel can null it out see bug 37574

  /*
   * This was added to accommodate a session replication requirement where an empty client has a
   * need to access the expired entry so that additional processing can be performed on it.
   *
   * This field is nether private nor final so that dunits can manipulate it as necessary.
   */
  @MutableForTesting
  public static boolean expireSendsEntryAsCallback =
      Boolean.getBoolean(DistributionConfig.GEMFIRE_PREFIX + "EXPIRE_SENDS_ENTRY_AS_CALLBACK");

  protected EntryExpiryTask(LocalRegion region, RegionEntry re) {
    super(region);
    this.re = re;
  }

  @Override
  protected ExpirationAttributes getTTLAttributes() {
    return getLocalRegion().getAttributes().getEntryTimeToLive();
  }

  @Override
  protected ExpirationAttributes getIdleAttributes() {
    return getLocalRegion().getAttributes().getEntryIdleTimeout();
  }

  protected RegionEntry getRegionEntry() {
    return this.re;
  }

  /**
   * Returns the tasks region entry if it "checks" out. The check is to see if the region entry
   * still exists.
   *
   * @throws EntryNotFoundException if the task no longer has a region entry or if the region entry
   *         it has is removed.
   */
  protected RegionEntry getCheckedRegionEntry() throws EntryNotFoundException {
    RegionEntry result = this.re;
    if (re == null || re.isDestroyedOrRemoved()) {
      throw new EntryNotFoundException("expiration task no longer has access to region entry");
    }
    return result;
  }

  @Override
  protected long getLastAccessedTime() throws EntryNotFoundException {
    RegionEntry re = getCheckedRegionEntry();
    try {
      return re.getLastAccessed();
    } catch (InternalStatisticsDisabledException e) {
      return 0;
    }
  }

  @Override
  protected long getLastModifiedTime() throws EntryNotFoundException {
    return getCheckedRegionEntry().getLastModified();
  }

  private Object getValueForCallback(LocalRegion r, Object k) {
    Region.Entry<?, ?> e = r.getEntry(k);
    return (e != null) ? e.getValue() : null;
  }

  private Object createExpireEntryCallback(LocalRegion r, Object k) {
    return expireSendsEntryAsCallback ? getValueForCallback(r, k) : null;
  }

  @Override
  protected boolean destroy(boolean isPending) throws CacheException {
    RegionEntry re = getCheckedRegionEntry();
    Object key = re.getKey();
    LocalRegion lr = getLocalRegion();
    @Released
    EntryEventImpl event = EntryEventImpl.create(lr, Operation.EXPIRE_DESTROY, key, null,
        createExpireEntryCallback(lr, key), false, lr.getMyId());
    try {
      event.setPendingSecondaryExpireDestroy(isPending);
      if (lr.generateEventID()) {
        event.setNewEventId(lr.getCache().getDistributedSystem());
      }
      lr.expireDestroy(event, true); // expectedOldValue
      return true;
    } finally {
      event.release();
    }
  }

  @Override
  protected boolean invalidate() throws TimeoutException, EntryNotFoundException {
    RegionEntry re = getCheckedRegionEntry();
    Object key = re.getKey();
    LocalRegion lr = getLocalRegion();
    @Released
    EntryEventImpl event = EntryEventImpl.create(lr, Operation.EXPIRE_INVALIDATE, key, null,
        createExpireEntryCallback(lr, key), false, lr.getMyId());
    try {
      if (lr.generateEventID()) {
        event.setNewEventId(lr.getCache().getDistributedSystem());
      }
      lr.expireInvalidate(event);
    } finally {
      event.release();
    }
    return true;
  }

  @Override
  protected boolean localDestroy() throws CacheException {
    RegionEntry re = getCheckedRegionEntry();
    Object key = re.getKey();
    LocalRegion lr = getLocalRegion();
    @Released
    EntryEventImpl event = EntryEventImpl.create(lr, Operation.EXPIRE_LOCAL_DESTROY, key, null,
        createExpireEntryCallback(lr, key), false, lr.getMyId());
    try {
      if (lr.generateEventID()) {
        event.setNewEventId(lr.getCache().getDistributedSystem());
      }
      lr.expireDestroy(event, false); // expectedOldValue
    } finally {
      event.release();
    }
    return true;
  }

  @Override
  protected boolean localInvalidate() throws EntryNotFoundException {
    RegionEntry re = getCheckedRegionEntry();
    Object key = re.getKey();
    LocalRegion lr = getLocalRegion();
    @Released
    EntryEventImpl event = EntryEventImpl.create(lr, Operation.EXPIRE_LOCAL_INVALIDATE, key, null,
        createExpireEntryCallback(lr, key), false, lr.getMyId());
    try {
      if (lr.generateEventID()) {
        event.setNewEventId(lr.getCache().getDistributedSystem());
      }
      lr.expireInvalidate(event);
    } finally {
      event.release();
    }
    return true;
  }

  @Override
  protected void reschedule() throws CacheException {
    if (isCacheClosing() || getLocalRegion().isClosed() || getLocalRegion().isDestroyed()
        || !isExpirationAllowed()) {
      return;
    }
    if (getExpirationTime() > 0) {
      addExpiryTask();
      if (expiryTaskListener != null) {
        expiryTaskListener.afterReschedule(this);
      }
    }
  }

  @Override
  protected void addExpiryTask() throws EntryNotFoundException {
    getLocalRegion().addExpiryTask(getCheckedRegionEntry());
  }

  @Override
  public String toString() {
    String result = super.toString();
    RegionEntry re = this.re;
    if (re != null) {
      result += ", " + re.getKey();
    }
    return result;
  }

  @Override
  protected void performTimeout() throws CacheException {
    // remove the task from the region's map first thing
    // so the next call to addExpiryTaskIfAbsent will
    // add a new task instead of doing nothing, which would
    // erroneously cancel expiration for this key.
    getLocalRegion().cancelExpiryTask(this.re, this);
    getLocalRegion().performExpiryTimeout(this);
  }

  @Override
  public boolean isPending() {
    RegionEntry re = this.re;
    if (re == null) {
      return false;
    }
    if (re.isDestroyedOrRemoved()) {
      return false;
    }
    ExpirationAction action = getAction();
    if (action == null) {
      return false;
    }
    if ((action.isInvalidate() || action.isLocalInvalidate()) && re.isInvalid()) {
      return false;
    }
    return true;
  }

  @Override
  protected ExpirationAction getAction() {
    long ttl = getTTLAttributes().getTimeout();
    long idle = getIdleAttributes().getTimeout();
    ExpirationAction action;
    if (ttl == 0) {
      action = getIdleAttributes().getAction();
    } else if (idle != 0 && idle < ttl) {
      action = getIdleAttributes().getAction();
    } else {
      action = getTTLAttributes().getAction();
    }
    return action;
  }

  @Override
  protected boolean isIdleExpiredOnOthers() throws EntryNotFoundException {
    if (getIdleAttributes().getTimeout() <= 0L) {
      // idle expiration is not being used
      return true;
    }
    if (getIdleAttributes().getAction().isLocal()) {
      // no need to consult with others if using a local action
      return true;
    }
    if (SystemPropertyHelper.restoreIdleExpirationBehavior()) {
      return true;
    }

    long latestLastAccessTime = getLatestLastAccessTimeOnOtherMembers();
    if (latestLastAccessTime > getLastAccessedTime()) {
      setLastAccessedTime(latestLastAccessTime);
      return false;
    }
    return true;
  }

  private long getLatestLastAccessTimeOnOtherMembers() {
    return getLocalRegion().getLatestLastAccessTimeFromOthers(getKey());
  }

  private void setLastAccessedTime(long lastAccessedTime) throws EntryNotFoundException {
    RegionEntry re = getCheckedRegionEntry();
    re.setLastAccessed(lastAccessedTime);
  }

  /**
   * Called by LocalRegion#performExpiryTimeout
   */
  @Override
  protected void basicPerformTimeout(boolean isPending) throws CacheException {
    if (!isExpirationAllowed()) {
      return;
    }
    if (!isExpirationPossible()) {
      reschedule();
      return;
    }
    // Need to figure out why it expired - ttl, or idle timeout?
    ExpirationAction action;
    long ttl = getTTLAttributes().getTimeout();
    long idle = getIdleAttributes().getTimeout();
    if (ttl == 0) {
      action = getIdleAttributes().getAction();
    } else if (idle != 0 && idle < ttl) {
      action = getIdleAttributes().getAction();
    } else {
      action = getTTLAttributes().getAction();
    }
    // if global scope get distributed lock for destroy and invalidate actions
    if (getLocalRegion().getScope().isGlobal() && (action.isDestroy() || action.isInvalidate())) {
      Lock lock = getLocalRegion().getDistributedLock(getCheckedRegionEntry().getKey());
      lock.lock();
      try {
        long expTime = getExpirationTime();
        if (expTime == 0L) {
          return;
        }
        if (getNow() >= expTime) {
          if (logger.isTraceEnabled()) {
            // NOTE: original finer message used this.toString() twice
            logger.trace(
                "{}.performTimeout().getExpirationTime() is {}; {}.expire({}). ttlExpiration: {}, idleExpiration: {}, ttlAttrs: {}, idleAttrs: {} action is: {}",
                this, expTime, this, action, ttl, idle, getTTLAttributes(), getIdleAttributes());
          }
          expire(action, isPending);
          return;
        }
      } finally {
        lock.unlock();
      }
    } else {
      if (logger.isTraceEnabled()) {
        logger.trace("{}..performTimeout().getExpirationTime() is {}", this, getExpirationTime());
      }
      expire(isPending);
      return;
    }
    reschedule();
  }

  @Override
  public Object getKey() {
    RegionEntry entry = this.re;
    if (entry == null) {
      throw new EntryDestroyedException();
    }
    return entry.getKey();
  }

  @Override
  public boolean cancel() {
    boolean superCancel = super.cancel();
    if (superCancel) {
      this.re = null;
      if (expiryTaskListener != null) {
        expiryTaskListener.afterCancel(this);
      }
    }
    return superCancel;
  }

}
