ASF Bugzilla – Attachment 34660 Details for
Bug 60623
When startStopThreads is 1, don't rely on an executor and instead start synchronously
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Proposed code changes (based on dev discussion)
bz66023.patch (text/plain), 14.35 KB, created by
John D. Ament
on 2017-01-22 14:09:00 UTC
(
hide
)
Description:
Proposed code changes (based on dev discussion)
Filename:
MIME Type:
Creator:
John D. Ament
Created:
2017-01-22 14:09:00 UTC
Size:
14.35 KB
patch
obsolete
>Index: java/org/apache/catalina/core/StartStopHandler.java >IDEA additional info: >Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP ><+>UTF-8 >=================================================================== >--- java/org/apache/catalina/core/StartStopHandler.java (revision db09ee4678fd3eabf779f73e41036ae84e390b39) >+++ java/org/apache/catalina/core/StartStopHandler.java (revision db09ee4678fd3eabf779f73e41036ae84e390b39) >@@ -0,0 +1,43 @@ >+/* >+ * 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.catalina.core; >+ >+import org.apache.catalina.Container; >+import org.apache.catalina.LifecycleException; >+import org.apache.tomcat.util.res.StringManager; >+ >+abstract class StartStopHandler { >+ protected static final StringManager sm = StringManager.getManager(Constants.Package); >+ abstract void start(Container[] children) throws LifecycleException; >+ abstract void stop(Container[] children) throws LifecycleException; >+ void stop() { >+ >+ } >+ >+ static StartStopHandler createStartStopHandler(String name, int threadCount) { >+ if(threadCount == 1) { >+ return SingleThreadedStartStopHandler.INSTANCE; >+ } >+ else { >+ return new MultiThreadedStartStopHandler(name, threadCount); >+ } >+ } >+ >+} >Index: java/org/apache/catalina/core/MultiThreadedStartStopHandler.java >IDEA additional info: >Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP ><+>UTF-8 >=================================================================== >--- java/org/apache/catalina/core/MultiThreadedStartStopHandler.java (revision db09ee4678fd3eabf779f73e41036ae84e390b39) >+++ java/org/apache/catalina/core/MultiThreadedStartStopHandler.java (revision db09ee4678fd3eabf779f73e41036ae84e390b39) >@@ -0,0 +1,156 @@ >+/* >+ * 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.catalina.core; >+ >+import org.apache.catalina.Container; >+import org.apache.catalina.LifecycleException; >+import org.apache.juli.logging.Log; >+import org.apache.juli.logging.LogFactory; >+ >+import java.util.ArrayList; >+import java.util.List; >+import java.util.concurrent.*; >+import java.util.concurrent.atomic.AtomicInteger; >+ >+public class MultiThreadedStartStopHandler extends StartStopHandler { >+ private final ThreadPoolExecutor startStopExecutor; >+ private static final Log log = LogFactory.getLog(MultiThreadedStartStopHandler.class); >+ >+ MultiThreadedStartStopHandler(String name, int threadCount) { >+ int actualThreadCount = getStartStopThreadsInternal(threadCount); >+ BlockingQueue<Runnable> startStopQueue = new LinkedBlockingQueue<>(); >+ startStopExecutor = new ThreadPoolExecutor(actualThreadCount,actualThreadCount, 10, >+ TimeUnit.SECONDS, >+ startStopQueue, new StartStopThreadFactory(name + "-startStop-")); >+ startStopExecutor.allowCoreThreadTimeOut(true); >+ } >+ >+ @Override >+ void start(Container[] children) throws LifecycleException{ >+ List<Future<Void>> results = new ArrayList<>(); >+ for(Container child : children) { >+ results.add(startStopExecutor.submit(new StartChild(child))); >+ } >+ handleFutures(results, "containerBase.threadedStartFailed"); >+ } >+ >+ @Override >+ void stop(Container[] children) throws LifecycleException{ >+ List<Future<Void>> results = new ArrayList<>(); >+ for(Container child : children) { >+ results.add(startStopExecutor.submit(new StopChild(child))); >+ } >+ } >+ >+ @Override >+ void stop() { >+ this.startStopExecutor.shutdownNow(); >+ } >+ >+ private void handleFutures(List<Future<Void>> results, String key) throws LifecycleException { >+ boolean fail = false; >+ for (Future<Void> result : results) { >+ try { >+ result.get(); >+ } catch (Exception e) { >+ log.error(sm.getString(key), e); >+ fail = true; >+ } >+ } >+ if (fail) { >+ throw new LifecycleException( >+ sm.getString(key)); >+ } >+ } >+ >+ /** >+ * Handles the special values. >+ */ >+ private static int getStartStopThreadsInternal(int threadCount) { >+ int result = threadCount; >+ >+ // Positive values are unchanged >+ if (result > 0) { >+ return result; >+ } >+ >+ // Zero == Runtime.getRuntime().availableProcessors() >+ // -ve == Runtime.getRuntime().availableProcessors() + value >+ // These two are the same >+ result = Runtime.getRuntime().availableProcessors() + result; >+ if (result < 1) { >+ result = 1; >+ } >+ return result; >+ } >+ >+ // ----------------------------- Inner classes used with start/stop Executor >+ >+ private static class StartChild implements Callable<Void> { >+ >+ private Container child; >+ >+ public StartChild(Container child) { >+ this.child = child; >+ } >+ >+ @Override >+ public Void call() throws LifecycleException { >+ child.start(); >+ return null; >+ } >+ } >+ >+ private static class StopChild implements Callable<Void> { >+ >+ private Container child; >+ >+ public StopChild(Container child) { >+ this.child = child; >+ } >+ >+ @Override >+ public Void call() throws LifecycleException { >+ if (child.getState().isAvailable()) { >+ child.stop(); >+ } >+ return null; >+ } >+ } >+ >+ private static class StartStopThreadFactory implements ThreadFactory { >+ private final ThreadGroup group; >+ private final AtomicInteger threadNumber = new AtomicInteger(1); >+ private final String namePrefix; >+ >+ public StartStopThreadFactory(String namePrefix) { >+ SecurityManager s = System.getSecurityManager(); >+ group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); >+ this.namePrefix = namePrefix; >+ } >+ >+ @Override >+ public Thread newThread(Runnable r) { >+ Thread thread = new Thread(group, r, namePrefix + threadNumber.getAndIncrement()); >+ thread.setDaemon(true); >+ return thread; >+ } >+ } >+} >Index: java/org/apache/catalina/core/SingleThreadedStartStopHandler.java >IDEA additional info: >Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP ><+>UTF-8 >=================================================================== >--- java/org/apache/catalina/core/SingleThreadedStartStopHandler.java (revision db09ee4678fd3eabf779f73e41036ae84e390b39) >+++ java/org/apache/catalina/core/SingleThreadedStartStopHandler.java (revision db09ee4678fd3eabf779f73e41036ae84e390b39) >@@ -0,0 +1,47 @@ >+/* >+ * 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.catalina.core; >+ >+import org.apache.catalina.Container; >+import org.apache.catalina.LifecycleException; >+ >+class SingleThreadedStartStopHandler extends StartStopHandler { >+ static SingleThreadedStartStopHandler INSTANCE = new SingleThreadedStartStopHandler(); >+ >+ private SingleThreadedStartStopHandler() { >+ >+ } >+ >+ @Override >+ void start(Container[] children) throws LifecycleException { >+ for (Container child : children) { >+ child.start(); >+ } >+ } >+ >+ @Override >+ void stop(Container[] children) throws LifecycleException { >+ for (Container child : children) { >+ if (child.getState().isAvailable()) { >+ child.stop(); >+ } >+ } >+ } >+} >Index: java/org/apache/catalina/core/ContainerBase.java >IDEA additional info: >Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP ><+>UTF-8 >=================================================================== >--- java/org/apache/catalina/core/ContainerBase.java (date 1484995685000) >+++ java/org/apache/catalina/core/ContainerBase.java (date 1481770564000) >@@ -276,7 +276,8 @@ > * children associated with this container. > */ > private int startStopThreads = 1; >- protected ThreadPoolExecutor startStopExecutor; >+ >+ private StartStopHandler startStopHandler; > > > // ------------------------------------------------------------- Properties >@@ -286,38 +287,11 @@ > return startStopThreads; > } > >- /** >- * Handles the special values. >- */ >- private int getStartStopThreadsInternal() { >- int result = getStartStopThreads(); >- >- // Positive values are unchanged >- if (result > 0) { >- return result; >- } >- >- // Zero == Runtime.getRuntime().availableProcessors() >- // -ve == Runtime.getRuntime().availableProcessors() + value >- // These two are the same >- result = Runtime.getRuntime().availableProcessors() + result; >- if (result < 1) { >- result = 1; >- } >- return result; >- } >- > @Override > public void setStartStopThreads(int startStopThreads) { > this.startStopThreads = startStopThreads; > >- // Use local copies to ensure thread safety >- ThreadPoolExecutor executor = startStopExecutor; >- if (executor != null) { >- int newThreads = getStartStopThreadsInternal(); >- executor.setMaximumPoolSize(newThreads); >- executor.setCorePoolSize(newThreads); >- } >+ this.startStopHandler = StartStopHandler.createStartStopHandler(getName(), startStopThreads); > } > > >@@ -893,13 +867,7 @@ > > @Override > protected void initInternal() throws LifecycleException { >- BlockingQueue<Runnable> startStopQueue = new LinkedBlockingQueue<>(); >- startStopExecutor = new ThreadPoolExecutor( >- getStartStopThreadsInternal(), >- getStartStopThreadsInternal(), 10, TimeUnit.SECONDS, >- startStopQueue, >- new StartStopThreadFactory(getName() + "-startStop-")); >- startStopExecutor.allowCoreThreadTimeOut(true); >+ this.startStopHandler = StartStopHandler.createStartStopHandler(getName(), getStartStopThreads()); > super.initInternal(); > } > >@@ -927,26 +895,7 @@ > } > > // Start our child containers, if any >- Container children[] = findChildren(); >- List<Future<Void>> results = new ArrayList<>(); >- for (int i = 0; i < children.length; i++) { >- results.add(startStopExecutor.submit(new StartChild(children[i]))); >- } >- >- boolean fail = false; >- for (Future<Void> result : results) { >- try { >- result.get(); >- } catch (Exception e) { >- log.error(sm.getString("containerBase.threadedStartFailed"), e); >- fail = true; >- } >- >- } >- if (fail) { >- throw new LifecycleException( >- sm.getString("containerBase.threadedStartFailed")); >- } >+ startStopHandler.start(findChildren()); > > // Start the Valves in our pipeline (including the basic), if any > if (pipeline instanceof Lifecycle) >@@ -983,25 +932,7 @@ > } > > // Stop our child containers, if any >- Container children[] = findChildren(); >- List<Future<Void>> results = new ArrayList<>(); >- for (int i = 0; i < children.length; i++) { >- results.add(startStopExecutor.submit(new StopChild(children[i]))); >- } >- >- boolean fail = false; >- for (Future<Void> result : results) { >- try { >- result.get(); >- } catch (Exception e) { >- log.error(sm.getString("containerBase.threadedStopFailed"), e); >- fail = true; >- } >- } >- if (fail) { >- throw new LifecycleException( >- sm.getString("containerBase.threadedStopFailed")); >- } >+ startStopHandler.stop(findChildren()); > > // Stop our subordinate components, if any > Realm realm = getRealmInternal(); >@@ -1042,8 +973,8 @@ > } > > // If init fails, this may be null >- if (startStopExecutor != null) { >- startStopExecutor.shutdownNow(); >+ if (startStopHandler != null) { >+ startStopHandler.stop(); > } > > super.destroyInternal();
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 60623
: 34660