Letsgetdugg

Random tech jargon

Browsing the 2009 May archive

I would be sitting on a gold mine.

SLOC	Directory	SLOC-by-Language (Sorted)
37890   src             java=37890
5026    contrib-utilities java=5026
4457    contrib-crud    java=4457
2259    contrib-mootools java=2259
1235    contrib-generaldao java=1235
1185    contrib-emailmanager java=1185
986     jetty-memcache  java=986
961     contrib-cache   java=961
787     jmemcached      java=786,sh=1
640     contrib-thumbnail java=640
503     contrib-blueprint java=503
181     contrib-snapshot java=181
32      contrib-nicedit java=32

Totals grouped by language (dominant language first):
java:         56141 (100.00%)
sh:               1 (0.00%)

Total Physical Source Lines of Code (SLOC)                = 56,142
Development Effort Estimate, Person-Years (Person-Months) = 13.73 (164.80)
 (Basic COCOMO model, Person-Months = 2.4 * (KSLOC**1.05))
Schedule Estimate, Years (Months)                         = 1.45 (17.39)
 (Basic COCOMO model, Months = 2.5 * (person-months**0.38))
Estimated Average Number of Developers (Effort/Schedule)  = 9.47
Total Estimated Cost to Develop                           = $ 1,855,214
 (average salary = $56,286/year, overhead = 2.40).
SLOCCount, Copyright (C) 2001-2004 David A. Wheeler
SLOCCount is Open Source Software/Free Software, licensed under the GNU GPL.
SLOCCount comes with ABSOLUTELY NO WARRANTY, and you are welcome to
redistribute it under certain conditions as specified by the GNU GPL license;
see the documentation for details.
Please credit this data as "generated using David A. Wheeler's 'SLOCCount'."
Tagged with

One of the first few things I have tackled while creating fabulously40 was stateless pagination. I wanted to keep all the public facing pages stateless to avoid session overhead. Wicket makes pagination brain dead simple at the cost of session use. I wanted to keep the simple programming model yet be completely stateless. Here is my solution to the problem.

Wicket a stateful framework, is actually really good at being stateless.

Example code on how to use it.

update: I would suggest using MixedParamHybridCodingStrategy with the stateless paging navigation to keep links clean.

StatelessDataView<Photo> dv;
add(dv = new StatelessDataView<Photo>("pics", getPhotoProvider(), amount, pageParams) {
                        private static final long serialVersionUID = 1L;

                        @Override
                        protected void populateItem(final Item<Photo> arg0) {
              }
});

// call back page class, page paramaters passed, the dataview and 12 pagination links.
add(new StatelessSimplePagingNavigator("nav", PhotosPage.class, pageParams, dataView, 12));

The dataview

package com.base.components;

import org.apache.wicket.PageParameters;
import org.apache.wicket.markup.repeater.data.DataView;
import org.apache.wicket.markup.repeater.data.IDataProvider;

public abstract class StatelessDataView<T> extends DataView<T> {
        private static final long serialVersionUID = 1L;
        private PageParameters pp;

        @Override
        protected boolean getStatelessHint() {
                return true;
        }

        protected int getPageNumber(final String param) {
                String numResult = param;
                if(numResult.contains(".wicket-")) {
                        numResult = numResult.substring(0,numResult.indexOf(".wicket-"));
                }
                return Integer.valueOf(numResult);
        }

        public StatelessDataView(final String id, final IDataProvider dataProvider, final PageParameters pp) {
                super(id, dataProvider);
                this.pp = pp;
                if (pp.getString(id) != null) {
                        int pageNum = getPageNumber(pp.getString(id));
                        if(pageNum != -1 && pageNum >= 0 && pageNum <= getPageCount()) {
                                setCurrentPage(getPageNumber(pp.getString(id)));
                        }
                }
        }

        public StatelessDataView(final String id, final IDataProvider dataProvider, final int itemsPerPage,
                        final PageParameters pp) {
                super(id, dataProvider, itemsPerPage);
                this.pp = pp;
                if (pp.getString(id) != null) {
                        int pageNum = getPageNumber(pp.getString(id));
                        if(pageNum != -1 && pageNum >= 0 && pageNum <= getPageCount()) {
                                setCurrentPage(getPageNumber(pp.getString(id)));
                        }
                }
        }

}

The paging navigator

package com.base.components;

import org.apache.wicket.Component;
import org.apache.wicket.PageParameters;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.navigation.paging.IPageable;
import org.apache.wicket.markup.html.navigation.paging.IPagingLabelProvider;
import org.apache.wicket.markup.html.navigation.paging.PagingNavigation;

public class StatelessSimplePagingNavigator extends SimplePagingNavigator {
        private static final long serialVersionUID = 1L;
        private Class clazz;
        private PageParameters pp;
        private int current_page;
        private int page_count;
        private String pageable_id;
        private String anchor = null;

        @Override
        protected boolean getStatelessHint() {
                return true;
        }

        public StatelessSimplePagingNavigator(final String id, final Class clazz, final PageParameters pp,
                        final IPageable pageable, final int viewsize) {
                this(id, clazz, pp, pageable, viewsize, false);
        }

        public StatelessSimplePagingNavigator(final String id, final Class clazz, final PageParameters pp,
                        final IPageable pageable, final int viewsize, final boolean anchorSelf) {
                super(id, pageable, viewsize, anchorSelf);
                this.clazz = clazz;
                this.pp = pp;
                this.current_page = pageable.getCurrentPage();
                this.page_count = pageable.getPageCount();
                this.pageable_id = ((Component) pageable).getId();
        }

        public StatelessSimplePagingNavigator(final String id, final Class clazz, final PageParameters pp,
                        final IPageable pageable, final int viewsize, final String anchor) {
                super(id, pageable, viewsize, false);
                this.clazz = clazz;
                this.pp = pp;
                this.current_page = pageable.getCurrentPage();
                this.page_count = pageable.getPageCount();
                this.pageable_id = ((Component) pageable).getId();
                this.anchor = anchor;
        }

        @Override
        protected void onBeforeRender() {
                super.onBeforeRender();
                addOrReplace(newStatelessPagingNavigationLink("next", pageable_id, current_page, 1));
                addOrReplace(newStatelessPagingNavigationLink("prev", pageable_id, current_page, -1));
        }

        @Override
        protected PagingNavigation newNavigation(final IPageable pageable, final IPagingLabelProvider labelProvider) {
                PagingNavigation pg = new PagingNavigation("navigation", pageable, labelProvider) {
                        private static final long serialVersionUID = 1L;

                        @Override
                        protected Link newPagingNavigationLink(final String id, final IPageable pageable, final int pageIndex) {
                                Component c = (Component) pageable;
                                // PageParameters p1 = new PageParameters();
                                // p1.putAll(pp);
                                pp.put(c.getId(), String.valueOf(pageIndex));
                                BookmarkablePageLink<Object> lnk = new BookmarkablePageLink<Object>(id, clazz, pp) {
                                        private static final long serialVersionUID = 1L;

                                        @Override
                                        protected void onComponentTag(final ComponentTag arg0) {
                                                super.onComponentTag(arg0);
                                                if (anchor != null) {
                                                        if(arg0.getString("href") != null) {
                                                                String href = arg0.getString("href").toString();
                                                                String atag = anchor.contains("#") ? anchor : "#" + anchor;
                                                                arg0.put("href", href + atag);
                                                        }
                                                }
                                        }

                                        @Override
                                        public boolean isEnabled() {
                                                return (current_page != pageIndex);
                                        }
                                };
                                if (isAnchorSelf()) {
                                        lnk.setAnchor(StatelessSimplePagingNavigator.this);
                                }
                                return lnk;
                        }
                };
                pg.setViewSize(getViewsize());
                return pg;
        }

        @Override
        protected Link<Object> newPagingNavigationIncrementLink(final String id, final IPageable pageable, final int increment) {
                Component c = (Component) pageable;
                final int page = Integer.valueOf(pp.getString(c.getId()));
                pp.put(c.getId(), String.valueOf(page + increment));
                return new BookmarkablePageLink<Object>(id, clazz, pp) {
                        private static final long serialVersionUID = 1L;

                        @Override
                        public boolean isVisible() {
                                return (page + increment) >= 0;
                        }
                };
        }

        protected Link<Object> newStatelessPagingNavigationLink(final String id, final String pageableId, final int currentPage,
                        final int increment) {
                // PageParameters p1 = new PageParameters();
                // p1.putAll(pp);
                pp.put(pageableId, String.valueOf(currentPage + increment));
                return new BookmarkablePageLink<Object>(id, clazz, pp) {
                        private static final long serialVersionUID = 1L;

                        @Override
                        public boolean isVisible() {
                                return (currentPage + increment) < page_count && (currentPage + increment) >= 0;
                        }
                };
        }

        @Override
        protected Link<Object> newPagingNavigationLink(final String id, final IPageable pageable, final int pageNumber) {
                Component c = (Component) pageable;
                // PageParameters p1 = new PageParameters();
                // p1.putAll(pp);
                pp.put(c.getId(), String.valueOf(pageNumber));
                return new BookmarkablePageLink(id, clazz, pp);
        }

}

Which inherits from

package com.base.components;

import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.navigation.paging.IPageable;
import org.apache.wicket.markup.html.navigation.paging.IPagingLabelProvider;
import org.apache.wicket.markup.html.navigation.paging.PagingNavigation;
import org.apache.wicket.markup.html.navigation.paging.PagingNavigator;

public class SimplePagingNavigator extends PagingNavigator {
        private static final long serialVersionUID = 1L;

        private int viewsize = 0;
        private boolean anchorSelf = false;

        public SimplePagingNavigator(final String id, final IPageable pageable, final int viewsize) {
                this(id, pageable, viewsize, false);
        }

        public SimplePagingNavigator(final String id, final IPageable pageable, final int viewsize, final boolean anchorSelf) {
                super(id, pageable);
                setOutputMarkupId(true);
                this.setViewsize(viewsize);
                this.setAnchorSelf(anchorSelf);
        }

        @Override
        protected void onBeforeRender() {
                if (get("navigation") != null) {
                        remove("navigation");
                }
                if (get("prev") != null) {
                        remove("prev");
                }
                if (get("next") != null) {
                        remove("next");
                }
                super.onBeforeRender();
                if (get("first") != null) {
                        remove("first");
                }
                if (get("last") != null) {
                        remove("last");
                }
                if (getViewsize() != 0) {
                        getPagingNavigation().setViewSize(getViewsize());
                }
        }

        @Override
        protected PagingNavigation newNavigation(final IPageable pageable, final IPagingLabelProvider labelProvider) {
                PagingNavigation pg = new PagingNavigation("navigation", pageable, labelProvider) {
                        private static final long serialVersionUID = 1L;

                        @Override
                        protected Link newPagingNavigationLink(final String id, final IPageable pageable, final int pageIndex) {
                                Link lnk = (Link) super.newPagingNavigationLink(id, pageable, pageIndex);
                                if (isAnchorSelf()) {
                                        lnk.setAnchor(SimplePagingNavigator.this);
                                }
                                return lnk;
                        }
                };
                pg.setViewSize(getViewsize());
                return pg;
        }

        @Override
        public boolean isVisible() {
                if (getPageable() != null) {
                        return (getPageable().getPageCount() > 1);
                }
                return true;
        }

        public void setAnchorSelf(final boolean anchorSelf) {
                this.anchorSelf = anchorSelf;
        }

        public boolean isAnchorSelf() {
                return anchorSelf;
        }

        public void setViewsize(final int viewsize) {
                this.viewsize = viewsize;
        }

        public int getViewsize() {
                return viewsize;
        }

}

<wicket:panel>
        <a wicket:id="prev">Previous</a>
    <span wicket:id="navigation">
                  <a wicket:id="pageLink" href="#"><span wicket:id="pageNumber">5</span></a>
    </span>
    <a wicket:id="next">Next</a>
  </wicket:panel>
Tagged with ,

I have dumped varnish as our primary cache due to multiple failures of service. I have tried to make it work but varnish kept insisting on producing 503 XID backend failures on perfectly healthy backends. I have tried doing all types of crazy configuration hacks such as forcing varnish to retry backends via a round-robin director. It did not work out all too well since the round trip added latency when varnish had to re-fetch the document multiple times. The final straw that broke the camel’s back was when varnish configured for a 256mb malloc store grew to an astonishing size of 780mb+ RSS.

I have switched to squid-3 and so far it has been stable and fast. I will later post a matching squid configuration to the one below that does the same thing.

Squid-3 will require this patch for it to compile on Solaris.

Varnish on Solaris is a dud.

List of failures

1. Producing 503 responses for perfectly healthy backends. Backend never even gets contacted.
2. Growing to a crazy size when using the malloc implementation.
3. Segfaulting every hour on the hour with the newest trunk r4080+

Here is the configuration I have used. Feel free to use it if varnish works for you.

#
# This is a basic VCL configuration file for varnish.  See the vcl(7)
# man page for details on VCL syntax and semantics.
#
# $Id: default.vcl 1818 2007-08-09 12:12:12Z des $
#

# Default backend definition.  Set this to point to your content
# server.

 # my wonderful re-try hack, that kinda works.
 director www_dir round-robin {
     { .backend = { .connect_timeout = 2s; .host="127.0.0.1"; .port="8001"; }  }
     { .backend = { .connect_timeout = 2s; .host="127.0.0.1"; .port="8001"; }  }
     { .backend = { .connect_timeout = 2s; .host="127.0.0.1"; .port="8001"; }  }
     { .backend = { .connect_timeout = 2s; .host="127.0.0.1"; .port="8001"; }  }
 }

#backend default { .host = "127.0.0.1"; .port = "8089"; .connect_timeout = 2s; }

sub vcl_recv {
 remove req.http.X-Forwarded-For;
 set req.http.X-Forwarded-For = client.ip;
 set req.grace = 2m;

    if (req.http.Accept-Encoding) {
        if (req.url ~ "\.(jpeg|jpg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|ico|swf|flv|dmg)") {
            # No point in compressing these
            remove req.http.Accept-Encoding;
        } elsif (req.http.Accept-Encoding ~ "gzip") {
            set req.http.Accept-Encoding = "gzip";
        } elsif (req.http.Accept-Encoding ~ "deflate") {
            set req.http.Accept-Encoding = "deflate";
        } else {
            # unkown algorithm
            remove req.http.Accept-Encoding;
        }
    }

# don't trust MSIE6
# if (req.http.user-agent ~ "MSIE [1-6]\.") {
#     remove req.http.Accept-Encoding;
# }

 if (req.http.host == "jira.fabulously40.com") {
   pipe;
 }

 if (req.request == "GET" || req.request == "HEAD") {
	if ( req.url ~ "\.(xml|gif|jpg|swf|css|png|jpeg|tiff|tif|svg|ico|pdf|ico|swf)") {
		remove req.http.cookie;
		lookup;
	}
	# avoid caching jsps
	if ( req.url ~ "\.js([^p]|$)" ) {
		remove req.http.cookie;
		lookup;
	}
 }

 # don't bother caching large files
 if(req.url ~ "\.(mp3|flv|mov|mp4|mpg|mpeg|avi|dmg)") {
     pipe;
 }

 if (req.request != "GET" && req.request != "HEAD") {
     pipe;
 }

 if (req.request == "POST") {
     pipe;
 }

 if (req.http.Expect || req.http.Authorization || req.http.Authenticate || req.http.WWW-Authenticate) {
    pipe;
 }

 # pipe pages with these cookies set
 if (req.http.cookie && req.http.cookie ~ "_.*_session=") {
     pipe;
 }
 if (req.http.cookie && req.http.cookie ~ "JSESSIONID=") {
     pipe;
 }
 if (req.http.cookie && req.http.cookie ~ "PHPSESSID=") {
     pipe;
 }
 if (req.http.cookie && req.http.cookie ~ "wordpress_logged_in") {
     pipe;
 }

 lookup;
}

sub vcl_error {
	# retry on errors
    if (obj.status == 503) {
        if ( req.restarts < 12 ) {
             restart;
         }
     }
}

sub vcl_fetch {

	# don't cache when these cookies are in place
	if(beresp.http.Location || beresp.http.WWW-Authenticate) {
	    pass;
	}
	if(beresp.http.cookie && beresp.http.cookie ~ "JSESSIONID=") {
	    pass;
	}
	if(beresp.http.Set-Cookie && beresp.http.Set-Cookie ~ "JSESSIONID=") {
	    pass;
	}
	if(beresp.http.cookie && beresp.http.cookie ~ "_.*_session=") {
	    pass;
	}
	if(beresp.http.Set-Cookie && beresp.http.Set-Cookie ~ "_.*_session=") {
	    pass;
	}
	if(beresp.http.cookie && beresp.http.cookie ~ "PHPSESSID=") {
	    pass;
	}
	if(beresp.http.Set-Cookie && beresp.http.Set-Cookie ~ "PHPSESSID=") {
	    pass;
	}
	if(beresp.http.cookie && beresp.http.cookie ~ "wordpress_logged_in") {
	    pass;
	}
	if(beresp.http.Set-Cookie && beresp.http.Set-Cookie ~ "wordpress_logged_in") {
	    pass;
	}
	if(beresp.http.Cache-Control && beresp.http.Cache-Control ~ "no-cache") {
	    pass;
	}
	if(beresp.http.Pragma && beresp.http.Pragma ~ "no-cache") {
	    pass;
	}

# avoid defaults since we *want* pages cached with cookies
#	if (!beresp.cacheable) {
#	    pass;
#	}
#	if (beresp.http.Set-Cookie) {
#		pass;
#	}

	#cache for 30 minutes..
	if((beresp.http.Cache-Control !~ "max-age" || beresp.http.Cache-Control !~ "s-maxage") && beresp.ttl < 1800s) {
		set beresp.ttl = 1800s;
	}
	set beresp.grace = 2m;

	# anonymous users get 10 min delay
	if(beresp.http.Content-Type && beresp.http.Content-Type ~ "html" && (beresp.http.Cache-Control !~ "max-age" ||  beresp.http.Cache-Control !~ "s-maxage")) {
	    set beresp.ttl = 600s;
	}

	# remove server affinity cookie from cached pages.
	if(beresp.http.Set-Cookie && beresp.http.Set-Cookie ~ "X-SERVERID=") {
	    remove beresp.http.Set-Cookie;
	}
	if(beresp.http.Set-Cookie && beresp.http.Set-Cookie ~ "SERVERID=") {
	    remove beresp.http.Set-Cookie;
	}
	if(beresp.http.X-Backend) {
	    remove beresp.http.X-Backend;
	}

	deliver;
}
Tagged with , , ,

I am about to run out the house for the Labor Day weekend, quickie post on my new coding url strategy.

MixedParamHybridUrlCodingStrategy lets you keep stateful multi-pagemap URLs clean while using mixed parameters.

Example…

mount(new MixedParamHybridUrlCodingStrategy("/questions",QuestionsPage.class,false,new String[]{"cat"}));

This will mount “/questions/stupid-category” and convert it to…

new PageParameters("cat","stupid-category");
package com.base.target.coding;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.wicket.IRequestTarget;
import org.apache.wicket.PageParameters;
import org.apache.wicket.protocol.http.request.WebRequestCodingStrategy;
import org.apache.wicket.request.target.coding.HybridUrlCodingStrategy;
import org.apache.wicket.util.string.AppendingStringBuffer;
import org.apache.wicket.util.value.ValueMap;

public class MixedParamHybridUrlCodingStrategy extends HybridUrlCodingStrategy {
        private final String[] parameterNames;

        public MixedParamHybridUrlCodingStrategy(final String mountPath, final Class pageClass) {
                super(mountPath, pageClass);
                this.parameterNames = new String[] {};
        }

        public MixedParamHybridUrlCodingStrategy(final String mountPath, final Class pageClass,final boolean refresh) {
                super(mountPath,pageClass,refresh);
                this.parameterNames = new String[] {};
        }

        public MixedParamHybridUrlCodingStrategy(final String mountPath, final Class pageClass,final String[] params) {
                super(mountPath,pageClass,false);
                this.parameterNames = params;
        }

        public MixedParamHybridUrlCodingStrategy(final String mountPath, final Class pageClass,final boolean refresh,final String[] params) {
                super(mountPath,pageClass,refresh);
                this.parameterNames = params;
        }

        @Override
        protected void appendParameters(final AppendingStringBuffer url, final Map parameters)
        {

                Set parameterNamesToAdd = new HashSet(parameters.keySet());
                // Find index of last specified parameter
                boolean foundParameter = false;
                int lastSpecifiedParameter = parameterNames.length;
                while (lastSpecifiedParameter != 0 && !foundParameter)
                {
                        foundParameter = parameters.containsKey(parameterNames[lastSpecifiedParameter]);
                }

                if (foundParameter)
                {
                        for (int i = 0; i <= lastSpecifiedParameter; i++)
                        {
                                String parameterName = parameterNames[i];
                                final Object param = parameters.get(parameterName);
                                String value = param instanceof String[] ? ((String[])param)[0] : (String)param;
                                if (value == null)
                                {
                                        value = "";
                                }
                                if (!url.endsWith("/"))
                                {
                                        url.append("/");
                                }
                                url.append(urlEncodePathComponent(value));
                                parameterNamesToAdd.remove(parameterName);
                        }
                }

                if (!parameterNamesToAdd.isEmpty())
                {
                        boolean first = true;
                        final Iterator iterator = parameterNamesToAdd.iterator();
                        while (iterator.hasNext())
                        {
                                url.append(first ? ‘?’ : ‘&’);
                                String parameterName = (String)iterator.next();
                                final Object param = parameters.get(parameterName);
                                String value = param instanceof String[] ? ((String[])param)[0] : (String)param;
                                url.append(urlEncodeQueryComponent(parameterName)).append("=").append(
                                                urlEncodeQueryComponent(value));
                                first = false;
                        }
                }

                String pageMap = (String)parameters.get(WebRequestCodingStrategy.PAGEMAP);
                if (pageMap != null)
                {
                        pageMap = WebRequestCodingStrategy.encodePageMapName(pageMap);
                        if (!url.endsWith("/"))
                        {
                                url.append("/");
                        }
                        url.append(WebRequestCodingStrategy.PAGEMAP).append("/").append(
                                        urlEncodePathComponent(pageMap));
                }
        }

        @Override
        public CharSequence encode(final IRequestTarget requestTarget) {
                String url = String.valueOf(super.encode(requestTarget));
                if(url.contains(".wicket")) {
                        // Rewrite URL from..  /foo?bar=5.wicket-xxx to /foo.wicket-xxx?bar=5
                        return url.replaceAll("(.*)\\?(.*)\\.(wicket-[0-9]+)$", "$1.$3?$2");
                }
                return url;
        }

        @Override
        protected ValueMap decodeParameters(final String urlFragment, final Map urlParameters)
        {

                PageParameters params = new PageParameters();
                if(urlFragment == null) {
                        return params;
                }

                // Add all url parameters and normalize
                for(Iterator<Map.Entry> itr = urlParameters.entrySet().iterator();itr.hasNext();) {
                        Map.Entry<String,String[]> e = itr.next();
                        if(e.getValue() != null) {
                                String val = (e.getValue())[0];
                                if(val != null) {
                                        if(val.contains(".wicket")) {
                                                val = val.substring(0,val.indexOf(".wicket"));
                                                urlParameters.put(e.getKey(), val);
                                        }
                                }
                        }
                }
                params.putAll(urlParameters);

                String urlPath = urlFragment;
                if (urlPath.startsWith("/"))
                {
                        urlPath = urlPath.substring(1);
                }

                if (urlPath.length() > 0)
                {
                        String[] pathParts = urlPath.split("/");
                        if (pathParts.length > parameterNames.length)
                        {
                                throw new IllegalArgumentException(
                                "Too many path parts, please provide sufficient number of path parameter names");
                        }

                        for (int i = 0; i < pathParts.length; i++)
                        {
                                if(pathParts[i].contains(".wicket")) {
                                        pathParts[i].substring(0,pathParts[i].indexOf(".wicket"));
                                }
                                if (WebRequestCodingStrategy.PAGEMAP.equals(pathParts[i]))
                                {
                                        params.put(WebRequestCodingStrategy.PAGEMAP,
                                                        WebRequestCodingStrategy.decodePageMapName(urlDecodePathComponent(pathParts[i])));
                                }
                                params.put(parameterNames[i], urlDecodePathComponent(pathParts[i]));
                        }

                }
                return params;
        }

}

Tagged with ,

This is a late night post, so I am just going to make it short. This patch lets you use QueuedThreadPool with the Grizzly Connector. This is a monkey patch, getMaxThreads() should be moved up into the Thread Interface.

--- GrizzlyConnection-old.java Sat May 2 01:08:02 2009 +++ GrizzlyConnector.java Sat May 2 00:56:37 2009 @@ -51,6 +51,8 @@ import org.mortbay.jetty.webapp.WebAppContext; import org.mortbay.log.Log; import org.mortbay.thread.BoundedThreadPool; +import org.mortbay.thread.QueuedThreadPool; +import org.mortbay.thread.ThreadPool; /* ------------------------------------------------------------------------------- */ /** @@ -178,8 +180,13 @@ controller.setProtocolChainInstanceHandler(instanceHandler); Pipeline pipeline = new DefaultPipeline(); - pipeline.setMaxThreads( - ((BoundedThreadPool)getServer().getThreadPool()).getMaxThreads()); + if(getServer().getThreadPool() instanceof BoundedThreadPool) { + pipeline.setMaxThreads( + ((BoundedThreadPool)getServer().getThreadPool()).getMaxThreads()); + } else { + pipeline.setMaxThreads( + ((QueuedThreadPool)getServer().getThreadPool()).getMaxThreads()); + } controller.setPipeline(pipeline); }
Tagged with , ,