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

org.apache.tapestry5.internal.services.PagePoolImpl Maven / Gradle / Ivy

Go to download

Central module for Tapestry, containing interfaces to the Java Servlet API and all core services and components.

There is a newer version: 5.8.6
Show newest version
// Copyright 2006, 2007, 2008, 2009 The Apache Software Foundation
//
// Licensed 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.tapestry5.internal.services;

import org.apache.tapestry5.SymbolConstants;
import org.apache.tapestry5.internal.structure.Page;
import org.apache.tapestry5.ioc.annotations.IntermediateType;
import org.apache.tapestry5.ioc.annotations.Symbol;
import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
import org.apache.tapestry5.ioc.services.ThreadLocale;
import org.apache.tapestry5.ioc.util.TimeInterval;
import org.apache.tapestry5.services.InvalidationListener;
import org.apache.tapestry5.services.UpdateListener;
import org.slf4j.Logger;

import java.util.Locale;
import java.util.Map;

/**
 * Registered as an invalidation listener with the page loader, the component messages source, and the component
 * template source. Any time any of those notice a change, then the entire page pool is wiped.
 * 

* The master page pool is, itself, divided into individual sub-pools, one for each combination of *

* This code is designed to handle high volume sites and deal with request fluctuations. *

* A soft limit on the number of page instances is enforced. Asking for a page instance when the soft limit has * been reached (or exceeded) will result in a delay until a page instance (released from another thread) is available. * The delay time is configurable. *

* A hard limit on the number of page instances is enforced. This number may not be exceeded. Requesting a page * instance when at the hard limit will result in a runtime exception. *

* As an {@link org.apache.tapestry5.services.UpdateListener}, the service will reduce the size of each page's pool by * eliminating pages that haven't been used recently. * * @see org.apache.tapestry5.internal.services.PagePoolCache */ public class PagePoolImpl implements PagePool, InvalidationListener, UpdateListener, PagePoolImplMBean { private final Logger logger; private final PageLoader pageLoader; private final ThreadLocale threadLocale; private int softLimit; private long softWait; private int hardLimit; private long activeWindow; private final Map pool = CollectionFactory.newMap(); public PagePoolImpl(Logger logger, PageLoader pageLoader, ThreadLocale threadLocale, @Symbol(SymbolConstants.PAGE_POOL_SOFT_LIMIT) int softLimit, @Symbol(SymbolConstants.PAGE_POOL_SOFT_WAIT) @IntermediateType(TimeInterval.class) long softWait, @Symbol(SymbolConstants.PAGE_POOL_HARD_LIMIT) int hardLimit, @Symbol(SymbolConstants.PAGE_POOL_ACTIVE_WINDOW) @IntermediateType(TimeInterval.class) long activeWindow) { this.logger = logger; this.pageLoader = pageLoader; this.threadLocale = threadLocale; this.softLimit = softLimit; this.softWait = softWait; this.hardLimit = hardLimit; this.activeWindow = activeWindow; } public Page checkout(String pageName) { PagePoolCache cache = get(pageName, threadLocale.getLocale()); return cache.checkout(); } public void release(Page page) { PagePoolCache cache = getPagePoolCache(page); // If the page is not "clean" of any request/client state, it can't go // back in the pool. if (page.detached()) { logger.error(ServicesMessages.pageIsDirty(page)); cache.remove(page); return; } cache.release(page); } public void discard(Page page) { getPagePoolCache(page).remove(page); } private PagePoolCache getPagePoolCache(Page page) { return get(page.getName(), page.getLocale()); } private synchronized PagePoolCache get(String pageName, Locale locale) { PageLocator locator = new PageLocator(pageName, locale); PagePoolCache result = pool.get(locator); if (result == null) { // TODO: It might be nice to allow individual pages to override the default limits. result = new PagePoolCache(pageName, locale, pageLoader, softLimit, softWait, hardLimit, activeWindow); pool.put(locator, result); } return result; } /** * Any time templates, classes or messages change, we throw out all instances. */ public synchronized void objectWasInvalidated() { clear(); } /** * On the periodic check for updates call, we clean up the caches, discarding unsued and out of date page * instances. */ public synchronized void checkForUpdates() { for (PagePoolCache cache : pool.values()) { cache.cleanup(); } } public void clear() { pool.clear(); } public int getSoftLimit() { return softLimit; } public void setSoftLimit(int softLimit) { this.softLimit = softLimit; objectWasInvalidated(); } public long getSoftWait() { return softWait; } public void setSoftWait(long softWait) { this.softWait = softWait; objectWasInvalidated(); } public int getHardLimit() { return hardLimit; } public void setHardLimit(int hardLimit) { this.hardLimit = hardLimit; objectWasInvalidated(); } public long getActiveWindow() { return activeWindow; } public void setActiveWindow(long activeWindow) { this.activeWindow = activeWindow; objectWasInvalidated(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy