CheckForDistributedDeadlocks no longer uses a VLA

- variable length arrays (VLAs) do not work with Visual Studio
- fix an off-by-one error. We incorrectly assumed there would always at
  least as many edges as there were nodes.
- refactor: reduce scope of transactionNodeStack by moving it into the
  function which uses it.
- refactor: break up the distinct uses of currentStackDepth into
  separate variables.
pull/1965/head
Brian Cloutier 2018-01-18 15:50:22 -08:00 committed by Brian Cloutier
parent 097fd15a89
commit 2efe80ce55
1 changed files with 16 additions and 5 deletions

View File

@ -135,6 +135,12 @@ CheckForDistributedDeadlocks(void)
bool deadlockFound = false; bool deadlockFound = false;
List *deadlockPath = NIL; List *deadlockPath = NIL;
/*
* Since we only see nodes which are waiting or being waited upon it's not
* possible to have more than edgeCount + 1 nodes.
*/
int maxStackDepth = edgeCount + 1;
/* we're only interested in finding deadlocks originating from this node */ /* we're only interested in finding deadlocks originating from this node */
if (transactionNode->transactionId.initiatorNodeIdentifier != localGroupId) if (transactionNode->transactionId.initiatorNodeIdentifier != localGroupId)
{ {
@ -144,7 +150,7 @@ CheckForDistributedDeadlocks(void)
ResetVisitedFields(adjacencyLists); ResetVisitedFields(adjacencyLists);
deadlockFound = CheckDeadlockForTransactionNode(transactionNode, deadlockFound = CheckDeadlockForTransactionNode(transactionNode,
edgeCount, maxStackDepth,
&deadlockPath); &deadlockPath);
if (deadlockFound) if (deadlockFound)
{ {
@ -233,22 +239,24 @@ CheckDeadlockForTransactionNode(TransactionNode *startingTransactionNode,
List **deadlockPath) List **deadlockPath)
{ {
List *toBeVisitedNodes = NIL; List *toBeVisitedNodes = NIL;
int currentStackDepth = 0; const int rootStackDepth = 0;
TransactionNode *transactionNodeStack[maxStackDepth]; TransactionNode **transactionNodeStack =
palloc0(maxStackDepth * sizeof(TransactionNode *));
/* /*
* We keep transactionNodeStack to keep track of the deadlock paths. At this point, * We keep transactionNodeStack to keep track of the deadlock paths. At this point,
* adjust the depth of the starting node and set the stack's first element with * adjust the depth of the starting node and set the stack's first element with
* the starting node. * the starting node.
*/ */
transactionNodeStack[currentStackDepth] = startingTransactionNode; transactionNodeStack[rootStackDepth] = startingTransactionNode;
PrependOutgoingNodesToQueue(startingTransactionNode, currentStackDepth, PrependOutgoingNodesToQueue(startingTransactionNode, rootStackDepth,
&toBeVisitedNodes); &toBeVisitedNodes);
/* traverse the graph and search for the deadlocks */ /* traverse the graph and search for the deadlocks */
while (toBeVisitedNodes != NIL) while (toBeVisitedNodes != NIL)
{ {
int currentStackDepth;
QueuedTransactionNode *queuedTransactionNode = QueuedTransactionNode *queuedTransactionNode =
(QueuedTransactionNode *) linitial(toBeVisitedNodes); (QueuedTransactionNode *) linitial(toBeVisitedNodes);
TransactionNode *currentTransactionNode = queuedTransactionNode->transactionNode; TransactionNode *currentTransactionNode = queuedTransactionNode->transactionNode;
@ -261,6 +269,7 @@ CheckDeadlockForTransactionNode(TransactionNode *startingTransactionNode,
BuildDeadlockPathList(queuedTransactionNode, transactionNodeStack, BuildDeadlockPathList(queuedTransactionNode, transactionNodeStack,
deadlockPath); deadlockPath);
pfree(transactionNodeStack);
return true; return true;
} }
@ -274,12 +283,14 @@ CheckDeadlockForTransactionNode(TransactionNode *startingTransactionNode,
/* set the stack's corresponding element with the current node */ /* set the stack's corresponding element with the current node */
currentStackDepth = queuedTransactionNode->currentStackDepth; currentStackDepth = queuedTransactionNode->currentStackDepth;
Assert(currentStackDepth < maxStackDepth);
transactionNodeStack[currentStackDepth] = currentTransactionNode; transactionNodeStack[currentStackDepth] = currentTransactionNode;
PrependOutgoingNodesToQueue(currentTransactionNode, currentStackDepth, PrependOutgoingNodesToQueue(currentTransactionNode, currentStackDepth,
&toBeVisitedNodes); &toBeVisitedNodes);
} }
pfree(transactionNodeStack);
return false; return false;
} }