/*
* ProActive Parallel Suite(TM):
* The Open Source library for parallel and distributed
* Workflows & Scheduling, Orchestration, Cloud Automation
* and Big Data Analysis on Enterprise Grids & Clouds.
*
* Copyright (c) 2007 - 2017 ActiveEon
* Contact: contact@activeeon.com
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation: version 3 of
* the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* If needed, contact us to obtain a release under GPL Version 2 or 3
* or a different license than the AGPL.
*/
package org.ow2.proactive_grid_cloud_portal.rm;
import java.io.File;
import org.apache.log4j.Logger;
import org.objectweb.proactive.api.PAActiveObject;
import org.objectweb.proactive.api.PAFuture;
import org.objectweb.proactive.core.util.log.ProActiveLogger;
import org.objectweb.proactive.utils.Sleeper;
import org.ow2.proactive.authentication.crypto.CredData;
import org.ow2.proactive.authentication.crypto.Credentials;
import org.ow2.proactive.resourcemanager.common.event.RMInitialState;
import org.ow2.proactive.resourcemanager.common.util.RMProxyUserInterface;
import org.ow2.proactive_grid_cloud_portal.webapp.PortalConfiguration;
/**
* Periodically request {@link RMProxyUserInterface#getMonitoring()} and store it locally.
* <p>
* The {@link RMInitialState} fetched from {@link RMProxyUserInterface} is a large object
* that is long to serialize, but is always the same for every client.
* <p>
* Use this class to start a thread that will periodically get this object
* using a watcher account, making the cached version available to any client instantly.
* <p>
* Refresh rate can be configured using {@link PortalConfiguration#RM_CACHE_REFRESHRATE}
*/
public class RMStateCaching {
private static Logger logger = ProActiveLogger.getLogger(RMStateCaching.class);
private static RMProxyUserInterface rm;
private static RMInitialState state;
private static Thread rmUpdater;
private static int refreshInterval;
private static boolean kill = false;
/**
* Start a thread that will periodically fetch {@link RMProxyUserInterface#getMonitoring()}.
* <p>
* Thread frequency can be customized using {@link PortalConfiguration#RM_CACHE_REFRESHRATE}.
* <p>
* Cached object can be retrieved using {@link #getRMInitialState()}.
* <p>
* Stop this thread by calling {@link #kill()}.
*/
public synchronized static void init() {
new Thread(new Runnable() {
@Override
public void run() {
state = new RMInitialState();
init_();
run_();
}
}).start();
}
private static void init_() {
refreshInterval = PortalConfiguration.RM_CACHE_REFRESHRATE.getValueAsInt();
while (rm == null) {
String url = PortalConfiguration.RM_URL.getValueAsString();
String cred_path = PortalConfiguration.RM_CACHE_CREDENTIALS.getValueAsStringOrNull();
try {
if (rm == null) {
rm = PAActiveObject.newActive(RMProxyUserInterface.class, new Object[] {});
if (cred_path != null && new File(cred_path).exists()) {
Credentials cred = Credentials.getCredentials(cred_path);
rm.init(url, cred);
} else {
String login = PortalConfiguration.RM_CACHE_LOGIN.getValueAsString();
String password = PortalConfiguration.RM_CACHE_PASSWORD.getValueAsString();
rm.init(url, new CredData(login, password));
}
}
} catch (Exception e) {
if (rm != null) {
PAActiveObject.terminateActiveObject(rm, true);
rm = null;
}
new Sleeper(8 * 1000, logger).sleep();
continue;
}
}
}
private static void run_() {
rmUpdater = new Thread(new Runnable() {
@Override
public void run() {
boolean isDebugEnabled = logger.isDebugEnabled();
long startTime = 0;
while (!kill) {
try {
if (isDebugEnabled) {
startTime = System.currentTimeMillis();
}
state = PAFuture.getFutureValue(rm.getRMInitialState());
if (isDebugEnabled) {
logger.debug("Updated RM initial state in " + (System.currentTimeMillis() - startTime) +
"ms");
}
} catch (Throwable t) {
logger.error("Exception occurrend while updating RM state cache, connection reset", t);
init_();
}
new Sleeper(refreshInterval, logger).sleep();
}
}
});
rmUpdater.setName("RM Initial State Cache Updater");
rmUpdater.setDaemon(true);
rmUpdater.start();
}
/**
* @return cached RM State as returned by {@link RMProxyUserInterface#getMonitoring()}
*/
public static RMInitialState getRMInitialState() {
return state;
}
/**
* Stop the RM State polling thread.
*/
public static void kill() {
RMStateCaching.kill = true;
}
}