bug 10847: sg got executed in a big transaction leading to the deadlock

This commit is contained in:
Alex Huang 2011-07-25 17:41:11 -07:00
parent 9c627a15f3
commit 200d2b9cd0

View File

@ -490,7 +490,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
@DB
protected <T extends VMInstanceVO> Ternary<T, ReservationContext, ItWorkVO> changeToStartState(VirtualMachineGuru<T> vmGuru, T vm, User caller, Account account)
throws ConcurrentOperationException {
throws ConcurrentOperationException {
long vmId = vm.getId();
ItWorkVO work = new ItWorkVO(UUID.randomUUID().toString(), _nodeId, State.Starting, vm.getType(), vm.getId());
@ -556,16 +556,19 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
throw new ConcurrentOperationException("Unable to change the state of " + vm);
}
@DB
protected <T extends VMInstanceVO> boolean changeState(T vm, Event event, Long hostId, ItWorkVO work, Step step) throws NoTransitionException {
Transaction txn = Transaction.currentTxn();
txn.start();
if (!stateTransitTo(vm, event, hostId)) {
return false;
}
// FIXME: We should do this better.
Step previousStep = work.getStep();
_workDao.updateStep(work, step);
txn.commit();
return true;
boolean result = false;
try {
result = stateTransitTo(vm, event, hostId);
return result;
} finally {
if (!result) {
_workDao.updateStep(work, previousStep);
}
}
}
@Override
@ -658,7 +661,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
}
}
}
VirtualMachineProfileImpl<T> vmProfile = new VirtualMachineProfileImpl<T>(vm, template, offering, account, params);
DeployDestination dest = null;
for (DeploymentPlanner planner : _planners) {
@ -916,7 +919,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
}
return true;
}
Long hostId = vm.getHostId();
if (hostId == null) {
try {
@ -1532,15 +1535,15 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
_alertMgr.sendAlert(alertType, vm.getDataCenterIdToDeployIn(), vm.getPodIdToDeployIn(), "VM (name: " + vm.getInstanceName() + ", id: " + vm.getId() + ") stopped on host " + hostDesc + " due to storage failure",
"Virtual Machine " + vm.getInstanceName() + " (id: " + vm.getId() + ") running on host [" + vm.getHostId() + "] stopped due to storage failure.");
}
if(trackExternalChange) {
if(vm.getHostId() == null || hostId != vm.getHostId()) {
try {
stateTransitTo(vm, VirtualMachine.Event.AgentReportMigrated, hostId);
} catch (NoTransitionException e) {
if(vm.getHostId() == null || hostId != vm.getHostId()) {
try {
stateTransitTo(vm, VirtualMachine.Event.AgentReportMigrated, hostId);
} catch (NoTransitionException e) {
s_logger.warn(e.getMessage());
}
}
}
}
// if (serverState == State.Migrating) {
@ -1604,9 +1607,9 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
} else if (agentState == State.Running) {
if (serverState == State.Starting) {
if (fullSync) {
try {
ensureVmRunningContext(hostId, vm, Event.AgentReportRunning);
} catch (OperationTimedoutException e) {
try {
ensureVmRunningContext(hostId, vm, Event.AgentReportRunning);
} catch (OperationTimedoutException e) {
s_logger.error("Exception during update for running vm: " + vm, e);
return null;
} catch (ResourceUnavailableException e) {
@ -1626,10 +1629,10 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
}
return command;
}
private void ensureVmRunningContext(long hostId, VMInstanceVO vm, Event cause) throws OperationTimedoutException, ResourceUnavailableException, NoTransitionException {
VirtualMachineGuru<VMInstanceVO> vmGuru = getVmGuru(vm);
s_logger.debug("VM state is starting on full sync so updating it to running");
vm = findById(vm.getType(), vm.getId());
try {
@ -1637,7 +1640,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
} catch (NoTransitionException e1) {
s_logger.warn(e1.getMessage());
}
s_logger.debug("VM's " + vm + " state is starting on full sync so updating it to Running");
vm = vmGuru.findById(vm.getId()); // this should ensure vm has the most up to date info
@ -1684,7 +1687,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
} else {
castedVm = info.vm;
}
HypervisorGuru hvGuru = _hvGuruMgr.getGuru(castedVm.getHypervisorType());
Command command = compareState(hostId, castedVm, info, true, hvGuru.trackVmHostChange());
@ -1702,10 +1705,10 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
} else {
HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vm.getHypervisorType());
if(hvGuru.trackVmHostChange()) {
Command command = compareState(hostId, vm, left, true, true);
if (command != null) {
commands.addCommand(command);
}
Command command = compareState(hostId, vm, left, true, true);
if (command != null) {
commands.addCommand(command);
}
} else {
s_logger.warn("Stopping a VM that we have no record of: " + left.name);
commands.addCommand(cleanup(left.name));
@ -1783,7 +1786,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
if (!(cmd instanceof StartupRoutingCommand)) {
return;
}
if (forRebalance) {
s_logger.debug("Not processing listener " + this + " as connect happens on rebalance process");
return;
@ -1867,5 +1870,5 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
this.guru = (VirtualMachineGuru<VMInstanceVO>) guru;
}
}
}