ttomcat-1778514358873.zip-extract/apache-tomcat-11.0.18-src/java/org/apache/tomcat/dbcp/pool2/impl/SoftReferenceObjectPool.java

Path
ttomcat-1778514358873.zip-extract/apache-tomcat-11.0.18-src/java/org/apache/tomcat/dbcp/pool2/impl/SoftReferenceObjectPool.java
Status
scanned
Type
file
Name
SoftReferenceObjectPool.java
Extension
.java
Programming language
Java
Mime type
text/plain
File type
ASCII text, with CRLF line terminators
Tag

      
    
Rootfs path

      
    
Size
16541 (16.2 KB)
MD5
476b26c37f3bc777847dfaeb9a35a7e0
SHA1
002f2d075554758d6d1ec4d640018088b8404834
SHA256
2c32c43ccd82cfa456295a8c4056dd2236b672581bcb4369af58ae3cf834da86
SHA512

      
    
SHA1_git
9ebd572e7de1361be628cd3d3c7a853c9de62a00
Is binary

      
    
Is text
True
Is archive

      
    
Is media

      
    
Is legal

      
    
Is manifest

      
    
Is readme

      
    
Is top level

      
    
Is key file

      
    
SoftReferenceObjectPool.java | 16.2 KB |

/* * 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 * * https://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.tomcat.dbcp.pool2.impl; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; import java.util.ArrayList; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Optional; import java.util.concurrent.BlockingDeque; import org.apache.tomcat.dbcp.pool2.BaseObjectPool; import org.apache.tomcat.dbcp.pool2.ObjectPool; import org.apache.tomcat.dbcp.pool2.PoolUtils; import org.apache.tomcat.dbcp.pool2.PooledObjectFactory; /** * A {@link java.lang.ref.SoftReference SoftReference} based {@link ObjectPool}. * <p> * This class is intended to be thread-safe. * </p> * * @param <T> * Type of element pooled in this pool. * * @since 2.0 */ public class SoftReferenceObjectPool<T> extends BaseObjectPool<T> { /** Factory to source pooled objects */ private final PooledObjectFactory<T> factory; /** * Queue of broken references that might be able to be removed from * {@code _pool}. This is used to help {@link #getNumIdle()} be more * accurate with minimal performance overhead. */ private final ReferenceQueue<T> refQueue = new ReferenceQueue<>(); /** Count of instances that have been checkout out to pool clients */ private int numActive; // @GuardedBy("this") /** Total number of instances that have been destroyed */ private long destroyCount; // @GuardedBy("this") /** Total number of instances that have been created */ private long createCount; // @GuardedBy("this") /** Idle references - waiting to be borrowed */ private final BlockingDeque<PooledSoftReference<T>> idleReferences = new LinkedBlockingDeque<>(); /** All references - checked out or waiting to be borrowed. */ private final ArrayList<PooledSoftReference<T>> allReferences = new ArrayList<>(); /** * Constructs a {@code SoftReferenceObjectPool} with the specified factory. * * @param factory object factory to use. */ public SoftReferenceObjectPool(final PooledObjectFactory<T> factory) { this.factory = factory; } /** * Creates an object, and places it into the pool. addObject() is useful for * "pre-loading" a pool with idle objects. * <p> * Before being added to the pool, the newly created instance is * {@link PooledObjectFactory#validateObject( * org.apache.tomcat.dbcp.pool2.PooledObject) validated} and * {@link PooledObjectFactory#passivateObject( * org.apache.tomcat.dbcp.pool2.PooledObject) passivated}. If * validation fails, the new instance is * {@link PooledObjectFactory#destroyObject( * org.apache.tomcat.dbcp.pool2.PooledObject) destroyed}. Exceptions * generated by the factory {@code makeObject} or * {@code passivate} are propagated to the caller. Exceptions * destroying instances are silently swallowed. * </p> * * @throws IllegalStateException * if invoked on a {@link #close() closed} pool * @throws Exception * when the {@link #getFactory() factory} has a problem creating * or passivating an object. */ @Override public synchronized void addObject() throws Exception { assertOpen(); if (factory == null) { throw new IllegalStateException( "Cannot add objects without a factory."); } final T obj = factory.makeObject().getObject(); createCount++; // Create and register with the queue final PooledSoftReference<T> ref = new PooledSoftReference<>( new SoftReference<>(obj, refQueue)); allReferences.add(ref); boolean success = true; if (!factory.validateObject(ref)) { success = false; } else { factory.passivateObject(ref); } final boolean shouldDestroy = !success; if (success) { idleReferences.add(ref); notifyAll(); // numActive has changed } if (shouldDestroy) { try { destroy(ref); } catch (final Exception ignored) { // ignored } } } /** * Borrows an object from the pool. If there are no idle instances available * in the pool, the configured factory's * {@link PooledObjectFactory#makeObject()} method is invoked to create a * new instance. * <p> * All instances are {@link PooledObjectFactory#activateObject( * org.apache.tomcat.dbcp.pool2.PooledObject) activated} * and {@link PooledObjectFactory#validateObject( * org.apache.tomcat.dbcp.pool2.PooledObject) * validated} before being returned by this method. If validation fails or * an exception occurs activating or validating an idle instance, the * failing instance is {@link PooledObjectFactory#destroyObject( * org.apache.tomcat.dbcp.pool2.PooledObject) * destroyed} and another instance is retrieved from the pool, validated and * activated. This process continues until either the pool is empty or an * instance passes validation. If the pool is empty on activation or it does * not contain any valid instances, the factory's {@code makeObject} * method is used to create a new instance. If the created instance either * raises an exception on activation or fails validation, * {@code NoSuchElementException} is thrown. Exceptions thrown by * {@code MakeObject} are propagated to the caller; but other than * {@code VirtualMachineError}, exceptions * generated by activation, validation or destroy methods are swallowed * silently. * </p> * * @throws NoSuchElementException * if a valid object cannot be provided * @throws IllegalStateException * if invoked on a {@link #close() closed} pool * @throws Exception * if an exception occurs creating a new instance * @return a valid, activated object instance */ @SuppressWarnings("null") // ref cannot be null @Override public synchronized T borrowObject() throws Exception { assertOpen(); T obj = null; boolean newlyCreated = false; PooledSoftReference<T> ref = null; while (null == obj) { if (idleReferences.isEmpty()) { if (null == factory) { throw new NoSuchElementException(); } newlyCreated = true; obj = factory.makeObject().getObject(); createCount++; // Do not register with the queue ref = new PooledSoftReference<>(new SoftReference<>(obj)); allReferences.add(ref); } else { ref = idleReferences.pollFirst(); obj = ref.getObject(); // Clear the reference so it will not be queued, but replace with a // a new, non-registered reference so we can still track this object // in allReferences ref.getReference().clear(); ref.setReference(new SoftReference<>(obj)); } if (null != factory && null != obj) { try { factory.activateObject(ref); if (!factory.validateObject(ref)) { throw new Exception("ValidateObject failed"); } } catch (final Throwable t) { PoolUtils.checkRethrow(t); try { destroy(ref); } catch (final Throwable t2) { PoolUtils.checkRethrow(t2); // Swallowed } finally { obj = null; } if (newlyCreated) { throw new NoSuchElementException("Could not create a validated object, cause: " + t); } } } } numActive++; ref.allocate(); return obj; } /** * Clears any objects sitting idle in the pool. */ @Override public synchronized void clear() { if (null != factory) { idleReferences.forEach(ref -> { try { if (null != ref.getObject()) { factory.destroyObject(ref); } } catch (final Exception ignored) { // ignored, keep destroying the rest } }); } idleReferences.clear(); pruneClearedReferences(); } /** * Closes this pool, and frees any resources associated with it. Invokes * {@link #clear()} to destroy and remove instances in the pool. * <p> * Calling {@link #addObject} or {@link #borrowObject} after invoking this * method on a pool will cause them to throw an * {@link IllegalStateException}. * </p> */ @Override public void close() { super.close(); clear(); } /** * Destroys a {@link PooledSoftReference} and removes it from the idle and all * references pools. * * @param toDestroy PooledSoftReference to destroy * @throws Exception If an error occurs while trying to destroy the object */ private void destroy(final PooledSoftReference<T> toDestroy) throws Exception { toDestroy.invalidate(); idleReferences.remove(toDestroy); allReferences.remove(toDestroy); try { factory.destroyObject(toDestroy); } finally { destroyCount++; toDestroy.getReference().clear(); } } /** * Finds the PooledSoftReference in allReferences that points to obj. * * @param obj returning object * @return PooledSoftReference wrapping a soft reference to obj */ private PooledSoftReference<T> findReference(final T obj) { final Optional<PooledSoftReference<T>> first = allReferences.stream() .filter(reference -> reference.getObject() != null && reference.getObject().equals(obj)).findFirst(); return first.orElse(null); } /** * Gets the {@link PooledObjectFactory} used by this pool to create and * manage object instances. * * @return the factory */ public synchronized PooledObjectFactory<T> getFactory() { return factory; } /** * Gets the number of instances currently borrowed from this pool. * * @return the number of instances currently borrowed from this pool */ @Override public synchronized int getNumActive() { return numActive; } /** * Gets an approximation not less than the of the number of idle * instances in the pool. * * @return estimated number of idle instances in the pool */ @Override public synchronized int getNumIdle() { pruneClearedReferences(); return idleReferences.size(); } @Override public synchronized void invalidateObject(final T obj) throws Exception { final PooledSoftReference<T> ref = findReference(obj); if (ref == null) { throw new IllegalStateException( "Object to invalidate is not currently part of this pool"); } if (factory != null) { destroy(ref); } numActive--; notifyAll(); // numActive has changed } /** * If any idle objects were garbage collected, remove their * {@link Reference} wrappers from the idle object pool. */ private void pruneClearedReferences() { // Remove wrappers for enqueued references from idle and allReferences lists removeClearedReferences(idleReferences.iterator()); removeClearedReferences(allReferences.iterator()); while (refQueue.poll() != null) { // loop until null } } /** * Clears cleared references from iterator's collection * @param iterator iterator over idle/allReferences */ private void removeClearedReferences(final Iterator<PooledSoftReference<T>> iterator) { PooledSoftReference<T> ref; while (iterator.hasNext()) { ref = iterator.next(); if (ref.getReference() == null || ref.getReference().refersTo(null)) { iterator.remove(); } } } /** * Returns an instance to the pool after successful validation and * passivation. The returning instance is destroyed if any of the following * are true: * <ul> * <li>the pool is closed</li> * <li>{@link PooledObjectFactory#validateObject( * org.apache.tomcat.dbcp.pool2.PooledObject) validation} fails * </li> * <li>{@link PooledObjectFactory#passivateObject( * org.apache.tomcat.dbcp.pool2.PooledObject) passivation} * throws an exception</li> * </ul> * Exceptions passivating or destroying instances are silently swallowed. * Exceptions validating instances are propagated to the client. * * @param obj * instance to return to the pool * @throws IllegalArgumentException * if obj is not currently part of this pool */ @Override public synchronized void returnObject(final T obj) throws Exception { boolean success = !isClosed(); final PooledSoftReference<T> ref = findReference(obj); if (ref == null) { throw new IllegalStateException( "Returned object not currently part of this pool"); } if (factory != null) { if (!factory.validateObject(ref)) { success = false; } else { try { factory.passivateObject(ref); } catch (final Exception e) { success = false; } } } final boolean shouldDestroy = !success; numActive--; if (success) { // Deallocate and add to the idle instance pool ref.deallocate(); idleReferences.add(ref); } notifyAll(); // numActive has changed if (shouldDestroy && factory != null) { try { destroy(ref); } catch (final Exception ignored) { // ignored } } } @Override protected void toStringAppendFields(final StringBuilder builder) { super.toStringAppendFields(builder); builder.append(", factory="); builder.append(factory); builder.append(", refQueue="); builder.append(refQueue); builder.append(", numActive="); builder.append(numActive); builder.append(", destroyCount="); builder.append(destroyCount); builder.append(", createCount="); builder.append(createCount); builder.append(", idleReferences="); builder.append(idleReferences); builder.append(", allReferences="); builder.append(allReferences); } }
Detected license expression
apache-2.0
Detected license expression (SPDX)
Apache-2.0
Percentage of license text
7.68
Copyrights

      
    
Holders

      
    
Authors

      
    
License detections License expression License expression SPDX
apache_2_0-eb6b5ae0-4f88-4e9b-d67c-c6c8e733b1cd apache-2.0 Apache-2.0
URL Start line End line
https://www.apache.org/licenses/LICENSE-2.0 9 9