Author: jawi
Date: Fri Nov 29 13:58:21 2013
New Revision: 1546563
URL: http://svn.apache.org/r1546563
Log:
ACE-433 - avoid multiple cycles to download & install DP:
- the agent controller now runs in its own thread, if it implements
Runnable;
- the download handler now waits until the download is completed and
installs it directly, making it no longer necessary to wait until
the controller runs again;
- made the AgentContextImpl#{start,stop} methods "atomic" when both
are called in a multi-threaded situation;
- cleanup handlers, components and controller when the AgentContextImpl
is stopped.
Modified:
ace/trunk/org.apache.ace.agent.itest/bnd.bnd
ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/BaseAgentTest.java
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/Activator.java
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/AgentContextImpl.java
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ComponentBase.java
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DefaultController.java
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DownloadHandleImpl.java
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/EventLoggerImpl.java
ace/trunk/org.apache.ace.agent/test/org/apache/ace/agent/impl/ConfigurationHandlerImplTest.java
ace/trunk/org.apache.ace.agent/test/org/apache/ace/agent/impl/EventLoggerImplTest.java
Modified: ace/trunk/org.apache.ace.agent.itest/bnd.bnd
URL:
http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent.itest/bnd.bnd?rev=1546563&r1=1546562&r2=1546563&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent.itest/bnd.bnd (original)
+++ ace/trunk/org.apache.ace.agent.itest/bnd.bnd Fri Nov 29 13:58:21 2013
@@ -65,7 +65,8 @@ Private-Package: aQute.bnd.annotation.co
-runproperties: \
org.apache.felix.eventadmin.Timeout=0,\
org.apache.felix.log.storeDebug=true,\
- org.apache.felix.log.maxSize=1000
+ org.apache.felix.log.maxSize=1000,\
+
org.osgi.framework.bootdelegation="com.yourkit.*,com.sun.*,sun.*,apple.*,com.apple.*"
Import-Package: org.apache.ace.agent,\
!org.osgi.service.component.annotations,\
*
Modified:
ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/BaseAgentTest.java
URL:
http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/BaseAgentTest.java?rev=1546563&r1=1546562&r2=1546563&view=diff
==============================================================================
---
ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/BaseAgentTest.java
(original)
+++
ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/BaseAgentTest.java
Fri Nov 29 13:58:21 2013
@@ -113,7 +113,7 @@ public abstract class BaseAgentTest exte
@Override
protected void configureProvisionedServices() throws Exception {
- resetAgentBundleState();
+ // resetAgentBundleState();
}
protected Bundle getAgentBundle() {
@@ -130,7 +130,7 @@ public abstract class BaseAgentTest exte
File dataDir = agentBundle.getBundleContext().getDataFile("");
// System.out.println("BaseAgentTest: Stopping agent bundle");
- agentBundle.stop();
+ agentBundle.stop(Bundle.STOP_TRANSIENT);
// System.out.println("BaseAgentTest: Cleaning bundle data dir (" +
dataDir + ")");
cleanDir(dataDir);
// System.out.println("BaseAgentTest: Cleaning system properties");
Modified:
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/Activator.java
URL:
http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/Activator.java?rev=1546563&r1=1546562&r2=1546563&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/Activator.java
(original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/Activator.java
Fri Nov 29 13:58:21 2013
@@ -67,8 +67,8 @@ public class Activator implements Bundle
*/
@Override
public void start(BundleContext bundleContext) throws Exception {
- // Essentially a single-threaded executor with scheduling support...
- m_executorService = new ScheduledThreadPoolExecutor(1 /* core pool
size */, new InternalThreadFactory());
+ // Essentially a two-threaded executor with scheduling support, one
thread is "reserved" for the controller...
+ m_executorService = new ScheduledThreadPoolExecutor(2 /* core pool
size */, new InternalThreadFactory());
m_dependencyTracker = new DependencyTrackerImpl(bundleContext, this);
@@ -240,7 +240,7 @@ public class Activator implements Bundle
* Internal thread factory that assigns recognizable names to the threads
it creates and sets them in daemon mode.
*/
public static class InternalThreadFactory implements ThreadFactory {
- private static final String NAME_TPL = "ACE Agent worker (%s)";
+ private static final String NAME_TPL = "ACE Agent Worker %s";
private final AtomicInteger m_count = new AtomicInteger();
@Override
Modified:
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/AgentContextImpl.java
URL:
http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/AgentContextImpl.java?rev=1546563&r1=1546562&r2=1546563&view=diff
==============================================================================
---
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/AgentContextImpl.java
(original)
+++
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/AgentContextImpl.java
Fri Nov 29 13:58:21 2013
@@ -23,7 +23,10 @@ import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.atomic.AtomicReference;
import org.apache.ace.agent.AgentContext;
import org.apache.ace.agent.AgentContextAware;
@@ -59,60 +62,37 @@ public class AgentContextImpl implements
ScheduledExecutorService.class
};
- private final Map<Class<?>, Object> m_handlers = new HashMap<Class<?>,
Object>();
- private final Set<Object> m_components = new LinkedHashSet<Object>();
+ private final Map<Class<?>, Object> m_handlers;
+ private final Set<Object> m_components;
+ private final AtomicReference<Object> m_controllerRef;
+ private final Semaphore m_semaphore;
private final File m_workDir;
+ private volatile Future<?> m_future;
+
public AgentContextImpl(File workDir) {
m_workDir = workDir;
+
+ m_semaphore = new Semaphore(1);
+ m_handlers = new HashMap<Class<?>, Object>();
+ m_components = new LinkedHashSet<Object>();
+ m_controllerRef = new AtomicReference<Object>();
}
/**
- * Start the context.
+ * Adds a component to this context.
*
- * @throws Exception
- * On failure.
+ * @param component
+ * The component to add, cannot be <code>null</code>.
*/
- public void start() throws Exception {
- // Make sure the agent-context is set for all known handlers before
they are started, this way we can ensure
- // they can properly call each other in their onStart() methods...
- for (Class<?> handlerIface : KNOWN_HANDLERS) {
- Object handler = m_handlers.get(handlerIface);
- if (handler == null) {
- throw new IllegalStateException("Can not start context.
Missing handler: " + handlerIface.getName());
- }
- initAgentContextAware(handler);
- }
- for (Object component : m_components) {
- initAgentContextAware(component);
- }
- // Ensure the handlers are started in a deterministic order...
- for (Class<?> handlerIface : KNOWN_HANDLERS) {
- Object handler = m_handlers.get(handlerIface);
- startAgentContextAware(handler);
- }
- for (Object component : m_components) {
- startAgentContextAware(component);
- }
-
- // TODO correctly handle custom controller components!
+ public void addComponent(Object component) {
+ m_components.add(component);
}
- /**
- * Stop the context.
- *
- * @throws Exception
- * On failure.
- */
- public void stop() throws Exception {
- for (Object component : m_components) {
- stopAgentContextAware(component);
- }
- for (int i = (KNOWN_HANDLERS.length - 1); i >= 0; i--) {
- Class<?> iface = KNOWN_HANDLERS[i];
- Object handler = m_handlers.get(iface);
- stopAgentContextAware(handler);
- }
+ @Override
+ public <T> T getHandler(Class<T> iface) {
+ Object result = m_handlers.get(iface);
+ return iface.cast(result);
}
@Override
@@ -120,10 +100,22 @@ public class AgentContextImpl implements
return m_workDir;
}
- @Override
- public <T> T getHandler(Class<T> iface) {
- Object result = m_handlers.get(iface);
- return iface.cast(result);
+ /**
+ * Sets the controller to use for the agent.
+ *
+ * @param controller
+ * the controller to use, cannot be <code>null</code>.
+ */
+ public void setController(Object controller) {
+ Object old;
+ do {
+ old = m_controllerRef.get();
+ }
+ while (!m_controllerRef.compareAndSet(old, controller));
+
+ if (old != null) {
+ stopController(old);
+ }
}
/**
@@ -139,27 +131,81 @@ public class AgentContextImpl implements
}
/**
- * Adds a component to this context.
+ * Start the context.
*
- * @param component
- * The component to add, cannot be <code>null</code>.
+ * @throws Exception
+ * On failure.
*/
- public void addComponent(Object component) {
- m_components.add(component);
+ public void start() throws Exception {
+ m_semaphore.acquire();
+ try {
+ // Make sure the agent-context is set for all known handlers
before they are started, this way we can ensure
+ // they can properly call each other in their onStart() methods...
+ for (Class<?> handlerIface : KNOWN_HANDLERS) {
+ Object handler = m_handlers.get(handlerIface);
+ if (handler == null) {
+ throw new IllegalStateException("Can not start context.
Missing handler: " + handlerIface.getName());
+ }
+ initAgentContextAware(handler);
+ }
+ for (Object component : m_components) {
+ initAgentContextAware(component);
+ }
+ // Ensure the handlers are started in a deterministic order...
+ for (Class<?> handlerIface : KNOWN_HANDLERS) {
+ Object handler = m_handlers.get(handlerIface);
+ startAgentContextAware(handler);
+ }
+ for (Object component : m_components) {
+ startAgentContextAware(component);
+ }
+
+ // Lastly, start the agent controller...
+ Object controller = m_controllerRef.get();
+ if (controller != null) {
+ startController(controller);
+ }
+ }
+ finally {
+ m_semaphore.release();
+ }
}
/**
- * Sets the controller to use for the agent.
+ * Stop the context.
*
- * @param controller
- * the controller to use, cannot be <code>null</code>.
+ * @throws Exception
+ * On failure.
*/
- public void setController(Object controller) {
- // For now this ensures the same behaviour as we had. This will change
in the near future!
- addComponent(controller);
+ public void stop() throws Exception {
+ m_semaphore.acquire();
+ try {
+ // First, stop the agent controller...
+ Object controller = m_controllerRef.get();
+ if (controller != null) {
+ stopController(controller);
+ }
+
+ for (Object component : m_components) {
+ stopAgentContextAware(component);
+ }
+ for (int i = (KNOWN_HANDLERS.length - 1); i >= 0; i--) {
+ Class<?> iface = KNOWN_HANDLERS[i];
+ Object handler = m_handlers.get(iface);
+ stopAgentContextAware(handler);
+ }
+ }
+ finally {
+ // We do *not* allow the handlers/components to be reused...
+ m_handlers.clear();
+ m_components.clear();
+ m_controllerRef.set(null);
+
+ m_semaphore.release();
+ }
}
- private void initAgentContextAware(Object object) throws Exception {
+ private void initAgentContextAware(Object object) {
if (object instanceof AgentContextAware) {
try {
((AgentContextAware) object).init(this);
@@ -181,6 +227,40 @@ public class AgentContextImpl implements
}
}
+ private void startController(final Object object) {
+ terminateRunningController();
+
+ initAgentContextAware(object);
+
+ // In case of a Runnable, we start a separate thread that executes
this task...
+ if (object instanceof Runnable) {
+ ScheduledExecutorService executorService =
getHandler(ScheduledExecutorService.class);
+ if (executorService == null || executorService.isShutdown()) {
+ return;
+ }
+
+ m_future = executorService.submit(new Runnable() {
+ private static final String NAME = "ACE Agent Controller";
+
+ @Override
+ public void run() {
+ // Annotate the name of the thread for debugging
purposes...
+ Thread.currentThread().setName(NAME);
+
+ startAgentContextAware(object);
+
+ ((Runnable) object).run();
+
+ stopAgentContextAware(object);
+ }
+ });
+ }
+ else {
+ // Expect the controller to handle its own execution...
+ startAgentContextAware(object);
+ }
+ }
+
private void stopAgentContextAware(Object object) {
if (object instanceof AgentContextAware) {
try {
@@ -191,4 +271,22 @@ public class AgentContextImpl implements
}
}
}
+
+ private void stopController(Object object) {
+ terminateRunningController();
+
+ if (!(object instanceof Runnable)) {
+ stopAgentContextAware(object);
+ }
+ }
+
+ /**
+ * Terminates any running controller (if any).
+ */
+ private void terminateRunningController() {
+ if (m_future != null) {
+ m_future.cancel(true /* mayInterruptWhileRunning */);
+ m_future = null;
+ }
+ }
}
Modified:
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ComponentBase.java
URL:
http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ComponentBase.java?rev=1546563&r1=1546562&r2=1546563&view=diff
==============================================================================
---
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ComponentBase.java
(original)
+++
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ComponentBase.java
Fri Nov 29 13:58:21 2013
@@ -20,6 +20,7 @@ package org.apache.ace.agent.impl;
import java.io.File;
import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.atomic.AtomicReference;
import org.apache.ace.agent.AgentContext;
import org.apache.ace.agent.AgentContextAware;
@@ -40,10 +41,11 @@ import org.apache.ace.agent.LoggingHandl
public abstract class ComponentBase implements AgentContextAware {
private final String m_identifier;
// Injected by AgentContextImpl...
- private volatile AgentContext m_context;
+ private final AtomicReference<AgentContext> m_contextRef;
public ComponentBase(String handlerIdentifier) {
m_identifier = handlerIdentifier;
+ m_contextRef = new AtomicReference<AgentContext>();
}
@Override
@@ -51,9 +53,9 @@ public abstract class ComponentBase impl
if (agentContext == null) {
throw new IllegalArgumentException("Context must not be null");
}
- if (m_context == null) {
- m_context = agentContext;
- }
+
+ setAgentContext(agentContext);
+
onInit();
}
@@ -62,8 +64,9 @@ public abstract class ComponentBase impl
if (agentContext == null) {
throw new IllegalArgumentException("Context must not be null");
}
- if (m_context == null) {
- m_context = agentContext;
+ else if (getAgentContext() != agentContext) {
+ // Just to be sure...
+ throw new IllegalStateException("Context changed between init and
start?!");
}
onStart();
}
@@ -74,15 +77,16 @@ public abstract class ComponentBase impl
onStop();
}
finally {
- m_context = null;
+ setAgentContext(null);
}
}
protected final AgentContext getAgentContext() {
- if (m_context == null) {
+ AgentContext context = m_contextRef.get();
+ if (context == null) {
throw new IllegalStateException("Handler is not started: " +
m_identifier);
}
- return m_context;
+ return context;
}
protected void onInit() throws Exception {
@@ -98,51 +102,51 @@ public abstract class ComponentBase impl
}
protected final IdentificationHandler getIdentificationHandler() {
- return m_context.getHandler(IdentificationHandler.class);
+ return getAgentContext().getHandler(IdentificationHandler.class);
}
protected final DiscoveryHandler getDiscoveryHandler() {
- return m_context.getHandler(DiscoveryHandler.class);
+ return getAgentContext().getHandler(DiscoveryHandler.class);
}
protected final ConnectionHandler getConnectionHandler() {
- return m_context.getHandler(ConnectionHandler.class);
+ return getAgentContext().getHandler(ConnectionHandler.class);
}
protected final DeploymentHandler getDeploymentHandler() {
- return m_context.getHandler(DeploymentHandler.class);
+ return getAgentContext().getHandler(DeploymentHandler.class);
}
protected final DownloadHandler getDownloadHandler() {
- return m_context.getHandler(DownloadHandler.class);
+ return getAgentContext().getHandler(DownloadHandler.class);
}
protected final ConfigurationHandler getConfigurationHandler() {
- return m_context.getHandler(ConfigurationHandler.class);
+ return getAgentContext().getHandler(ConfigurationHandler.class);
}
protected final AgentUpdateHandler getAgentUpdateHandler() {
- return m_context.getHandler(AgentUpdateHandler.class);
+ return getAgentContext().getHandler(AgentUpdateHandler.class);
}
protected final FeedbackHandler getFeedbackHandler() {
- return m_context.getHandler(FeedbackHandler.class);
+ return getAgentContext().getHandler(FeedbackHandler.class);
}
protected final LoggingHandler getLoggingHandler() {
- return m_context.getHandler(LoggingHandler.class);
+ return getAgentContext().getHandler(LoggingHandler.class);
}
protected final EventsHandler getEventsHandler() {
- return m_context.getHandler(EventsHandler.class);
+ return getAgentContext().getHandler(EventsHandler.class);
}
protected final ScheduledExecutorService getExecutorService() {
- return m_context.getHandler(ScheduledExecutorService.class);
+ return getAgentContext().getHandler(ScheduledExecutorService.class);
}
protected final File getWorkDir() {
- return m_context.getWorkDir();
+ return getAgentContext().getWorkDir();
}
protected final void logDebug(String message, Object... args) {
@@ -176,4 +180,12 @@ public abstract class ComponentBase impl
protected final void logError(String message, Throwable cause, Object...
args) {
getLoggingHandler().logError(m_identifier, message, cause, args);
}
+
+ private void setAgentContext(AgentContext agentContext) {
+ AgentContext old;
+ do {
+ old = m_contextRef.get();
+ }
+ while (!m_contextRef.compareAndSet(old, agentContext));
+ }
}
Modified:
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DefaultController.java
URL:
http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DefaultController.java?rev=1546563&r1=1546562&r2=1546563&view=diff
==============================================================================
---
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DefaultController.java
(original)
+++
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DefaultController.java
Fri Nov 29 13:58:21 2013
@@ -18,7 +18,6 @@
*/
package org.apache.ace.agent.impl;
-import static org.apache.ace.agent.AgentConstants.CONFIG_CONTROLLER_DISABLED;
import static
org.apache.ace.agent.AgentConstants.CONFIG_CONTROLLER_FIXPACKAGES;
import static org.apache.ace.agent.AgentConstants.CONFIG_CONTROLLER_RETRIES;
import static org.apache.ace.agent.AgentConstants.CONFIG_CONTROLLER_STREAMING;
@@ -37,17 +36,15 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
-import org.apache.ace.agent.AgentConstants;
import org.apache.ace.agent.DownloadHandle;
import org.apache.ace.agent.DownloadHandle.DownloadProgressListener;
import org.apache.ace.agent.DownloadResult;
import org.apache.ace.agent.EventListener;
+import org.apache.ace.agent.EventsHandler;
import org.apache.ace.agent.FeedbackChannel;
import org.apache.ace.agent.InstallationFailedException;
import org.apache.ace.agent.RetryAfterException;
@@ -63,143 +60,76 @@ public class DefaultController extends C
* completion this installer will reschedule the controller.
*/
static class DownloadUpdateInstaller extends UpdateInstaller implements
DownloadProgressListener {
- private volatile DownloadHandle m_downloadHandle;
- private volatile UpdateInfo m_updateInfo;
- private volatile Future<DownloadResult> m_future;
+ private volatile String m_type;
public DownloadUpdateInstaller(DefaultController controller) {
super(controller);
}
@Override
- public void doInstallUpdate(final UpdateHandler delegate, final
UpdateInfo updateInfo) throws RetryAfterException {
+ public void doInstallUpdate(UpdateHandler delegate, UpdateInfo
updateInfo) throws RetryAfterException {
+ m_type = updateInfo.m_type;
+
DefaultController controller = getController();
+ controller.logInfo("Starting download of %s update, %s => %s...",
m_type, updateInfo.m_from, updateInfo.m_to);
- String type = updateInfo.m_type;
- Version fromVersion = updateInfo.m_from;
- Version toVersion = updateInfo.m_to;
-
- if (m_downloadHandle != null) {
- // Ongoing download?
- if (m_updateInfo != null &&
!m_updateInfo.m_to.equals(toVersion)) {
- controller.logInfo("Cancelling download of %s update for
%s because a newer version is available...", m_updateInfo.m_type,
m_updateInfo.m_to);
-
- clearDownloadState();
- }
- }
-
- if (m_downloadHandle == null) {
- controller.logInfo("Starting download of %s update, %s =>
%s...", updateInfo.m_type, updateInfo.m_from, updateInfo.m_to);
-
- m_updateInfo = updateInfo;
- m_future = null;
-
- m_downloadHandle = delegate.getDownloadHandle(updateInfo.m_to,
updateInfo.m_fixPackage);
- }
-
- if (m_future == null) {
- m_future = m_downloadHandle.start(this);
- }
- else {
- if (!m_future.isDone()) {
- controller.logDebug("Still awaiting completion of
download...");
- return;
- }
- else if (m_future.isCancelled()) {
- controller.logInfo("Download of %s update is CANCELLED.
Resuming download...", type);
-
- // We're stopped early...
- m_future = m_downloadHandle.start(this);
- return;
- }
+ try {
+ DownloadHandle downloadHandle =
delegate.getDownloadHandle(updateInfo.m_to, updateInfo.m_fixPackage);
try {
- try {
- DownloadResult downloadResult = m_future.get();
+ Future<DownloadResult> future = downloadHandle.start(this);
+ DownloadResult downloadResult = future.get();
- if (downloadResult.isComplete()) {
- controller.logInfo("Installing %s update %s =>
%s...", type, fromVersion, toVersion);
+ if (downloadResult.isComplete()) {
+ controller.logInfo("Installing %s update %s => %s...",
m_type, updateInfo.m_from, updateInfo.m_to);
- startInstallation(updateInfo);
+ startInstallation(updateInfo);
- delegate.install(downloadResult.getInputStream());
+ delegate.install(downloadResult.getInputStream());
- installationSuccess(updateInfo);
+ installationSuccess(updateInfo);
- clearDownloadState();
- }
- else {
- controller.logInfo("Download of %s update is
STOPPED. Resuming download...", type);
-
- // We're stopped early...
- m_future = m_downloadHandle.start(this);
- }
+ // Clean up any temporary files...
+ downloadHandle.discard();
}
- catch (InterruptedException exception) {
- controller.logInfo("Download of %s update is
INTERRUPTED. Resuming download...", type);
-
- // We're stopped early...
- m_future = m_downloadHandle.start(this);
+ }
+ catch (InterruptedException exception) {
+ controller.logInfo("Download of %s update is INTERRUPTED.
Resuming download later on...", m_type);
+ }
+ catch (ExecutionException exception) {
+ Throwable cause = exception.getCause();
+ if (cause instanceof RetryAfterException) {
+ throw (RetryAfterException) cause;
}
- catch (ExecutionException exception) {
- clearDownloadState();
-
- Throwable cause = exception.getCause();
- if (cause instanceof RetryAfterException) {
- throw (RetryAfterException) cause;
- }
- else if (cause instanceof InstallationFailedException)
{
- throw (InstallationFailedException) cause;
- }
- else if (cause instanceof IOException) {
- throw (IOException) cause;
- }
- else {
- throw new RuntimeException("Failed to handle
cause!", cause);
- }
+ else if (cause instanceof InstallationFailedException) {
+ throw (InstallationFailedException) cause;
+ }
+ else if (cause instanceof IOException) {
+ throw (IOException) cause;
+ }
+ else {
+ throw new RuntimeException("Failed to handle cause!",
cause);
}
}
- catch (RetryAfterException ex) {
- // Does not cause the installation to end...
- throw ex;
- }
- catch (InstallationFailedException ex) {
- // All other exceptions cause the installation to
end/fail...
- installationFailed(updateInfo, ex);
- }
- catch (IOException ex) {
- // All other exceptions cause the installation to
end/fail...
- installationFailed(updateInfo, ex);
- }
+ }
+ catch (InstallationFailedException exception) {
+ // Installation failed...
+ installationFailed(updateInfo, exception);
+ }
+ catch (IOException exception) {
+ // I/O exception causes the installation to fail...
+ installationFailed(updateInfo, exception);
}
}
@Override
public void progress(long bytesRead) {
- if (m_updateInfo != null) {
- getController().logInfo("%d bytes of %s update downloaded...",
bytesRead, m_updateInfo.m_type);
- }
+ getController().logInfo("%d bytes of %s update downloaded...",
bytesRead, m_type);
}
@Override
public void doReset() {
- if (m_downloadHandle != null) {
- getController().logInfo("Cancelling deployment package
download for version %s because of reset...", m_updateInfo.m_to);
- m_downloadHandle.discard();
- }
- clearDownloadState();
- }
-
- private void clearDownloadState() {
- if (m_downloadHandle != null) {
- m_downloadHandle.discard();
- }
- m_downloadHandle = null;
- if (m_future != null && !m_future.isDone()) {
- m_future.cancel(true /* mayInterruptIfRunning */);
- }
- m_future = null;
- m_updateInfo = null;
+ // Nop
}
}
@@ -360,11 +290,12 @@ public class DefaultController extends C
*
* @param updateInfo
* the information about the update;
- * @param cause
+ * @param exception
* the (optional) cause why the installation failed.
*/
- protected final void installationFailed(UpdateInfo updateInfo,
InstallationFailedException cause) {
- getController().logWarning("Installation of deployment package
failed: %s!", cause, cause.getReason());
+ protected final void installationFailed(UpdateInfo updateInfo,
InstallationFailedException exception) {
+ // InstallationFailedException is a catch-all wrapper exception,
so use its cause directly...
+ getController().logWarning("Installation of %s update failed:
%s!", exception.getCause(), updateInfo.m_type, exception.getReason());
m_lastVersionSuccessful = false;
m_failureCount++;
@@ -380,7 +311,7 @@ public class DefaultController extends C
* the (optional) cause why the installation failed.
*/
protected final void installationFailed(UpdateInfo updateInfo,
IOException cause) {
- getController().logWarning("Installation of deployment package
failed: generic I/O exception.", cause);
+ getController().logWarning("Installation of %s update failed:
generic I/O exception.", cause, updateInfo.m_type);
m_lastVersionSuccessful = false;
m_failureCount++;
@@ -439,10 +370,8 @@ public class DefaultController extends C
}
}
- private volatile ScheduledFuture<?> m_scheduledFuture;
private volatile UpdateInstaller m_updateInstaller;
- private final AtomicBoolean m_disabled;
private final AtomicBoolean m_updateStreaming;
private final AtomicBoolean m_fixPackage;
private final AtomicLong m_maxRetries;
@@ -452,7 +381,6 @@ public class DefaultController extends C
public DefaultController() {
super("controller");
- m_disabled = new
AtomicBoolean(Boolean.getBoolean(AgentConstants.CONFIG_CONTROLLER_DISABLED));
m_interval = new AtomicLong(60);
m_syncDelay = new AtomicLong(5);
@@ -464,12 +392,7 @@ public class DefaultController extends C
@Override
public void handle(String topic, Map<String, String> payload) {
if (EVENT_AGENT_CONFIG_CHANGED.equals(topic)) {
- String value = payload.get(CONFIG_CONTROLLER_DISABLED);
- if (value != null && !"".equals(value)) {
- m_disabled.set(Boolean.parseBoolean(value));
- }
-
- value = payload.get(CONFIG_CONTROLLER_STREAMING);
+ String value = payload.get(CONFIG_CONTROLLER_STREAMING);
if (value != null && !"".equals(value)) {
m_updateStreaming.set(Boolean.parseBoolean(value));
}
@@ -509,36 +432,42 @@ public class DefaultController extends C
}
}
- logDebug("Config changed: disabled: %s, update: %s, fixPkg: %s,
syncDelay: %d, syncInterval: %d, maxRetries: %d", m_disabled.get(),
m_updateStreaming.get(), m_fixPackage.get(), m_syncDelay.get(),
m_interval.get(), m_maxRetries.get());
-
- scheduleRunAfterDelay();
+ logDebug("Config changed: update: %s, fixPkg: %s, syncDelay: %d,
syncInterval: %d, maxRetries: %d", m_updateStreaming.get(), m_fixPackage.get(),
m_syncDelay.get(), m_interval.get(), m_maxRetries.get());
}
}
@Override
public void run() {
- boolean disabled = m_disabled.get();
- long interval = m_interval.get();
+ long interval = m_syncDelay.get();
- if (disabled) {
- logDebug("Controller disabled by configuration. Skipping...");
- return;
- }
- try {
- logDebug("Controller syncing...");
- runFeedback();
- runAgentUpdate();
- runDeploymentUpdate();
- logDebug("Sync completed. Rescheduled in %d seconds", interval);
- }
- catch (RetryAfterException e) {
- // any method may throw this causing the sync to abort. The server
is busy so no sense in trying
- // anything else until the retry window has passed.
- interval = e.getBackoffTime();
- logWarning("Sync received retry exception from server. Rescheduled
in %d seconds", interval);
- }
- finally {
- scheduleRun(interval);
+ while (!isInterrupted()) {
+ try {
+ logDebug("Scheduling controller to run in %d seconds...",
interval);
+
+ TimeUnit.SECONDS.sleep(interval);
+
+ logDebug("Controller syncing...");
+
+ runFeedback();
+ runAgentUpdate();
+ runDeploymentUpdate();
+
+ interval = m_interval.get();
+
+ logDebug("Sync completed...");
+ }
+ catch (RetryAfterException e) {
+ // any method may throw this causing the sync to abort. The
server is busy so no sense in trying
+ // anything else until the retry window has passed.
+ interval = e.getBackoffTime();
+ logWarning("Sync received retry exception from server.
Rescheduled in %d seconds...", interval);
+ }
+ catch (InterruptedException exception) {
+ logDebug(exception.getMessage());
+
+ // Ok; break out of our main loop...
+ Thread.currentThread().interrupt();
+ }
}
}
@@ -548,38 +477,14 @@ public class DefaultController extends C
}
@Override
- protected void onStart() throws Exception {
- scheduleRunAfterDelay();
- }
-
- @Override
protected void onStop() throws Exception {
- getEventsHandler().removeListener(this);
-
+ EventsHandler eventsHandler = getEventsHandler();
+ if (eventsHandler != null) {
+ eventsHandler.removeListener(this);
+ }
if (m_updateInstaller != null) {
m_updateInstaller.reset();
- }
-
- unscheduleRun();
- }
-
- protected void scheduleRunAfterDelay() {
- long delay = m_syncDelay.get();
-
- scheduleRun(delay);
-
- logDebug("Controller scheduled to run in %d seconds", delay);
- }
-
- protected void scheduleRun(long seconds) {
- unscheduleRun();
-
- ScheduledExecutorService executor = getExecutorService();
- if (executor.isShutdown()) {
- logWarning("Cannot schedule controller task, executor is shut
down!");
- }
- else {
- m_scheduledFuture = executor.schedule(this, seconds,
TimeUnit.SECONDS);
+ m_updateInstaller = null;
}
}
@@ -653,7 +558,11 @@ public class DefaultController extends C
return m_updateInstaller;
}
- private void runAgentUpdate() throws RetryAfterException {
+ private void runAgentUpdate() throws RetryAfterException,
InterruptedException {
+ if (isInterrupted()) {
+ throw new InterruptedException("Controller was interrupted, not
running agent updates check...");
+ }
+
logDebug("Checking for agent updates...");
long maxRetries = m_maxRetries.get();
@@ -668,7 +577,11 @@ public class DefaultController extends C
}
}
- private void runDeploymentUpdate() throws RetryAfterException {
+ private void runDeploymentUpdate() throws RetryAfterException,
InterruptedException {
+ if (isInterrupted()) {
+ throw new InterruptedException("Controller was interrupted, not
running deployment updates check...");
+ }
+
logDebug("Checking for deployment updates...");
long maxRetries = m_maxRetries.get();
@@ -683,7 +596,11 @@ public class DefaultController extends C
}
}
- private void runFeedback() throws RetryAfterException {
+ private void runFeedback() throws RetryAfterException,
InterruptedException {
+ if (isInterrupted()) {
+ throw new InterruptedException("Controller was interrupted, not
running feedback synchronization...");
+ }
+
Set<String> names = getFeedbackChannelNames();
logDebug("Synchronizing feedback channels: %s", names);
@@ -704,8 +621,10 @@ public class DefaultController extends C
}
}
- private void unscheduleRun() {
- if (m_scheduledFuture != null)
- m_scheduledFuture.cancel(false /* mayInterruptWhileRunning */);
+ /**
+ * @return <code>true</code> if the execution of this controller is
interrupted, <code>false</code> otherwise.
+ */
+ private static boolean isInterrupted() {
+ return Thread.interrupted();
}
}
Modified:
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DownloadHandleImpl.java
URL:
http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DownloadHandleImpl.java?rev=1546563&r1=1546562&r2=1546563&view=diff
==============================================================================
---
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DownloadHandleImpl.java
(original)
+++
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DownloadHandleImpl.java
Fri Nov 29 13:58:21 2013
@@ -45,6 +45,8 @@ class DownloadHandleImpl implements Down
m_url = url;
m_file = new File(m_handler.getDataLocation(), getDownloadFileName());
+
+ m_handler.logDebug("Created download handle for %s in %s.",
m_file.getName(), m_file.getPath());
}
@Override
Modified:
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/EventLoggerImpl.java
URL:
http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/EventLoggerImpl.java?rev=1546563&r1=1546562&r2=1546563&view=diff
==============================================================================
---
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/EventLoggerImpl.java
(original)
+++
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/EventLoggerImpl.java
Fri Nov 29 13:58:21 2013
@@ -56,7 +56,7 @@ public class EventLoggerImpl extends Com
private final Set<Integer> m_excludeEventList;
public EventLoggerImpl(BundleContext bundleContext) {
- super("auditlogger");
+ super("eventlogger");
m_bundleContext = bundleContext;
m_isStarted = new AtomicBoolean(false);
Modified:
ace/trunk/org.apache.ace.agent/test/org/apache/ace/agent/impl/ConfigurationHandlerImplTest.java
URL:
http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/test/org/apache/ace/agent/impl/ConfigurationHandlerImplTest.java?rev=1546563&r1=1546562&r2=1546563&view=diff
==============================================================================
---
ace/trunk/org.apache.ace.agent/test/org/apache/ace/agent/impl/ConfigurationHandlerImplTest.java
(original)
+++
ace/trunk/org.apache.ace.agent/test/org/apache/ace/agent/impl/ConfigurationHandlerImplTest.java
Fri Nov 29 13:58:21 2013
@@ -34,16 +34,15 @@ import org.testng.annotations.Test;
* Testing {@link ConfigurationHandlerImpl}.
*/
public class ConfigurationHandlerImplTest extends BaseAgentTest {
-
private AgentContextImpl m_agentContextImpl;
- @BeforeMethod
+ @BeforeMethod(alwaysRun = true)
public void setUpAgain(Method method) throws Exception {
m_agentContextImpl = mockAgentContext(method.getName());
replayTestMocks();
}
- @AfterMethod
+ @AfterMethod(alwaysRun = true)
public void tearDownAgain(Method method) throws Exception {
m_agentContextImpl.stop();
verifyTestMocks();
@@ -51,12 +50,28 @@ public class ConfigurationHandlerImplTes
}
@Test
- public void testConfigClean() throws Exception {
+ public void testConfigBooleanProps() throws Exception {
+ ConfigurationHandler configurationHandler = new
ConfigurationHandlerImpl();
+
+ resetConfigurationHandler(configurationHandler);
+ configurationHandler =
m_agentContextImpl.getHandler(ConfigurationHandler.class);
+
+ configureAgent(configurationHandler, "boolean1", "true", "boolean2",
"false");
+
+ assertEquals(configurationHandler.getBoolean("boolean1", false), true);
+ assertEquals(configurationHandler.getBoolean("boolean2", true), false);
+
+ assertEquals(configurationHandler.getBoolean("booleanX", true), true);
+ assertEquals(configurationHandler.getBoolean("booleanY", false),
false);
+ }
+
+ @Test
+ public void testConfigClean() throws Exception {
ConfigurationHandler configurationHandler = new
ConfigurationHandlerImpl();
- m_agentContextImpl.stop();
- m_agentContextImpl.setHandler(ConfigurationHandler.class,
configurationHandler);
- m_agentContextImpl.start();
+
+ resetConfigurationHandler(configurationHandler);
+
configurationHandler =
m_agentContextImpl.getHandler(ConfigurationHandler.class);
assertNotNull(configurationHandler.keySet());
@@ -65,9 +80,9 @@ public class ConfigurationHandlerImplTes
// should be persisted
configurationHandler = new ConfigurationHandlerImpl();
- m_agentContextImpl.stop();
- m_agentContextImpl.setHandler(ConfigurationHandler.class,
configurationHandler);
- m_agentContextImpl.start();
+
+ resetConfigurationHandler(configurationHandler);
+
configurationHandler =
m_agentContextImpl.getHandler(ConfigurationHandler.class);
assertNotNull(configurationHandler.keySet());
@@ -76,6 +91,22 @@ public class ConfigurationHandlerImplTes
}
@Test
+ public void testConfigLongProps() throws Exception {
+ ConfigurationHandler configurationHandler = new
ConfigurationHandlerImpl();
+
+ resetConfigurationHandler(configurationHandler);
+
+ configurationHandler =
m_agentContextImpl.getHandler(ConfigurationHandler.class);
+
+ configureAgent(configurationHandler, "long1", "42", "long2", "4");
+
+ assertEquals(configurationHandler.getLong("long1", 0l), 42);
+ assertEquals(configurationHandler.getLong("long2", 0l), 4l);
+
+ assertEquals(configurationHandler.getLong("longX", 42l), 42l);
+ }
+
+ @Test
public void testConfigSystemProps() throws Exception {
String systemKey1 = AgentConstants.CONFIG_KEY_NAMESPACE + "key1";
String systemKey2 = AgentConstants.CONFIG_KEY_NAMESPACE + "key2";
@@ -83,10 +114,7 @@ public class ConfigurationHandlerImplTes
System.setProperty(systemKey1, "value1");
System.setProperty(systemKey2, "value2");
- m_agentContextImpl.stop();
-
- m_agentContextImpl.setHandler(ConfigurationHandler.class, new
ConfigurationHandlerImpl());
- m_agentContextImpl.start();
+ resetConfigurationHandler();
ConfigurationHandler configurationHandler =
m_agentContextImpl.getHandler(ConfigurationHandler.class);
@@ -100,10 +128,7 @@ public class ConfigurationHandlerImplTes
System.clearProperty(systemKey1);
System.clearProperty(systemKey2);
- m_agentContextImpl.stop();
-
- m_agentContextImpl.setHandler(ConfigurationHandler.class, new
ConfigurationHandlerImpl());
- m_agentContextImpl.start();
+ resetConfigurationHandler();
configurationHandler =
m_agentContextImpl.getHandler(ConfigurationHandler.class);
@@ -119,9 +144,8 @@ public class ConfigurationHandlerImplTes
configureAgent(configurationHandler, systemKey1, "newvalue1",
systemKey2, "newvalue2");
- m_agentContextImpl.stop();
- m_agentContextImpl.setHandler(ConfigurationHandler.class, new
ConfigurationHandlerImpl());
- m_agentContextImpl.start();
+ resetConfigurationHandler();
+
configurationHandler =
m_agentContextImpl.getHandler(ConfigurationHandler.class);
assertNotNull(configurationHandler.keySet());
@@ -136,9 +160,8 @@ public class ConfigurationHandlerImplTes
System.setProperty(systemKey1 + AgentConstants.CONFIG_KEY_RETAIN,
"true");
System.setProperty(systemKey2 + AgentConstants.CONFIG_KEY_RETAIN,
"true");
- m_agentContextImpl.stop();
- m_agentContextImpl.setHandler(ConfigurationHandler.class, new
ConfigurationHandlerImpl());
- m_agentContextImpl.start();
+ resetConfigurationHandler();
+
configurationHandler =
m_agentContextImpl.getHandler(ConfigurationHandler.class);
assertNotNull(configurationHandler.keySet());
@@ -147,38 +170,17 @@ public class ConfigurationHandlerImplTes
assertEquals(configurationHandler.get(systemKey2, "qqq"), "value2");
}
- @Test
- public void testConfigBooleanProps() throws Exception {
-
- ConfigurationHandler configurationHandler = new
ConfigurationHandlerImpl();
- m_agentContextImpl.stop();
- m_agentContextImpl.setHandler(ConfigurationHandler.class,
configurationHandler);
- m_agentContextImpl.start();
- configurationHandler =
m_agentContextImpl.getHandler(ConfigurationHandler.class);
-
- configureAgent(configurationHandler, "boolean1", "true", "boolean2",
"false");
-
- assertEquals(configurationHandler.getBoolean("boolean1", false), true);
- assertEquals(configurationHandler.getBoolean("boolean2", true), false);
-
- assertEquals(configurationHandler.getBoolean("booleanX", true), true);
- assertEquals(configurationHandler.getBoolean("booleanY", false),
false);
+ private void resetConfigurationHandler() throws Exception {
+ resetConfigurationHandler(new ConfigurationHandlerImpl());
}
- @Test
- public void testConfigLongProps() throws Exception {
+ private void resetConfigurationHandler(ConfigurationHandler
configurationHandler) throws Exception {
+ ConfigurationHandler oldConfigurationHandler =
m_agentContextImpl.getHandler(ConfigurationHandler.class);
+ if (oldConfigurationHandler instanceof ComponentBase) {
+ ((ComponentBase) oldConfigurationHandler).stop();
+ }
- ConfigurationHandler configurationHandler = new
ConfigurationHandlerImpl();
- m_agentContextImpl.stop();
m_agentContextImpl.setHandler(ConfigurationHandler.class,
configurationHandler);
m_agentContextImpl.start();
- configurationHandler =
m_agentContextImpl.getHandler(ConfigurationHandler.class);
-
- configureAgent(configurationHandler, "long1", "42", "long2", "4");
-
- assertEquals(configurationHandler.getLong("long1", 0l), 42);
- assertEquals(configurationHandler.getLong("long2", 0l), 4l);
-
- assertEquals(configurationHandler.getLong("longX", 42l), 42l);
}
}
Modified:
ace/trunk/org.apache.ace.agent/test/org/apache/ace/agent/impl/EventLoggerImplTest.java
URL:
http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/test/org/apache/ace/agent/impl/EventLoggerImplTest.java?rev=1546563&r1=1546562&r2=1546563&view=diff
==============================================================================
---
ace/trunk/org.apache.ace.agent/test/org/apache/ace/agent/impl/EventLoggerImplTest.java
(original)
+++
ace/trunk/org.apache.ace.agent/test/org/apache/ace/agent/impl/EventLoggerImplTest.java
Fri Nov 29 13:58:21 2013
@@ -43,7 +43,7 @@ public class EventLoggerImplTest extends
static class TestFeedbackChannel implements FeedbackChannel {
int m_lastType = 0;
-
+
@Override
public void sendFeedback() throws RetryAfterException, IOException {
}
@@ -52,24 +52,24 @@ public class EventLoggerImplTest extends
public void write(int type, Map<String, String> properties) throws
IOException {
m_lastType = type;
}
-
+
public int getLastTtype() {
return m_lastType;
}
-
+
public void reset() {
m_lastType = 0;
}
}
-
+
static class TestFeedbackHandler implements FeedbackHandler {
Map<String, FeedbackChannel> channels = new HashMap<String,
FeedbackChannel>();
-
+
TestFeedbackHandler() {
channels.put("auditlog", new TestFeedbackChannel());
}
-
+
@Override
public Set<String> getChannelNames() throws IOException {
return channels.keySet();
@@ -79,14 +79,14 @@ public class EventLoggerImplTest extends
public FeedbackChannel getChannel(String name) throws IOException {
return channels.get("auditlog");
}
-
+
}
-
+
private AgentContextImpl m_agentContext;
private EventLoggerImpl m_eventLogger;
private EventsHandler m_eventsHandler;
- @BeforeClass
+ @BeforeClass(alwaysRun = true)
public void setUpOnceAgain() throws Exception {
m_agentContext = mockAgentContext();
@@ -99,18 +99,19 @@ public class EventLoggerImplTest extends
m_agentContext.start();
}
-
- @AfterClass
+
+ @AfterClass(alwaysRun = true)
public void tearDownOnceAgain() throws Exception {
m_agentContext.stop();
verifyTestMocks();
clearTestMocks();
}
- @BeforeMethod
+ @BeforeMethod(alwaysRun = true)
public void reset() throws Exception {
// create a new eventlogger for every test
m_eventLogger = new EventLoggerImpl(mockBundleContext());
+ m_eventLogger.init(m_agentContext);
m_eventsHandler.addListener(m_eventLogger);
m_eventLogger.start(m_agentContext);
@@ -119,19 +120,19 @@ public class EventLoggerImplTest extends
TestFeedbackChannel channel = (TestFeedbackChannel)
feedbackHandler.getChannel("auditlog");
channel.reset();
}
-
+
@SuppressWarnings("deprecation")
@Test
public void testWriteEvent() throws Exception {
FrameworkEvent event = new FrameworkEvent(32, new Object());
m_eventLogger.frameworkEvent(event);
-
+
FeedbackHandler feedbackHandler =
m_agentContext.getHandler(FeedbackHandler.class);
TestFeedbackChannel channel = (TestFeedbackChannel)
feedbackHandler.getChannel("auditlog");
assertEquals(channel.getLastTtype(), 1001);
-
+
}
-
+
@SuppressWarnings("deprecation")
@Test
public void testExcludeEvent() throws Exception {
@@ -144,7 +145,7 @@ public class EventLoggerImplTest extends
TestFeedbackChannel channel = (TestFeedbackChannel)
feedbackHandler.getChannel("auditlog");
// make sure the configuration is written to the channel
assertEquals(channel.getLastTtype(), 2000);
-
+
m_eventLogger.frameworkEvent(event);
// make sure nothing is written to the channel