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

org.eclipse.persistence.internal.identitymaps.CacheIdentityMap Maven / Gradle / Ivy

There is a newer version: 5.0.0-B03
Show newest version
/*
 * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.internal.identitymaps;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.internal.sessions.AbstractSession;

/**
 * 

Purpose: A fixed size LRU cache

* Using a linked list as well as the map from the superclass a LRU cache is maintained. * When a get is executed the LRU list is updated and when a new object is inserted the object * at the start of the list is deleted (provided the maxSize has been reached). *

Responsibilities:

    *
  • Guarantees identity through primary key values *
  • Keeps the LRU linked list updated. *
* @since TOPLink/Java 1.0 */ public class CacheIdentityMap extends FullIdentityMap { /** Provide handles on the linked list */ protected LinkedCacheKey first; /** Provide handles on the linked list */ protected LinkedCacheKey last; public CacheIdentityMap(int size, ClassDescriptor descriptor, AbstractSession session, boolean isolated) { super(size, descriptor, session, isolated); this.first = new LinkedCacheKey(CacheId.EMPTY, null, null, 0, isIsolated); this.last = new LinkedCacheKey(CacheId.EMPTY, null, null, 0, isIsolated); this.first.setNext(this.last); this.last.setPrevious(this.first); } @Override public CacheKey createCacheKey(Object primaryKey, Object object, Object writeLockValue, long readTime) { return new LinkedCacheKey(primaryKey, object, writeLockValue, readTime, isIsolated); } /** * Reduces the size of the receiver down to the maxSize removing objects from the * start of the linked list. */ protected void ensureFixedSize() { // protect the case where someone attempts to break the cache by // setting max size to 0. synchronized(this.first) { while (getMaxSize() > 0 && getSize() > getMaxSize()) { remove(last.getPrevious()); } } } /** * Access the object within the table for the given primaryKey. * Move the accessed key to the top of the order keys linked list to maintain LRU. * @param primaryKeys is the primary key for the object to search for. * @return the LinkedCacheKey or null if none found for primaryKey */ @Override public CacheKey getCacheKey(Object primaryKeys, boolean forMerge) { LinkedCacheKey cacheKey = (LinkedCacheKey)super.getCacheKey(primaryKeys, forMerge); if (cacheKey != null) { synchronized (this.first) { removeLink(cacheKey); insertLink(cacheKey); } } return cacheKey; } /** * Insert a new element into the linked list of LinkedCacheKeys. * New elements (Recently Used) are added at the end (last). * Callers of this method must synchronize on the start of the list (this.first). * @return the added LinkedCacheKey */ protected LinkedCacheKey insertLink(LinkedCacheKey key) { if (key == null){ return key; } this.first.getNext().setPrevious(key); key.setNext(this.first.getNext()); key.setPrevious(this.first); this.first.setNext(key); return key; } /** * Also insert the link if the cacheKey is put. */ @Override protected CacheKey putCacheKeyIfAbsent(CacheKey searchKey) { synchronized(this.first) { CacheKey cacheKey = super.putCacheKeyIfAbsent(searchKey); if (cacheKey == null) { insertLink((LinkedCacheKey)searchKey); ensureFixedSize(); } return cacheKey; } } /** * Remove the LinkedCacheKey from the cache as well as from the linked list. * @return the LinkedCacheKey to be removed. */ @Override public Object remove(CacheKey key) { synchronized (this.first) { super.remove(key); // The key may be null if was missing, just null should be returned in this case. if (key == null) { return null; } return removeLink((LinkedCacheKey)key).getObject(); } } /** * Remove the LinkedCacheKey from the linked list. * Callers of this method must synchronize on the start of the list (this.first). * @return the removed LinkedCacheKey. */ protected LinkedCacheKey removeLink(LinkedCacheKey key) { // callers of this method must be synchronized on this.first if (key == null || key.getPrevious() == null || key.getNext() == null){ //already removed by a competing thread, just return return key; } key.getPrevious().setNext(key.getNext()); key.getNext().setPrevious(key.getPrevious()); key.setNext(null); key.setPrevious(null); return key; } /** * INTERNAL: * This method will be used to update the max cache size, any objects exceeding the max cache size will * be remove from the cache. Please note that this does not remove the object from the identityMap, except in * the case of the CacheIdentityMap. */ @Override public synchronized void updateMaxSize(int maxSize) { setMaxSize(maxSize); ensureFixedSize(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy