![JAR search and dependency download from the Maven repository](/logo.png)
com.microsoft.windowsazure.serviceruntime.RoleEnvironment Maven / Gradle / Ivy
/**
* Copyright Microsoft Corporation
*
* Licensed 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 com.microsoft.windowsazure.serviceruntime;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
/**
* Represents the Windows Azure environment in which an instance of a role is
* running.
*/
public final class RoleEnvironment {
private static final String VersionEndpointEnvironmentName = "WaRuntimeEndpoint";
private static final String VersionEndpointFixedPath = "\\\\.\\pipe\\WindowsAzureRuntime";
private static final String clientId;
private static RuntimeClient runtimeClient;
private static AtomicReference currentGoalState;
private static AtomicReference currentEnvironmentData;
private static List changingListeners;
private static List changedListeners;
private static List stoppingListeners;
private static AtomicReference lastState;
private static final Calendar maxDateTime;
static {
try {
JAXBContext.newInstance(RoleEnvironment.class.getPackage().getName());
}
catch (JAXBException e) {
e.printStackTrace();
}
clientId = UUID.randomUUID().toString();
maxDateTime = javax.xml.bind.DatatypeConverter.parseDateTime("9999-12-31T23:59:59.9999999");
}
private RoleEnvironment() {
};
private static synchronized void initialize() {
if (runtimeClient == null) {
String endpoint = System.getenv(VersionEndpointEnvironmentName);
if (endpoint == null) {
endpoint = VersionEndpointFixedPath;
}
RuntimeKernel kernel = RuntimeKernel.getKernel();
try {
runtimeClient = kernel.getRuntimeVersionManager().getRuntimeClient(endpoint);
}
catch (Throwable t) {
throw new RoleEnvironmentNotAvailableException(t);
}
changingListeners = new LinkedList();
changedListeners = new LinkedList();
stoppingListeners = new LinkedList();
try {
currentGoalState = new AtomicReference(runtimeClient.getCurrentGoalState());
currentEnvironmentData = new AtomicReference(
runtimeClient.getRoleEnvironmentData());
}
catch (InterruptedException e) {
throw new RoleEnvironmentNotAvailableException(e);
}
lastState = new AtomicReference();
runtimeClient.addGoalStateChangedListener(new GoalStateChangedListener() {
@Override
public void goalStateChanged(GoalState newGoalState) {
switch (newGoalState.getExpectedState()) {
case STARTED:
if (newGoalState.getIncarnation().compareTo(currentGoalState.get().getIncarnation()) > 0) {
processGoalStateChange(newGoalState);
}
break;
case STOPPED:
raiseStoppingEvent();
CurrentState stoppedState = new AcquireCurrentState(clientId,
newGoalState.getIncarnation(), CurrentStatus.STOPPED, maxDateTime);
runtimeClient.setCurrentState(stoppedState);
break;
}
}
});
}
else {
try {
currentGoalState.set(runtimeClient.getCurrentGoalState());
currentEnvironmentData.set(runtimeClient.getRoleEnvironmentData());
}
catch (InterruptedException e) {
throw new RoleEnvironmentNotAvailableException(e);
}
}
}
private static void processGoalStateChange(GoalState newGoalState) {
List changes = new LinkedList();
RoleEnvironmentChangingEvent changingEvent = new RoleEnvironmentChangingEvent(changes);
CurrentState last = lastState.get();
calculateChanges(changes);
if (changes.isEmpty()) {
acceptLatestIncarnation(newGoalState, last);
}
else {
for (RoleEnvironmentChangingListener listener : changingListeners) {
try {
listener.roleEnvironmentChanging(changingEvent);
}
catch (Throwable t) {
t.printStackTrace();
}
}
if (changingEvent.isCancelled()) {
CurrentState recycleState = new AcquireCurrentState(clientId, newGoalState.getIncarnation(),
CurrentStatus.RECYCLE, maxDateTime);
runtimeClient.setCurrentState(recycleState);
return;
}
acceptLatestIncarnation(newGoalState, last);
try {
currentEnvironmentData.set(runtimeClient.getRoleEnvironmentData());
}
catch (InterruptedException e) {
throw new RoleEnvironmentNotAvailableException(e);
}
for (RoleEnvironmentChangedListener listener : changedListeners) {
try {
listener.roleEnvironmentChanged(new RoleEnvironmentChangedEvent(changes));
}
catch (Throwable t) {
t.printStackTrace();
}
}
}
}
private static void acceptLatestIncarnation(GoalState newGoalState, CurrentState last) {
if (last != null && last instanceof AcquireCurrentState) {
AcquireCurrentState acquireState = (AcquireCurrentState) last;
CurrentState acceptState = new AcquireCurrentState(clientId, newGoalState.getIncarnation(),
acquireState.getStatus(), acquireState.getExpiration());
runtimeClient.setCurrentState(acceptState);
}
currentGoalState.set(newGoalState);
}
private static void calculateChanges(List changes) {
RoleEnvironmentData current = currentEnvironmentData.get();
RoleEnvironmentData newData;
try {
newData = runtimeClient.getRoleEnvironmentData();
}
catch (InterruptedException e) {
throw new RoleEnvironmentNotAvailableException(e);
}
Map currentConfig = current.getConfigurationSettings();
Map newConfig = newData.getConfigurationSettings();
Map currentRoles = current.getRoles();
Map newRoles = newData.getRoles();
for (String setting : currentConfig.keySet()) {
if (newConfig.containsKey(setting)) {
if (!newConfig.get(setting).equals(currentConfig.get(setting))) {
changes.add(new RoleEnvironmentConfigurationSettingChange(setting));
}
}
else {
changes.add(new RoleEnvironmentConfigurationSettingChange(setting));
}
}
for (String setting : newConfig.keySet()) {
if (!currentConfig.containsKey(setting)) {
changes.add(new RoleEnvironmentConfigurationSettingChange(setting));
}
}
Set changedRoleSet = new HashSet();
for (String role : currentRoles.keySet()) {
if (newRoles.containsKey(role)) {
Role currentRole = currentRoles.get(role);
Role newRole = newRoles.get(role);
for (String instance : currentRole.getInstances().keySet()) {
if (newRole.getInstances().containsKey(instance)) {
RoleInstance currentInstance = currentRole.getInstances().get(instance);
RoleInstance newInstance = newRole.getInstances().get(instance);
if (currentInstance.getUpdateDomain() == newInstance.getUpdateDomain()
&& currentInstance.getFaultDomain() == newInstance.getFaultDomain()) {
for (String endpoint : currentInstance.getInstanceEndpoints().keySet()) {
if (newInstance.getInstanceEndpoints().containsKey(endpoint)) {
RoleInstanceEndpoint currentEndpoint = currentInstance.getInstanceEndpoints().get(
endpoint);
RoleInstanceEndpoint newEndpoint = newInstance.getInstanceEndpoints().get(endpoint);
if (!currentEndpoint.getProtocol().equals(newEndpoint.getProtocol())
|| !currentEndpoint.getIpEndPoint().equals(newEndpoint.getIpEndPoint())) {
changedRoleSet.add(role);
}
}
else {
changedRoleSet.add(role);
}
}
}
else {
changedRoleSet.add(role);
}
}
else {
changedRoleSet.add(role);
}
}
}
else {
changedRoleSet.add(role);
}
}
for (String role : newRoles.keySet()) {
if (currentRoles.containsKey(role)) {
Role currentRole = currentRoles.get(role);
Role newRole = newRoles.get(role);
for (String instance : newRole.getInstances().keySet()) {
if (currentRole.getInstances().containsKey(instance)) {
RoleInstance currentInstance = currentRole.getInstances().get(instance);
RoleInstance newInstance = newRole.getInstances().get(instance);
if (currentInstance.getUpdateDomain() == newInstance.getUpdateDomain()
&& currentInstance.getFaultDomain() == newInstance.getFaultDomain()) {
for (String endpoint : newInstance.getInstanceEndpoints().keySet()) {
if (currentInstance.getInstanceEndpoints().containsKey(endpoint)) {
RoleInstanceEndpoint currentEndpoint = currentInstance.getInstanceEndpoints().get(
endpoint);
RoleInstanceEndpoint newEndpoint = newInstance.getInstanceEndpoints().get(endpoint);
if (!currentEndpoint.getProtocol().equals(newEndpoint.getProtocol())
|| !currentEndpoint.getIpEndPoint().equals(newEndpoint.getIpEndPoint())) {
changedRoleSet.add(role);
}
}
else {
changedRoleSet.add(role);
}
}
}
else {
changedRoleSet.add(role);
}
}
else {
changedRoleSet.add(role);
}
}
}
else {
changedRoleSet.add(role);
}
}
for (String role : changedRoleSet) {
changes.add(new RoleEnvironmentTopologyChange(role));
}
}
private static synchronized void raiseStoppingEvent() {
for (RoleEnvironmentStoppingListener listener : stoppingListeners) {
try {
listener.roleEnvironmentStopping();
}
catch (Throwable t) {
t.printStackTrace();
}
}
}
/**
* Returns a {@link RoleInstance} object that represents the role instance
* in which this code is currently executing.
*
* @return A RoleInstance
object that represents the role
* instance in which this code is currently executing.
*/
public static RoleInstance getCurrentRoleInstance() {
initialize();
return currentEnvironmentData.get().getCurrentInstance();
}
/**
* Returns the deployment ID that uniquely identifies the deployment in
* which this role instance is running.
*
* @return A String
object that represents the deployment ID.
*/
public static String getDeploymentId() {
initialize();
return currentEnvironmentData.get().getDeploymentId();
}
/**
* Indicates whether the role instance is running in the Windows Azure
* environment.
*
* @return true
if this instance is running in the development
* fabric or in the Windows Azure environment in the cloud;
* otherwise, false
.
*/
public static boolean isAvailable() {
try {
initialize();
}
catch (RoleEnvironmentNotAvailableException ex) {
}
return runtimeClient != null;
}
/**
* Indicates whether the role instance is running in the development fabric.
*
* @return true
if this instance is running in the development
* fabric; otherwise, false
.
*/
public static boolean isEmulated() {
initialize();
return currentEnvironmentData.get().isEmulated();
}
/**
* Returns the set of {@link Role} objects defined for your service.
*
* Roles are defined in the service definition file.
*
* @return A java.util.Map
object containing the set of {@link Role} objects that represent the roles
* defined for your
* service.
*/
public static Map getRoles() {
initialize();
return currentEnvironmentData.get().getRoles();
}
/**
* Retrieves the settings in the service configuration file.
*
* A role's configuration settings are defined in the service definition file. Values for configuration settings are
* set in the service configuration file.
*
* @return A java.util.Map
object containing the String
objects that represent the
* configuration
* settings.
*/
public static Map getConfigurationSettings() {
initialize();
return currentEnvironmentData.get().getConfigurationSettings();
}
/**
* Retrieves the set of named local storage resources.
*
* @return A java.util.Map
object containing the String
objects that represent the local
* storage
* resources.
*/
public static Map getLocalResources() {
initialize();
return currentEnvironmentData.get().getLocalResources();
}
/**
* Requests that the current role instance be stopped and restarted.
*
* Before the role instance is recycled, the Windows Azure load balancer takes the role instance out of rotation.
* This ensures that no new requests are routed to the instance while it is restarting.
*
* A call to RequestRecycle
initiates the normal shutdown cycle. Windows Azure raises the
* Stopping
event and calls the OnStop
method so that you can run the necessary code to
* prepare the instance to be recycled.
*/
public static void requestRecycle() {
initialize();
CurrentState recycleState = new AcquireCurrentState(clientId, currentGoalState.get().getIncarnation(),
CurrentStatus.RECYCLE, maxDateTime);
runtimeClient.setCurrentState(recycleState);
}
/**
* Sets the status of the role instance.
*
* An instance may indicate that it is in one of two states: Ready or Busy. If an instance's state is Ready, it is
* prepared to receive requests from the load balancer. If the instance's state is Busy, it will not receive
* requests from the load balancer.
*
* @param status
* A {@link RoleInstanceStatus} value that indicates whether the
* instance is ready or busy.
* @param expiration_utc
* A java.util.Date
value that specifies the
* expiration date and time of the status.
*
*/
public static void setStatus(RoleInstanceStatus status, Date expiration_utc) {
initialize();
CurrentStatus currentStatus = CurrentStatus.STARTED;
switch (status) {
case Busy:
currentStatus = CurrentStatus.BUSY;
break;
case Ready:
currentStatus = CurrentStatus.STARTED;
}
Calendar expiration = Calendar.getInstance();
expiration.setTime(expiration_utc);
CurrentState newState = new AcquireCurrentState(clientId, currentGoalState.get().getIncarnation(),
currentStatus, expiration);
lastState.set(newState);
runtimeClient.setCurrentState(newState);
}
/**
* Clears the status of the role instance.
*
* An instance may indicate that it has completed communicating status by calling this method.
*
*/
public static void clearStatus() {
initialize();
CurrentState newState = new ReleaseCurrentState(clientId);
lastState.set(newState);
runtimeClient.setCurrentState(newState);
}
/**
* Adds an event listener for the Changed
event, which occurs
* after a configuration change has been applied to a role instance.
*
* A Changed
event is encapsulated in a {@link RoleEnvironmentChangedEvent} object.
*
* @param listener
* A {@link RoleEnvironmentChangedListener} object that
* represents the event listener to add.
*
* @see #removeRoleEnvironmentChangedListener
*/
public static synchronized void addRoleEnvironmentChangedListener(RoleEnvironmentChangedListener listener) {
initialize();
changedListeners.add(listener);
}
/**
* Removes an event listener for the Changed
event.
*
* @param listener
* A {@link RoleEnvironmentChangedListener} object that
* represents the event listener to remove.
*
* @see #addRoleEnvironmentChangedListener
*/
public static synchronized void removeRoleEnvironmentChangedListener(RoleEnvironmentChangedListener listener) {
initialize();
changedListeners.remove(listener);
}
/**
* Adds an event listener for the Changing
event, which occurs
* before a change to the service configuration is applied to the running
* instances of the role.
*
* Service configuration changes are applied on-the-fly to running role instances. Configuration changes include
* changes to the service configuration changes and changes to the number of instances in the service.
*
* This event occurs after the new configuration file has been submitted to Windows Azure but before the changes
* have been applied to each running role instance. This event can be cancelled for a given instance to prevent the
* configuration change.
*
* Note that cancelling this event causes the instance to be automatically recycled. When the instance is recycled,
* the configuration change is applied when it restarts.
*
* A Changing
event is encapsulated in a {@link RoleEnvironmentChangingEvent} object.
*
* @param listener
* A {@link RoleEnvironmentChangingListener} object that
* represents the event listener to add.
*
* @see #removeRoleEnvironmentChangingListener
*/
public static synchronized void addRoleEnvironmentChangingListener(RoleEnvironmentChangingListener listener) {
initialize();
changingListeners.add(listener);
}
/**
* Removes an event listener for the Changing
event.
*
* @param listener
* A {@link RoleEnvironmentChangingListener} object that
* represents the event listener to remove.
*
* @see #addRoleEnvironmentChangingListener
*/
public static void removeRoleEnvironmentChangingListener(RoleEnvironmentChangingListener listener) {
initialize();
changingListeners.remove(listener);
}
/**
* Adds an event listener for the Stopping
event, which occurs
* wheen the role is stopping.
*
* @param listener
* A {@link RoleEnvironmentStoppingListener} object that
* represents the event listener to add.
*
* @see #removeRoleEnvironmentStoppingListener
*/
public static synchronized void addRoleEnvironmentStoppingListener(RoleEnvironmentStoppingListener listener) {
initialize();
stoppingListeners.add(listener);
}
/**
* Removes an event listener for the Stopping
event.
*
* @param listener
* A {@link RoleEnvironmentStoppingListener} object that
* represents the event listener to remove.
*
* @see #addRoleEnvironmentStoppingListener
*/
public static synchronized void removeRoleEnvironmentStoppingListener(RoleEnvironmentStoppingListener listener) {
initialize();
stoppingListeners.remove(listener);
}
}