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 ,

Update: Just an update, All the issues with Varnish on Solaris have been fixed with the 2.1.4 release. We have been using Varnish on our Solaris production servers since the release with great stability and performance. A big thanks to the Varnish devs and slink for the eventport fixes.

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 , ,