cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bfede...@apache.org
Subject [03/10] git commit: updated refs/heads/ui-restyle to fbb0499
Date Thu, 03 Oct 2013 19:47:56 GMT
Add Manage Context framework

The managed context framework provides a simple way to add logic
to ACS at the various entry points of the system.  As threads are
launched and ran listeners can be registered for onEntry or onLeave
of the managed context.  This framework will be used specifically
to handle DB transaction checking and setting up the CallContext.
This framework is need to transition away from ACS custom AOP to
Spring AOP.


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/aed5e9dc
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/aed5e9dc
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/aed5e9dc

Branch: refs/heads/ui-restyle
Commit: aed5e9dc2a6882139bc38073923be5a3bacfd9d2
Parents: a2bf7f0
Author: Darren Shepherd <darren.s.shepherd@gmail.com>
Authored: Wed Oct 2 09:51:58 2013 -0700
Committer: Darren Shepherd <darren.s.shepherd@gmail.com>
Committed: Wed Oct 2 13:09:52 2013 -0700

----------------------------------------------------------------------
 agent/src/com/cloud/agent/Agent.java            |  10 +-
 .../consoleproxy/ConsoleProxyResource.java      |   6 +-
 .../apache/cloudstack/context/CallContext.java  |  29 +-
 .../cloudstack/context/CallContextListener.java |  53 ++++
 .../service/controller/s3/ServiceProvider.java  |   6 +-
 client/tomcatconf/applicationContext.xml.in     |  16 ++
 .../template/HttpTemplateDownloader.java        |   6 +-
 .../storage/template/S3TemplateDownloader.java  |   5 +-
 .../template/TemplateDownloaderBase.java        |   5 +-
 .../cloudstack/context/ServerContexts.java      |  67 -----
 .../com/cloud/agent/manager/AgentAttache.java   |   5 +-
 .../cloud/agent/manager/AgentManagerImpl.java   |  46 ++--
 .../manager/ClusteredAgentManagerImpl.java      |  19 +-
 .../cloud/agent/manager/DirectAgentAttache.java |   9 +-
 .../com/cloud/vm/VirtualMachineManagerImpl.java |   9 +-
 .../orchestration/NetworkOrchestrator.java      |   9 +-
 .../cache/manager/StorageCacheManagerImpl.java  |   7 +-
 .../cloudstack/storage/LocalHostEndpoint.java   |  13 +-
 .../cloudstack/storage/RemoteHostEndPoint.java  |   5 +-
 .../com/cloud/cluster/ClusterManagerImpl.java   |  21 +-
 .../cluster/ClusterServiceServletContainer.java |   6 +-
 .../com/cloud/utils/db/ConnectionConcierge.java |   6 +-
 .../client/ClientTransportProvider.java         |   8 +-
 .../server/ServerTransportProvider.java         |  10 +-
 .../jobs/AsyncJobExecutionContext.java          |   4 +-
 .../jobs/impl/AsyncJobManagerImpl.java          |  14 +-
 .../framework/jobs/impl/AsyncJobMonitor.java    |   7 +-
 framework/managed-context/pom.xml               |  36 +++
 .../context/AbstractManagedContextListener.java |  32 +++
 .../managed/context/ManagedContext.java         |  33 +++
 .../managed/context/ManagedContextListener.java |  36 +++
 .../managed/context/ManagedContextRunnable.java |  86 ++++++
 .../context/ManagedContextTimerTask.java        |  37 +++
 .../managed/context/ManagedContextUtils.java    |  55 ++++
 .../context/impl/DefaultManagedContext.java     | 155 +++++++++++
 .../managed/threadlocal/ManagedThreadLocal.java |  82 ++++++
 .../context/impl/DefaultManagedContextTest.java | 269 +++++++++++++++++++
 framework/pom.xml                               |   1 +
 .../mom/rabbitmq/RabbitMQEventBus.java          |   8 +-
 .../hypervisor/kvm/resource/KVMHAMonitor.java   |   7 +-
 .../com/cloud/ucs/manager/UcsManagerImpl.java   |   6 +-
 .../lb/ElasticLoadBalancerManagerImpl.java      |   6 +-
 pom.xml                                         |  11 +
 .../src/com/cloud/alert/AlertManagerImpl.java   |   5 +-
 .../com/cloud/api/ApiAsyncJobDispatcher.java    |  16 +-
 server/src/com/cloud/api/ApiServer.java         |  10 +-
 server/src/com/cloud/api/ApiServlet.java        |  16 +-
 .../deploy/DeploymentPlanningManagerImpl.java   |   6 +-
 .../ha/HighAvailabilityManagerExtImpl.java      |   6 +-
 .../cloud/ha/HighAvailabilityManagerImpl.java   | 137 +++++-----
 .../network/ExternalDeviceUsageManagerImpl.java |   6 +-
 .../network/lb/LBHealthCheckManagerImpl.java    |   6 +-
 .../VirtualNetworkApplianceManagerImpl.java     | 102 ++++---
 .../security/SecurityGroupManagerImpl.java      |  10 +-
 .../security/SecurityGroupManagerImpl2.java     |  12 +-
 .../com/cloud/network/vpc/VpcManagerImpl.java   |   8 +-
 .../com/cloud/projects/ProjectManagerImpl.java  |   7 +-
 .../resourcelimit/ResourceLimitManagerImpl.java |   6 +-
 .../com/cloud/server/ManagementServerImpl.java  |   9 +-
 server/src/com/cloud/server/StatsCollector.java |  21 +-
 .../com/cloud/storage/StorageManagerImpl.java   |   6 +-
 .../storage/download/DownloadListener.java      |  10 +-
 .../storage/snapshot/SnapshotSchedulerImpl.java |   9 +-
 .../cloud/storage/upload/UploadListener.java    |  10 +-
 .../cloud/storage/upload/UploadMonitorImpl.java |   6 +-
 .../com/cloud/template/TemplateManagerImpl.java |   5 +-
 .../src/com/cloud/user/AccountManagerImpl.java  |  15 +-
 .../src/com/cloud/vm/SystemVmLoadScanner.java   |  10 +-
 server/src/com/cloud/vm/UserVmManagerImpl.java  |   8 +-
 usage/src/com/cloud/usage/UsageManagerImpl.java |  24 +-
 .../src/com/cloud/usage/parser/UsageParser.java |   5 +-
 utils/pom.xml                                   |  15 +-
 .../vmware/util/VmwareContextPool.java          |   8 +-
 73 files changed, 1338 insertions(+), 437 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/agent/src/com/cloud/agent/Agent.java
----------------------------------------------------------------------
diff --git a/agent/src/com/cloud/agent/Agent.java b/agent/src/com/cloud/agent/Agent.java
index f309474..c713e45 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");

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/agent/src/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java
----------------------------------------------------------------------
diff --git a/agent/src/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java b/agent/src/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java
index ee5c361..6f49f47 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 {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/api/src/org/apache/cloudstack/context/CallContext.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/context/CallContext.java b/api/src/org/apache/cloudstack/context/CallContext.java
index 114f626..a9867d3 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<CallContext> s_currentContext = new ThreadLocal<CallContext>();
+    private static ManagedThreadLocal<CallContext> s_currentContext = new ManagedThreadLocal<CallContext>();
+    private static ManagedThreadLocal<Stack<CallContext>> s_currentContextStack = 
+            new ManagedThreadLocal<Stack<CallContext>>() {
+                @Override
+                protected Stack<CallContext> initialValue() {
+                    return new Stack<CallContext>();
+                }
+    };
 
     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<CallContext> stack = s_currentContextStack.get();
+        stack.pop();
+
+        if ( ! stack.isEmpty() ) {
+            s_currentContext.set(stack.peek());
+        }
+
         return context;
     }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/api/src/org/apache/cloudstack/context/CallContextListener.java
----------------------------------------------------------------------
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 0000000..9464f3d
--- /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<Object> {
+    
+    @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);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/awsapi/src/com/cloud/bridge/service/controller/s3/ServiceProvider.java
----------------------------------------------------------------------
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 a0892cc..2623efe 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);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/client/tomcatconf/applicationContext.xml.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/applicationContext.xml.in b/client/tomcatconf/applicationContext.xml.in
index 9b6636a..6dda5c7 100644
--- a/client/tomcatconf/applicationContext.xml.in
+++ b/client/tomcatconf/applicationContext.xml.in
@@ -53,6 +53,22 @@
   </bean>
 
   <!--
+    Managed Context
+  -->
+  <bean id="ManagedContext" class="org.apache.cloudstack.managed.context.impl.DefaultManagedContext" >
+    <property name="listeners">
+        <list>
+            <bean class="org.apache.cloudstack.context.CallContextListener" />
+        </list>
+    </property>
+  </bean>
+
+  <bean class="org.apache.cloudstack.managed.context.ManagedContextRunnable" factory-method="initializeGlobalContext" 
+    autowire-candidate="false" >
+    <constructor-arg><ref bean="ManagedContext"/></constructor-arg>
+  </bean>
+
+  <!--
     RPC/Async/EventBus
   -->
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/core/src/com/cloud/storage/template/HttpTemplateDownloader.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/storage/template/HttpTemplateDownloader.java b/core/src/com/cloud/storage/template/HttpTemplateDownloader.java
index 8789615..f0f1962 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) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/core/src/com/cloud/storage/template/S3TemplateDownloader.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/storage/template/S3TemplateDownloader.java b/core/src/com/cloud/storage/template/S3TemplateDownloader.java
index 05ed64b..dd595ea 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) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/core/src/com/cloud/storage/template/TemplateDownloaderBase.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/storage/template/TemplateDownloaderBase.java b/core/src/com/cloud/storage/template/TemplateDownloaderBase.java
index bdbdd45..7cbd4ef 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) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/engine/components-api/src/org/apache/cloudstack/context/ServerContexts.java
----------------------------------------------------------------------
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 b9c249c..0000000
--- 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);
-    }
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/engine/orchestration/src/com/cloud/agent/manager/AgentAttache.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/com/cloud/agent/manager/AgentAttache.java b/engine/orchestration/src/com/cloud/agent/manager/AgentAttache.java
index 67deba0..5b1007b 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) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/engine/orchestration/src/com/cloud/agent/manager/AgentManagerImpl.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/com/cloud/agent/manager/AgentManagerImpl.java b/engine/orchestration/src/com/cloud/agent/manager/AgentManagerImpl.java
index 51f6d72..4202015 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<String, String> 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 {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/engine/orchestration/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java b/engine/orchestration/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java
index 76e1d8e..48f096a 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);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/engine/orchestration/src/com/cloud/agent/manager/DirectAgentAttache.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/com/cloud/agent/manager/DirectAgentAttache.java b/engine/orchestration/src/com/cloud/agent/manager/DirectAgentAttache.java
index 5b5d8d2..2808c6a 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;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
index 560bab2..8bf419f 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");

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
----------------------------------------------------------------------
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 0b13fb4..3c4b1ed 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();
             }
         }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/engine/storage/cache/src/org/apache/cloudstack/storage/cache/manager/StorageCacheManagerImpl.java
----------------------------------------------------------------------
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 7f335c5..bb8d67d 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
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/engine/storage/src/org/apache/cloudstack/storage/LocalHostEndpoint.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/LocalHostEndpoint.java b/engine/storage/src/org/apache/cloudstack/storage/LocalHostEndpoint.java
index 83d34a0..53803bf 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<Answer> callback;
 
@@ -107,7 +106,7 @@ public class LocalHostEndpoint implements EndPoint {
         }
 
         @Override
-        public void run() {
+        protected void runInContext() {
             Answer answer = sendMessage(cmd);
             callback.complete(answer);
         }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/engine/storage/src/org/apache/cloudstack/storage/RemoteHostEndPoint.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/RemoteHostEndPoint.java b/engine/storage/src/org/apache/cloudstack/storage/RemoteHostEndPoint.java
index 3693813..3cae2b9 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<Answer> callback;
         Answer answer;
 
@@ -162,7 +163,7 @@ public class RemoteHostEndPoint implements EndPoint {
         }
 
         @Override
-        public void run() {
+        protected void runInContext() {
             callback.complete(answer);
         }
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/framework/cluster/src/com/cloud/cluster/ClusterManagerImpl.java
----------------------------------------------------------------------
diff --git a/framework/cluster/src/com/cloud/cluster/ClusterManagerImpl.java b/framework/cluster/src/com/cloud/cluster/ClusterManagerImpl.java
index 0f1cf9d..56d405e 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 {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/framework/cluster/src/com/cloud/cluster/ClusterServiceServletContainer.java
----------------------------------------------------------------------
diff --git a/framework/cluster/src/com/cloud/cluster/ClusterServiceServletContainer.java b/framework/cluster/src/com/cloud/cluster/ClusterServiceServletContainer.java
index def3e17..019d83d 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()) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/framework/db/src/com/cloud/utils/db/ConnectionConcierge.java
----------------------------------------------------------------------
diff --git a/framework/db/src/com/cloud/utils/db/ConnectionConcierge.java b/framework/db/src/com/cloud/utils/db/ConnectionConcierge.java
index 0294334..c3c24f9 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<String, ConnectionConcierge> entry : _conns.entrySet()) {
                         ConnectionConcierge concierge = entry.getValue();

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/framework/ipc/src/org/apache/cloudstack/framework/client/ClientTransportProvider.java
----------------------------------------------------------------------
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 023b318..923578c 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) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/framework/ipc/src/org/apache/cloudstack/framework/server/ServerTransportProvider.java
----------------------------------------------------------------------
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 b19a7c9..45c3e2a 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) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJobExecutionContext.java
----------------------------------------------------------------------
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 0136593..595800d 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<AsyncJobExecutionContext> s_currentExectionContext = new ThreadLocal<AsyncJobExecutionContext>();
+	private static ManagedThreadLocal<AsyncJobExecutionContext> s_currentExectionContext = new ManagedThreadLocal<AsyncJobExecutionContext>();
 
 	public AsyncJobExecutionContext() {
 	}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java
----------------------------------------------------------------------
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 2ddb115..93d50c1 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<SyncQueueItemVO> 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)) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/AsyncJobMonitor.java
----------------------------------------------------------------------
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 ad0da35..8ea7528 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();
 			}
 			

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/framework/managed-context/pom.xml
----------------------------------------------------------------------
diff --git a/framework/managed-context/pom.xml b/framework/managed-context/pom.xml
new file mode 100644
index 0000000..b4a9d83
--- /dev/null
+++ b/framework/managed-context/pom.xml
@@ -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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>cloud-framework-managed-context</artifactId>
+  <name>Apache CloudStack Framework - Managed Context</name>
+  <parent>
+    <groupId>org.apache.cloudstack</groupId>
+    <artifactId>cloud-maven-standard</artifactId>
+    <version>4.3.0-SNAPSHOT</version>
+    <relativePath>../../maven-standard/pom.xml</relativePath>
+  </parent>
+  <dependencies>
+      <dependency>
+          <groupId>org.slf4j</groupId>
+          <artifactId>slf4j-api</artifactId>
+      </dependency>
+  </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/framework/managed-context/src/main/java/org/apache/cloudstack/managed/context/AbstractManagedContextListener.java
----------------------------------------------------------------------
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 0000000..21f63a6
--- /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<T> implements ManagedContextListener<T> {
+
+    @Override
+    public T onEnterContext(boolean reentry) {
+        return null;
+    }
+
+    @Override
+    public void onLeaveContext(T data, boolean reentry) {
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/framework/managed-context/src/main/java/org/apache/cloudstack/managed/context/ManagedContext.java
----------------------------------------------------------------------
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 0000000..5023725
--- /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> T callWithContext(Callable<T> callable) throws Exception;
+    
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/framework/managed-context/src/main/java/org/apache/cloudstack/managed/context/ManagedContextListener.java
----------------------------------------------------------------------
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 0000000..2f85a5f
--- /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<T> {
+
+    /**
+     * @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);
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/framework/managed-context/src/main/java/org/apache/cloudstack/managed/context/ManagedContextRunnable.java
----------------------------------------------------------------------
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 0000000..2f3d0c8
--- /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

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/framework/managed-context/src/main/java/org/apache/cloudstack/managed/context/ManagedContextTimerTask.java
----------------------------------------------------------------------
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 0000000..894d27c
--- /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();
+    
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/framework/managed-context/src/main/java/org/apache/cloudstack/managed/context/ManagedContextUtils.java
----------------------------------------------------------------------
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 0000000..75bb205
--- /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<Object> OWNER = new ThreadLocal<Object>();
+    
+    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;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/framework/managed-context/src/main/java/org/apache/cloudstack/managed/context/impl/DefaultManagedContext.java
----------------------------------------------------------------------
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 0000000..6f5cbc9
--- /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<ManagedContextListener<?>> listeners = 
+            new CopyOnWriteArrayList<ManagedContextListener<?>>();
+
+    @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<Object>() {
+                @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> T callWithContext(Callable<T> callable) throws Exception {
+        Object owner = new Object();
+        
+        Stack<ListenerInvocation> invocations = new Stack<ListenerInvocation>();
+        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<Object>) 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<ManagedContextListener<?>> getListeners() {
+        return listeners;
+    }
+
+    public void setListeners(List<ManagedContextListener<?>> listeners) {
+        this.listeners = new CopyOnWriteArrayList<ManagedContextListener<?>>(listeners);
+    }
+    
+    private static class ListenerInvocation {
+        ManagedContextListener<Object> listener;
+        Object data;
+
+        public ListenerInvocation(ManagedContextListener<Object> listener, Object data) {
+            super();
+            this.listener = listener;
+            this.data = data;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aed5e9dc/framework/managed-context/src/main/java/org/apache/cloudstack/managed/threadlocal/ManagedThreadLocal.java
----------------------------------------------------------------------
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 0000000..bde535c
--- /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<T> extends ThreadLocal<T> {
+
+    private static final ThreadLocal<Map<Object,Object>> MANAGED_THREAD_LOCAL = new ThreadLocal<Map<Object,Object>>() {
+        @Override
+        protected Map<Object, Object> initialValue() {
+            return new HashMap<Object, Object>();
+        }
+    };
+    
+    private static boolean VALIDATE_CONTEXT = false;
+    private static final Logger log = LoggerFactory.getLogger(ManagedThreadLocal.class);
+    
+    @SuppressWarnings("unchecked")
+    @Override
+    public T get() {
+        validateInContext(this);
+        Map<Object,Object> 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<Object,Object> map = MANAGED_THREAD_LOCAL.get();
+        map.put(this, value);
+    }
+    
+    public static void reset() {
+        validateInContext(null);
+        MANAGED_THREAD_LOCAL.remove();
+    }
+
+    @Override
+    public void remove() {
+        Map<Object,Object> 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;
+    }
+}


Mime
View raw message