|
| 1 | +#include<stddef.h> |
| 2 | +#include<stdlib.h> |
| 3 | +#include<string.h> |
| 4 | +#include"ddd.h" |
| 5 | + |
| 6 | +staticboolrecursiveTraverseGraph(Vertex*root,Vertex*v,intmarker); |
| 7 | + |
| 8 | +staticClustercluster; |
| 9 | + |
| 10 | +voidinitGraph(Graph*graph) |
| 11 | +{ |
| 12 | +memset(graph->hashtable,0,sizeof(graph->hashtable)); |
| 13 | +graph->freeEdges=NULL; |
| 14 | +graph->freeVertexes=NULL; |
| 15 | +graph->marker=0; |
| 16 | +} |
| 17 | + |
| 18 | +staticinlineEdge*newEdge(Graph*graph) |
| 19 | +{ |
| 20 | +Edge*edge=graph->freeEdges; |
| 21 | +if (edge==NULL) { |
| 22 | +edge= (Edge*)malloc(sizeof(Edge)); |
| 23 | + }else { |
| 24 | +graph->freeEdges=edge->next; |
| 25 | + } |
| 26 | +returnedge; |
| 27 | +} |
| 28 | + |
| 29 | +staticinlinevoidfreeVertex(Graph*graph,Vertex*vertex) |
| 30 | +{ |
| 31 | +inth=vertex->xid %MAX_TRANSACTIONS; |
| 32 | +Vertex**vpp=&graph->hashtable[h]; |
| 33 | +while (*vpp!=vertex) { |
| 34 | +vpp=&(*vpp)->next; |
| 35 | + } |
| 36 | +*vpp=vertex->next; |
| 37 | +vertex->next=graph->freeVertexes; |
| 38 | +graph->freeVertexes=vertex; |
| 39 | + |
| 40 | +} |
| 41 | + |
| 42 | +staticinlinevoidfreeEdge(Graph*graph,Edge*edge) |
| 43 | +{ |
| 44 | +edge->next=graph->freeEdges; |
| 45 | +graph->freeEdges=edge; |
| 46 | +} |
| 47 | + |
| 48 | +staticinlineVertex*newVertex(Graph*graph) |
| 49 | +{ |
| 50 | +Vertex*v=graph->freeVertexes; |
| 51 | +if (v==NULL) { |
| 52 | +v= (Vertex*)malloc(sizeof(Vertex)); |
| 53 | + }else { |
| 54 | +graph->freeVertexes=v->next; |
| 55 | + } |
| 56 | +returnv; |
| 57 | +} |
| 58 | + |
| 59 | +staticinlineVertex*findVertex(Graph*graph,xid_txid) |
| 60 | +{ |
| 61 | +xid_th=xid %MAX_TRANSACTIONS; |
| 62 | +Vertex*v; |
| 63 | +for (v=graph->hashtable[h];v!=NULL;v=v->next) { |
| 64 | +if (v->xid==xid) { |
| 65 | +returnv; |
| 66 | + } |
| 67 | + } |
| 68 | +v=newVertex(graph); |
| 69 | +l2_list_init(&v->outgoingEdges); |
| 70 | +v->xid=xid; |
| 71 | +v->nIncomingEdges=0; |
| 72 | +v->next=graph->hashtable[h]; |
| 73 | +graph->hashtable[h]=v; |
| 74 | +returnv; |
| 75 | +} |
| 76 | + |
| 77 | +staticinlineNode*findNode(Cluster*cluster,nodeid_tnode_id) |
| 78 | +{ |
| 79 | +size_th=node_id %MAX_STREAMS; |
| 80 | +Node*node; |
| 81 | +for (node=cluster->hashtable[h];node!=NULL;node=node->collision) { |
| 82 | +if (node->node_id==node_id) { |
| 83 | +returnnode; |
| 84 | + } |
| 85 | + } |
| 86 | +node= (Node*)malloc(sizeof(Node)); |
| 87 | +node->node_id=node_id; |
| 88 | +node->edges=NULL; |
| 89 | +node->collision=cluster->hashtable[h]; |
| 90 | +cluster->hashtable[h]=node; |
| 91 | +returnnode; |
| 92 | +} |
| 93 | + |
| 94 | +voidaddSubgraph(Graph*graph,nodeid_tnode_id,xid_t*xids,intn_xids) |
| 95 | +{ |
| 96 | +xid_t*last=xids+n_xids; |
| 97 | +Edge*e,*next,*edges=NULL; |
| 98 | +Node*node=findNode(&cluster,node_id); |
| 99 | +while (xids!=last) { |
| 100 | +Vertex*src=findVertex(graph,*xids++); |
| 101 | +xid_txid; |
| 102 | +while ((xid=*xids++)!=0) { |
| 103 | +Vertex*dst=findVertex(graph,xid); |
| 104 | +e=newEdge(graph); |
| 105 | +dst->nIncomingEdges+=1; |
| 106 | +e->dst=dst; |
| 107 | +e->src=src; |
| 108 | +e->next=edges; |
| 109 | +edges=e; |
| 110 | +l2_list_link(&src->outgoingEdges,&e->node); |
| 111 | + } |
| 112 | + } |
| 113 | +for (e=node->edges;e!=NULL;e=next) { |
| 114 | +next=e->next; |
| 115 | +l2_list_unlink(&e->node); |
| 116 | +if (--e->dst->nIncomingEdges==0&&l2_list_is_empty(&e->dst->outgoingEdges)) { |
| 117 | +freeVertex(graph,e->dst); |
| 118 | + } |
| 119 | +if (e->src->nIncomingEdges==0&&l2_list_is_empty(&e->src->outgoingEdges)) { |
| 120 | +freeVertex(graph,e->src); |
| 121 | + } |
| 122 | +freeEdge(graph,e); |
| 123 | + } |
| 124 | +node->edges=edges; |
| 125 | +} |
| 126 | + |
| 127 | +staticboolrecursiveTraverseGraph(Vertex*root,Vertex*v,intmarker) |
| 128 | +{ |
| 129 | +L2List*l; |
| 130 | +Edge*e; |
| 131 | +v->visited=marker; |
| 132 | +for (l=v->outgoingEdges.next;l!=&v->outgoingEdges;l=e->node.next) { |
| 133 | +e= (Edge*)l; |
| 134 | +if (e->dst==root) { |
| 135 | +return true; |
| 136 | + }elseif (e->dst->visited!=marker&&recursiveTraverseGraph(root,e->dst,marker)) {/* loop */ |
| 137 | +return true; |
| 138 | + } |
| 139 | + } |
| 140 | +return false; |
| 141 | +} |
| 142 | + |
| 143 | +booldetectDeadLock(Graph*graph,xid_troot) |
| 144 | +{ |
| 145 | +Vertex*v; |
| 146 | +for (v=graph->hashtable[root %MAX_TRANSACTIONS];v!=NULL;v=v->next) { |
| 147 | +if (v->xid==root) { |
| 148 | +if (recursiveTraverseGraph(v,v,++graph->marker)) { |
| 149 | +return true; |
| 150 | + } |
| 151 | +break; |
| 152 | + } |
| 153 | + } |
| 154 | +return false; |
| 155 | +} |