All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.geode.internal.cache.lru.LRUAlgorithm Maven / Gradle / Ivy

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

import org.apache.geode.InternalGemFireException;
import org.apache.geode.StatisticsFactory;
import org.apache.geode.cache.*;
import org.apache.geode.internal.cache.BucketRegion;
import org.apache.geode.internal.cache.PlaceHolderDiskRegion;
import org.apache.geode.internal.i18n.LocalizedStrings;

import java.io.*;
import java.util.*;

/**
 * Eviction controllers that extend this class evict the least recently used (LRU) entry in the
 * region whose capacity they controller. In order to provide an efficient computation of the LRU
 * entry, GemFire uses special internal data structures for managing the contents of a region. As a
 * result, there are several restrictions that are placed on regions whose capacity is governed by
 * an LRU algorithm.
 *
 * 
    * *
  • If the capacity of a region is to be controlled by an LRU algorithm, then the region must be * created with {@link org.apache.geode.cache.EvictionAttributes} * *
  • The eviction controller of a region governed by an LRU algorithm cannot be changed.
  • * *
  • An LRU algorithm cannot be applied to a region after the region has been created.
  • * *
* * LRU algorithms also specify what {@linkplain org.apache.geode.cache.EvictionAction action} should * be performed upon the least recently used entry when the capacity is reached. Currently, there * are two supported actions: {@linkplain org.apache.geode.cache.EvictionAction#LOCAL_DESTROY * locally destroying} the entry (which is the * {@linkplain org.apache.geode.cache.EvictionAction#DEFAULT_EVICTION_ACTION default}), thus freeing * up space in the VM, and {@linkplain org.apache.geode.cache.EvictionAction#OVERFLOW_TO_DISK * overflowing} the value of the entry to disk. * *

* * {@link org.apache.geode.cache.EvictionAttributes Eviction controllers} that use an LRU algorithm * maintain certain region-dependent state (such as the maximum number of entries allowed in the * region). As a result, an instance of LRUAlgorithm cannot be shared among multiple * regions. Attempts to create a region with a LRU-based capacity controller that has already been * used to create another region will result in an {@link IllegalStateException} being thrown. * * @since GemFire 3.2 */ public abstract class LRUAlgorithm implements CacheCallback, Serializable, Cloneable { /** * The key for setting the eviction-action property of an LRUAlgorithm */ public static final String EVICTION_ACTION = "eviction-action"; //////////////////////// Instance Fields /////////////////////// /** What to do upon eviction */ protected EvictionAction evictionAction; /** Used to dynamically track the changing region limit. */ protected transient LRUStatistics stats; /** The helper created by this LRUAlgorithm */ private transient EnableLRU helper; protected BucketRegion bucketRegion; ///////////////////////// Constructors ///////////////////////// /** * Creates a new LRUAlgorithm with the given {@linkplain EvictionAction eviction * action}. */ protected LRUAlgorithm(EvictionAction evictionAction, Region region) { bucketRegion = (BucketRegion) (region instanceof BucketRegion ? region : null); setEvictionAction(evictionAction); this.helper = createLRUHelper(); } /////////////////////// Instance Methods /////////////////////// /** * Used to hook up a bucketRegion late during disk recover. */ public void setBucketRegion(Region r) { if (r instanceof BucketRegion) { this.bucketRegion = (BucketRegion) r; this.bucketRegion.setLimit(getLimit()); } } /** * Sets the action that is performed on the least recently used entry when it is evicted from the * VM. * * @throws IllegalArgumentException If evictionAction specifies an unknown eviction * action. * * @see EvictionAction */ protected void setEvictionAction(EvictionAction evictionAction) { this.evictionAction = evictionAction; } /** * Gets the action that is performed on the least recently used entry when it is evicted from the * VM. * * @return one of the following constants: {@link EvictionAction#LOCAL_DESTROY}, * {@link EvictionAction#OVERFLOW_TO_DISK} */ public EvictionAction getEvictionAction() { return this.evictionAction; } /** * For internal use only. Returns a helper object used internally by the GemFire cache * implementation. */ public final EnableLRU getLRUHelper() { synchronized (this) { // Synchronize with readObject/writeObject to avoid race // conditions with copy sharing. See bug 31047. return this.helper; } } private void writeObject(java.io.ObjectOutputStream out) throws IOException { synchronized (this) { // See bug 31047 out.writeObject(this.evictionAction); } } private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { synchronized (this) { // See bug 31047 this.evictionAction = (EvictionAction) in.readObject(); this.helper = createLRUHelper(); } } // public void writeExternal(ObjectOutput out) // throws IOException { // out.writeObject(this.evictionAction); // } // public void readExternal(ObjectInput in) // throws IOException, ClassNotFoundException { // String evictionAction = (String) in.readObject(); // this.setEvictionAction(evictionAction); // } // protected Object readResolve() throws ObjectStreamException { // if (this.helper == null) { // this.helper = createLRUHelper(); // } // return this; // } /** * Creates a new LRUHelper tailed for this LRU algorithm implementation. */ protected abstract EnableLRU createLRUHelper(); /** * Returns the "limit" as defined by this LRU algorithm */ public abstract long getLimit(); /** * Set the limiting parameter used to determine when eviction is needed. */ public abstract void setLimit(int maximum); /** * This method is an artifact when eviction controllers used to called capacity controllers and * were configured in the cache.xml file as Declarable * * @since GemFire 4.1.1 */ public abstract Properties getProperties(); /** * Releases resources obtained by this LRUAlgorithm */ public void close() { if (this.stats != null) { if (bucketRegion != null) { this.stats.incEvictions(bucketRegion.getEvictions() * -1); this.stats.decrementCounter(bucketRegion.getCounter()); bucketRegion.close(); } else { this.stats.close(); } } } /** * Returns a copy of this LRU-based eviction controller. This method is a artifact when capacity * controllers were used on a Region */ @Override public Object clone() throws CloneNotSupportedException { synchronized (this) { LRUAlgorithm clone = (LRUAlgorithm) super.clone(); clone.stats = null; synchronized (clone) { clone.helper = clone.createLRUHelper(); } return clone; } } /** * Return true if the specified capacity controller is compatible with this */ @Override public boolean equals(Object cc) { if (cc == null) return false; if (!getClass().isAssignableFrom(cc.getClass())) return false; LRUAlgorithm other = (LRUAlgorithm) cc; if (!other.evictionAction.equals(this.evictionAction)) return false; return true; } /* * (non-Javadoc) * * @see java.lang.Object#hashCode() * * Note that we just need to make sure that equal objects return equal hashcodes; nothing really * elaborate is done here. */ @Override public int hashCode() { return this.evictionAction.hashCode(); } /** * Force subclasses to have a reasonable toString * * @since GemFire 4.0 */ @Override public abstract String toString(); ////////////////////// Inner Classes ////////////////////// /** * A partial implementation of the EnableLRU interface that contains code common to * all LRUAlgorithms. */ protected abstract class AbstractEnableLRU implements EnableLRU { /** The region whose capacity is controller by this eviction controller */ private volatile transient String regionName; public long limit() { if (stats == null) { throw new InternalGemFireException( LocalizedStrings.LRUAlgorithm_LRU_STATS_IN_EVICTION_CONTROLLER_INSTANCE_SHOULD_NOT_BE_NULL .toLocalizedString()); } if (bucketRegion != null) { return bucketRegion.getLimit(); } return stats.getLimit(); } public String getRegionName() { return this.regionName; } public void setRegionName(Object region) { String fullPathName; if (region instanceof Region) { fullPathName = ((Region) region).getFullPath(); } else if (region instanceof PlaceHolderDiskRegion) { PlaceHolderDiskRegion phdr = (PlaceHolderDiskRegion) region; if (phdr.isBucket()) { fullPathName = phdr.getPrName(); } else { fullPathName = phdr.getName(); } } else { throw new IllegalStateException("expected Region or PlaceHolderDiskRegion"); } if (this.regionName != null && !this.regionName.equals(fullPathName)) { throw new IllegalArgumentException( LocalizedStrings.LRUAlgorithm_LRU_EVICTION_CONTROLLER_0_ALREADY_CONTROLS_THE_CAPACITY_OF_1_IT_CANNOT_ALSO_CONTROL_THE_CAPACITY_OF_REGION_2 .toLocalizedString( new Object[] {LRUAlgorithm.this, this.regionName, fullPathName})); } this.regionName = fullPathName; // store the name not the region since // region is not fully constructed yet } protected void setStats(LRUStatistics stats) { LRUAlgorithm.this.stats = stats; } public LRUStatistics initStats(Object region, StatisticsFactory sf) { setRegionName(region); final LRUStatistics stats = new LRUStatistics(sf, getRegionName(), this); stats.setLimit(LRUAlgorithm.this.getLimit()); stats.setDestroysLimit(1000); setStats(stats); return stats; } public LRUStatistics getStats() { return LRUAlgorithm.this.stats; } public EvictionAction getEvictionAction() { return LRUAlgorithm.this.evictionAction; } public void afterEviction() { // Do nothing } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy