/** * 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.camel.impl; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import org.apache.camel.Consumer; import org.apache.camel.ContextTestSupport; import org.apache.camel.Endpoint; import org.apache.camel.Exchange; import org.apache.camel.Processor; import org.apache.camel.Producer; import org.apache.camel.spi.EndpointUtilizationStatistics; /** * @version */ public class DefaultProducerCacheTest extends ContextTestSupport { private final AtomicInteger stopCounter = new AtomicInteger(); private final AtomicInteger shutdownCounter = new AtomicInteger(); public void testCacheProducerAcquireAndRelease() throws Exception { ProducerCache cache = new ProducerCache(this, context); cache.start(); assertEquals("Size should be 0", 0, cache.size()); // test that we cache at most 1000 producers to avoid it eating to much memory for (int i = 0; i < 1003; i++) { Endpoint e = context.getEndpoint("direct:queue:" + i); Producer p = cache.acquireProducer(e); cache.releaseProducer(e, p); } // the eviction is async so force cleanup cache.cleanUp(); assertEquals("Size should be 1000", 1000, cache.size()); cache.stop(); } public void testCacheStopExpired() throws Exception { ProducerCache cache = new ProducerCache(this, context, 5); cache.start(); assertEquals("Size should be 0", 0, cache.size()); for (int i = 0; i < 8; i++) { Endpoint e = new MyEndpoint(true, i); Producer p = cache.acquireProducer(e); cache.releaseProducer(e, p); } // the eviction is async so force cleanup cache.cleanUp(); assertEquals("Size should be 5", 5, cache.size()); // the eviction listener is async so sleep a bit Thread.sleep(1000); // should have stopped the 3 evicted assertEquals(3, stopCounter.get()); cache.stop(); // should have stopped all 8 assertEquals(8, stopCounter.get()); } public void testReleaseProducerInvokesStopAndShutdownByNonSingletonProducers() throws Exception { ProducerCache cache = new ProducerCache(this, context, 1); cache.start(); assertEquals("Size should be 0", 0, cache.size()); for (int i = 0; i < 3; i++) { Endpoint e = new MyEndpoint(false, i); Producer p = cache.acquireProducer(e); cache.releaseProducer(e, p); } assertEquals("Size should be 0", 0, cache.size()); // should have stopped all 3 assertEquals(3, stopCounter.get()); // should have shutdown all 3 assertEquals(3, shutdownCounter.get()); cache.stop(); // no more stop after stopping the cache assertEquals(3, stopCounter.get()); // no more shutdown after stopping the cache assertEquals(3, shutdownCounter.get()); } public void testExtendedStatistics() throws Exception { ProducerCache cache = new ProducerCache(this, context, 5); cache.setExtendedStatistics(true); cache.start(); assertEquals("Size should be 0", 0, cache.size()); // use 1 = 2 times // use 2 = 3 times // use 3..4 = 1 times // use 5 = 0 times Endpoint e = new MyEndpoint(true, 1); Producer p = cache.acquireProducer(e); cache.releaseProducer(e, p); e = new MyEndpoint(true, 1); p = cache.acquireProducer(e); cache.releaseProducer(e, p); e = new MyEndpoint(true, 2); p = cache.acquireProducer(e); cache.releaseProducer(e, p); e = new MyEndpoint(true, 2); p = cache.acquireProducer(e); cache.releaseProducer(e, p); e = new MyEndpoint(true, 2); p = cache.acquireProducer(e); cache.releaseProducer(e, p); e = new MyEndpoint(true, 3); p = cache.acquireProducer(e); cache.releaseProducer(e, p); e = new MyEndpoint(true, 4); p = cache.acquireProducer(e); cache.releaseProducer(e, p); assertEquals("Size should be 4", 4, cache.size()); EndpointUtilizationStatistics stats = cache.getEndpointUtilizationStatistics(); assertEquals(4, stats.size()); Map<String, Long> recent = stats.getStatistics(); assertEquals(2, recent.get("my://1").longValue()); assertEquals(3, recent.get("my://2").longValue()); assertEquals(1, recent.get("my://3").longValue()); assertEquals(1, recent.get("my://4").longValue()); assertNull(recent.get("my://5")); cache.stop(); } private final class MyEndpoint extends DefaultEndpoint { private final boolean isSingleton; private final int number; private MyEndpoint(boolean isSingleton, int number) { this.isSingleton = isSingleton; this.number = number; } @Override public Producer createProducer() throws Exception { return new MyProducer(this); } @Override public Consumer createConsumer(Processor processor) throws Exception { return null; } @Override public boolean isSingleton() { return isSingleton; } @Override public String getEndpointUri() { return "my://" + number; } } private final class MyProducer extends DefaultProducer { MyProducer(Endpoint endpoint) { super(endpoint); } @Override public void process(Exchange exchange) throws Exception { // noop } @Override protected void doStop() throws Exception { stopCounter.incrementAndGet(); } @Override protected void doShutdown() throws Exception { shutdownCounter.incrementAndGet(); } } }