diff --git a/agent/src/com/cloud/agent/Agent.java b/agent/src/com/cloud/agent/Agent.java index f309474fbc5..c713e459262 100755 --- a/agent/src/com/cloud/agent/Agent.java +++ b/agent/src/com/cloud/agent/Agent.java @@ -26,7 +26,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Timer; -import java.util.TimerTask; import java.util.concurrent.ExecutorService; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.SynchronousQueue; @@ -36,6 +35,7 @@ import java.util.concurrent.atomic.AtomicInteger; import javax.naming.ConfigurationException; +import org.apache.cloudstack.managed.context.ManagedContextTimerTask; import org.apache.log4j.Logger; import com.cloud.agent.api.AgentControlAnswer; @@ -731,7 +731,7 @@ public class Agent implements HandlerFactory, IAgentControl { } } - public class WatchTask extends TimerTask { + public class WatchTask extends ManagedContextTimerTask { protected Request _request; protected Agent _agent; protected Link _link; @@ -744,7 +744,7 @@ public class Agent implements HandlerFactory, IAgentControl { } @Override - public void run() { + protected void runInContext() { if (s_logger.isTraceEnabled()) { s_logger.trace("Scheduling " + (_request instanceof Response ? "Ping" : "Watch Task")); } @@ -760,7 +760,7 @@ public class Agent implements HandlerFactory, IAgentControl { } } - public class StartupTask extends TimerTask { + public class StartupTask extends ManagedContextTimerTask { protected Link _link; protected volatile boolean cancelled = false; @@ -782,7 +782,7 @@ public class Agent implements HandlerFactory, IAgentControl { } @Override - public synchronized void run() { + protected synchronized void runInContext() { if (!cancelled) { if (s_logger.isInfoEnabled()) { s_logger.info("The startup command is now cancelled"); diff --git a/agent/src/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java b/agent/src/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java index ee5c36176c8..6f49f47a1ed 100644 --- a/agent/src/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java +++ b/agent/src/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java @@ -32,6 +32,7 @@ import java.util.Properties; import javax.naming.ConfigurationException; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.log4j.Logger; import com.cloud.agent.Agent.ExitStatus; @@ -357,8 +358,9 @@ public class ConsoleProxyResource extends ServerResourceBase implements private void launchConsoleProxy(final byte[] ksBits, final String ksPassword, final String encryptorPassword) { final Object resource = this; if (_consoleProxyMain == null) { - _consoleProxyMain = new Thread(new Runnable() { - public void run() { + _consoleProxyMain = new Thread(new ManagedContextRunnable() { + @Override + protected void runInContext() { try { Class consoleProxyClazz = Class.forName("com.cloud.consoleproxy.ConsoleProxy"); try { diff --git a/api/src/org/apache/cloudstack/context/CallContext.java b/api/src/org/apache/cloudstack/context/CallContext.java index 114f626cf95..a9867d3bb70 100644 --- a/api/src/org/apache/cloudstack/context/CallContext.java +++ b/api/src/org/apache/cloudstack/context/CallContext.java @@ -18,8 +18,10 @@ package org.apache.cloudstack.context; import java.util.HashMap; import java.util.Map; +import java.util.Stack; import java.util.UUID; +import org.apache.cloudstack.managed.threadlocal.ManagedThreadLocal; import org.apache.log4j.Logger; import org.apache.log4j.NDC; @@ -37,7 +39,14 @@ import com.cloud.utils.exception.CloudRuntimeException; */ public class CallContext { private static final Logger s_logger = Logger.getLogger(CallContext.class); - private static final ThreadLocal s_currentContext = new ThreadLocal(); + private static ManagedThreadLocal s_currentContext = new ManagedThreadLocal(); + private static ManagedThreadLocal> s_currentContextStack = + new ManagedThreadLocal>() { + @Override + protected Stack initialValue() { + return new Stack(); + } + }; private String contextId; private Account account; @@ -115,6 +124,9 @@ public class CallContext { if (s_logger.isTraceEnabled()) { s_logger.trace("Registered: " + callingContext); } + + s_currentContextStack.get().push(callingContext); + return callingContext; } @@ -162,10 +174,15 @@ public class CallContext { return register(user, account); } + public static void unregisterAll() { + while ( unregister() != null ) { + // NOOP + } + } + public static CallContext unregister() { CallContext context = s_currentContext.get(); if (context == null) { - s_logger.debug("No context to remove"); return null; } s_currentContext.remove(); @@ -183,6 +200,14 @@ public class CallContext { s_logger.trace("Popping from NDC: " + contextId); } } + + Stack stack = s_currentContextStack.get(); + stack.pop(); + + if ( ! stack.isEmpty() ) { + s_currentContext.set(stack.peek()); + } + return context; } diff --git a/api/src/org/apache/cloudstack/context/CallContextListener.java b/api/src/org/apache/cloudstack/context/CallContextListener.java new file mode 100644 index 00000000000..9464f3d596e --- /dev/null +++ b/api/src/org/apache/cloudstack/context/CallContextListener.java @@ -0,0 +1,53 @@ +/* + * 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.cloudstack.context; + +import javax.annotation.PostConstruct; +import javax.inject.Inject; + +import org.apache.cloudstack.managed.context.ManagedContextListener; + +import com.cloud.utils.db.EntityManager; + +public class CallContextListener implements ManagedContextListener { + + @Inject + EntityManager entityMgr; + + @Override + public Object onEnterContext(boolean reentry) { + if ( ! reentry ) { + CallContext.registerSystemCallContextOnceOnly(); + } + + return null; + } + + @Override + public void onLeaveContext(Object unused, boolean reentry) { + if ( ! reentry ) { + CallContext.unregisterAll(); + } + } + + @PostConstruct + public void init() { + CallContext.init(entityMgr); + } +} diff --git a/awsapi/src/com/cloud/bridge/service/controller/s3/ServiceProvider.java b/awsapi/src/com/cloud/bridge/service/controller/s3/ServiceProvider.java index a0892cc979b..2623efe1f61 100644 --- a/awsapi/src/com/cloud/bridge/service/controller/s3/ServiceProvider.java +++ b/awsapi/src/com/cloud/bridge/service/controller/s3/ServiceProvider.java @@ -35,6 +35,7 @@ import javax.annotation.PostConstruct; import javax.inject.Inject; import org.apache.axis2.AxisFault; +import org.apache.cloudstack.managed.context.ManagedContextTimerTask; import org.apache.log4j.Logger; import org.apache.log4j.xml.DOMConfigurator; import org.springframework.stereotype.Component; @@ -280,10 +281,9 @@ public class ServiceProvider extends ManagerBase { } private TimerTask getHeartbeatTask() { - return new TimerTask() { - + return new ManagedContextTimerTask() { @Override - public void run() { + protected void runInContext() { try { mhost.setLastHeartbeatTime(DateHelper.currentGMTTime()); mhostDao.updateHeartBeat(mhost); diff --git a/client/tomcatconf/applicationContext.xml.in b/client/tomcatconf/applicationContext.xml.in index 9b6636abca5..6dda5c707af 100644 --- a/client/tomcatconf/applicationContext.xml.in +++ b/client/tomcatconf/applicationContext.xml.in @@ -52,6 +52,22 @@ + + + + + + + + + + + + + diff --git a/core/src/com/cloud/storage/template/HttpTemplateDownloader.java b/core/src/com/cloud/storage/template/HttpTemplateDownloader.java index 878961524e3..f0f19629841 100644 --- a/core/src/com/cloud/storage/template/HttpTemplateDownloader.java +++ b/core/src/com/cloud/storage/template/HttpTemplateDownloader.java @@ -40,7 +40,7 @@ import org.apache.commons.httpclient.auth.AuthScope; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.params.HttpMethodParams; import org.apache.log4j.Logger; - +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.storage.command.DownloadCommand.ResourceType; import com.cloud.agent.api.storage.Proxy; @@ -52,7 +52,7 @@ import com.cloud.utils.UriUtils; * Download a template file using HTTP * */ -public class HttpTemplateDownloader implements TemplateDownloader { +public class HttpTemplateDownloader extends ManagedContextRunnable implements TemplateDownloader { public static final Logger s_logger = Logger.getLogger(HttpTemplateDownloader.class.getName()); private static final MultiThreadedHttpConnectionManager s_httpClientManager = new MultiThreadedHttpConnectionManager(); @@ -350,7 +350,7 @@ public class HttpTemplateDownloader implements TemplateDownloader { } @Override - public void run() { + protected void runInContext() { try { download(resume, completionCallback); } catch (Throwable t) { diff --git a/core/src/com/cloud/storage/template/S3TemplateDownloader.java b/core/src/com/cloud/storage/template/S3TemplateDownloader.java index 05ed64bfb1e..dd595ea3c97 100644 --- a/core/src/com/cloud/storage/template/S3TemplateDownloader.java +++ b/core/src/com/cloud/storage/template/S3TemplateDownloader.java @@ -50,6 +50,7 @@ import com.amazonaws.services.s3.model.StorageClass; import com.amazonaws.services.s3.transfer.TransferManager; import com.amazonaws.services.s3.transfer.Upload; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.storage.command.DownloadCommand.ResourceType; import com.cloud.agent.api.storage.Proxy; @@ -62,7 +63,7 @@ import com.cloud.utils.UriUtils; * Download a template file using HTTP * */ -public class S3TemplateDownloader implements TemplateDownloader { +public class S3TemplateDownloader extends ManagedContextRunnable implements TemplateDownloader { public static final Logger s_logger = Logger.getLogger(S3TemplateDownloader.class.getName()); private static final MultiThreadedHttpConnectionManager s_httpClientManager = new MultiThreadedHttpConnectionManager(); @@ -361,7 +362,7 @@ public class S3TemplateDownloader implements TemplateDownloader { } @Override - public void run() { + protected void runInContext() { try { download(resume, completionCallback); } catch (Throwable t) { diff --git a/core/src/com/cloud/storage/template/TemplateDownloaderBase.java b/core/src/com/cloud/storage/template/TemplateDownloaderBase.java index bdbdd457be1..7cbd4efe02d 100644 --- a/core/src/com/cloud/storage/template/TemplateDownloaderBase.java +++ b/core/src/com/cloud/storage/template/TemplateDownloaderBase.java @@ -18,11 +18,12 @@ package com.cloud.storage.template; import java.io.File; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.log4j.Logger; import com.cloud.storage.StorageLayer; -public abstract class TemplateDownloaderBase implements TemplateDownloader { +public abstract class TemplateDownloaderBase extends ManagedContextRunnable implements TemplateDownloader { private static final Logger s_logger = Logger.getLogger(TemplateDownloaderBase.class); protected String _downloadUrl; @@ -123,7 +124,7 @@ public abstract class TemplateDownloaderBase implements TemplateDownloader { } @Override - public void run() { + protected void runInContext() { try { download(_resume, _callback); } catch (Exception e) { diff --git a/engine/components-api/src/org/apache/cloudstack/context/ServerContexts.java b/engine/components-api/src/org/apache/cloudstack/context/ServerContexts.java deleted file mode 100644 index b9c249ce620..00000000000 --- a/engine/components-api/src/org/apache/cloudstack/context/ServerContexts.java +++ /dev/null @@ -1,67 +0,0 @@ -// 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.cloudstack.context; - -import org.apache.cloudstack.framework.jobs.AsyncJob; - -import com.cloud.utils.db.Transaction; - -/** - * ServerContextInitializer is responsible for properly setting up the - * contexts that all of the CloudStack code expects. This includes - * - CallContext - * - JobContext - * - TransactionContext - */ -public class ServerContexts { - public static void registerUserContext(long userId, long accountId) { - Transaction txn = Transaction.open(Thread.currentThread().getName()); - CallContext context = CallContext.register(userId, accountId); - context.putContextParameter("Transaction", txn); -// AsyncJobExecutionContext.registerPseudoExecutionContext(userId, accountId); - } - - public static void unregisterUserContext() { - CallContext context = CallContext.unregister(); - if (context != null) { -// AsyncJobExecutionContext.unregister(); - Transaction txn = (Transaction)context.getContextParameter("Transaction"); - txn.close(Thread.currentThread().getName()); - } - } - - /** - * Use this method to initialize the internal background threads. - */ - public static void registerSystemContext() { - Transaction txn = Transaction.open(Thread.currentThread().getName()); - CallContext context = CallContext.registerSystemCallContextOnceOnly(); - context.putContextParameter("Transaction", txn); -// AsyncJobExecutionContext.registerPseudoExecutionContext(Account.ACCOUNT_ID_SYSTEM, User.UID_SYSTEM); - } - - public static void unregisterSystemContext() { - CallContext context = CallContext.unregister(); -// AsyncJobExecutionContext.unregister(); - Transaction txn = (Transaction)context.getContextParameter("Transaction"); - txn.close(Thread.currentThread().getName()); - } - - public static void registerJobContext(long userId, long accountId, AsyncJob job) { - CallContext.register(userId, accountId); - } -} diff --git a/engine/orchestration/src/com/cloud/agent/manager/AgentAttache.java b/engine/orchestration/src/com/cloud/agent/manager/AgentAttache.java index 67deba0d648..5b1007b26f0 100755 --- a/engine/orchestration/src/com/cloud/agent/manager/AgentAttache.java +++ b/engine/orchestration/src/com/cloud/agent/manager/AgentAttache.java @@ -31,6 +31,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.log4j.Logger; import com.cloud.agent.Listener; @@ -497,14 +498,14 @@ public abstract class AgentAttache { */ protected abstract boolean isClosed(); - protected class Alarm implements Runnable { + protected class Alarm extends ManagedContextRunnable { long _seq; public Alarm(long seq) { _seq = seq; } @Override - public void run() { + protected void runInContext() { try { Listener listener = unregisterListener(_seq); if (listener != null) { diff --git a/engine/orchestration/src/com/cloud/agent/manager/AgentManagerImpl.java b/engine/orchestration/src/com/cloud/agent/manager/AgentManagerImpl.java index 51f6d72109e..42020153448 100755 --- a/engine/orchestration/src/com/cloud/agent/manager/AgentManagerImpl.java +++ b/engine/orchestration/src/com/cloud/agent/manager/AgentManagerImpl.java @@ -38,13 +38,12 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; -import org.apache.log4j.Logger; - -import org.apache.cloudstack.context.ServerContexts; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.Configurable; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.utils.identity.ManagementServerNode; +import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; import com.cloud.agent.Listener; @@ -843,7 +842,7 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl return true; } - protected class DisconnectTask implements Runnable { + protected class DisconnectTask extends ManagedContextRunnable { AgentAttache _attache; Status.Event _event; boolean _investigate; @@ -855,7 +854,7 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl } @Override - public void run() { + protected void runInContext() { try { if (_investigate == true) { handleDisconnectWithInvestigation(_attache, _event); @@ -1017,7 +1016,7 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl return attache; } - protected class SimulateStartTask implements Runnable { + protected class SimulateStartTask extends ManagedContextRunnable { ServerResource resource; Map details; long id; @@ -1029,8 +1028,7 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl } @Override - public void run() { - ServerContexts.registerSystemContext(); + protected void runInContext() { try { if (s_logger.isDebugEnabled()) { s_logger.debug("Simulating start for resource " + resource.getName() + " id " + id); @@ -1054,13 +1052,11 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl } } catch (Exception e) { s_logger.warn("Unable to simulate start on resource " + id + " name " + resource.getName(), e); - } finally { - ServerContexts.unregisterSystemContext(); } } } - protected class HandleAgentConnectTask implements Runnable { + protected class HandleAgentConnectTask extends ManagedContextRunnable { Link _link; Command[] _cmds; Request _request; @@ -1071,22 +1067,16 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl _request = request; } - @Override - public void run() { - ServerContexts.registerSystemContext(); - try { - _request.logD("Processing the first command "); - StartupCommand[] startups = new StartupCommand[_cmds.length]; - for (int i = 0; i < _cmds.length; i++) { - startups[i] = (StartupCommand)_cmds[i]; - } + protected void runInContext() { + _request.logD("Processing the first command "); + StartupCommand[] startups = new StartupCommand[_cmds.length]; + for (int i = 0; i < _cmds.length; i++) { + startups[i] = (StartupCommand)_cmds[i]; + } - AgentAttache attache = handleConnectedAgent(_link, startups, _request); - if (attache == null) { - s_logger.warn("Unable to create attache for agent: " + _request); - } - } finally { - ServerContexts.unregisterSystemContext(); + AgentAttache attache = handleConnectedAgent(_link, startups, _request); + if (attache == null) { + s_logger.warn("Unable to create attache for agent: " + _request); } } } @@ -1439,9 +1429,9 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl _pingMap.put(agentId, InaccurateClock.getTimeInSeconds()); } - protected class MonitorTask implements Runnable { + protected class MonitorTask extends ManagedContextRunnable { @Override - public void run() { + protected void runInContext() { s_logger.trace("Agent Monitor is started."); try { diff --git a/engine/orchestration/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java b/engine/orchestration/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java index 76e1d8e33b6..48f096ade22 100755 --- a/engine/orchestration/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java +++ b/engine/orchestration/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java @@ -32,7 +32,6 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.Timer; -import java.util.TimerTask; import java.util.concurrent.Executors; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.ScheduledExecutorService; @@ -51,6 +50,8 @@ import com.google.gson.Gson; import org.apache.cloudstack.framework.config.ConfigDepot; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; +import org.apache.cloudstack.managed.context.ManagedContextTimerTask; import org.apache.cloudstack.utils.identity.ManagementServerNode; import com.cloud.agent.AgentManager; @@ -231,9 +232,9 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust } } - private class DirectAgentScanTimerTask extends TimerTask { + private class DirectAgentScanTimerTask extends ManagedContextTimerTask { @Override - public void run() { + protected void runInContext() { try { runDirectAgentScanTimerTask(); } catch (Throwable e) { @@ -746,7 +747,7 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust _timer.schedule(new AgentLoadBalancerTask(), 30000); } - public class AgentLoadBalancerTask extends TimerTask { + public class AgentLoadBalancerTask extends ManagedContextTimerTask { protected volatile boolean cancelled = false; public AgentLoadBalancerTask() { @@ -764,7 +765,7 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust } @Override - public synchronized void run() { + protected synchronized void runInContext() { try { if (!cancelled) { startRebalanceAgents(); @@ -925,9 +926,9 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust } private Runnable getTransferScanTask() { - return new Runnable() { + return new ManagedContextRunnable() { @Override - public void run() { + protected void runInContext() { try { if (s_logger.isTraceEnabled()) { s_logger.trace("Clustered agent transfer scan check, management server id:" + _nodeId); @@ -1173,7 +1174,7 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust } - protected class RebalanceTask implements Runnable { + protected class RebalanceTask extends ManagedContextRunnable { Long hostId = null; Long currentOwnerId = null; Long futureOwnerId = null; @@ -1186,7 +1187,7 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust } @Override - public void run() { + protected void runInContext() { try { if (s_logger.isDebugEnabled()) { s_logger.debug("Rebalancing host id=" + hostId); diff --git a/engine/orchestration/src/com/cloud/agent/manager/DirectAgentAttache.java b/engine/orchestration/src/com/cloud/agent/manager/DirectAgentAttache.java index 5b5d8d21289..2808c6af91a 100755 --- a/engine/orchestration/src/com/cloud/agent/manager/DirectAgentAttache.java +++ b/engine/orchestration/src/com/cloud/agent/manager/DirectAgentAttache.java @@ -21,6 +21,7 @@ import java.util.List; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.log4j.Logger; import com.cloud.agent.api.Answer; @@ -127,9 +128,9 @@ public class DirectAgentAttache extends AgentAttache { } } - protected class PingTask implements Runnable { + protected class PingTask extends ManagedContextRunnable { @Override - public synchronized void run() { + protected synchronized void runInContext() { try { ServerResource resource = _resource; @@ -160,7 +161,7 @@ public class DirectAgentAttache extends AgentAttache { } - protected class Task implements Runnable { + protected class Task extends ManagedContextRunnable { Request _req; public Task(Request req) { @@ -168,7 +169,7 @@ public class DirectAgentAttache extends AgentAttache { } @Override - public void run() { + protected void runInContext() { long seq = _req.getSequence(); try { ServerResource resource = _resource; diff --git a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java index 560bab26fff..8bf419f1a65 100755 --- a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -47,6 +47,7 @@ import org.apache.cloudstack.framework.config.ConfigDepot; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.Configurable; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.utils.identity.ManagementServerNode; @@ -1835,9 +1836,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } } - protected class CleanupTask implements Runnable { + protected class CleanupTask extends ManagedContextRunnable { @Override - public void run() { + protected void runInContext() { s_logger.trace("VM Operation Thread Running"); try { _workDao.cleanup(VmOpCleanupWait.value()); @@ -2588,9 +2589,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } } - protected class TransitionTask implements Runnable { + protected class TransitionTask extends ManagedContextRunnable { @Override - public void run() { + protected void runInContext() { GlobalLock lock = GlobalLock.getInternLock("TransitionChecking"); if (lock == null) { s_logger.debug("Couldn't get the global lock"); diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java index 0b13fb40003..3c4b1ed5e72 100755 --- a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java @@ -37,15 +37,14 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; import org.apache.log4j.Logger; - import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.context.CallContext; -import org.apache.cloudstack.context.ServerContexts; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.framework.config.ConfigDepot; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.Configurable; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.region.PortableIpDao; import com.cloud.agent.AgentManager; @@ -2195,10 +2194,9 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra return result; } - public class NetworkGarbageCollector implements Runnable { + public class NetworkGarbageCollector extends ManagedContextRunnable { @Override - public void run() { - ServerContexts.registerSystemContext(); + protected void runInContext() { GlobalLock gcLock = GlobalLock.getInternLock("Network.GC.Lock"); try { if (gcLock.lock(3)) { @@ -2210,7 +2208,6 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra } } finally { gcLock.releaseRef(); - ServerContexts.unregisterSystemContext(); } } diff --git a/engine/storage/cache/src/org/apache/cloudstack/storage/cache/manager/StorageCacheManagerImpl.java b/engine/storage/cache/src/org/apache/cloudstack/storage/cache/manager/StorageCacheManagerImpl.java index 7f335c53315..bb8d67d321f 100644 --- a/engine/storage/cache/src/org/apache/cloudstack/storage/cache/manager/StorageCacheManagerImpl.java +++ b/engine/storage/cache/src/org/apache/cloudstack/storage/cache/manager/StorageCacheManagerImpl.java @@ -45,6 +45,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.Scope; import org.apache.cloudstack.engine.subsystem.api.storage.StorageCacheManager; import org.apache.cloudstack.framework.async.AsyncCallFuture; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.storage.cache.allocator.StorageCacheAllocator; import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager; import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; @@ -145,10 +146,10 @@ public class StorageCacheManagerImpl implements StorageCacheManager, Manager { return true; } - protected class CacheReplacementRunner implements Runnable { + protected class CacheReplacementRunner extends ManagedContextRunnable { @Override - public void run() { + protected void runInContext() { GlobalLock replacementLock = null; try { replacementLock = GlobalLock.getInternLock("storageCacheMgr.replacement"); @@ -271,4 +272,4 @@ public class StorageCacheManagerImpl implements StorageCacheManager, Manager { public boolean deleteCacheObject(DataObject data) { return data.getDataStore().delete(data); } -} \ No newline at end of file +} diff --git a/engine/storage/src/org/apache/cloudstack/storage/LocalHostEndpoint.java b/engine/storage/src/org/apache/cloudstack/storage/LocalHostEndpoint.java index 83d34a07f4a..53803bf594c 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/LocalHostEndpoint.java +++ b/engine/storage/src/org/apache/cloudstack/storage/LocalHostEndpoint.java @@ -21,24 +21,23 @@ import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import com.cloud.configuration.Config; -import com.cloud.utils.component.ComponentContext; +import javax.inject.Inject; import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; -import org.apache.cloudstack.framework.config.dao.ConfigurationDaoImpl; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.storage.command.CopyCommand; import org.apache.cloudstack.storage.command.DownloadCommand; import org.apache.cloudstack.storage.resource.LocalNfsSecondaryStorageResource; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; +import com.cloud.configuration.Config; import com.cloud.resource.ServerResource; +import com.cloud.utils.component.ComponentContext; import com.cloud.utils.net.NetUtils; -import javax.inject.Inject; - public class LocalHostEndpoint implements EndPoint { private ScheduledExecutorService executor; protected ServerResource resource; @@ -97,7 +96,7 @@ public class LocalHostEndpoint implements EndPoint { return new Answer(cmd, false, "unsupported command:" + cmd.toString()); } - private class CmdRunner implements Runnable { + private class CmdRunner extends ManagedContextRunnable { final Command cmd; final AsyncCompletionCallback callback; @@ -107,7 +106,7 @@ public class LocalHostEndpoint implements EndPoint { } @Override - public void run() { + protected void runInContext() { Answer answer = sendMessage(cmd); callback.complete(answer); } diff --git a/engine/storage/src/org/apache/cloudstack/storage/RemoteHostEndPoint.java b/engine/storage/src/org/apache/cloudstack/storage/RemoteHostEndPoint.java index 369381358a8..3cae2b95f1d 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/RemoteHostEndPoint.java +++ b/engine/storage/src/org/apache/cloudstack/storage/RemoteHostEndPoint.java @@ -26,6 +26,7 @@ import javax.inject.Inject; import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; @@ -104,7 +105,7 @@ public class RemoteHostEndPoint implements EndPoint { throw new CloudRuntimeException("Failed to send command, due to Agent:" + getId() + ", " + errMsg); } - private class CmdRunner implements Listener, Runnable { + private class CmdRunner extends ManagedContextRunnable implements Listener { final AsyncCompletionCallback callback; Answer answer; @@ -162,7 +163,7 @@ public class RemoteHostEndPoint implements EndPoint { } @Override - public void run() { + protected void runInContext() { callback.complete(answer); } } diff --git a/framework/cluster/src/com/cloud/cluster/ClusterManagerImpl.java b/framework/cluster/src/com/cloud/cluster/ClusterManagerImpl.java index 0f1cf9da487..56d405e98e9 100644 --- a/framework/cluster/src/com/cloud/cluster/ClusterManagerImpl.java +++ b/framework/cluster/src/com/cloud/cluster/ClusterManagerImpl.java @@ -48,6 +48,7 @@ import org.apache.log4j.Logger; import org.apache.cloudstack.framework.config.ConfigDepot; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.Configurable; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.utils.identity.ManagementServerNode; import com.cloud.cluster.dao.ManagementServerHostDao; @@ -217,18 +218,18 @@ public class ClusterManagerImpl extends ManagerBase implements ClusterManager, C } private Runnable getClusterPduSendingTask() { - return new Runnable() { + return new ManagedContextRunnable() { @Override - public void run() { + protected void runInContext() { onSendingClusterPdu(); } }; } private Runnable getClusterPduNotificationTask() { - return new Runnable() { + return new ManagedContextRunnable() { @Override - public void run() { + protected void runInContext() { onNotifyingClusterPdu(); } }; @@ -289,9 +290,9 @@ public class ClusterManagerImpl extends ManagerBase implements ClusterManager, C if(pdu == null) continue; - _executor.execute(new Runnable() { + _executor.execute(new ManagedContextRunnable() { @Override - public void run() { + protected void runInContext() { if(pdu.getPduType() == ClusterServicePdu.PDU_TYPE_RESPONSE) { ClusterServiceRequestPdu requestPdu = popRequestPdu(pdu.getAckSequenceId()); if(requestPdu != null) { @@ -528,9 +529,9 @@ public class ClusterManagerImpl extends ManagerBase implements ClusterManager, C } private Runnable getHeartbeatTask() { - return new Runnable() { + return new ManagedContextRunnable() { @Override - public void run() { + protected void runInContext() { Transaction txn = Transaction.open("ClusterHeartbeat"); try { Profiler profiler = new Profiler(); @@ -636,9 +637,9 @@ public class ClusterManagerImpl extends ManagerBase implements ClusterManager, C } private Runnable getNotificationTask() { - return new Runnable() { + return new ManagedContextRunnable() { @Override - public void run() { + protected void runInContext() { while(true) { synchronized(_notificationMsgs) { try { diff --git a/framework/cluster/src/com/cloud/cluster/ClusterServiceServletContainer.java b/framework/cluster/src/com/cloud/cluster/ClusterServiceServletContainer.java index def3e178116..019d83de8ac 100644 --- a/framework/cluster/src/com/cloud/cluster/ClusterServiceServletContainer.java +++ b/framework/cluster/src/com/cloud/cluster/ClusterServiceServletContainer.java @@ -22,6 +22,7 @@ import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.http.ConnectionClosedException; import org.apache.http.HttpException; import org.apache.http.impl.DefaultConnectionReuseStrategy; @@ -129,8 +130,9 @@ public class ClusterServiceServletContainer { final DefaultHttpServerConnection conn = new DefaultHttpServerConnection(); conn.bind(socket, _params); - _executor.execute(new Runnable() { - public void run() { + _executor.execute(new ManagedContextRunnable() { + @Override + protected void runInContext() { HttpContext context = new BasicHttpContext(null); try { while(!Thread.interrupted() && conn.isOpen()) { diff --git a/framework/db/src/com/cloud/utils/db/ConnectionConcierge.java b/framework/db/src/com/cloud/utils/db/ConnectionConcierge.java index 029433453bf..c3c24f94766 100644 --- a/framework/db/src/com/cloud/utils/db/ConnectionConcierge.java +++ b/framework/db/src/com/cloud/utils/db/ConnectionConcierge.java @@ -30,6 +30,7 @@ import java.util.concurrent.atomic.AtomicInteger; import javax.management.StandardMBean; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.log4j.Logger; import com.cloud.utils.concurrency.NamedThreadFactory; @@ -198,10 +199,9 @@ public class ConnectionConcierge { _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("ConnectionConcierge")); - _executor.scheduleAtFixedRate(new Runnable() { - + _executor.scheduleAtFixedRate(new ManagedContextRunnable() { @Override - public void run() { + protected void runInContext() { s_logger.trace("connection concierge keep alive task"); for (Map.Entry entry : _conns.entrySet()) { ConnectionConcierge concierge = entry.getValue(); diff --git a/framework/ipc/src/org/apache/cloudstack/framework/client/ClientTransportProvider.java b/framework/ipc/src/org/apache/cloudstack/framework/client/ClientTransportProvider.java index 023b3181b20..923578cf5f1 100644 --- a/framework/ipc/src/org/apache/cloudstack/framework/client/ClientTransportProvider.java +++ b/framework/ipc/src/org/apache/cloudstack/framework/client/ClientTransportProvider.java @@ -27,6 +27,7 @@ import org.apache.cloudstack.framework.serializer.MessageSerializer; import org.apache.cloudstack.framework.transport.TransportEndpoint; import org.apache.cloudstack.framework.transport.TransportEndpointSite; import org.apache.cloudstack.framework.transport.TransportProvider; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import com.cloud.utils.concurrency.NamedThreadFactory; @@ -62,10 +63,9 @@ public class ClientTransportProvider implements TransportProvider { _executor = Executors.newFixedThreadPool(_poolSize, new NamedThreadFactory("Transport-Worker")); _connection = new ClientTransportConnection(this); - _executor.execute(new Runnable() { - - @Override - public void run() { + _executor.execute(new ManagedContextRunnable() { + @Override + protected void runInContext() { try { _connection.connect(_serverAddress, _serverPort); } catch(Throwable e) { diff --git a/framework/ipc/src/org/apache/cloudstack/framework/server/ServerTransportProvider.java b/framework/ipc/src/org/apache/cloudstack/framework/server/ServerTransportProvider.java index b19a7c9265f..45c3e2a41d7 100644 --- a/framework/ipc/src/org/apache/cloudstack/framework/server/ServerTransportProvider.java +++ b/framework/ipc/src/org/apache/cloudstack/framework/server/ServerTransportProvider.java @@ -31,6 +31,7 @@ import org.apache.cloudstack.framework.transport.TransportEndpoint; import org.apache.cloudstack.framework.transport.TransportEndpointSite; import org.apache.cloudstack.framework.transport.TransportPdu; import org.apache.cloudstack.framework.transport.TransportProvider; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.log4j.Logger; import com.cloud.utils.concurrency.NamedThreadFactory; @@ -132,11 +133,10 @@ public class ServerTransportProvider implements TransportProvider { @Override public void requestSiteOutput(final TransportEndpointSite site) { - _executor.execute(new Runnable() { - - @Override - public void run() { - try { + _executor.execute(new ManagedContextRunnable() { + @Override + protected void runInContext() { + try { site.processOutput(); site.ackOutputProcessSignal(); } catch(Throwable e) { diff --git a/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJobExecutionContext.java b/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJobExecutionContext.java index 01365939127..595800d2524 100644 --- a/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJobExecutionContext.java +++ b/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJobExecutionContext.java @@ -17,12 +17,12 @@ package org.apache.cloudstack.framework.jobs; import org.apache.log4j.Logger; - import org.apache.cloudstack.framework.jobs.dao.AsyncJobJoinMapDao; import org.apache.cloudstack.framework.jobs.impl.AsyncJobJoinMapVO; import org.apache.cloudstack.framework.jobs.impl.JobSerializerHelper; import org.apache.cloudstack.framework.jobs.impl.SyncQueueItem; import org.apache.cloudstack.jobs.JobInfo; +import org.apache.cloudstack.managed.threadlocal.ManagedThreadLocal; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; @@ -39,7 +39,7 @@ public class AsyncJobExecutionContext { _joinMapDao = joinMapDao; } - private static ThreadLocal s_currentExectionContext = new ThreadLocal(); + private static ManagedThreadLocal s_currentExectionContext = new ManagedThreadLocal(); public AsyncJobExecutionContext() { } diff --git a/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java b/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java index 2ddb1158c8c..93d50c11233 100644 --- a/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java +++ b/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java @@ -36,7 +36,6 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; import org.apache.log4j.Logger; - import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.framework.config.ConfigDepot; import org.apache.cloudstack.framework.config.ConfigKey; @@ -54,6 +53,7 @@ import org.apache.cloudstack.framework.messagebus.MessageDetector; import org.apache.cloudstack.framework.messagebus.PublishScope; import org.apache.cloudstack.jobs.JobInfo; import org.apache.cloudstack.jobs.JobInfo.Status; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.utils.identity.ManagementServerNode; import com.cloud.cluster.ClusterManagerListener; @@ -490,9 +490,9 @@ public class AsyncJobManagerImpl extends ManagerBase implements AsyncJobManager, } private Runnable getExecutorRunnable(final AsyncJob job) { - return new Runnable() { + return new ManagedContextRunnable() { @Override - public void run() { + protected void runInContext() { Transaction txn = null; long runNumber = getJobRunNumber(); @@ -687,9 +687,9 @@ public class AsyncJobManagerImpl extends ManagerBase implements AsyncJobManager, } private Runnable getHeartbeatTask() { - return new Runnable() { + return new ManagedContextRunnable() { @Override - public void run() { + protected void runInContext() { Transaction txn = Transaction.open("AsyncJobManagerImpl.getHeartbeatTask"); try { List l = _queueMgr.dequeueFromAny(getMsid(), MAX_ONETIME_SCHEDULE_SIZE); @@ -724,9 +724,9 @@ public class AsyncJobManagerImpl extends ManagerBase implements AsyncJobManager, @DB private Runnable getGCTask() { - return new Runnable() { + return new ManagedContextRunnable() { @Override - public void run() { + protected void runInContext() { GlobalLock scanLock = GlobalLock.getInternLock("AsyncJobManagerGC"); try { if (scanLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION)) { diff --git a/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/AsyncJobMonitor.java b/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/AsyncJobMonitor.java index ad0da35adb3..8ea75289dfd 100644 --- a/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/AsyncJobMonitor.java +++ b/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/AsyncJobMonitor.java @@ -26,12 +26,12 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; import org.apache.log4j.Logger; - import org.apache.cloudstack.framework.jobs.AsyncJob; import org.apache.cloudstack.framework.jobs.AsyncJobManager; import org.apache.cloudstack.framework.messagebus.MessageBus; import org.apache.cloudstack.framework.messagebus.MessageDispatcher; import org.apache.cloudstack.framework.messagebus.MessageHandler; +import org.apache.cloudstack.managed.context.ManagedContextTimerTask; import com.cloud.utils.component.ManagerBase; @@ -97,10 +97,9 @@ public class AsyncJobMonitor extends ManagerBase { throws ConfigurationException { _messageBus.subscribe(AsyncJob.Topics.JOB_HEARTBEAT, MessageDispatcher.getDispatcher(this)); - _timer.scheduleAtFixedRate(new TimerTask() { - + _timer.scheduleAtFixedRate(new ManagedContextTimerTask() { @Override - public void run() { + protected void runInContext() { heartbeat(); } diff --git a/framework/managed-context/pom.xml b/framework/managed-context/pom.xml new file mode 100644 index 00000000000..b4a9d83a005 --- /dev/null +++ b/framework/managed-context/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + cloud-framework-managed-context + Apache CloudStack Framework - Managed Context + + org.apache.cloudstack + cloud-maven-standard + 4.3.0-SNAPSHOT + ../../maven-standard/pom.xml + + + + org.slf4j + slf4j-api + + + diff --git a/framework/managed-context/src/main/java/org/apache/cloudstack/managed/context/AbstractManagedContextListener.java b/framework/managed-context/src/main/java/org/apache/cloudstack/managed/context/AbstractManagedContextListener.java new file mode 100644 index 00000000000..21f63a68f81 --- /dev/null +++ b/framework/managed-context/src/main/java/org/apache/cloudstack/managed/context/AbstractManagedContextListener.java @@ -0,0 +1,32 @@ +/* + * 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.cloudstack.managed.context; + +public class AbstractManagedContextListener implements ManagedContextListener { + + @Override + public T onEnterContext(boolean reentry) { + return null; + } + + @Override + public void onLeaveContext(T data, boolean reentry) { + } + +} \ No newline at end of file diff --git a/framework/managed-context/src/main/java/org/apache/cloudstack/managed/context/ManagedContext.java b/framework/managed-context/src/main/java/org/apache/cloudstack/managed/context/ManagedContext.java new file mode 100644 index 00000000000..5023725d0de --- /dev/null +++ b/framework/managed-context/src/main/java/org/apache/cloudstack/managed/context/ManagedContext.java @@ -0,0 +1,33 @@ +/* + * 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.cloudstack.managed.context; + +import java.util.concurrent.Callable; + +public interface ManagedContext { + + public void registerListener(ManagedContextListener listener); + + public void unregisterListener(ManagedContextListener listener); + + public void runWithContext(Runnable run); + + public T callWithContext(Callable callable) throws Exception; + +} \ No newline at end of file diff --git a/framework/managed-context/src/main/java/org/apache/cloudstack/managed/context/ManagedContextListener.java b/framework/managed-context/src/main/java/org/apache/cloudstack/managed/context/ManagedContextListener.java new file mode 100644 index 00000000000..2f85a5f69ab --- /dev/null +++ b/framework/managed-context/src/main/java/org/apache/cloudstack/managed/context/ManagedContextListener.java @@ -0,0 +1,36 @@ +/* + * 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.cloudstack.managed.context; + +public interface ManagedContextListener { + + /** + * @param reentry True if listener is being invoked in a nested context + * @return + */ + public T onEnterContext(boolean reentry); + + + /** + * @param data The data returned from the onEnterContext call + * @param reentry True if listener is being invoked in a nested context + */ + public void onLeaveContext(T data, boolean reentry); + +} diff --git a/framework/managed-context/src/main/java/org/apache/cloudstack/managed/context/ManagedContextRunnable.java b/framework/managed-context/src/main/java/org/apache/cloudstack/managed/context/ManagedContextRunnable.java new file mode 100644 index 00000000000..2f3d0c8a71f --- /dev/null +++ b/framework/managed-context/src/main/java/org/apache/cloudstack/managed/context/ManagedContextRunnable.java @@ -0,0 +1,86 @@ +/* + * 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.cloudstack.managed.context; + +import org.apache.cloudstack.managed.context.impl.DefaultManagedContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class ManagedContextRunnable implements Runnable { + + private static final int SLEEP_COUNT = 120; + + private static final Logger log = LoggerFactory.getLogger(ManagedContextRunnable.class); + private static final ManagedContext DEFAULT_MANAGED_CONTEXT = new DefaultManagedContext(); + private static ManagedContext context; + private static boolean managedContext = false; + + + /* This is slightly dirty, but the idea is that we only save the ManagedContext + * in a static global. Any ManagedContextListener can be a fully managed object + * and not have to rely on global statics + */ + public static ManagedContext initializeGlobalContext(ManagedContext context) { + setManagedContext(true); + return ManagedContextRunnable.context = context; + } + + @Override + final public void run() { + getContext().runWithContext(new Runnable() { + @Override + public void run() { + runInContext(); + } + }); + } + + protected abstract void runInContext(); + + protected ManagedContext getContext() { + if ( ! managedContext ) + return DEFAULT_MANAGED_CONTEXT; + + for ( int i = 0 ; i < SLEEP_COUNT ; i++ ) { + if ( context == null ) { + try { + Thread.sleep(1000); + + if ( context == null ) + log.info("Sleeping until ManagedContext becomes available"); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } else { + return context; + } + } + + throw new RuntimeException("Failed to obtain ManagedContext"); + } + + public static boolean isManagedContext() { + return managedContext; + } + + public static void setManagedContext(boolean managedContext) { + ManagedContextRunnable.managedContext = managedContext; + } + +} \ No newline at end of file diff --git a/framework/managed-context/src/main/java/org/apache/cloudstack/managed/context/ManagedContextTimerTask.java b/framework/managed-context/src/main/java/org/apache/cloudstack/managed/context/ManagedContextTimerTask.java new file mode 100644 index 00000000000..894d27c7c42 --- /dev/null +++ b/framework/managed-context/src/main/java/org/apache/cloudstack/managed/context/ManagedContextTimerTask.java @@ -0,0 +1,37 @@ +/* + * 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.cloudstack.managed.context; + +import java.util.TimerTask; + +public abstract class ManagedContextTimerTask extends TimerTask { + + @Override + public final void run() { + new ManagedContextRunnable() { + @Override + protected void runInContext() { + ManagedContextTimerTask.this.runInContext(); + } + }.run(); + } + + protected abstract void runInContext(); + +} diff --git a/framework/managed-context/src/main/java/org/apache/cloudstack/managed/context/ManagedContextUtils.java b/framework/managed-context/src/main/java/org/apache/cloudstack/managed/context/ManagedContextUtils.java new file mode 100644 index 00000000000..75bb2056f02 --- /dev/null +++ b/framework/managed-context/src/main/java/org/apache/cloudstack/managed/context/ManagedContextUtils.java @@ -0,0 +1,55 @@ +/* + * 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.cloudstack.managed.context; + +public class ManagedContextUtils { + + private static final ThreadLocal OWNER = new ThreadLocal(); + + public static boolean setAndCheckOwner(Object owner) { + if ( OWNER.get() == null ) { + OWNER.set(owner); + return true; + } + + return false; + } + + public static boolean clearOwner(Object owner) { + if ( OWNER.get() == owner ) { + OWNER.remove(); + return true; + } + + return false; + } + + public static boolean isInContext() { + return OWNER.get() != null; + } + + public static void rethrowException(Throwable t) { + if ( t instanceof RuntimeException ) { + throw (RuntimeException)t; + } else if ( t instanceof Error ) { + throw (Error)t; + } + } + +} diff --git a/framework/managed-context/src/main/java/org/apache/cloudstack/managed/context/impl/DefaultManagedContext.java b/framework/managed-context/src/main/java/org/apache/cloudstack/managed/context/impl/DefaultManagedContext.java new file mode 100644 index 00000000000..6f5cbc98bec --- /dev/null +++ b/framework/managed-context/src/main/java/org/apache/cloudstack/managed/context/impl/DefaultManagedContext.java @@ -0,0 +1,155 @@ +/* + * 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.cloudstack.managed.context.impl; + +import java.util.List; +import java.util.Stack; +import java.util.concurrent.Callable; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.apache.cloudstack.managed.context.ManagedContext; +import org.apache.cloudstack.managed.context.ManagedContextListener; +import org.apache.cloudstack.managed.context.ManagedContextUtils; +import org.apache.cloudstack.managed.threadlocal.ManagedThreadLocal; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DefaultManagedContext implements ManagedContext { + + private static final Logger log = LoggerFactory.getLogger(DefaultManagedContext.class); + + List> listeners = + new CopyOnWriteArrayList>(); + + @Override + public void registerListener(ManagedContextListener listener) { + listeners.add(listener); + } + + @Override + public void unregisterListener(ManagedContextListener listener) { + listeners.remove(listener); + } + + @Override + public void runWithContext(final Runnable run) { + try { + callWithContext(new Callable() { + @Override + public Object call() throws Exception { + run.run(); + return null; + } + }); + } catch (Exception e) { + /* Only care about non-checked exceptions + * as the nature of runnable prevents checked + * exceptions from happening + */ + ManagedContextUtils.rethrowException(e); + } + } + + @SuppressWarnings("unchecked") + @Override + public T callWithContext(Callable callable) throws Exception { + Object owner = new Object(); + + Stack invocations = new Stack(); + boolean reentry = ! ManagedContextUtils.setAndCheckOwner(owner); + Throwable firstError = null; + + try { + for ( ManagedContextListener listener : listeners ) { + Object data = null; + + try { + data = listener.onEnterContext(reentry); + } catch ( Throwable t ) { + /* If one listener fails, still call all other listeners + * and then we will call onLeaveContext for all + */ + if ( firstError == null ) { + firstError = t; + } + log.error("Failed onEnterContext for listener [{}]", listener, t); + } + + /* Stack data structure is used because in between onEnter and onLeave + * the listeners list could have changed + */ + invocations.push(new ListenerInvocation((ManagedContextListener) listener, data)); + } + + try { + if ( firstError == null ) { + /* Only call if all the listeners didn't blow up on onEnterContext */ + return callable.call(); + } else { + throwException(firstError); + return null; + } + } finally { + Throwable lastError = null; + + while ( ! invocations.isEmpty() ) { + ListenerInvocation invocation = invocations.pop(); + try { + invocation.listener.onLeaveContext(invocation.data, reentry); + } catch ( Throwable t ) { + lastError = t; + log.error("Failed onLeaveContext for listener [{}]", invocation.listener, t); + } + } + + if ( firstError == null && lastError != null ) { + throwException(lastError); + } + } + } finally { + if ( ManagedContextUtils.clearOwner(owner) ) + ManagedThreadLocal.reset(); + } + }; + + protected void throwException(Throwable t) throws Exception { + ManagedContextUtils.rethrowException(t); + if ( t instanceof Exception ) { + throw (Exception)t; + } + } + public List> getListeners() { + return listeners; + } + + public void setListeners(List> listeners) { + this.listeners = new CopyOnWriteArrayList>(listeners); + } + + private static class ListenerInvocation { + ManagedContextListener listener; + Object data; + + public ListenerInvocation(ManagedContextListener listener, Object data) { + super(); + this.listener = listener; + this.data = data; + } + } +} diff --git a/framework/managed-context/src/main/java/org/apache/cloudstack/managed/threadlocal/ManagedThreadLocal.java b/framework/managed-context/src/main/java/org/apache/cloudstack/managed/threadlocal/ManagedThreadLocal.java new file mode 100644 index 00000000000..bde535cc179 --- /dev/null +++ b/framework/managed-context/src/main/java/org/apache/cloudstack/managed/threadlocal/ManagedThreadLocal.java @@ -0,0 +1,82 @@ +/* + * 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.cloudstack.managed.threadlocal; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.cloudstack.managed.context.ManagedContextUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ManagedThreadLocal extends ThreadLocal { + + private static final ThreadLocal> MANAGED_THREAD_LOCAL = new ThreadLocal>() { + @Override + protected Map initialValue() { + return new HashMap(); + } + }; + + private static boolean VALIDATE_CONTEXT = false; + private static final Logger log = LoggerFactory.getLogger(ManagedThreadLocal.class); + + @SuppressWarnings("unchecked") + @Override + public T get() { + validateInContext(this); + Map map = MANAGED_THREAD_LOCAL.get(); + Object result = map.get(this); + if ( result == null ) { + result = initialValue(); + map.put(this, result); + } + return (T) result; + } + + @Override + public void set(T value) { + validateInContext(this); + Map map = MANAGED_THREAD_LOCAL.get(); + map.put(this, value); + } + + public static void reset() { + validateInContext(null); + MANAGED_THREAD_LOCAL.remove(); + } + + @Override + public void remove() { + Map map = MANAGED_THREAD_LOCAL.get(); + map.remove(this); + } + + private static void validateInContext(Object tl) { + if ( VALIDATE_CONTEXT && ! ManagedContextUtils.isInContext() ) { + String msg = "Using a managed thread local in a non managed context this WILL cause errors at runtime. TL [" + + tl + "]"; + log.error(msg, new IllegalStateException(msg)); + } + } + + public static void setValidateInContext(boolean validate) { + VALIDATE_CONTEXT = validate; + } +} diff --git a/framework/managed-context/src/test/java/org/apache/cloudstack/managed/context/impl/DefaultManagedContextTest.java b/framework/managed-context/src/test/java/org/apache/cloudstack/managed/context/impl/DefaultManagedContextTest.java new file mode 100644 index 00000000000..aa2d2e6dca0 --- /dev/null +++ b/framework/managed-context/src/test/java/org/apache/cloudstack/managed/context/impl/DefaultManagedContextTest.java @@ -0,0 +1,269 @@ +/* + * 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.cloudstack.managed.context.impl; + +import static org.junit.Assert.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; + +import org.apache.cloudstack.managed.context.ManagedContextListener; +import org.apache.cloudstack.managed.threadlocal.ManagedThreadLocal; +import org.junit.Before; +import org.junit.Test; + +public class DefaultManagedContextTest { + + DefaultManagedContext context; + + @Before + public void init() { + ManagedThreadLocal.setValidateInContext(false); + + context = new DefaultManagedContext(); + } + + @Test + public void testCallable() throws Exception { + assertEquals(5, context.callWithContext(new Callable() { + @Override + public Integer call() throws Exception { + return 5; + } + }).intValue()); + } + + @Test + public void testRunnable() throws Exception { + final List touch = new ArrayList(); + + context.runWithContext(new Runnable() { + @Override + public void run() { + touch.add(new Object()); + } + }); + + assertEquals(1, touch.size()); + } + + @Test + public void testGoodListeners() throws Exception { + final List touch = new ArrayList(); + + context.registerListener(new ManagedContextListener() { + @Override + public Object onEnterContext(boolean reentry) { + touch.add("enter"); + return "hi"; + } + + @Override + public void onLeaveContext(Object data, boolean reentry) { + touch.add("leave"); + assertEquals("hi", data); + } + }); + + context.registerListener(new ManagedContextListener() { + @Override + public Object onEnterContext(boolean reentry) { + touch.add("enter1"); + return "hi"; + } + + @Override + public void onLeaveContext(Object data, boolean reentry) { + touch.add("leave1"); + assertEquals("hi", data); + } + }); + + assertEquals(5, context.callWithContext(new Callable() { + @Override + public Integer call() throws Exception { + return 5; + } + }).intValue()); + + assertEquals("enter", touch.get(0)); + assertEquals("enter1", touch.get(1)); + assertEquals("leave1", touch.get(2)); + assertEquals("leave", touch.get(3)); + } + + @Test + public void testBadListeners() throws Exception { + final List touch = new ArrayList(); + + context.registerListener(new ManagedContextListener() { + @Override + public Object onEnterContext(boolean reentry) { + touch.add("enter"); + throw new RuntimeException("I'm a failure"); + } + + @Override + public void onLeaveContext(Object data, boolean reentry) { + touch.add("leave"); + assertNull(data); + } + }); + + context.registerListener(new ManagedContextListener() { + @Override + public Object onEnterContext(boolean reentry) { + touch.add("enter1"); + return "hi"; + } + + @Override + public void onLeaveContext(Object data, boolean reentry) { + touch.add("leave1"); + assertEquals("hi", data); + } + }); + + try { + context.callWithContext(new Callable() { + @Override + public Integer call() throws Exception { + return 5; + } + }).intValue(); + + fail(); + } catch ( Throwable t ) { + assertTrue(t instanceof RuntimeException); + assertEquals("I'm a failure", t.getMessage()); + } + + assertEquals("enter", touch.get(0)); + assertEquals("enter1", touch.get(1)); + assertEquals("leave1", touch.get(2)); + assertEquals("leave", touch.get(3)); + } + + @Test + public void testBadInvocation() throws Exception { + final List touch = new ArrayList(); + + context.registerListener(new ManagedContextListener() { + @Override + public Object onEnterContext(boolean reentry) { + touch.add("enter"); + return "hi"; + } + + @Override + public void onLeaveContext(Object data, boolean reentry) { + touch.add("leave"); + assertEquals("hi", data); + } + }); + + context.registerListener(new ManagedContextListener() { + @Override + public Object onEnterContext(boolean reentry) { + touch.add("enter1"); + return "hi1"; + } + + @Override + public void onLeaveContext(Object data, boolean reentry) { + touch.add("leave1"); + assertEquals("hi1", data); + } + }); + + try { + context.callWithContext(new Callable() { + @Override + public Integer call() throws Exception { + throw new RuntimeException("I'm a failure"); + } + }).intValue(); + + fail(); + } catch ( Throwable t ) { + assertTrue(t.getMessage(), t instanceof RuntimeException); + assertEquals("I'm a failure", t.getMessage()); + } + + assertEquals("enter", touch.get(0)); + assertEquals("enter1", touch.get(1)); + assertEquals("leave1", touch.get(2)); + assertEquals("leave", touch.get(3)); + } + + @Test + public void testBadListernInExit() throws Exception { + final List touch = new ArrayList(); + + context.registerListener(new ManagedContextListener() { + @Override + public Object onEnterContext(boolean reentry) { + touch.add("enter"); + return "hi"; + } + + @Override + public void onLeaveContext(Object data, boolean reentry) { + touch.add("leave"); + assertEquals("hi", data); + + throw new RuntimeException("I'm a failure"); + } + }); + + context.registerListener(new ManagedContextListener() { + @Override + public Object onEnterContext(boolean reentry) { + touch.add("enter1"); + return "hi1"; + } + + @Override + public void onLeaveContext(Object data, boolean reentry) { + touch.add("leave1"); + assertEquals("hi1", data); + } + }); + + try { + context.callWithContext(new Callable() { + @Override + public Integer call() throws Exception { + return 5; + } + }).intValue(); + + fail(); + } catch ( Throwable t ) { + assertTrue(t.getMessage(), t instanceof RuntimeException); + assertEquals("I'm a failure", t.getMessage()); + } + + assertEquals("enter", touch.get(0)); + assertEquals("enter1", touch.get(1)); + assertEquals("leave1", touch.get(2)); + assertEquals("leave", touch.get(3)); + } +} diff --git a/framework/pom.xml b/framework/pom.xml index 1764076d498..4ea2df14cf2 100644 --- a/framework/pom.xml +++ b/framework/pom.xml @@ -37,5 +37,6 @@ cluster db config + managed-context diff --git a/plugins/event-bus/rabbitmq/src/org/apache/cloudstack/mom/rabbitmq/RabbitMQEventBus.java b/plugins/event-bus/rabbitmq/src/org/apache/cloudstack/mom/rabbitmq/RabbitMQEventBus.java index 1c0c6bef6f2..478c8d7aaed 100644 --- a/plugins/event-bus/rabbitmq/src/org/apache/cloudstack/mom/rabbitmq/RabbitMQEventBus.java +++ b/plugins/event-bus/rabbitmq/src/org/apache/cloudstack/mom/rabbitmq/RabbitMQEventBus.java @@ -20,7 +20,9 @@ package org.apache.cloudstack.mom.rabbitmq; import com.rabbitmq.client.*; + import org.apache.cloudstack.framework.events.*; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.log4j.Logger; import com.cloud.utils.Ternary; @@ -28,6 +30,7 @@ import com.cloud.utils.component.ManagerBase; import javax.ejb.Local; import javax.naming.ConfigurationException; + import java.io.IOException; import java.net.ConnectException; import java.util.Map; @@ -493,12 +496,13 @@ public class RabbitMQEventBus extends ManagerBase implements EventBus { } // retry logic to connect back to AMQP server after loss of connection - private class ReconnectionTask implements Runnable { + private class ReconnectionTask extends ManagedContextRunnable { boolean connected = false; Connection connection = null; - public void run() { + @Override + protected void runInContext() { while (!connected) { try { diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHAMonitor.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHAMonitor.java index 0e4d9eea8ac..1117110e2b8 100644 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHAMonitor.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHAMonitor.java @@ -20,7 +20,10 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; + +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.log4j.Logger; + import com.cloud.utils.script.Script; import org.libvirt.Connect; @@ -68,10 +71,10 @@ public class KVMHAMonitor extends KVMHABase implements Runnable { } } - private class Monitor implements Runnable { + private class Monitor extends ManagedContextRunnable { @Override - public void run() { + protected void runInContext() { synchronized (_storagePool) { for (String uuid : _storagePool.keySet()) { NfsStoragePool primaryStoragePool = _storagePool.get(uuid); diff --git a/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsManagerImpl.java b/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsManagerImpl.java index 8da9da086af..9dfe91d5124 100755 --- a/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsManagerImpl.java +++ b/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsManagerImpl.java @@ -31,7 +31,6 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; import org.apache.log4j.Logger; - import org.apache.cloudstack.api.AddUcsManagerCmd; import org.apache.cloudstack.api.AssociateUcsProfileToBladeCmd; import org.apache.cloudstack.api.DeleteUcsManagerCmd; @@ -43,6 +42,7 @@ import org.apache.cloudstack.api.response.UcsBladeResponse; import org.apache.cloudstack.api.response.UcsManagerResponse; import org.apache.cloudstack.api.response.UcsProfileResponse; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import com.cloud.configuration.Config; import com.cloud.dc.ClusterDetailsDao; @@ -98,7 +98,7 @@ public class UcsManagerImpl implements UcsManager { private ScheduledExecutorService syncBladesExecutor; private int syncBladeInterval; - private class SyncBladesThread implements Runnable { + private class SyncBladesThread extends ManagedContextRunnable { private void discoverNewBlades(Map previous, Map now, UcsManagerVO mgr) { @@ -156,7 +156,7 @@ public class UcsManagerImpl implements UcsManager { } @Override - public void run() { + protected void runInContext() { try { List mgrs = ucsDao.listAll(); for (UcsManagerVO mgr : mgrs) { diff --git a/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java b/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java index 6b719eb1476..3f8fc5c6f9d 100644 --- a/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java +++ b/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java @@ -36,11 +36,11 @@ import javax.naming.ConfigurationException; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; - import org.apache.cloudstack.api.command.user.loadbalancer.CreateLoadBalancerRuleCmd; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; @@ -749,9 +749,9 @@ public class ElasticLoadBalancerManagerImpl extends ManagerBase implements Elast _gcCandidateElbVmIds = currentGcCandidates; } - public class CleanupThread implements Runnable { + public class CleanupThread extends ManagedContextRunnable { @Override - public void run() { + protected void runInContext() { garbageCollectUnusedElbVms(); } diff --git a/pom.xml b/pom.xml index 1c85bc43d30..d8c6f405d7f 100644 --- a/pom.xml +++ b/pom.xml @@ -172,6 +172,7 @@ test client services + maven-standard @@ -380,6 +381,16 @@ wsdl4j 1.4 + + org.slf4j + slf4j-api + 1.7.5 + + + org.slf4j + slf4j-log4j12 + 1.7.5 + diff --git a/server/src/com/cloud/alert/AlertManagerImpl.java b/server/src/com/cloud/alert/AlertManagerImpl.java index 6f5d25a61c1..ed0c9fdcb46 100755 --- a/server/src/com/cloud/alert/AlertManagerImpl.java +++ b/server/src/com/cloud/alert/AlertManagerImpl.java @@ -48,6 +48,7 @@ import org.apache.cloudstack.framework.config.ConfigDepot; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.Configurable; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.managed.context.ManagedContextTimerTask; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; @@ -455,9 +456,9 @@ public class AlertManagerImpl extends ManagerBase implements AlertManager, Confi } - class CapacityChecker extends TimerTask { + class CapacityChecker extends ManagedContextTimerTask { @Override - public void run() { + protected void runInContext() { try { s_logger.debug("Running Capacity Checker ... "); checkForAlerts(); diff --git a/server/src/com/cloud/api/ApiAsyncJobDispatcher.java b/server/src/com/cloud/api/ApiAsyncJobDispatcher.java index 7092ef3779f..22ccb891e62 100644 --- a/server/src/com/cloud/api/ApiAsyncJobDispatcher.java +++ b/server/src/com/cloud/api/ApiAsyncJobDispatcher.java @@ -36,6 +36,7 @@ import org.apache.cloudstack.framework.jobs.AsyncJob; import org.apache.cloudstack.framework.jobs.AsyncJobDispatcher; import org.apache.cloudstack.framework.jobs.AsyncJobManager; import org.apache.cloudstack.jobs.JobInfo; +import org.apache.cloudstack.managed.context.ManagedContext; import com.cloud.user.Account; import com.cloud.user.User; @@ -51,12 +52,23 @@ public class ApiAsyncJobDispatcher extends AdapterBase implements AsyncJobDispat @Inject private AsyncJobManager _asyncJobMgr; @Inject private EntityManager _entityMgr; + @Inject + ManagedContext _managedContext; public ApiAsyncJobDispatcher() { } - @Override - public void runJob(AsyncJob job) { + @Override + public void runJob(final AsyncJob job) { + _managedContext.runWithContext(new Runnable() { + @Override + public void run() { + runJobInContext(job); + } + }); + } + + protected void runJobInContext(AsyncJob job) { BaseAsyncCmd cmdObj = null; try { Class cmdClass = Class.forName(job.getCmd()); diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java index 26789e3a81a..b73045d5fce 100755 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -119,6 +119,7 @@ import org.apache.cloudstack.framework.config.impl.ConfigurationVO; import org.apache.cloudstack.framework.jobs.AsyncJob; import org.apache.cloudstack.framework.jobs.AsyncJobManager; import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import com.cloud.api.response.ApiResponseSerializer; import com.cloud.configuration.Config; @@ -183,11 +184,6 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer public ApiServer() { } - @PostConstruct - void initComponent() { - CallContext.init(_entityMgr); - } - @Override public boolean configure(String name, Map params) throws ConfigurationException { init(); @@ -976,7 +972,7 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer } } - static class WorkerTask implements Runnable { + static class WorkerTask extends ManagedContextRunnable { private final HttpService _httpService; private final HttpServerConnection _conn; @@ -986,7 +982,7 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer } @Override - public void run() { + protected void runInContext() { HttpContext context = new BasicHttpContext(null); try { while (!Thread.interrupted() && _conn.isOpen()) { diff --git a/server/src/com/cloud/api/ApiServlet.java b/server/src/com/cloud/api/ApiServlet.java index 552327c83d1..def18d0919d 100755 --- a/server/src/com/cloud/api/ApiServlet.java +++ b/server/src/com/cloud/api/ApiServlet.java @@ -34,11 +34,11 @@ import javax.servlet.http.HttpSession; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; import org.springframework.web.context.support.SpringBeanAutowiringSupport; - import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.context.CallContext; +import org.apache.cloudstack.managed.context.ManagedContext; import com.cloud.exception.CloudAuthenticationException; import com.cloud.user.Account; @@ -57,6 +57,8 @@ public class ApiServlet extends HttpServlet { @Inject AccountService _accountMgr; @Inject EntityManager _entityMgr; + @Inject + ManagedContext _managedContext; public ApiServlet() { } @@ -105,8 +107,16 @@ public class ApiServlet extends HttpServlet { } } - @SuppressWarnings("unchecked") - private void processRequest(HttpServletRequest req, HttpServletResponse resp) { + private void processRequest(final HttpServletRequest req, final HttpServletResponse resp) { + _managedContext.runWithContext(new Runnable() { + @Override + public void run() { + processRequestInContext(req, resp); + } + }); + } + + private void processRequestInContext(HttpServletRequest req, HttpServletResponse resp) { StringBuffer auditTrailSb = new StringBuffer(); auditTrailSb.append(" " + req.getRemoteAddr()); auditTrailSb.append(" -- " + req.getMethod() + " "); diff --git a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java index 8cd44f44673..dcfb24c9d33 100644 --- a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java +++ b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java @@ -22,7 +22,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Timer; -import java.util.TimerTask; import java.util.TreeSet; import javax.ejb.Local; @@ -43,6 +42,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.framework.messagebus.MessageBus; import org.apache.cloudstack.framework.messagebus.MessageSubscriber; +import org.apache.cloudstack.managed.context.ManagedContextTimerTask; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.utils.identity.ManagementServerNode; @@ -688,9 +688,9 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy return false; } - class HostReservationReleaseChecker extends TimerTask { + class HostReservationReleaseChecker extends ManagedContextTimerTask { @Override - public void run() { + protected void runInContext() { try { s_logger.debug("Checking if any host reservation can be released ... "); checkHostReservations(); diff --git a/server/src/com/cloud/ha/HighAvailabilityManagerExtImpl.java b/server/src/com/cloud/ha/HighAvailabilityManagerExtImpl.java index f1e0f3f5dec..1107a7a031d 100644 --- a/server/src/com/cloud/ha/HighAvailabilityManagerExtImpl.java +++ b/server/src/com/cloud/ha/HighAvailabilityManagerExtImpl.java @@ -26,8 +26,8 @@ import javax.naming.ConfigurationException; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; - import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import com.cloud.alert.AlertManager; import com.cloud.usage.dao.UsageJobDao; @@ -65,9 +65,9 @@ public class HighAvailabilityManagerExtImpl extends HighAvailabilityManagerImpl return true; } - protected class UsageServerMonitorTask implements Runnable { + protected class UsageServerMonitorTask extends ManagedContextRunnable{ @Override - public void run() { + protected void runInContext() { if (s_logger.isInfoEnabled()) { s_logger.info("checking health of usage server"); } diff --git a/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java b/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java index 464b9524556..59337c0326d 100755 --- a/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java +++ b/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java @@ -31,10 +31,10 @@ import javax.naming.ConfigurationException; import org.apache.log4j.Logger; import org.apache.log4j.NDC; - -import org.apache.cloudstack.context.ServerContexts; import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.managed.context.ManagedContext; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import com.cloud.agent.AgentManager; import com.cloud.alert.AlertManager; @@ -116,6 +116,9 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements HighAvai @Inject ClusterDetailsDao _clusterDetailsDao; long _serverId; + + @Inject + ManagedContext _managedContext; List _investigators; public List getInvestigators() { @@ -773,9 +776,9 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements HighAvai return true; } - protected class CleanupTask implements Runnable { + protected class CleanupTask extends ManagedContextRunnable { @Override - public void run() { + protected void runInContext() { s_logger.info("HA Cleanup Thread Running"); try { @@ -793,71 +796,75 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements HighAvai @Override public void run() { - ServerContexts.registerSystemContext(); - try { - s_logger.info("Starting work"); - while (!_stopped) { - HaWorkVO work = null; - try { - s_logger.trace("Checking the database"); - work = _haDao.take(_serverId); - if (work == null) { - try { - synchronized (this) { - wait(_timeToSleep); - } - continue; - } catch (final InterruptedException e) { - s_logger.info("Interrupted"); - continue; - } - } - - NDC.push("work-" + work.getId()); - s_logger.info("Processing " + work); - - try { - final WorkType wt = work.getWorkType(); - Long nextTime = null; - if (wt == WorkType.Migration) { - nextTime = migrate(work); - } else if (wt == WorkType.HA) { - nextTime = restart(work); - } else if (wt == WorkType.Stop || wt == WorkType.CheckStop || wt == WorkType.ForceStop) { - nextTime = stopVM(work); - } else if (wt == WorkType.Destroy) { - nextTime = destroyVM(work); - } else { - assert false : "How did we get here with " + wt.toString(); - continue; - } - - if (nextTime == null) { - s_logger.info("Completed " + work); - work.setStep(Step.Done); - } else { - s_logger.info("Rescheduling " + work + " to try again at " + new Date(nextTime << 10)); - work.setTimeToTry(nextTime); - work.setServerId(null); - work.setDateTaken(null); - } - } catch (Exception e) { - s_logger.error("Terminating " + work, e); - work.setStep(Step.Error); - } - _haDao.update(work.getId(), work); - } catch (final Throwable th) { - s_logger.error("Caught this throwable, ", th); - } finally { - if (work != null) { - NDC.pop(); - } - } + s_logger.info("Starting work"); + while (!_stopped) { + _managedContext.runWithContext(new Runnable() { + @Override + public void run() { + runWithContext(); } - s_logger.info("Time to go home!"); - } finally { - ServerContexts.unregisterSystemContext(); + }); } + s_logger.info("Time to go home!"); + } + + private void runWithContext() { + HaWorkVO work = null; + try { + s_logger.trace("Checking the database"); + work = _haDao.take(_serverId); + if (work == null) { + try { + synchronized (this) { + wait(_timeToSleep); + } + return; + } catch (final InterruptedException e) { + s_logger.info("Interrupted"); + return; + } + } + + NDC.push("work-" + work.getId()); + s_logger.info("Processing " + work); + + try { + final WorkType wt = work.getWorkType(); + Long nextTime = null; + if (wt == WorkType.Migration) { + nextTime = migrate(work); + } else if (wt == WorkType.HA) { + nextTime = restart(work); + } else if (wt == WorkType.Stop || wt == WorkType.CheckStop || wt == WorkType.ForceStop) { + nextTime = stopVM(work); + } else if (wt == WorkType.Destroy) { + nextTime = destroyVM(work); + } else { + assert false : "How did we get here with " + wt.toString(); + return; + } + + if (nextTime == null) { + s_logger.info("Completed " + work); + work.setStep(Step.Done); + } else { + s_logger.info("Rescheduling " + work + " to try again at " + new Date(nextTime << 10)); + work.setTimeToTry(nextTime); + work.setServerId(null); + work.setDateTaken(null); + } + } catch (Exception e) { + s_logger.error("Terminating " + work, e); + work.setStep(Step.Error); + } + _haDao.update(work.getId(), work); + } catch (final Throwable th) { + s_logger.error("Caught this throwable, ", th); + } finally { + if (work != null) { + NDC.pop(); + } + } } public synchronized void wakup() { diff --git a/server/src/com/cloud/network/ExternalDeviceUsageManagerImpl.java b/server/src/com/cloud/network/ExternalDeviceUsageManagerImpl.java index f5c6eeca18d..00dd25c4a86 100644 --- a/server/src/com/cloud/network/ExternalDeviceUsageManagerImpl.java +++ b/server/src/com/cloud/network/ExternalDeviceUsageManagerImpl.java @@ -31,8 +31,8 @@ import javax.naming.ConfigurationException; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; - import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import com.cloud.agent.AgentManager; import com.cloud.agent.api.ExternalNetworkResourceUsageAnswer; @@ -331,14 +331,14 @@ public class ExternalDeviceUsageManagerImpl extends ManagerBase implements Exter } } - protected class ExternalDeviceNetworkUsageTask implements Runnable { + protected class ExternalDeviceNetworkUsageTask extends ManagedContextRunnable { public ExternalDeviceNetworkUsageTask() { } @Override - public void run() { + protected void runInContext() { GlobalLock scanLock = GlobalLock.getInternLock("ExternalDeviceNetworkUsageManagerImpl"); try { if (scanLock.lock(20)) { diff --git a/server/src/com/cloud/network/lb/LBHealthCheckManagerImpl.java b/server/src/com/cloud/network/lb/LBHealthCheckManagerImpl.java index 1daa3f0dc1c..4794ee425ba 100644 --- a/server/src/com/cloud/network/lb/LBHealthCheckManagerImpl.java +++ b/server/src/com/cloud/network/lb/LBHealthCheckManagerImpl.java @@ -29,8 +29,8 @@ import javax.naming.ConfigurationException; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; - import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import com.cloud.configuration.Config; import com.cloud.exception.ResourceUnavailableException; @@ -87,9 +87,9 @@ public class LBHealthCheckManagerImpl extends ManagerBase implements LBHealthChe return this.name; } - protected class UpdateLBHealthCheck implements Runnable { + protected class UpdateLBHealthCheck extends ManagedContextRunnable { @Override - public void run() { + protected void runInContext() { try { updateLBHealthCheck(Scheme.Public); updateLBHealthCheck(Scheme.Internal); diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index 043c376f558..5ea75604ebe 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -41,16 +41,15 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; -import org.apache.log4j.Logger; - import org.apache.cloudstack.api.command.admin.router.UpgradeRouterCmd; import org.apache.cloudstack.context.CallContext; -import org.apache.cloudstack.context.ServerContexts; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.framework.config.ConfigDepot; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.utils.identity.ManagementServerNode; +import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; import com.cloud.agent.Listener; @@ -852,14 +851,13 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V } - protected class NetworkUsageTask implements Runnable { + protected class NetworkUsageTask extends ManagedContextRunnable { public NetworkUsageTask() { } @Override - public void run() { - ServerContexts.registerSystemContext(); + protected void runInContext() { try{ final List routers = _routerDao.listByStateAndNetworkType(State.Running, GuestType.Isolated, mgmtSrvrId); s_logger.debug("Found " + routers.size() + " running routers. "); @@ -957,19 +955,17 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V } } catch (Exception e) { s_logger.warn("Error while collecting network stats", e); - } finally { - ServerContexts.unregisterSystemContext(); } } } - protected class NetworkStatsUpdateTask implements Runnable { + protected class NetworkStatsUpdateTask extends ManagedContextRunnable { public NetworkStatsUpdateTask() { } @Override - public void run() { + protected void runInContext() { GlobalLock scanLock = GlobalLock.getInternLock("network.stats"); try { if(scanLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION)) { @@ -1201,7 +1197,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V return priority; } - protected class RvRStatusUpdateTask implements Runnable { + protected class RvRStatusUpdateTask extends ManagedContextRunnable { public RvRStatusUpdateTask() { } @@ -1280,60 +1276,54 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V } @Override - public void run() { - ServerContexts.registerSystemContext(); - try { - while (true) { - try { - Long networkId = _vrUpdateQueue.take(); // This is a blocking call so this thread won't run all the time if no work item in queue. - List routers = _routerDao.listByNetworkAndRole(networkId, Role.VIRTUAL_ROUTER); - - if (routers.size() != 2) { - continue; - } - /* - * We update the router pair which the lower id router owned by this mgmt server, in order - * to prevent duplicate update of router status from cluster mgmt servers - */ - DomainRouterVO router0 = routers.get(0); - DomainRouterVO router1 = routers.get(1); - DomainRouterVO router = router0; - if ((router0.getId() < router1.getId()) && router0.getHostId() != null) { - router = router0; - } else { - router = router1; - } - if (router.getHostId() == null) { - s_logger.debug("Skip router pair (" + router0.getInstanceName() + "," + router1.getInstanceName() + ") due to can't find host"); - continue; - } - HostVO host = _hostDao.findById(router.getHostId()); - if (host == null || host.getManagementServerId() == null || - host.getManagementServerId() != ManagementServerNode.getManagementServerId()) { - s_logger.debug("Skip router pair (" + router0.getInstanceName() + "," + router1.getInstanceName() + ") due to not belong to this mgmt server"); - continue; - } - updateRoutersRedundantState(routers); - checkDuplicateMaster(routers); - checkSanity(routers); - } catch (Exception ex) { - s_logger.error("Fail to complete the RvRStatusUpdateTask! ", ex); - } + protected void runInContext() { + while (true) { + try { + Long networkId = _vrUpdateQueue.take(); // This is a blocking call so this thread won't run all the time if no work item in queue. + List routers = _routerDao.listByNetworkAndRole(networkId, Role.VIRTUAL_ROUTER); + + if (routers.size() != 2) { + continue; + } + /* + * We update the router pair which the lower id router owned by this mgmt server, in order + * to prevent duplicate update of router status from cluster mgmt servers + */ + DomainRouterVO router0 = routers.get(0); + DomainRouterVO router1 = routers.get(1); + DomainRouterVO router = router0; + if ((router0.getId() < router1.getId()) && router0.getHostId() != null) { + router = router0; + } else { + router = router1; + } + if (router.getHostId() == null) { + s_logger.debug("Skip router pair (" + router0.getInstanceName() + "," + router1.getInstanceName() + ") due to can't find host"); + continue; + } + HostVO host = _hostDao.findById(router.getHostId()); + if (host == null || host.getManagementServerId() == null || + host.getManagementServerId() != ManagementServerNode.getManagementServerId()) { + s_logger.debug("Skip router pair (" + router0.getInstanceName() + "," + router1.getInstanceName() + ") due to not belong to this mgmt server"); + continue; + } + updateRoutersRedundantState(routers); + checkDuplicateMaster(routers); + checkSanity(routers); + } catch (Exception ex) { + s_logger.error("Fail to complete the RvRStatusUpdateTask! ", ex); } - } finally { - ServerContexts.unregisterSystemContext(); } } } - protected class CheckRouterTask implements Runnable { + protected class CheckRouterTask extends ManagedContextRunnable { public CheckRouterTask() { } @Override - public void run() { - ServerContexts.registerSystemContext(); + protected void runInContext() { try { final List routers = _routerDao.listIsolatedByHostId(null); s_logger.debug("Found " + routers.size() + " routers to update status. "); @@ -1350,8 +1340,6 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V } } catch (Exception ex) { s_logger.error("Fail to complete the CheckRouterTask! ", ex); - } finally { - ServerContexts.unregisterSystemContext(); } } } diff --git a/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java b/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java index 18ee0f1124f..8b2db9dde90 100755 --- a/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java +++ b/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java @@ -40,7 +40,6 @@ import javax.naming.ConfigurationException; import org.apache.commons.codec.digest.DigestUtils; import org.apache.log4j.Logger; - import org.apache.cloudstack.api.command.user.securitygroup.AuthorizeSecurityGroupEgressCmd; import org.apache.cloudstack.api.command.user.securitygroup.AuthorizeSecurityGroupIngressCmd; import org.apache.cloudstack.api.command.user.securitygroup.CreateSecurityGroupCmd; @@ -50,6 +49,7 @@ import org.apache.cloudstack.api.command.user.securitygroup.RevokeSecurityGroupI import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.utils.identity.ManagementServerNode; import com.cloud.agent.AgentManager; @@ -187,9 +187,9 @@ public class SecurityGroupManagerImpl extends ManagerBase implements SecurityGro } } - public class WorkerThread implements Runnable { + public class WorkerThread extends ManagedContextRunnable { @Override - public void run() { + protected void runInContext() { try { Transaction txn = Transaction.open("SG Work"); try { @@ -210,9 +210,9 @@ public class SecurityGroupManagerImpl extends ManagerBase implements SecurityGro } } - public class CleanupThread implements Runnable { + public class CleanupThread extends ManagedContextRunnable { @Override - public void run() { + protected void runInContext() { try { Transaction txn = Transaction.open("SG Cleanup"); try { diff --git a/server/src/com/cloud/network/security/SecurityGroupManagerImpl2.java b/server/src/com/cloud/network/security/SecurityGroupManagerImpl2.java index a42881ec905..2fee7f312c8 100644 --- a/server/src/com/cloud/network/security/SecurityGroupManagerImpl2.java +++ b/server/src/com/cloud/network/security/SecurityGroupManagerImpl2.java @@ -25,8 +25,10 @@ import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; import javax.ejb.Local; +import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.cloudstack.managed.context.ManagedContext; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; @@ -54,6 +56,9 @@ public class SecurityGroupManagerImpl2 extends SecurityGroupManagerImpl{ SecurityGroupWorkTracker _workTracker; SecurityManagerMBeanImpl _mBean; + @Inject + ManagedContext _managedContext; + WorkerThread[] _workers; private Set _disabledVms = Collections.newSetFromMap(new ConcurrentHashMap()); private boolean _schedulerDisabled = false; @@ -68,7 +73,12 @@ public class SecurityGroupManagerImpl2 extends SecurityGroupManagerImpl{ public void run() { while (true) { try{ - work(); + _managedContext.runWithContext(new Runnable() { + @Override + public void run() { + work(); + } + }); } catch (final Throwable th) { s_logger.error("SG Work: Caught this throwable, ", th); } diff --git a/server/src/com/cloud/network/vpc/VpcManagerImpl.java b/server/src/com/cloud/network/vpc/VpcManagerImpl.java index 73b3aea66a2..651e82c6d21 100644 --- a/server/src/com/cloud/network/vpc/VpcManagerImpl.java +++ b/server/src/com/cloud/network/vpc/VpcManagerImpl.java @@ -31,8 +31,6 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; -import org.apache.log4j.Logger; - import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.api.command.user.vpc.ListPrivateGatewaysCmd; import org.apache.cloudstack.api.command.user.vpc.ListStaticRoutesCmd; @@ -40,6 +38,8 @@ import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.framework.config.ConfigDepot; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; +import org.apache.log4j.Logger; import com.cloud.configuration.Config; import com.cloud.configuration.ConfigurationManager; @@ -1932,9 +1932,9 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis } } - protected class VpcCleanupTask implements Runnable { + protected class VpcCleanupTask extends ManagedContextRunnable { @Override - public void run() { + protected void runInContext() { try { GlobalLock lock = GlobalLock.getInternLock("VpcCleanup"); if (lock == null) { diff --git a/server/src/com/cloud/projects/ProjectManagerImpl.java b/server/src/com/cloud/projects/ProjectManagerImpl.java index edcdf3f1a2b..a385739f9aa 100755 --- a/server/src/com/cloud/projects/ProjectManagerImpl.java +++ b/server/src/com/cloud/projects/ProjectManagerImpl.java @@ -42,7 +42,7 @@ import javax.naming.ConfigurationException; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; - +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -83,7 +83,6 @@ import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.db.DB; import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; - import com.sun.mail.smtp.SMTPMessage; import com.sun.mail.smtp.SMTPSSLTransport; import com.sun.mail.smtp.SMTPTransport; @@ -1003,9 +1002,9 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager { } } - public class ExpiredInvitationsCleanup implements Runnable { + public class ExpiredInvitationsCleanup extends ManagedContextRunnable { @Override - public void run() { + protected void runInContext() { try { TimeZone.getDefault(); List invitationsToExpire = _projectInvitationDao.listInvitationsToExpire(_invitationTimeOut); diff --git a/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java b/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java index 376e943393b..1f8713aae76 100755 --- a/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java +++ b/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java @@ -32,9 +32,9 @@ import javax.naming.ConfigurationException; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; - import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -939,13 +939,13 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim return _resourceCountDao.getResourceCount(account.getId(), ResourceOwnerType.Account, type); } - protected class ResourceCountCheckTask implements Runnable { + protected class ResourceCountCheckTask extends ManagedContextRunnable { public ResourceCountCheckTask() { } @Override - public void run() { + protected void runInContext() { s_logger.info("Running resource count check periodic task"); List domains = _domainDao.findImmediateChildrenForParent(DomainVO.ROOT_DOMAIN); diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 1c316103424..0a0fcdc08c3 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -432,6 +432,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.framework.config.impl.ConfigurationVO; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; @@ -2862,9 +2863,9 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe return cmdList; } - protected class EventPurgeTask implements Runnable { + protected class EventPurgeTask extends ManagedContextRunnable { @Override - public void run() { + protected void runInContext() { try { GlobalLock lock = GlobalLock.getInternLock("EventPurge"); if (lock == null) { @@ -2896,9 +2897,9 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe } } - protected class AlertPurgeTask implements Runnable { + protected class AlertPurgeTask extends ManagedContextRunnable { @Override - public void run() { + protected void runInContext() { try { GlobalLock lock = GlobalLock.getInternLock("AlertPurge"); if (lock == null) { diff --git a/server/src/com/cloud/server/StatsCollector.java b/server/src/com/cloud/server/StatsCollector.java index 5e110aa53d5..b4ec9155faf 100755 --- a/server/src/com/cloud/server/StatsCollector.java +++ b/server/src/com/cloud/server/StatsCollector.java @@ -37,6 +37,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; @@ -230,9 +231,9 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc } - class HostCollector implements Runnable { + class HostCollector extends ManagedContextRunnable { @Override - public void run() { + protected void runInContext() { try { s_logger.debug("HostStatsCollector is running..."); @@ -273,9 +274,9 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc } } - class VmStatsCollector implements Runnable { + class VmStatsCollector extends ManagedContextRunnable { @Override - public void run() { + protected void runInContext() { try { s_logger.debug("VmStatsCollector is running..."); @@ -350,9 +351,9 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc return _VmStats.get(id); } - class VmDiskStatsUpdaterTask implements Runnable { + class VmDiskStatsUpdaterTask extends ManagedContextRunnable { @Override - public void run() { + protected void runInContext() { GlobalLock scanLock = GlobalLock.getInternLock("vm.disk.stats"); try { if(scanLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION)) { @@ -397,9 +398,9 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc } } - class VmDiskStatsTask implements Runnable { + class VmDiskStatsTask extends ManagedContextRunnable { @Override - public void run() { + protected void runInContext() { // collect the vm disk statistics(total) from hypervisor. added by weizhou, 2013.03. Transaction txn = Transaction.open(Transaction.CLOUD_DB); try { @@ -520,9 +521,9 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc } } - class StorageCollector implements Runnable { + class StorageCollector extends ManagedContextRunnable { @Override - public void run() { + protected void runInContext() { try { if (s_logger.isDebugEnabled()) { s_logger.debug("StorageCollector is running..."); diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index 415111d4c91..c046057db51 100755 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -43,7 +43,6 @@ import javax.naming.ConfigurationException; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; - import org.apache.cloudstack.api.command.admin.storage.AddImageStoreCmd; import org.apache.cloudstack.api.command.admin.storage.CancelPrimaryStorageMaintenanceCmd; import org.apache.cloudstack.api.command.admin.storage.CreateSecondaryStagingStoreCmd; @@ -74,6 +73,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeAp import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; import org.apache.cloudstack.framework.async.AsyncCallFuture; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDao; import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; @@ -1243,13 +1243,13 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C return (PrimaryDataStoreInfo) dataStoreMgr.getDataStore(primaryStorage.getId(), DataStoreRole.Primary); } - protected class StorageGarbageCollector implements Runnable { + protected class StorageGarbageCollector extends ManagedContextRunnable { public StorageGarbageCollector() { } @Override - public void run() { + protected void runInContext() { try { s_logger.trace("Storage Garbage Collection Thread is running."); diff --git a/server/src/com/cloud/storage/download/DownloadListener.java b/server/src/com/cloud/storage/download/DownloadListener.java index e5efcb2bbd7..91ae0ae786a 100755 --- a/server/src/com/cloud/storage/download/DownloadListener.java +++ b/server/src/com/cloud/storage/download/DownloadListener.java @@ -27,7 +27,6 @@ import javax.inject.Inject; import org.apache.log4j.Level; import org.apache.log4j.Logger; - import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; @@ -36,6 +35,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService; import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; +import org.apache.cloudstack.managed.context.ManagedContextTimerTask; import org.apache.cloudstack.storage.command.DownloadCommand; import org.apache.cloudstack.storage.command.DownloadCommand.ResourceType; import org.apache.cloudstack.storage.command.DownloadProgressCommand; @@ -68,7 +68,7 @@ import com.cloud.utils.exception.CloudRuntimeException; public class DownloadListener implements Listener { - private static final class StatusTask extends TimerTask { + private static final class StatusTask extends ManagedContextTimerTask { private final DownloadListener dl; private final RequestType reqType; @@ -78,13 +78,13 @@ public class DownloadListener implements Listener { } @Override - public void run() { + protected void runInContext() { dl.sendCommand(reqType); } } - private static final class TimeoutTask extends TimerTask { + private static final class TimeoutTask extends ManagedContextTimerTask { private final DownloadListener dl; public TimeoutTask( DownloadListener dl) { @@ -92,7 +92,7 @@ public class DownloadListener implements Listener { } @Override - public void run() { + protected void runInContext() { dl.checkProgress(); } } diff --git a/server/src/com/cloud/storage/snapshot/SnapshotSchedulerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotSchedulerImpl.java index 52e20f02c08..15e9cd3438a 100644 --- a/server/src/com/cloud/storage/snapshot/SnapshotSchedulerImpl.java +++ b/server/src/com/cloud/storage/snapshot/SnapshotSchedulerImpl.java @@ -33,11 +33,11 @@ import org.springframework.stereotype.Component; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.command.user.snapshot.CreateSnapshotCmd; -import org.apache.cloudstack.context.ServerContexts; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.framework.jobs.AsyncJobManager; import org.apache.cloudstack.framework.jobs.dao.AsyncJobDao; import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO; +import org.apache.cloudstack.managed.context.ManagedContextTimerTask; import com.cloud.api.ApiDispatcher; import com.cloud.api.ApiGsonHelper; @@ -371,17 +371,14 @@ public class SnapshotSchedulerImpl extends ManagerBase implements SnapshotSchedu _testClockTimer.schedule(_testTimerTask, 100*1000L, 60*1000L); } else { - TimerTask timerTask = new TimerTask() { + TimerTask timerTask = new ManagedContextTimerTask() { @Override - public void run() { - ServerContexts.registerSystemContext(); + protected void runInContext() { try { Date currentTimestamp = new Date(); poll(currentTimestamp); } catch (Throwable t) { s_logger.warn("Catch throwable in snapshot scheduler ", t); - } finally { - ServerContexts.unregisterSystemContext(); } } }; diff --git a/server/src/com/cloud/storage/upload/UploadListener.java b/server/src/com/cloud/storage/upload/UploadListener.java index 09db421617f..add58774c28 100755 --- a/server/src/com/cloud/storage/upload/UploadListener.java +++ b/server/src/com/cloud/storage/upload/UploadListener.java @@ -27,7 +27,6 @@ import javax.inject.Inject; import org.apache.log4j.Level; import org.apache.log4j.Logger; - import org.apache.cloudstack.api.command.user.iso.ExtractIsoCmd; import org.apache.cloudstack.api.command.user.template.ExtractTemplateCmd; import org.apache.cloudstack.api.command.user.volume.ExtractVolumeCmd; @@ -38,6 +37,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; import org.apache.cloudstack.framework.jobs.AsyncJobManager; import org.apache.cloudstack.jobs.JobInfo; +import org.apache.cloudstack.managed.context.ManagedContextTimerTask; import com.cloud.agent.Listener; import com.cloud.agent.api.AgentControlAnswer; @@ -63,7 +63,7 @@ import com.cloud.utils.exception.CloudRuntimeException; public class UploadListener implements Listener { - private static final class StatusTask extends TimerTask { + private static final class StatusTask extends ManagedContextTimerTask { private final UploadListener ul; private final RequestType reqType; @@ -73,13 +73,13 @@ public class UploadListener implements Listener { } @Override - public void run() { + protected void runInContext() { ul.sendCommand(reqType); } } - private static final class TimeoutTask extends TimerTask { + private static final class TimeoutTask extends ManagedContextTimerTask { private final UploadListener ul; public TimeoutTask(UploadListener ul) { @@ -87,7 +87,7 @@ public class UploadListener implements Listener { } @Override - public void run() { + protected void runInContext() { ul.checkProgress(); } } diff --git a/server/src/com/cloud/storage/upload/UploadMonitorImpl.java b/server/src/com/cloud/storage/upload/UploadMonitorImpl.java index 12378de870d..4eb4900e67d 100755 --- a/server/src/com/cloud/storage/upload/UploadMonitorImpl.java +++ b/server/src/com/cloud/storage/upload/UploadMonitorImpl.java @@ -34,13 +34,13 @@ import javax.naming.ConfigurationException; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; - import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.framework.jobs.AsyncJobManager; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity; @@ -441,13 +441,13 @@ public class UploadMonitorImpl extends ManagerBase implements UploadMonitor { } - protected class StorageGarbageCollector implements Runnable { + protected class StorageGarbageCollector extends ManagedContextRunnable { public StorageGarbageCollector() { } @Override - public void run() { + protected void runInContext() { try { GlobalLock scanLock = GlobalLock.getInternLock("uploadmonitor.storageGC"); try { diff --git a/server/src/com/cloud/template/TemplateManagerImpl.java b/server/src/com/cloud/template/TemplateManagerImpl.java index 5240102a879..c1ce89205ad 100755 --- a/server/src/com/cloud/template/TemplateManagerImpl.java +++ b/server/src/com/cloud/template/TemplateManagerImpl.java @@ -73,6 +73,7 @@ import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.Configurable; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.framework.jobs.AsyncJobManager; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.storage.command.AttachCommand; import org.apache.cloudstack.storage.command.CommandResult; import org.apache.cloudstack.storage.command.DettachCommand; @@ -488,9 +489,9 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, for (final StoragePoolVO pool : pools) { if (pool.getDataCenterId() == zoneId) { s_logger.info("Schedule to preload template " + template.getId() + " into primary storage " + pool.getId()); - _preloadExecutor.execute(new Runnable() { + _preloadExecutor.execute(new ManagedContextRunnable() { @Override - public void run() { + protected void runInContext() { try { reallyRun(); } catch (Throwable e) { diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index 396319af538..ae93548b7e2 100755 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -50,9 +50,9 @@ import org.apache.cloudstack.api.command.admin.user.DeleteUserCmd; import org.apache.cloudstack.api.command.admin.user.RegisterCmd; import org.apache.cloudstack.api.command.admin.user.UpdateUserCmd; import org.apache.cloudstack.context.CallContext; -import org.apache.cloudstack.context.ServerContexts; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.region.gslb.GlobalLoadBalancerRuleDao; import com.cloud.api.ApiDBUtils; @@ -1492,18 +1492,10 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M return _userDao.remove(id); } - public class ResourceCountCalculateTask implements Runnable { + protected class AccountCleanupTask extends ManagedContextRunnable { @Override - public void run() { - - } - } - - protected class AccountCleanupTask implements Runnable { - @Override - public void run() { + protected void runInContext() { try { - ServerContexts.registerSystemContext(); GlobalLock lock = GlobalLock.getInternLock("AccountCleanup"); if (lock == null) { s_logger.debug("Couldn't get the global lock"); @@ -1585,7 +1577,6 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M s_logger.error("Exception ", e); } finally { lock.unlock(); - ServerContexts.unregisterSystemContext(); } } catch (Exception e) { s_logger.error("Exception ", e); diff --git a/server/src/com/cloud/vm/SystemVmLoadScanner.java b/server/src/com/cloud/vm/SystemVmLoadScanner.java index 3932c3b9641..6e5521632c2 100644 --- a/server/src/com/cloud/vm/SystemVmLoadScanner.java +++ b/server/src/com/cloud/vm/SystemVmLoadScanner.java @@ -21,8 +21,7 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import org.apache.log4j.Logger; - -import org.apache.cloudstack.context.ServerContexts; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import com.cloud.utils.Pair; import com.cloud.utils.concurrency.NamedThreadFactory; @@ -64,17 +63,14 @@ public class SystemVmLoadScanner { } private Runnable getCapacityScanTask() { - return new Runnable() { + return new ManagedContextRunnable() { @Override - public void run() { - ServerContexts.registerSystemContext(); + protected void runInContext() { try { reallyRun(); } catch (Throwable e) { s_logger.warn("Unexpected exception " + e.getMessage(), e); - } finally { - ServerContexts.unregisterSystemContext(); } } diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 55d166ce1a9..6e879161276 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -61,7 +61,6 @@ import org.apache.cloudstack.api.command.user.vm.UpgradeVMCmd; import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd; import org.apache.cloudstack.api.command.user.vmgroup.DeleteVMGroupCmd; import org.apache.cloudstack.context.CallContext; -import org.apache.cloudstack.context.ServerContexts; import org.apache.cloudstack.engine.cloud.entity.api.VirtualMachineEntity; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService; @@ -72,6 +71,7 @@ import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.Configurable; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.framework.jobs.AsyncJobManager; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.storage.to.TemplateObjectTO; @@ -1708,13 +1708,12 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } } - protected class ExpungeTask implements Runnable { + protected class ExpungeTask extends ManagedContextRunnable { public ExpungeTask() { } @Override - public void run() { - ServerContexts.registerSystemContext(); + protected void runInContext() { GlobalLock scanLock = GlobalLock.getInternLock("UserVMExpunge"); try { if (scanLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION)) { @@ -1748,7 +1747,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } } finally { scanLock.releaseRef(); - ServerContexts.unregisterSystemContext(); } } diff --git a/usage/src/com/cloud/usage/UsageManagerImpl.java b/usage/src/com/cloud/usage/UsageManagerImpl.java index 90ce4db7635..5f2867450ae 100644 --- a/usage/src/com/cloud/usage/UsageManagerImpl.java +++ b/usage/src/com/cloud/usage/UsageManagerImpl.java @@ -35,10 +35,10 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; import org.apache.log4j.Logger; - import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.managed.context.ManagedContext; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.usage.UsageTypes; - import org.springframework.stereotype.Component; import com.cloud.alert.AlertManager; @@ -279,7 +279,17 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna return true; } + @Override public void run() { + new ManagedContextRunnable() { + @Override + protected void runInContext() { + runInContext(); + } + }; + } + + protected void runInContext() { if (s_logger.isInfoEnabled()) { s_logger.info("starting usage job..."); } @@ -1651,8 +1661,9 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna m_usageVMSnapshotDao.persist(vsVO); } - private class Heartbeat implements Runnable { - public void run() { + private class Heartbeat extends ManagedContextRunnable { + @Override + protected void runInContext() { Transaction usageTxn = Transaction.open(Transaction.USAGE_DB); try { if(!m_heartbeatLock.lock(3)) { // 3 second timeout @@ -1757,8 +1768,9 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna } } - private class SanityCheck implements Runnable { - public void run() { + private class SanityCheck extends ManagedContextRunnable { + @Override + protected void runInContext() { UsageSanityChecker usc = new UsageSanityChecker(); try { String errors = usc.runSanityCheck(); diff --git a/usage/src/com/cloud/usage/parser/UsageParser.java b/usage/src/com/cloud/usage/parser/UsageParser.java index 410e876fd1c..80437d579a0 100644 --- a/usage/src/com/cloud/usage/parser/UsageParser.java +++ b/usage/src/com/cloud/usage/parser/UsageParser.java @@ -18,12 +18,13 @@ package com.cloud.usage.parser; import java.util.Date; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.log4j.Logger; -public abstract class UsageParser implements Runnable { +public abstract class UsageParser extends ManagedContextRunnable { public static final Logger s_logger = Logger.getLogger(UsageParser.class.getName()); - public void run() { + protected void runInContext() { try { parse(null); } catch (Exception e) { diff --git a/utils/pom.xml b/utils/pom.xml index 09c960258a6..35012b23343 100644 --- a/utils/pom.xml +++ b/utils/pom.xml @@ -26,7 +26,12 @@ 4.3.0-SNAPSHOT ../pom.xml - + + + org.apache.cloudstack + cloud-framework-managed-context + ${project.version} + org.springframework spring-context @@ -35,6 +40,14 @@ log4j log4j + + org.slf4j + slf4j-api + + + org.slf4j + slf4j-log4j12 + cglib cglib-nodep diff --git a/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareContextPool.java b/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareContextPool.java index 18af7cd2338..c36b3a8ce24 100644 --- a/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareContextPool.java +++ b/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareContextPool.java @@ -23,6 +23,8 @@ import java.util.Map; import java.util.Timer; import java.util.TimerTask; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; +import org.apache.cloudstack.managed.context.ManagedContextTimerTask; import org.apache.log4j.Logger; public class VmwareContextPool { @@ -117,9 +119,9 @@ public class VmwareContextPool { } private TimerTask getTimerTask() { - return new TimerTask() { - @Override - public void run() { + return new ManagedContextTimerTask() { + @Override + protected void runInContext() { try { // doIdleCheck();