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