final boolean forceNewPlan) {
EntityGroupState currentState = state;
int versionOfOfflineNode = -1;
EntityGroupPlan plan = null;
long maxEntityGroupServerStartupWaitTime = -1;
EntityGroupInfo entityGroup = state.getEntityGroup();
for (int i = 1; i <= maximumAttempts && !server.isStopped(); i++) {
if (plan == null) { // Get a server for the entityGroup at first
plan = getEntityGroupPlan(entityGroup, forceNewPlan);
}
if (plan == null) {
LOG.debug("Unable to determine a plan to assign " + entityGroup);
this.timeoutMonitor.setAllEntityGroupServersOffline(true);
return; // Should get reassigned later when EGIT times out.
}
if (setOfflineInZK && versionOfOfflineNode == -1) {
// get the version of the znode after setting it to OFFLINE.
// versionOfOfflineNode will be -1 if the znode was not set to OFFLINE
versionOfOfflineNode = setOfflineInZooKeeper(currentState,
plan.getDestination());
if (versionOfOfflineNode != -1) {
if (isDisabledorDisablingEntityGroupInEGIT(entityGroup)) {
return;
}
// In case of assignment from EnableTableHandler table state is
// ENABLING. Any how
// EnableTableHandler will set ENABLED after assigning all the table
// entityGroups. If we
// try to set to ENABLED directly then client API may think table is
// enabled.
// When we have a case such as all the entityGroups are added directly
// into .META. and we call
// assignEntityGroup then we need to make the table ENABLED. Hence in
// such case the table
// will not be in ENABLING or ENABLED state.
String tableName = entityGroup.getTableNameAsString();
if (!zkTable.isEnablingTable(tableName)
&& !zkTable.isEnabledTable(tableName)) {
LOG.debug("Setting table " + tableName + " to ENABLED state.");
setEnabledTable(tableName);
}
}
}
if (setOfflineInZK && versionOfOfflineNode == -1) {
return;
}
if (this.server.isStopped()) {
LOG.debug("Server stopped; skipping assign of " + entityGroup);
return;
}
try {
LOG.info("Assigning entityGroup "
+ entityGroup.getEntityGroupNameAsString() + " to "
+ plan.getDestination().toString());
// Transition EntityGroupState to PENDING_OPEN
currentState = entityGroupStates.updateEntityGroupState(entityGroup,
EntityGroupState.State.PENDING_OPEN, plan.getDestination());
// Send OPEN RPC. This can fail if the server on other end is is not up.
// Pass the version that was obtained while setting the node to OFFLINE.
EntityGroupOpeningState entityGroupOpenState = serverManager
.sendEntityGroupOpen(plan.getDestination(), entityGroup,
versionOfOfflineNode);
if (entityGroupOpenState == EntityGroupOpeningState.ALREADY_OPENED) {
processAlreadyOpenedEntityGroup(entityGroup, plan.getDestination());
} else if (entityGroupOpenState == EntityGroupOpeningState.FAILED_OPENING) {
// Failed opening this entityGroup
throw new Exception("Get entityGroupOpeningState="
+ entityGroupOpenState);
}
break;
} catch (Throwable t) {
if (t instanceof RemoteException) {
t = ((RemoteException) t).unwrapRemoteException();
}
boolean entityGroupAlreadyInTransitionException = false;
boolean serverNotRunningYet = false;
boolean socketTimedOut = false;
if (t instanceof EntityGroupAlreadyInTransitionException) {
entityGroupAlreadyInTransitionException = true;
if (LOG.isDebugEnabled()) {
LOG.debug("Failed assignment in: " + plan.getDestination()
+ " due to " + t.getMessage());
}
} else if (t instanceof ServerNotRunningYetException) {
if (maxEntityGroupServerStartupWaitTime < 0) {
maxEntityGroupServerStartupWaitTime = System.currentTimeMillis()
+ this.server.getConfiguration().getLong(
"wasp.entityGroupserver.rpc.startup.waittime", 60000);
}
try {
long now = System.currentTimeMillis();
if (now < maxEntityGroupServerStartupWaitTime) {
LOG.debug("Server is not yet up; waiting up to "
+ (maxEntityGroupServerStartupWaitTime - now) + "ms", t);
serverNotRunningYet = true;
Thread.sleep(100);
i--; // reset the try count
} else {
LOG.debug("Server is not up for a while; try a new one", t);
}
} catch (InterruptedException ie) {
LOG.warn(
"Failed to assign " + entityGroup.getEntityGroupNameAsString()
+ " since interrupted", ie);
Thread.currentThread().interrupt();
return;
}
} else if (t instanceof java.net.SocketTimeoutException
&& this.serverManager.isServerOnline(plan.getDestination())) {
// In case socket is timed out and the entityGroup server is still
// online,
// the openEntityGroup RPC could have been accepted by the server and
// just the response didn't go through. So we will retry to
// open the entityGroup on the same server to avoid possible
// double assignment.
socketTimedOut = true;
if (LOG.isDebugEnabled()) {
LOG.debug(
"Call openEntityGroup() to " + plan.getDestination()
+ " has timed out when trying to assign "
+ entityGroup.getEntityGroupNameAsString()
+ ", but the entityGroup might already be opened on "
+ plan.getDestination() + ".", t);
}
}
LOG.warn(
"Failed assignment of "
+ entityGroup.getEntityGroupNameAsString()
+ " to "
+ plan.getDestination()
+ ", trying to assign "
+ (entityGroupAlreadyInTransitionException
|| serverNotRunningYet || socketTimedOut ? "to the same entityGroup server because of EntityGroupAlreadyInTransitionException"
+ "/ServerNotRunningYetException/SocketTimeoutException;"
: "elsewhere instead; ") + "try=" + i + " of "
+ this.maximumAttempts, t);
if (i == this.maximumAttempts) {
// Don't reset the entityGroup state or get a new plan any more.
// This is the last try.
continue;
}
// If entityGroup opened on destination of present plan, reassigning to
// new
// FSERVER may cause double assignments. In case of
// EntityGroupAlreadyInTransitionException
// reassigning to same FSERVER.
EntityGroupPlan newPlan = plan;
if (!(entityGroupAlreadyInTransitionException || serverNotRunningYet || socketTimedOut)) {
// Force a new plan and reassign. Will return null if no servers.
// The new plan could be the same as the existing plan since we don't
// exclude the server of the original plan, which should not be
// excluded since it could be the only server up now.
newPlan = getEntityGroupPlan(entityGroup, true);
}
if (newPlan == null) {
this.timeoutMonitor.setAllEntityGroupServersOffline(true);
LOG.warn("Unable to find a viable location to assign entityGroup "
+ entityGroup.getEntityGroupNameAsString());
return;
}
if (plan != newPlan
&& !plan.getDestination().equals(newPlan.getDestination())) {
// Clean out plan we failed execute and one that doesn't look like