Skip to content

Commit aed5e9d

Browse files
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.
1 parent a2bf7f0 commit aed5e9d

73 files changed

Lines changed: 1338 additions & 437 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

agent/src/com/cloud/agent/Agent.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import java.util.List;
2727
import java.util.Map;
2828
import java.util.Timer;
29-
import java.util.TimerTask;
3029
import java.util.concurrent.ExecutorService;
3130
import java.util.concurrent.LinkedBlockingQueue;
3231
import java.util.concurrent.SynchronousQueue;
@@ -36,6 +35,7 @@
3635

3736
import javax.naming.ConfigurationException;
3837

38+
import org.apache.cloudstack.managed.context.ManagedContextTimerTask;
3939
import org.apache.log4j.Logger;
4040

4141
import com.cloud.agent.api.AgentControlAnswer;
@@ -731,7 +731,7 @@ public void run() {
731731
}
732732
}
733733

734-
public class WatchTask extends TimerTask {
734+
public class WatchTask extends ManagedContextTimerTask {
735735
protected Request _request;
736736
protected Agent _agent;
737737
protected Link _link;
@@ -744,7 +744,7 @@ public WatchTask(final Link link, final Request request, final Agent agent) {
744744
}
745745

746746
@Override
747-
public void run() {
747+
protected void runInContext() {
748748
if (s_logger.isTraceEnabled()) {
749749
s_logger.trace("Scheduling " + (_request instanceof Response ? "Ping" : "Watch Task"));
750750
}
@@ -760,7 +760,7 @@ public void run() {
760760
}
761761
}
762762

763-
public class StartupTask extends TimerTask {
763+
public class StartupTask extends ManagedContextTimerTask {
764764
protected Link _link;
765765
protected volatile boolean cancelled = false;
766766

@@ -782,7 +782,7 @@ public synchronized boolean cancel() {
782782
}
783783

784784
@Override
785-
public synchronized void run() {
785+
protected synchronized void runInContext() {
786786
if (!cancelled) {
787787
if (s_logger.isInfoEnabled()) {
788788
s_logger.info("The startup command is now cancelled");

agent/src/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
import javax.naming.ConfigurationException;
3434

35+
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
3536
import org.apache.log4j.Logger;
3637

3738
import com.cloud.agent.Agent.ExitStatus;
@@ -357,8 +358,9 @@ public String getName() {
357358
private void launchConsoleProxy(final byte[] ksBits, final String ksPassword, final String encryptorPassword) {
358359
final Object resource = this;
359360
if (_consoleProxyMain == null) {
360-
_consoleProxyMain = new Thread(new Runnable() {
361-
public void run() {
361+
_consoleProxyMain = new Thread(new ManagedContextRunnable() {
362+
@Override
363+
protected void runInContext() {
362364
try {
363365
Class<?> consoleProxyClazz = Class.forName("com.cloud.consoleproxy.ConsoleProxy");
364366
try {

api/src/org/apache/cloudstack/context/CallContext.java

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@
1818

1919
import java.util.HashMap;
2020
import java.util.Map;
21+
import java.util.Stack;
2122
import java.util.UUID;
2223

24+
import org.apache.cloudstack.managed.threadlocal.ManagedThreadLocal;
2325
import org.apache.log4j.Logger;
2426
import org.apache.log4j.NDC;
2527

@@ -37,7 +39,14 @@
3739
*/
3840
public class CallContext {
3941
private static final Logger s_logger = Logger.getLogger(CallContext.class);
40-
private static final ThreadLocal<CallContext> s_currentContext = new ThreadLocal<CallContext>();
42+
private static ManagedThreadLocal<CallContext> s_currentContext = new ManagedThreadLocal<CallContext>();
43+
private static ManagedThreadLocal<Stack<CallContext>> s_currentContextStack =
44+
new ManagedThreadLocal<Stack<CallContext>>() {
45+
@Override
46+
protected Stack<CallContext> initialValue() {
47+
return new Stack<CallContext>();
48+
}
49+
};
4150

4251
private String contextId;
4352
private Account account;
@@ -115,6 +124,9 @@ public static CallContext register(User callingUser, Account callingAccount, Str
115124
if (s_logger.isTraceEnabled()) {
116125
s_logger.trace("Registered: " + callingContext);
117126
}
127+
128+
s_currentContextStack.get().push(callingContext);
129+
118130
return callingContext;
119131
}
120132

@@ -162,10 +174,15 @@ public static CallContext register(long callingUserId, long callingAccountId) th
162174
return register(user, account);
163175
}
164176

177+
public static void unregisterAll() {
178+
while ( unregister() != null ) {
179+
// NOOP
180+
}
181+
}
182+
165183
public static CallContext unregister() {
166184
CallContext context = s_currentContext.get();
167185
if (context == null) {
168-
s_logger.debug("No context to remove");
169186
return null;
170187
}
171188
s_currentContext.remove();
@@ -183,6 +200,14 @@ public static CallContext unregister() {
183200
s_logger.trace("Popping from NDC: " + contextId);
184201
}
185202
}
203+
204+
Stack<CallContext> stack = s_currentContextStack.get();
205+
stack.pop();
206+
207+
if ( ! stack.isEmpty() ) {
208+
s_currentContext.set(stack.peek());
209+
}
210+
186211
return context;
187212
}
188213

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.cloudstack.context;
20+
21+
import javax.annotation.PostConstruct;
22+
import javax.inject.Inject;
23+
24+
import org.apache.cloudstack.managed.context.ManagedContextListener;
25+
26+
import com.cloud.utils.db.EntityManager;
27+
28+
public class CallContextListener implements ManagedContextListener<Object> {
29+
30+
@Inject
31+
EntityManager entityMgr;
32+
33+
@Override
34+
public Object onEnterContext(boolean reentry) {
35+
if ( ! reentry ) {
36+
CallContext.registerSystemCallContextOnceOnly();
37+
}
38+
39+
return null;
40+
}
41+
42+
@Override
43+
public void onLeaveContext(Object unused, boolean reentry) {
44+
if ( ! reentry ) {
45+
CallContext.unregisterAll();
46+
}
47+
}
48+
49+
@PostConstruct
50+
public void init() {
51+
CallContext.init(entityMgr);
52+
}
53+
}

awsapi/src/com/cloud/bridge/service/controller/s3/ServiceProvider.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import javax.inject.Inject;
3636

3737
import org.apache.axis2.AxisFault;
38+
import org.apache.cloudstack.managed.context.ManagedContextTimerTask;
3839
import org.apache.log4j.Logger;
3940
import org.apache.log4j.xml.DOMConfigurator;
4041
import org.springframework.stereotype.Component;
@@ -280,10 +281,9 @@ private void loadStartupProperties() {
280281
}
281282

282283
private TimerTask getHeartbeatTask() {
283-
return new TimerTask() {
284-
284+
return new ManagedContextTimerTask() {
285285
@Override
286-
public void run() {
286+
protected void runInContext() {
287287
try {
288288
mhost.setLastHeartbeatTime(DateHelper.currentGMTTime());
289289
mhostDao.updateHeartBeat(mhost);

client/tomcatconf/applicationContext.xml.in

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,22 @@
5252
</property>
5353
</bean>
5454

55+
<!--
56+
Managed Context
57+
-->
58+
<bean id="ManagedContext" class="org.apache.cloudstack.managed.context.impl.DefaultManagedContext" >
59+
<property name="listeners">
60+
<list>
61+
<bean class="org.apache.cloudstack.context.CallContextListener" />
62+
</list>
63+
</property>
64+
</bean>
65+
66+
<bean class="org.apache.cloudstack.managed.context.ManagedContextRunnable" factory-method="initializeGlobalContext"
67+
autowire-candidate="false" >
68+
<constructor-arg><ref bean="ManagedContext"/></constructor-arg>
69+
</bean>
70+
5571
<!--
5672
RPC/Async/EventBus
5773
-->

core/src/com/cloud/storage/template/HttpTemplateDownloader.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
import org.apache.commons.httpclient.methods.GetMethod;
4141
import org.apache.commons.httpclient.params.HttpMethodParams;
4242
import org.apache.log4j.Logger;
43-
43+
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
4444
import org.apache.cloudstack.storage.command.DownloadCommand.ResourceType;
4545

4646
import com.cloud.agent.api.storage.Proxy;
@@ -52,7 +52,7 @@
5252
* Download a template file using HTTP
5353
*
5454
*/
55-
public class HttpTemplateDownloader implements TemplateDownloader {
55+
public class HttpTemplateDownloader extends ManagedContextRunnable implements TemplateDownloader {
5656
public static final Logger s_logger = Logger.getLogger(HttpTemplateDownloader.class.getName());
5757
private static final MultiThreadedHttpConnectionManager s_httpClientManager = new MultiThreadedHttpConnectionManager();
5858

@@ -350,7 +350,7 @@ public int getDownloadPercent() {
350350
}
351351

352352
@Override
353-
public void run() {
353+
protected void runInContext() {
354354
try {
355355
download(resume, completionCallback);
356356
} catch (Throwable t) {

core/src/com/cloud/storage/template/S3TemplateDownloader.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
import com.amazonaws.services.s3.transfer.TransferManager;
5151
import com.amazonaws.services.s3.transfer.Upload;
5252

53+
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
5354
import org.apache.cloudstack.storage.command.DownloadCommand.ResourceType;
5455

5556
import com.cloud.agent.api.storage.Proxy;
@@ -62,7 +63,7 @@
6263
* Download a template file using HTTP
6364
*
6465
*/
65-
public class S3TemplateDownloader implements TemplateDownloader {
66+
public class S3TemplateDownloader extends ManagedContextRunnable implements TemplateDownloader {
6667
public static final Logger s_logger = Logger.getLogger(S3TemplateDownloader.class.getName());
6768
private static final MultiThreadedHttpConnectionManager s_httpClientManager = new MultiThreadedHttpConnectionManager();
6869

@@ -361,7 +362,7 @@ public int getDownloadPercent() {
361362
}
362363

363364
@Override
364-
public void run() {
365+
protected void runInContext() {
365366
try {
366367
download(resume, completionCallback);
367368
} catch (Throwable t) {

core/src/com/cloud/storage/template/TemplateDownloaderBase.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@
1818

1919
import java.io.File;
2020

21+
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
2122
import org.apache.log4j.Logger;
2223

2324
import com.cloud.storage.StorageLayer;
2425

25-
public abstract class TemplateDownloaderBase implements TemplateDownloader {
26+
public abstract class TemplateDownloaderBase extends ManagedContextRunnable implements TemplateDownloader {
2627
private static final Logger s_logger = Logger.getLogger(TemplateDownloaderBase.class);
2728

2829
protected String _downloadUrl;
@@ -123,7 +124,7 @@ public long getMaxTemplateSizeInBytes() {
123124
}
124125

125126
@Override
126-
public void run() {
127+
protected void runInContext() {
127128
try {
128129
download(_resume, _callback);
129130
} catch (Exception e) {

engine/components-api/src/org/apache/cloudstack/context/ServerContexts.java

Lines changed: 0 additions & 67 deletions
This file was deleted.

0 commit comments

Comments
 (0)