/******************************************************************************* * Copyright (c) 1998, 2015 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 v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * Oracle - initial API and implementation from Oracle TopLink ******************************************************************************/ package org.eclipse.persistence.internal.identitymaps; import java.util.*; import org.eclipse.persistence.descriptors.ClassDescriptor; import org.eclipse.persistence.internal.sessions.AbstractSession; /** * Unit of work specific identity map which avoid additional overhead not required in unit of work, * such as locking and synchronization. * @author James Sutherland * @since TopLink 10.1.3.1 */ public class UnitOfWorkIdentityMap extends FullIdentityMap { protected UnitOfWorkIdentityMap() { } public UnitOfWorkIdentityMap(int size, ClassDescriptor descriptor, AbstractSession session, boolean isolated) { super(); this.maxSize = size; // PERF: Use a HashMap as more efficient than a ConcurrentMap and single threaded. this.cacheKeys = new HashMap(size); this.descriptor = descriptor; this.session = session; this.isIsolated = isolated; } @Override public CacheKey createCacheKey(Object primaryKey, Object object, Object writeLockValue, long readTime) { return new CacheKey(primaryKey, object, writeLockValue, readTime, true); } /** * Avoid acquiring any lock as uow is single threaded. */ @Override public CacheKey acquireDeferredLock(Object primaryKey, boolean isCacheCheckComplete) { CacheKey cacheKey = getCacheKey(primaryKey, false); if (cacheKey == null) { CacheKey newCacheKey = createCacheKey(primaryKey, null, null, 0); cacheKey = putCacheKeyIfAbsent(newCacheKey); if (cacheKey == null) { return newCacheKey; } } return cacheKey; } /** * Avoid acquiring any lock as uow is single threaded. */ @Override public CacheKey acquireLock(Object primaryKey, boolean forMerge, boolean isCacheCheckComplete) { CacheKey cacheKey = getCacheKey(primaryKey, forMerge); if (cacheKey == null) { CacheKey newCacheKey = createCacheKey(primaryKey, null, null, 0); cacheKey = putCacheKeyIfAbsent(newCacheKey); if (cacheKey == null) { return newCacheKey; } } return cacheKey; } /** * Avoid acquiring any lock as uow is single threaded. */ @Override public CacheKey acquireLockNoWait(Object primaryKey, boolean forMerge) { CacheKey cacheKey = getCacheKey(primaryKey, forMerge); if (cacheKey == null) { CacheKey newCacheKey = createCacheKey(primaryKey, null, null, 0); cacheKey = putCacheKeyIfAbsent(newCacheKey); if (cacheKey == null) { return newCacheKey; } } return cacheKey; } /** * Avoid acquiring any lock as uow is single threaded. */ @Override public CacheKey acquireLockWithWait(Object primaryKey, boolean forMerge, int wait) { CacheKey cacheKey = getCacheKey(primaryKey, forMerge); if (cacheKey == null) { CacheKey newCacheKey = createCacheKey(primaryKey, null, null, 0); cacheKey = putCacheKeyIfAbsent(newCacheKey); if (cacheKey == null) { return newCacheKey; } } return cacheKey; } /** * Avoid acquiring any lock as uow is single threaded. */ @Override public CacheKey acquireReadLockOnCacheKey(Object primaryKey) { return acquireReadLockOnCacheKeyNoWait(primaryKey); } /** * Avoid acquiring any lock as uow is single threaded. */ @Override public CacheKey acquireReadLockOnCacheKeyNoWait(Object primaryKey) { CacheKey newCacheKey = createCacheKey(primaryKey, null, null, 0); CacheKey cacheKey = getCacheKey(newCacheKey, false); if (cacheKey == null) { return newCacheKey; } return cacheKey; } /** * Avoid acquiring any lock as uow is single threaded. */ @Override protected CacheKey getCacheKeyWithReadLock(Object primaryKey) { return getCacheKey(primaryKey, false); } /** * Use hashmap put, as no concurrency in unit of work. */ protected CacheKey putCacheKeyIfAbsent(CacheKey searchKey) { searchKey.setOwningMap(this); this.cacheKeys.put(searchKey.getKey(), searchKey); return null; } /** * Avoid acquiring any lock as uow is single threaded. */ @Override public Object remove(CacheKey cacheKey) { if (cacheKey != null) { this.cacheKeys.remove(cacheKey.getKey()); cacheKey.setOwningMap(null); } else { return null; } return cacheKey.getObject(); } /** * Avoid acquiring any lock as uow is single threaded. */ @Override public void resetCacheKey(CacheKey key, Object object, Object writeLockValue, long readTime) { key.setObject(object); key.setWriteLockValue(writeLockValue); key.setReadTime(readTime); } /** * Avoid acquiring any lock as uow is single threaded. */ @Override public void setWriteLockValue(Object primaryKey, Object writeLockValue) { CacheKey cacheKey = getCacheKeyForLock(primaryKey); if (cacheKey != null) { cacheKey.setWriteLockValue(writeLockValue); } } }