|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* rea.c --
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* This file holds the reverse engineering algorithm common for
|
|
Packit |
022b05 |
* dump-cm.c and dump-svg.c.
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Copyright (c) 2000 A. Mueller, Technical University of Braunschweig.
|
|
Packit |
022b05 |
* Copyright (c) 2005 K. Sperner, Technical University of Braunschweig.
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* See the file "COPYING" for information on usage and redistribution
|
|
Packit |
022b05 |
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* @(#) $Id: rea.c 7823 2008-03-01 13:53:12Z schoenw $
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
#include <config.h>
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
#include <stdio.h>
|
|
Packit |
022b05 |
#include <stdlib.h>
|
|
Packit |
022b05 |
#include <string.h>
|
|
Packit |
022b05 |
#include <ctype.h>
|
|
Packit |
022b05 |
#ifdef HAVE_WIN_H
|
|
Packit |
022b05 |
#include "win.h"
|
|
Packit |
022b05 |
#endif
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
#include "smi.h"
|
|
Packit |
022b05 |
#include "smidump.h"
|
|
Packit |
022b05 |
#include "rea.h"
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* Constants used by the reverse engineering algorithm.
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
static char *pointer[] = {
|
|
Packit |
022b05 |
"Index", NULL
|
|
Packit |
022b05 |
};
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
static char *suffix[] = {
|
|
Packit |
022b05 |
"OrZero", NULL
|
|
Packit |
022b05 |
};
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
static char *supportObjs[] = {
|
|
Packit |
022b05 |
"RowStatus", "StorageType", NULL
|
|
Packit |
022b05 |
};
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
static char *baseTypes[] = {
|
|
Packit |
022b05 |
"Integer32", "OctetString", "Unsigned32", "Integer64",
|
|
Packit |
022b05 |
"Unsigned64", "Float32", "Float64", "Float128",
|
|
Packit |
022b05 |
"Enumeration", "Counter32", "Counter64","Bits",
|
|
Packit |
022b05 |
"Gauge", "Gauge32", "Integer", "TimeTicks",
|
|
Packit |
022b05 |
"IpAddress", "Opaque", "ObjectIdentifier",
|
|
Packit |
022b05 |
NULL
|
|
Packit |
022b05 |
};
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* driver output control
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* variables for svg-output
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* When you change CANVASHEIGHT, CANVASWIDTH values here, you should
|
|
Packit |
022b05 |
* also change them in initSvg() and the cgi-script.
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
int CANVASHEIGHT = 700; /* height of the svg */
|
|
Packit |
022b05 |
int CANVASWIDTH = 1100; /* width of the svg */
|
|
Packit |
022b05 |
int SHOW_DEPRECATED = 0; /* false, show deprecated objects */
|
|
Packit |
022b05 |
int SHOW_DEPR_OBSOLETE = 0; /* false, show deprecated and
|
|
Packit |
022b05 |
obsolete objects */
|
|
Packit |
022b05 |
int STATIC_OUTPUT = 0; /* false, enable interactivity */
|
|
Packit |
022b05 |
/* variables for cm-driver */
|
|
Packit |
022b05 |
int XPLAIN = 0; /* false, generates ASCII output */
|
|
Packit |
022b05 |
int XPLAIN_DEBUG = 0; /* false, generates additional
|
|
Packit |
022b05 |
output in xplain-mode */
|
|
Packit |
022b05 |
int SUPPRESS_DEPRECATED = 1; /* true, suppresses deprecated
|
|
Packit |
022b05 |
objects */
|
|
Packit |
022b05 |
/* common variables */
|
|
Packit |
022b05 |
int PRINT_DETAILED_ATTR = 1; /* true, prints all column
|
|
Packit |
022b05 |
objects */
|
|
Packit |
022b05 |
int IGNORE_IMPORTED_NODES = 1; /* true, ignores nodes which are
|
|
Packit |
022b05 |
imported from other MIBs*/
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* global variables
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
Graph *graph = NULL; /* the graph */
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/* ------ Misc. ----------------- */
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* cmpSmiNodes
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Compares two SmiNode and returns 1 if they are equal and 0 otherwise.
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
int cmpSmiNodes(SmiNode *node1, SmiNode *node2)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
SmiModule *module1, *module2;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
module1 = smiGetNodeModule(node1);
|
|
Packit |
022b05 |
module2 = smiGetNodeModule(node2);
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (!node1 || !node2 || !module1 || !module2) return 0;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
return (strcmp(node1->name, node2->name) == 0 &&
|
|
Packit |
022b05 |
strcmp(module1->name, module2->name) == 0);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* strpfxlen
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Returns the number of identical characters at the beginning of s1 and s2.
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
static int strpfxlen(const char *s1, const char *s2)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
int i;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (i = 0; s1[i] && s2[i]; i++) {
|
|
Packit |
022b05 |
if (s1[i] != s2[i]) {
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
return i;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/* ------ Graph primitives ------ */
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* graphInsertNode
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Inserts a new node into an existing graph.
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Result : pointer to the new node
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
GraphNode *graphInsertNode(Graph *graph, SmiNode *smiNode)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
GraphNode *newNode;
|
|
Packit |
022b05 |
GraphNode *tNode;
|
|
Packit |
022b05 |
GraphNode *lastNode;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
newNode = xmalloc(sizeof(GraphNode));
|
|
Packit |
022b05 |
memset(newNode, 0, sizeof(GraphNode));
|
|
Packit |
022b05 |
newNode->smiNode = smiNode;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (graph->nodes == NULL) {
|
|
Packit |
022b05 |
graph->nodes = newNode;
|
|
Packit |
022b05 |
return newNode;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
lastNode = NULL;
|
|
Packit |
022b05 |
for (tNode = graph->nodes; tNode; tNode = tNode->nextPtr) {
|
|
Packit |
022b05 |
lastNode = tNode;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
lastNode->nextPtr = newNode;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
return newNode;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* graphInsertComponent
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Inserts a new component into an existing graph.
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Result : pointer to the new component
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
GraphComponent *graphInsertComponent(Graph *graph)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
GraphComponent *newComponent;
|
|
Packit |
022b05 |
GraphComponent *tComponent;
|
|
Packit |
022b05 |
GraphComponent *lastComponent;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
newComponent = xmalloc(sizeof(GraphComponent));
|
|
Packit |
022b05 |
memset(newComponent, 0, sizeof(GraphComponent));
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (graph->components == NULL) {
|
|
Packit |
022b05 |
graph->components = newComponent;
|
|
Packit |
022b05 |
return newComponent;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
lastComponent = NULL;
|
|
Packit |
022b05 |
for (tComponent = graph->components; tComponent;
|
|
Packit |
022b05 |
tComponent = tComponent->nextPtr) {
|
|
Packit |
022b05 |
lastComponent = tComponent;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
lastComponent->nextPtr = newComponent;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
return newComponent;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* graphInsertEdge
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Inserts a new edge into an existing list of edges.
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Input : graph = pointer to an edge structure
|
|
Packit |
022b05 |
* startNode = pointer to the starting node of the edge
|
|
Packit |
022b05 |
* endNode = pointer to the ending node of the edge
|
|
Packit |
022b05 |
* indexkind = type of relationship between the two nodes
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Result : pointer to the new edge
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
static GraphEdge *graphInsertEdge(Graph *graph, GraphNode *startNode,
|
|
Packit |
022b05 |
GraphNode *endNode,
|
|
Packit |
022b05 |
SmiIndexkind indexkind,
|
|
Packit |
022b05 |
GraphEnhIndex enhancedindex)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
GraphEdge *newEdge;
|
|
Packit |
022b05 |
GraphEdge *tEdge;
|
|
Packit |
022b05 |
GraphEdge *lastEdge;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
newEdge = xmalloc(sizeof(GraphEdge));
|
|
Packit |
022b05 |
memset(newEdge, 0, sizeof(GraphEdge));
|
|
Packit |
022b05 |
newEdge->startNode = startNode;
|
|
Packit |
022b05 |
newEdge->endNode = endNode;
|
|
Packit |
022b05 |
newEdge->indexkind = indexkind;
|
|
Packit |
022b05 |
newEdge->connection = GRAPH_CON_ASSOCIATION;
|
|
Packit |
022b05 |
newEdge->enhancedindex = enhancedindex;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
switch (newEdge->indexkind) {
|
|
Packit |
022b05 |
case SMI_INDEX_AUGMENT :
|
|
Packit |
022b05 |
newEdge->cardinality = GRAPH_CARD_ONE_TO_ONE;
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
case SMI_INDEX_SPARSE :
|
|
Packit |
022b05 |
newEdge->cardinality = GRAPH_CARD_ONE_TO_ZERO_OR_ONE;
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
case SMI_INDEX_EXPAND :
|
|
Packit |
022b05 |
newEdge->cardinality = GRAPH_CARD_UNKNOWN;
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
case SMI_INDEX_REORDER :
|
|
Packit |
022b05 |
newEdge->cardinality = GRAPH_CARD_ONE_TO_ONE;
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
case SMI_INDEX_INDEX :
|
|
Packit |
022b05 |
newEdge->cardinality = GRAPH_CARD_UNKNOWN;
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
case SMI_INDEX_UNKNOWN :
|
|
Packit |
022b05 |
newEdge->cardinality = GRAPH_CARD_UNKNOWN;
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (graph->edges == NULL) {
|
|
Packit |
022b05 |
graph->edges = newEdge;
|
|
Packit |
022b05 |
return newEdge;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
lastEdge = NULL;
|
|
Packit |
022b05 |
for (tEdge = graph->edges; tEdge; tEdge = tEdge->nextPtr) {
|
|
Packit |
022b05 |
lastEdge = tEdge;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
lastEdge->nextPtr = newEdge;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
return newEdge;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* graphExit
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Frees all memory allocated by the graph.
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
void graphExit(Graph *graph)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
GraphEdge *tEdge, *dummyEdge;
|
|
Packit |
022b05 |
GraphNode *tNode, *dummyNode;
|
|
Packit |
022b05 |
GraphComponent *tComponent, *dummyComponent;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (graph) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
dummyNode = NULL;
|
|
Packit |
022b05 |
tNode = graph->nodes;
|
|
Packit |
022b05 |
while (tNode != NULL) {
|
|
Packit |
022b05 |
dummyNode = tNode;
|
|
Packit |
022b05 |
tNode = tNode->nextPtr;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
xfree(dummyNode);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
dummyEdge = NULL;
|
|
Packit |
022b05 |
tEdge = graph->edges;
|
|
Packit |
022b05 |
while (tEdge != NULL) {
|
|
Packit |
022b05 |
dummyEdge = tEdge;
|
|
Packit |
022b05 |
tEdge = tEdge->nextPtr;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
xfree(dummyEdge);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
dummyComponent = NULL;
|
|
Packit |
022b05 |
tComponent = graph->components;
|
|
Packit |
022b05 |
while (tComponent != NULL) {
|
|
Packit |
022b05 |
dummyComponent = tComponent;
|
|
Packit |
022b05 |
tComponent = tComponent->nextPtr;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
xfree(dummyComponent);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
xfree(graph);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* graphGetFirstEdgeByNode
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Returns the first edge adjacent to the given node (as startNode or EndNode).
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
GraphEdge *graphGetFirstEdgeByNode(Graph *graph, GraphNode *node)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
GraphEdge *tEdge;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (!graph || !node) {
|
|
Packit |
022b05 |
return NULL;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (tEdge = graph->edges; tEdge; tEdge = tEdge->nextPtr) {
|
|
Packit |
022b05 |
/*if (tEdge->startNode->smiNode->name == node->smiNode->name ||
|
|
Packit |
022b05 |
tEdge->endNode->smiNode->name == node->smiNode->name) break;*/
|
|
Packit |
022b05 |
if (cmpSmiNodes(tEdge->startNode->smiNode, node->smiNode) ||
|
|
Packit |
022b05 |
cmpSmiNodes(tEdge->endNode->smiNode, node->smiNode)) break;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
return tEdge;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* graphGetNextEdgeByNode
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Returns the next edge adjacent to the given node (as startNode or EndNode)
|
|
Packit |
022b05 |
* after the given edge.
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
GraphEdge *graphGetNextEdgeByNode(Graph *graph,
|
|
Packit |
022b05 |
GraphEdge *edge,
|
|
Packit |
022b05 |
GraphNode *node)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
GraphEdge *tEdge;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (!graph || !node) {
|
|
Packit |
022b05 |
return NULL;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (tEdge = graph->edges; tEdge; tEdge = tEdge->nextPtr) {
|
|
Packit |
022b05 |
/*if (tEdge->startNode->smiNode->name ==
|
|
Packit |
022b05 |
edge->startNode->smiNode->name &&
|
|
Packit |
022b05 |
tEdge->endNode->smiNode->name ==
|
|
Packit |
022b05 |
edge->endNode->smiNode->name) break;*/
|
|
Packit |
022b05 |
if (cmpSmiNodes(tEdge->startNode->smiNode,edge->startNode->smiNode) &&
|
|
Packit |
022b05 |
cmpSmiNodes(tEdge->endNode->smiNode,edge->endNode->smiNode))
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (tEdge = tEdge->nextPtr; tEdge; tEdge = tEdge->nextPtr) {
|
|
Packit |
022b05 |
/*if (tEdge->startNode->smiNode->name == node->smiNode->name ||
|
|
Packit |
022b05 |
tEdge->endNode->smiNode->name == node->smiNode->name) break;*/
|
|
Packit |
022b05 |
if (cmpSmiNodes(tEdge->startNode->smiNode, node->smiNode) ||
|
|
Packit |
022b05 |
cmpSmiNodes(tEdge->endNode->smiNode, node->smiNode)) break;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
return tEdge;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* graphCheckForRedundantEdge
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Finds redundant edges and returns 1 if one is found and 0 otherwise.
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
static int graphCheckForRedundantEdge(Graph *graph,
|
|
Packit |
022b05 |
GraphNode *startNode,
|
|
Packit |
022b05 |
GraphNode *endNode)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
GraphEdge *tEdge;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (!graph || !startNode || !endNode) {
|
|
Packit |
022b05 |
return 0;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (tEdge = graph->edges; tEdge; tEdge = tEdge->nextPtr) {
|
|
Packit |
022b05 |
/*if (tEdge->startNode->smiNode->name == startNode->smiNode->name &&
|
|
Packit |
022b05 |
tEdge->endNode->smiNode->name == endNode->smiNode->name) {*/
|
|
Packit |
022b05 |
if (cmpSmiNodes(tEdge->startNode->smiNode, startNode->smiNode) &&
|
|
Packit |
022b05 |
cmpSmiNodes(tEdge->endNode->smiNode, endNode->smiNode)) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
return 1;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
return 0;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* graphGetNode
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Returns the graph node containing smiNode.
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
static GraphNode *graphGetNode(Graph *graph, SmiNode *smiNode)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
GraphNode *tNode;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (!smiNode || !graph) {
|
|
Packit |
022b05 |
return NULL;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (tNode = graph->nodes; tNode; tNode = tNode->nextPtr) {
|
|
Packit |
022b05 |
if (tNode->smiNode->name == smiNode->name) {
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
return tNode;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* graphShowNodes
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Prints the nodes of the graph.
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
void graphShowNodes(Graph *graph)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
GraphNode *tNode;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (!graph->nodes) {
|
|
Packit |
022b05 |
printf("No nodes!\n");
|
|
Packit |
022b05 |
return;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (tNode = graph->nodes; tNode; tNode = tNode->nextPtr) {
|
|
Packit |
022b05 |
if (tNode->smiNode->nodekind == SMI_NODEKIND_TABLE)
|
|
Packit |
022b05 |
printf(" [TABLE]");
|
|
Packit |
022b05 |
else printf("[SCALAR]");
|
|
Packit |
022b05 |
printf("%40s [%s]\n", tNode->smiNode->name,
|
|
Packit |
022b05 |
smiGetNodeModule(tNode->smiNode)->name);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* graphShowEdges
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Prints the edges with their attributes in the following order :
|
|
Packit |
022b05 |
* - start node
|
|
Packit |
022b05 |
* - reason for the link
|
|
Packit |
022b05 |
* - connection type in UML
|
|
Packit |
022b05 |
* - cardinality
|
|
Packit |
022b05 |
* - index relationship derived from the row-objects of the tables
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
static void graphShowEdges(Graph *graph)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
GraphEdge *tEdge;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (!graph->edges) {
|
|
Packit |
022b05 |
printf("No edges!\n");
|
|
Packit |
022b05 |
return;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (tEdge = graph->edges; tEdge; tEdge = tEdge->nextPtr) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (XPLAIN_DEBUG) {
|
|
Packit |
022b05 |
switch (tEdge->enhancedindex) {
|
|
Packit |
022b05 |
case GRAPH_ENHINDEX_UNKNOWN :
|
|
Packit |
022b05 |
printf("[UNKNOWN] ");
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
case GRAPH_ENHINDEX_NOTIFICATION :
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
case GRAPH_ENHINDEX_NAMES :
|
|
Packit |
022b05 |
printf(" [NAMES] ");
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
case GRAPH_ENHINDEX_TYPES :
|
|
Packit |
022b05 |
printf(" [TYPES] ");
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
case GRAPH_ENHINDEX_INDEX :
|
|
Packit |
022b05 |
printf(" [INDEX] ");
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
case GRAPH_ENHINDEX_REROUTE :
|
|
Packit |
022b05 |
printf("[REROUTE] ");
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
case GRAPH_ENHINDEX_POINTER :
|
|
Packit |
022b05 |
printf("[POINTER] ");
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
switch (tEdge->connection) {
|
|
Packit |
022b05 |
case GRAPH_CON_AGGREGATION:
|
|
Packit |
022b05 |
printf("AG.");
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
case GRAPH_CON_DEPENDENCY:
|
|
Packit |
022b05 |
printf("D. ");
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
case GRAPH_CON_ASSOCIATION:
|
|
Packit |
022b05 |
printf("A. ");
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
case GRAPH_CON_UNKNOWN:
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
switch (tEdge->cardinality) {
|
|
Packit |
022b05 |
case GRAPH_CARD_UNKNOWN :
|
|
Packit |
022b05 |
printf(" (-:-) ");
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
case GRAPH_CARD_ONE_TO_ONE :
|
|
Packit |
022b05 |
printf(" (1:1) ");
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
case GRAPH_CARD_ONE_TO_MANY :
|
|
Packit |
022b05 |
printf(" (1:n) ");
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
case GRAPH_CARD_ZERO_TO_ONE :
|
|
Packit |
022b05 |
printf(" (0:1) ");
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
case GRAPH_CARD_ZERO_TO_MANY :
|
|
Packit |
022b05 |
printf(" (0:n) ");
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
case GRAPH_CARD_ONE_TO_ZERO_OR_ONE :
|
|
Packit |
022b05 |
printf("(1:0..1) ");
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
switch (tEdge->indexkind) {
|
|
Packit |
022b05 |
case SMI_INDEX_UNKNOWN :
|
|
Packit |
022b05 |
printf("GENERIC ");
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
case SMI_INDEX_INDEX :
|
|
Packit |
022b05 |
printf(" INDEX ");
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
case SMI_INDEX_AUGMENT :
|
|
Packit |
022b05 |
printf("AUGMENT ");
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
case SMI_INDEX_SPARSE :
|
|
Packit |
022b05 |
printf(" SPARSE ");
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
case SMI_INDEX_EXPAND :
|
|
Packit |
022b05 |
printf(" EXPAND ");
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
case SMI_INDEX_REORDER :
|
|
Packit |
022b05 |
printf("REORDER ");
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
printf("%29s - ",tEdge->startNode->smiNode->name);
|
|
Packit |
022b05 |
printf("%s\n",tEdge->endNode->smiNode->name);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/* ------ algorithm primitives ------ */
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* algCountIndexElements
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Returns the number of index elements in a given row entry.
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
static int algCountIndexElements(SmiNode *smiNode)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
int count;
|
|
Packit |
022b05 |
SmiElement *smiElement;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (smiNode->nodekind != SMI_NODEKIND_ROW) {
|
|
Packit |
022b05 |
return 0;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
count = 0;
|
|
Packit |
022b05 |
for (smiElement = smiGetFirstElement(smiNode);
|
|
Packit |
022b05 |
smiElement;
|
|
Packit |
022b05 |
smiElement = smiGetNextElement(smiElement)) {
|
|
Packit |
022b05 |
count++;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
return count;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* algInsertEdge
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Inserts an edge in a given graph. The edge is adjacent to snode
|
|
Packit |
022b05 |
* and enode.
|
|
Packit |
022b05 |
* The type of edge is given in indexkind and the enhanced index as
|
|
Packit |
022b05 |
* an additional information in enhancedindex.
|
|
Packit |
022b05 |
* Nodes which are not loaded yet into the node list of the graph
|
|
Packit |
022b05 |
* are added (nodes from imported MIBs).
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
static void algInsertEdge(SmiNode *snode, SmiNode *enode,
|
|
Packit |
022b05 |
SmiIndexkind indexkind,
|
|
Packit |
022b05 |
GraphEnhIndex enhancedindex)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
GraphNode *startNode;
|
|
Packit |
022b05 |
GraphNode *endNode;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (!graph) return;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
startNode = graphGetNode(graph, snode);
|
|
Packit |
022b05 |
endNode = graphGetNode(graph, enode);
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/* insert imported nodes into graph if needed */
|
|
Packit |
022b05 |
if (startNode == NULL) {
|
|
Packit |
022b05 |
if (IGNORE_IMPORTED_NODES) return;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
startNode = graphInsertNode(graph, snode);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
if (endNode == NULL) {
|
|
Packit |
022b05 |
if (IGNORE_IMPORTED_NODES) return;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
endNode = graphInsertNode(graph, enode);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (graphCheckForRedundantEdge(graph, startNode, endNode) == 0 &&
|
|
Packit |
022b05 |
graphCheckForRedundantEdge(graph, endNode, startNode) == 0) {
|
|
Packit |
022b05 |
graphInsertEdge(graph, startNode, endNode, indexkind, enhancedindex);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* algGetGroupByFatherNode
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Returns the group number associated with the father node of the
|
|
Packit |
022b05 |
* given node. If there is no group the result is 0 for no
|
|
Packit |
022b05 |
* grouping.
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
static int algGetGroupByFatherNode(SmiNode *smiNode)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
GraphNode *tNode;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (tNode = graph->nodes; tNode; tNode = tNode->nextPtr) {
|
|
Packit |
022b05 |
if (tNode->smiNode->nodekind == SMI_NODEKIND_SCALAR &&
|
|
Packit |
022b05 |
!graphGetFirstEdgeByNode(graph, tNode)) {
|
|
Packit |
022b05 |
if (cmpSmiNodes(smiGetParentNode(smiNode),
|
|
Packit |
022b05 |
smiGetParentNode(tNode->smiNode))) {
|
|
Packit |
022b05 |
return tNode->group;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
return 0;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* algGetNumberOfGroups
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Returns the number of groups.
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
int algGetNumberOfGroups()
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
GraphNode *tNode;
|
|
Packit |
022b05 |
int maxGroup;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
maxGroup = 0;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (tNode = graph->nodes; tNode; tNode = tNode->nextPtr) {
|
|
Packit |
022b05 |
maxGroup = max(maxGroup, tNode->group);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
return maxGroup;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* algPrintGroup
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Prints the group with the number group.
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
static void algPrintGroup(int group)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
GraphNode *tNode;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (tNode = graph->nodes; tNode; tNode = tNode->nextPtr) {
|
|
Packit |
022b05 |
if (tNode->group == group) {
|
|
Packit |
022b05 |
printf("%2d - %35s\n", group, tNode->smiNode->name);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* algGetTypeDescription
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Returns the description of the data type used in smiNode.
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
char *algGetTypeDescription(SmiNode *smiNode)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
SmiType *smiType, *parentType;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
smiType = smiGetNodeType(smiNode);
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (!smiType || smiNode->nodekind == SMI_NODEKIND_TABLE)
|
|
Packit |
022b05 |
return NULL;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (smiType->decl == SMI_DECL_IMPLICIT_TYPE) {
|
|
Packit |
022b05 |
parentType = smiGetParentType(smiType);
|
|
Packit |
022b05 |
smiType = parentType;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
return smiType->description;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* algGetTypeName
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Returns the name of the data type used in smiNode.
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
char *algGetTypeName(SmiNode *smiNode)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
SmiType *smiType, *parentType;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
smiType = smiGetNodeType(smiNode);
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (!smiType || smiNode->nodekind == SMI_NODEKIND_TABLE)
|
|
Packit |
022b05 |
return NULL;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (smiType->decl == SMI_DECL_IMPLICIT_TYPE) {
|
|
Packit |
022b05 |
parentType = smiGetParentType(smiType);
|
|
Packit |
022b05 |
smiType = parentType;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
return smiType->name;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* algGetTypeModule
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Returns the module which defines the data type used in smiNode.
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
SmiModule *algGetTypeModule(SmiNode *smiNode)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
SmiType *smiType, *parentType;
|
|
Packit |
022b05 |
SmiModule *smiModule;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
smiType = smiGetNodeType(smiNode);
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (!smiType || smiNode->nodekind == SMI_NODEKIND_TABLE)
|
|
Packit |
022b05 |
return NULL;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (smiType->decl == SMI_DECL_IMPLICIT_TYPE) {
|
|
Packit |
022b05 |
parentType = smiGetParentType(smiType);
|
|
Packit |
022b05 |
smiType = parentType;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
smiModule = smiGetTypeModule(smiType);
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
return smiModule;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* algCountElementsFromOtherTables
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Returns the number of index objects derived from other tables than
|
|
Packit |
022b05 |
* the given one.
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
static int algCountElementsFromOtherTables(SmiNode *smiNode)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
SmiElement *smiElement;
|
|
Packit |
022b05 |
SmiNode *tNode;
|
|
Packit |
022b05 |
int elems = 0;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (smiElement = smiGetFirstElement(smiNode);
|
|
Packit |
022b05 |
smiElement;
|
|
Packit |
022b05 |
smiElement = smiGetNextElement(smiElement)) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
tNode = smiGetElementNode(smiElement);
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (cmpSmiNodes(smiGetParentNode(smiGetParentNode(tNode)),
|
|
Packit |
022b05 |
smiGetParentNode(smiNode)) != 1) {
|
|
Packit |
022b05 |
elems++;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
return elems;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* algGetNumberOfRows
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Returns the number of rows =
|
|
Packit |
022b05 |
* number of elements in smiNode - number of rows
|
|
Packit |
022b05 |
* + RowStatus-Objects + StorageType-Objects
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* If the number is > 0 it is only a supporting table (like entLPMappingTable)
|
|
Packit |
022b05 |
* and if the number is < 0 it is a "full" table (like ifTable).
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Subroutine for algCheckForDependency.
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
static int algGetNumberOfRows(SmiNode *smiNode)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
SmiNode *tSmiNode;
|
|
Packit |
022b05 |
SmiNode *table;
|
|
Packit |
022b05 |
int i, elemCount;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
elemCount = 0;
|
|
Packit |
022b05 |
table = smiNode;
|
|
Packit |
022b05 |
tSmiNode = smiGetFirstChildNode(table);
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
elemCount = algCountIndexElements(tSmiNode) -
|
|
Packit |
022b05 |
algCountElementsFromOtherTables(tSmiNode);
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (tSmiNode = smiGetNextNode(tSmiNode, SMI_NODEKIND_COLUMN);
|
|
Packit |
022b05 |
tSmiNode;
|
|
Packit |
022b05 |
tSmiNode = smiGetNextNode(tSmiNode, SMI_NODEKIND_COLUMN)) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (cmpSmiNodes(table, smiGetParentNode(smiGetParentNode(tSmiNode)))
|
|
Packit |
022b05 |
!= 1) {
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (i = 0; supportObjs[i]; i++) {
|
|
Packit |
022b05 |
char *typeName = algGetTypeName(tSmiNode);
|
|
Packit |
022b05 |
if (typeName && (strcasecmp(typeName, supportObjs[i]) == 0)) {
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (!supportObjs[i]) elemCount--;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
return elemCount;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* isBaseType
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* returns 1 if smiElement is a basetype used in SMIv2/SMIng. Otherwise
|
|
Packit |
022b05 |
* the result is 0.
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
int isBaseType(SmiNode *node)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
int i;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (i = 0; baseTypes[i]; i++) {
|
|
Packit |
022b05 |
if (strcasecmp(algGetTypeName(node), baseTypes[i]) == 0) {
|
|
Packit |
022b05 |
return 1;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
return 0;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* algFindEqualType
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Looks in all tables indices for an equal type to the type used in typeNode.
|
|
Packit |
022b05 |
* It returns the first table found which is different to startTable.
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Subroutine for algCheckForDependency.
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
static SmiNode *algFindEqualType(SmiNode *startTable, SmiNode *typeNode)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
SmiElement *smiElement;
|
|
Packit |
022b05 |
SmiNode *tSmiNode;
|
|
Packit |
022b05 |
char *typeName;
|
|
Packit |
022b05 |
GraphNode *tNode;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
typeName = algGetTypeName(typeNode);
|
|
Packit |
022b05 |
/* if (isBaseType(typeNode)) return NULL; */
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (tNode = graph->nodes; tNode; tNode = tNode->nextPtr) {
|
|
Packit |
022b05 |
if (tNode->smiNode->nodekind == SMI_NODEKIND_TABLE) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
tSmiNode = tNode->smiNode;
|
|
Packit |
022b05 |
if (cmpSmiNodes(tSmiNode, startTable) == 1) break;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (smiElement = smiGetFirstElement(
|
|
Packit |
022b05 |
smiGetFirstChildNode(tSmiNode));
|
|
Packit |
022b05 |
smiElement;
|
|
Packit |
022b05 |
smiElement = smiGetNextElement(smiElement)) {
|
|
Packit |
022b05 |
/* found type matching ? */
|
|
Packit |
022b05 |
if (strcmp(typeName,
|
|
Packit |
022b05 |
algGetTypeName(smiGetElementNode
|
|
Packit |
022b05 |
(smiElement))) == 0) {
|
|
Packit |
022b05 |
return tSmiNode;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
return NULL;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* 0 = totaly equal (order and objects)
|
|
Packit |
022b05 |
* 1 = equal objects but different order
|
|
Packit |
022b05 |
* 2 = inequal
|
|
Packit |
022b05 |
* 3 = error;
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
static int equalElements(SmiNode *firstRow, SmiNode *secondRow)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
int i,j,number1, number2;
|
|
Packit |
022b05 |
SmiElement *elemFirst, *elemSecond;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (!firstRow->nodekind == SMI_NODEKIND_ROW ||
|
|
Packit |
022b05 |
!secondRow->nodekind == SMI_NODEKIND_ROW) {
|
|
Packit |
022b05 |
/* printf("no row entries\n"); */
|
|
Packit |
022b05 |
return 3;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (cmpSmiNodes(firstRow, secondRow) == 1) {
|
|
Packit |
022b05 |
/* printf("same objects\n"); */
|
|
Packit |
022b05 |
return 3;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
number1 = algCountIndexElements(firstRow);
|
|
Packit |
022b05 |
number2 = algCountIndexElements(secondRow);
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (number1 != number2) {
|
|
Packit |
022b05 |
/* printf("Different number of elements\n"); */
|
|
Packit |
022b05 |
return 2;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
i = 0;
|
|
Packit |
022b05 |
for (elemFirst = smiGetFirstElement(firstRow);
|
|
Packit |
022b05 |
elemFirst;
|
|
Packit |
022b05 |
elemFirst = smiGetNextElement(elemFirst)) {
|
|
Packit |
022b05 |
i++;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
j = 0;
|
|
Packit |
022b05 |
for (elemSecond = smiGetFirstElement(secondRow);
|
|
Packit |
022b05 |
elemSecond;
|
|
Packit |
022b05 |
elemSecond = smiGetNextElement(elemSecond)) {
|
|
Packit |
022b05 |
j++;
|
|
Packit |
022b05 |
if (i == j && cmpSmiNodes(smiGetElementNode(elemFirst),
|
|
Packit |
022b05 |
smiGetElementNode(elemSecond)) == 1) {
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/* maybe same elements but in different order */
|
|
Packit |
022b05 |
if (!elemSecond) break;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
if (!elemFirst) {
|
|
Packit |
022b05 |
/* printf("totaly equal\n"); */
|
|
Packit |
022b05 |
return 0;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (elemFirst = smiGetFirstElement(firstRow);
|
|
Packit |
022b05 |
elemFirst;
|
|
Packit |
022b05 |
elemFirst = smiGetNextElement(elemFirst)) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (elemSecond = smiGetFirstElement(secondRow);
|
|
Packit |
022b05 |
elemSecond;
|
|
Packit |
022b05 |
elemSecond = smiGetNextElement(elemSecond)) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (cmpSmiNodes(smiGetElementNode(elemFirst),
|
|
Packit |
022b05 |
smiGetElementNode(elemSecond)) == 1) {
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/* maybe same elements but in different order */
|
|
Packit |
022b05 |
if (!elemSecond) break;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (!elemFirst) {
|
|
Packit |
022b05 |
/* printf("Equal\n"); */
|
|
Packit |
022b05 |
return 1;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
else {
|
|
Packit |
022b05 |
/* printf("inequal"); */
|
|
Packit |
022b05 |
return 2;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* algIsIndexElement
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Tests whether a given node is part of the index of a particular
|
|
Packit |
022b05 |
* table. Returns 1 if the node is an index node and 0 otherwise.
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
int algIsIndexElement(SmiNode *table, SmiNode *node)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
SmiElement *smiElement;
|
|
Packit |
022b05 |
SmiNode *row;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (node->nodekind != SMI_NODEKIND_TABLE) {
|
|
Packit |
022b05 |
return 0;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
row = smiGetFirstChildNode(table);
|
|
Packit |
022b05 |
if (!row || row->nodekind != SMI_NODEKIND_ROW) {
|
|
Packit |
022b05 |
return 0;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (smiElement = smiGetFirstElement(row);
|
|
Packit |
022b05 |
smiElement;
|
|
Packit |
022b05 |
smiElement = smiGetNextElement(smiElement)) {
|
|
Packit |
022b05 |
SmiNode *indexNode = smiGetElementNode(smiElement);
|
|
Packit |
022b05 |
if (cmpSmiNodes(indexNode, node)) {
|
|
Packit |
022b05 |
return 1;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
return 0;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/* -------------- main functions ------------------------------------------- */
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* algCheckForExpandRel
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Checks the given table for an expand relationship to an other table.
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* 1. gets the expanded table (father node of smiNode)
|
|
Packit |
022b05 |
* 2. gets the base table by walking through the elements of the smiNode
|
|
Packit |
022b05 |
* starting at the end. The first table found which is different from the
|
|
Packit |
022b05 |
* expanded table is the first candidate for the base table.
|
|
Packit |
022b05 |
* 3. comparing the number of elements in both tables
|
|
Packit |
022b05 |
* if the number in the expanded table is greater -> 5.
|
|
Packit |
022b05 |
* if the number in the base table is greater -> 4.
|
|
Packit |
022b05 |
* 4. getting a second base table candidate :
|
|
Packit |
022b05 |
* It is possible that a table expands an other table which is expanded
|
|
Packit |
022b05 |
* by this.
|
|
Packit |
022b05 |
* Therefore it is hard to track the base table.
|
|
Packit |
022b05 |
* - scanning all tables which are different from the expanded table
|
|
Packit |
022b05 |
* - the base table must have :
|
|
Packit |
022b05 |
* - least elements
|
|
Packit |
022b05 |
* - the same elementes must occur as in the expanded table
|
|
Packit |
022b05 |
* 5. the elements in both tables are checked for equality
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
static void algCheckForExpandRel(SmiNode *smiNode)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
SmiNode *tNode;
|
|
Packit |
022b05 |
SmiNode *baseTable;
|
|
Packit |
022b05 |
SmiNode *expTable;
|
|
Packit |
022b05 |
SmiElement *smiElement;
|
|
Packit |
022b05 |
SmiElement *findElement;
|
|
Packit |
022b05 |
unsigned int refcounter;
|
|
Packit |
022b05 |
unsigned int basecounter;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (!smiNode) return;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
expTable = smiGetParentNode(smiNode);
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/* count the elements in the given table <- father of smiNode */
|
|
Packit |
022b05 |
refcounter = algCountIndexElements(smiNode);
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/* find the base table <- via the last element which does not refer to
|
|
Packit |
022b05 |
the expTable */
|
|
Packit |
022b05 |
baseTable = NULL;
|
|
Packit |
022b05 |
for (smiElement = smiGetFirstElement(smiNode);
|
|
Packit |
022b05 |
smiElement;
|
|
Packit |
022b05 |
smiElement = smiGetNextElement(smiElement)) {
|
|
Packit |
022b05 |
tNode = smiGetElementNode(smiElement);
|
|
Packit |
022b05 |
tNode = smiGetParentNode(tNode);
|
|
Packit |
022b05 |
tNode = smiGetParentNode(tNode);
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (cmpSmiNodes(tNode, expTable) == 1) break;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
baseTable = tNode;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (!baseTable) return;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/* count the elements in the basetable */
|
|
Packit |
022b05 |
basecounter = algCountIndexElements(smiGetFirstChildNode(baseTable));
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/* are baseTable and expTable identical ? */
|
|
Packit |
022b05 |
if (basecounter >= refcounter) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/* searching for new base table candidate in order to handle multiple
|
|
Packit |
022b05 |
indices */
|
|
Packit |
022b05 |
for (baseTable = smiGetNextNode(baseTable, SMI_NODEKIND_TABLE);
|
|
Packit |
022b05 |
baseTable;
|
|
Packit |
022b05 |
baseTable = smiGetNextNode(baseTable, SMI_NODEKIND_TABLE)) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
basecounter = algCountIndexElements(smiGetFirstChildNode(baseTable));
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (basecounter < refcounter) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (smiElement = smiGetFirstElement(
|
|
Packit |
022b05 |
smiGetFirstChildNode(expTable));
|
|
Packit |
022b05 |
smiElement;
|
|
Packit |
022b05 |
smiElement = smiGetNextElement(smiElement)) {
|
|
Packit |
022b05 |
tNode = smiGetElementNode(smiElement);
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*if (smiGetParentNode(smiGetParentNode(tNode))->name ==
|
|
Packit |
022b05 |
expTable->name) break; */
|
|
Packit |
022b05 |
if (cmpSmiNodes(smiGetParentNode(smiGetParentNode(tNode)),
|
|
Packit |
022b05 |
expTable) == 1) break;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (findElement = smiGetFirstElement(
|
|
Packit |
022b05 |
smiGetFirstChildNode(baseTable));
|
|
Packit |
022b05 |
findElement;
|
|
Packit |
022b05 |
findElement = smiGetNextElement(findElement)) {
|
|
Packit |
022b05 |
if (cmpSmiNodes(tNode, smiGetElementNode(findElement))
|
|
Packit |
022b05 |
== 1) break;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (!findElement) {
|
|
Packit |
022b05 |
return;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (!baseTable) {
|
|
Packit |
022b05 |
return;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (smiElement = smiGetFirstElement(smiGetFirstChildNode(baseTable));
|
|
Packit |
022b05 |
smiElement;
|
|
Packit |
022b05 |
smiElement = smiGetNextElement(smiElement)) {
|
|
Packit |
022b05 |
tNode = smiGetElementNode(smiElement);
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (findElement = smiGetFirstElement(smiGetFirstChildNode(expTable));
|
|
Packit |
022b05 |
findElement;
|
|
Packit |
022b05 |
findElement = smiGetNextElement(findElement)) {
|
|
Packit |
022b05 |
if (cmpSmiNodes(tNode, smiGetElementNode(findElement)) == 1)
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (!findElement) {
|
|
Packit |
022b05 |
return;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
algInsertEdge(baseTable, expTable, SMI_INDEX_EXPAND,
|
|
Packit |
022b05 |
GRAPH_ENHINDEX_INDEX);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* algCheckForSparseRel
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Checks the given table for a sparse relationship to an other table.
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Criterias for a sparse relationship :
|
|
Packit |
022b05 |
* - same number of index elements in both tables
|
|
Packit |
022b05 |
* - the same order of this elements
|
|
Packit |
022b05 |
* 1. Getting the basetable via the last element in the index of smiNode.
|
|
Packit |
022b05 |
* 2. comparing the number of elements
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
static void algCheckForSparseRel(SmiNode *smiNode)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
SmiNode *tNode = NULL;
|
|
Packit |
022b05 |
SmiNode *table;
|
|
Packit |
022b05 |
SmiElement *smiElement;
|
|
Packit |
022b05 |
unsigned int basecounter;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (!smiNode) return;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
table = smiGetParentNode(smiNode);
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
basecounter = algCountIndexElements(smiNode);
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/* getting the basetable via the father node of the last element
|
|
Packit |
022b05 |
to handle multiple instanceing */
|
|
Packit |
022b05 |
for (smiElement = smiGetFirstElement(smiNode);
|
|
Packit |
022b05 |
smiElement;
|
|
Packit |
022b05 |
smiElement = smiGetNextElement(smiElement)) {
|
|
Packit |
022b05 |
tNode = smiGetElementNode(smiElement);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (! tNode) {
|
|
Packit |
022b05 |
return;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
tNode = smiGetParentNode(tNode);
|
|
Packit |
022b05 |
if (equalElements(smiNode, tNode) == 0) {
|
|
Packit |
022b05 |
algInsertEdge(smiGetParentNode(tNode), smiGetParentNode(smiNode),
|
|
Packit |
022b05 |
SMI_INDEX_SPARSE, GRAPH_ENHINDEX_INDEX);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* algCheckForReOrderRel
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Checks the given table for a reorder relationship to an other table.
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Criterias for reoder relationships :
|
|
Packit |
022b05 |
* - same number of elements
|
|
Packit |
022b05 |
* - same elements must occur in a different order
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
static void algCheckForReorderRel(SmiNode *smiNode)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
SmiNode *tNode;
|
|
Packit |
022b05 |
GraphNode *graphNode;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (!smiNode) {
|
|
Packit |
022b05 |
return;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (graphNode = graph->nodes;
|
|
Packit |
022b05 |
graphNode;
|
|
Packit |
022b05 |
graphNode = graphNode->nextPtr) {
|
|
Packit |
022b05 |
tNode = graphNode->smiNode;
|
|
Packit |
022b05 |
if (tNode->nodekind == SMI_NODEKIND_TABLE) {
|
|
Packit |
022b05 |
if (equalElements(smiNode, smiGetFirstChildNode(tNode)) == 1) {
|
|
Packit |
022b05 |
algInsertEdge(smiGetParentNode(smiNode), tNode,
|
|
Packit |
022b05 |
SMI_INDEX_REORDER, GRAPH_ENHINDEX_INDEX);
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* algGetIndexkind
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Gets the indexkind of the given table. The row object of the table is
|
|
Packit |
022b05 |
* passed to this function.
|
|
Packit |
022b05 |
* Therefore three subfunctions are called to get the indexkind.
|
|
Packit |
022b05 |
* - algChechForExpandRel
|
|
Packit |
022b05 |
* - algCheckForSparseRel
|
|
Packit |
022b05 |
* - algCheckForReOrderRel
|
|
Packit |
022b05 |
* Look there for further information.
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
static void algGetIndexkind(SmiNode *row)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
algCheckForExpandRel(row);
|
|
Packit |
022b05 |
algCheckForSparseRel(row);
|
|
Packit |
022b05 |
algCheckForReorderRel(row);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* algLinkTables
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Links the tables of the given module.
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* 1. Getting the tables and the scalars from the given module.
|
|
Packit |
022b05 |
* 2. Linking the tables :
|
|
Packit |
022b05 |
* - AUGMENT no work to do just adding the corresponding edge
|
|
Packit |
022b05 |
* - for other relationships the subfunction algGetIndexkind is called
|
|
Packit |
022b05 |
* look there for further information
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
void algLinkTables()
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
GraphNode *tGraphNode;
|
|
Packit |
022b05 |
SmiNode *node;
|
|
Packit |
022b05 |
SmiNode *tSmiNode;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/* linking the tables */
|
|
Packit |
022b05 |
for (tGraphNode = graph->nodes;
|
|
Packit |
022b05 |
tGraphNode;
|
|
Packit |
022b05 |
tGraphNode = tGraphNode->nextPtr) {
|
|
Packit |
022b05 |
node = tGraphNode->smiNode;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (node->nodekind == SMI_NODEKIND_TABLE) {
|
|
Packit |
022b05 |
node = smiGetFirstChildNode(node);
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (node->nodekind == SMI_NODEKIND_ROW) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/* get the relationship between the tables and insert
|
|
Packit |
022b05 |
the edges */
|
|
Packit |
022b05 |
if (node->indexkind == SMI_INDEX_INDEX) {
|
|
Packit |
022b05 |
algGetIndexkind(node);
|
|
Packit |
022b05 |
} else {
|
|
Packit |
022b05 |
tSmiNode = node;
|
|
Packit |
022b05 |
node = smiGetRelatedNode(node);
|
|
Packit |
022b05 |
node = smiGetParentNode(node);
|
|
Packit |
022b05 |
algInsertEdge(node,
|
|
Packit |
022b05 |
smiGetParentNode(tSmiNode),
|
|
Packit |
022b05 |
tSmiNode->indexkind,
|
|
Packit |
022b05 |
GRAPH_ENHINDEX_INDEX);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (XPLAIN) {
|
|
Packit |
022b05 |
printf("--- Second Phase - linking the tables\n\n");
|
|
Packit |
022b05 |
graphShowEdges(graph);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* algCheckLinksByName
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Reordering the connections by looking at the names.
|
|
Packit |
022b05 |
* Related objects are linked (if their names are related).
|
|
Packit |
022b05 |
* Every expand relationship is examined. Therefore number of
|
|
Packit |
022b05 |
* identical characters at the beginning of the both table names is
|
|
Packit |
022b05 |
* counted.
|
|
Packit |
022b05 |
* Then every sparse relationship (only the ending node) is checked if
|
|
Packit |
022b05 |
* there is better connection with more identical characters at the beginning.
|
|
Packit |
022b05 |
* The starting node must be same as in the expand relationship to make sure
|
|
Packit |
022b05 |
* that there are no unrelated tables are linked.
|
|
Packit |
022b05 |
* Only legal overlappings lead to a new edge. A illegal overlap is :
|
|
Packit |
022b05 |
* - when the next character in both strings is a lower case character
|
|
Packit |
022b05 |
* because if something like this is detected the two strings are
|
|
Packit |
022b05 |
* corresponding in the middle of their names and not at defined points
|
|
Packit |
022b05 |
* like suffix or prefix (-> the next character must be upper case or NULL)
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
void algCheckLinksByName()
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
GraphEdge *tEdge, *tEdge2, *newEdge;
|
|
Packit |
022b05 |
char *start, *end, *end2;
|
|
Packit |
022b05 |
int overlap, longestOverlap, i;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (tEdge = graph->edges; tEdge; tEdge = tEdge->nextPtr) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (tEdge->indexkind == SMI_INDEX_EXPAND) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
start = tEdge->startNode->smiNode->name;
|
|
Packit |
022b05 |
end = tEdge->endNode->smiNode->name;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
overlap = strpfxlen(start,end);
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* looking for better connection with longer overlap
|
|
Packit |
022b05 |
* maybe better to traverse the edges with graphGetNextEdgeByNode
|
|
Packit |
022b05 |
* using tEdge->startNode
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
newEdge = NULL;
|
|
Packit |
022b05 |
longestOverlap = overlap;
|
|
Packit |
022b05 |
for (tEdge2 = graphGetFirstEdgeByNode(graph,tEdge->startNode);
|
|
Packit |
022b05 |
tEdge2;
|
|
Packit |
022b05 |
tEdge2 = graphGetNextEdgeByNode(graph, tEdge2,
|
|
Packit |
022b05 |
tEdge->startNode)) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* must be a sparse relationship to get a correct new edge
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
if (tEdge2->indexkind == SMI_INDEX_SPARSE) {
|
|
Packit |
022b05 |
end2 = tEdge2->endNode->smiNode->name;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* new overlap longer and different tables ?
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
i = strpfxlen(end,end2);
|
|
Packit |
022b05 |
if (overlap < i &&
|
|
Packit |
022b05 |
!cmpSmiNodes(tEdge->endNode->smiNode,
|
|
Packit |
022b05 |
tEdge2->endNode->smiNode)) {
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* legal overlap ?
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
if (islower((int)end[i]) && islower((int)end2[i])) {
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
longestOverlap=i;
|
|
Packit |
022b05 |
newEdge = tEdge2;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/* better connection found -> changing the edge */
|
|
Packit |
022b05 |
if (newEdge) {
|
|
Packit |
022b05 |
tEdge->startNode = newEdge->endNode;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (XPLAIN) {
|
|
Packit |
022b05 |
printf("\n--- Third Phase - reordering the connections\n\n");
|
|
Packit |
022b05 |
graphShowEdges(graph);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* algLinkObjectsByNames
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Links Scalars to Tables using the prefix
|
|
Packit |
022b05 |
* Links Tables to Tables using the prefix
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
static void algLinkObjectsByNames()
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
GraphNode *tNode, *tNode2;
|
|
Packit |
022b05 |
int overlap,minoverlap,new;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/* getting the minimum overlap for all nodes */
|
|
Packit |
022b05 |
minoverlap = 10000;
|
|
Packit |
022b05 |
tNode2 = graph->nodes;
|
|
Packit |
022b05 |
if (tNode2) {
|
|
Packit |
022b05 |
for (tNode = tNode2->nextPtr; tNode; tNode = tNode->nextPtr) {
|
|
Packit |
022b05 |
minoverlap = min(minoverlap, strpfxlen(tNode->smiNode->name,
|
|
Packit |
022b05 |
tNode2->smiNode->name));
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* prefix overlap of one is too short to create any usefull edges
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
if (minoverlap == 1) return;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (tNode = graph->nodes; tNode; tNode = tNode->nextPtr) {
|
|
Packit |
022b05 |
if (!graphGetFirstEdgeByNode(graph, tNode)) {
|
|
Packit |
022b05 |
overlap = minoverlap;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (tNode2 = graph->nodes; tNode2; tNode2 = tNode2->nextPtr) {
|
|
Packit |
022b05 |
if (cmpSmiNodes(tNode->smiNode, tNode2->smiNode)) continue;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
new = strpfxlen(tNode->smiNode->name, tNode2->smiNode->name);
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (new >= overlap) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* no scalar - scalar edges
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
if (tNode->smiNode->nodekind == SMI_NODEKIND_SCALAR &&
|
|
Packit |
022b05 |
tNode2->smiNode->nodekind == SMI_NODEKIND_SCALAR) {
|
|
Packit |
022b05 |
continue;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* is it a legal prefix
|
|
Packit |
022b05 |
* (if the next char is NULL || uppercase)
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
if (tNode->smiNode->name[new] &&
|
|
Packit |
022b05 |
tNode2->smiNode->name[new]) {
|
|
Packit |
022b05 |
if (!isupper((int)tNode->smiNode->name[new]) ||
|
|
Packit |
022b05 |
!isupper((int)tNode2->smiNode->name[new])) continue;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
overlap = new;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (overlap == minoverlap) continue;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
new = 0;
|
|
Packit |
022b05 |
for (tNode2 = graph->nodes; tNode2; tNode2 = tNode2->nextPtr) {
|
|
Packit |
022b05 |
if (cmpSmiNodes(tNode->smiNode, tNode2->smiNode)) continue;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
new = strpfxlen(tNode->smiNode->name, tNode2->smiNode->name);
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (new == overlap && new > minoverlap) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* a scalar should only be adjacent to one node
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
if (tNode2->smiNode->nodekind == SMI_NODEKIND_SCALAR &&
|
|
Packit |
022b05 |
graphGetFirstEdgeByNode(graph,tNode2)) continue;
|
|
Packit |
022b05 |
if (tNode->smiNode->nodekind == SMI_NODEKIND_SCALAR &&
|
|
Packit |
022b05 |
graphGetFirstEdgeByNode(graph,tNode)) continue;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* adding only table -> scalar edges
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
if (tNode->smiNode->nodekind == SMI_NODEKIND_SCALAR &&
|
|
Packit |
022b05 |
tNode2->smiNode->nodekind == SMI_NODEKIND_SCALAR) {
|
|
Packit |
022b05 |
continue;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (tNode->smiNode->nodekind == SMI_NODEKIND_SCALAR) {
|
|
Packit |
022b05 |
algInsertEdge(tNode2->smiNode, tNode->smiNode,
|
|
Packit |
022b05 |
SMI_INDEX_UNKNOWN,
|
|
Packit |
022b05 |
GRAPH_ENHINDEX_NAMES);
|
|
Packit |
022b05 |
} else {
|
|
Packit |
022b05 |
algInsertEdge(tNode->smiNode, tNode2->smiNode,
|
|
Packit |
022b05 |
SMI_INDEX_UNKNOWN,
|
|
Packit |
022b05 |
GRAPH_ENHINDEX_NAMES);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* algGroupScalars
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Grouping the scalars using a common fathernode.
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
static void algGroupScalars()
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
GraphNode *tNode;
|
|
Packit |
022b05 |
int actGroup, fGroup;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
actGroup = 0;
|
|
Packit |
022b05 |
for (tNode = graph->nodes; tNode; tNode = tNode->nextPtr) {
|
|
Packit |
022b05 |
if (!graphGetFirstEdgeByNode(graph, tNode) &&
|
|
Packit |
022b05 |
tNode->smiNode->nodekind == SMI_NODEKIND_SCALAR) {
|
|
Packit |
022b05 |
fGroup = algGetGroupByFatherNode(tNode->smiNode);
|
|
Packit |
022b05 |
if (fGroup == 0) {
|
|
Packit |
022b05 |
tNode->group = ++actGroup;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
else {
|
|
Packit |
022b05 |
tNode->group = fGroup;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (XPLAIN) {
|
|
Packit |
022b05 |
printf("Scalar Groups : \n");
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (algGetNumberOfGroups() != 0) {
|
|
Packit |
022b05 |
for (actGroup = 1;
|
|
Packit |
022b05 |
actGroup <= algGetNumberOfGroups();
|
|
Packit |
022b05 |
actGroup++) {
|
|
Packit |
022b05 |
algPrintGroup(actGroup);
|
|
Packit |
022b05 |
printf("\n");
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
} else printf("No groups!\n");
|
|
Packit |
022b05 |
printf("\n");
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* algLinkLonelyTables
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Links isolated tables with other tables via the types of the
|
|
Packit |
022b05 |
* index objects.
|
|
Packit |
022b05 |
* If no type is found the types are checked via the suffix if they differ
|
|
Packit |
022b05 |
* only in the range (-OrZero). Therefore the suffix-vector is checked.
|
|
Packit |
022b05 |
* Basetypes used in SMIv1/v2/ng are sorted out.
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
static void algLinkLonelyTables()
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
SmiElement *smiElement, *smiElement2 = NULL;
|
|
Packit |
022b05 |
GraphNode *tNode, *tNode2;
|
|
Packit |
022b05 |
int i;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (tNode = graph->nodes; tNode; tNode = tNode->nextPtr) {
|
|
Packit |
022b05 |
if (!graphGetFirstEdgeByNode(graph, tNode) &&
|
|
Packit |
022b05 |
tNode->smiNode->nodekind == SMI_NODEKIND_TABLE) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (smiElement = smiGetFirstElement(
|
|
Packit |
022b05 |
smiGetFirstChildNode(tNode->smiNode));
|
|
Packit |
022b05 |
smiElement;
|
|
Packit |
022b05 |
smiElement = smiGetNextElement(smiElement)) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (tNode2 = graph->nodes;
|
|
Packit |
022b05 |
tNode2;
|
|
Packit |
022b05 |
tNode2 = tNode2->nextPtr) {
|
|
Packit |
022b05 |
if (tNode->smiNode->nodekind == SMI_NODEKIND_TABLE &&
|
|
Packit |
022b05 |
tNode != tNode2) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (smiElement2 = smiGetFirstElement(
|
|
Packit |
022b05 |
smiGetFirstChildNode(tNode2->smiNode));
|
|
Packit |
022b05 |
smiElement2;
|
|
Packit |
022b05 |
smiElement2 = smiGetNextElement(smiElement2)) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (strcasecmp(algGetTypeName(
|
|
Packit |
022b05 |
smiGetElementNode(smiElement2)),
|
|
Packit |
022b05 |
algGetTypeName(
|
|
Packit |
022b05 |
smiGetElementNode(smiElement)))
|
|
Packit |
022b05 |
== 0) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (isBaseType(smiGetElementNode(smiElement))
|
|
Packit |
022b05 |
== 1){
|
|
Packit |
022b05 |
continue;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
graphInsertEdge(graph,tNode2, tNode,
|
|
Packit |
022b05 |
SMI_INDEX_UNKNOWN,
|
|
Packit |
022b05 |
GRAPH_ENHINDEX_TYPES);
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
else {
|
|
Packit |
022b05 |
for (i = 0; suffix[i]; i++) {
|
|
Packit |
022b05 |
if (strstr(
|
|
Packit |
022b05 |
algGetTypeName(
|
|
Packit |
022b05 |
smiGetElementNode(smiElement)),
|
|
Packit |
022b05 |
suffix[i])) {
|
|
Packit |
022b05 |
graphInsertEdge(graph,tNode2,
|
|
Packit |
022b05 |
tNode,
|
|
Packit |
022b05 |
SMI_INDEX_UNKNOWN,
|
|
Packit |
022b05 |
GRAPH_ENHINDEX_TYPES);
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (suffix[i]) break;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
if (smiElement2) break;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
if (tNode2) break;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* algConnectLonelyNodes
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Connect the isolated nodes (scalars and tables)
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* 1. Trying to link tables via the type of the index objects
|
|
Packit |
022b05 |
* 2. Trying to link scalars to tables using the names
|
|
Packit |
022b05 |
* 3. Trying to group scalars which have not been adjacent to any edge.
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
void algConnectLonelyNodes()
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
if (XPLAIN) {
|
|
Packit |
022b05 |
printf("\n--- Fourth Phase - connecting isolated nodes\n\n");
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
algLinkLonelyTables();
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
algLinkObjectsByNames();
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
algGroupScalars();
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (XPLAIN) {
|
|
Packit |
022b05 |
graphShowEdges(graph);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* Subfunction of algCheckForDependencies
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* change UML-edges to dependecy if possible
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
static void createDependencies()
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
GraphEdge *tEdge;
|
|
Packit |
022b05 |
int elemCount;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (tEdge = graph->edges; tEdge; tEdge = tEdge->nextPtr) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (tEdge->indexkind == SMI_INDEX_UNKNOWN) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (tEdge->startNode->smiNode->nodekind == SMI_NODEKIND_TABLE &&
|
|
Packit |
022b05 |
tEdge->endNode->smiNode->nodekind == SMI_NODEKIND_TABLE) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
elemCount = algGetNumberOfRows(tEdge->startNode->smiNode);
|
|
Packit |
022b05 |
if (elemCount >= 0) tEdge->connection = GRAPH_CON_DEPENDENCY;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
elemCount = algGetNumberOfRows(tEdge->endNode->smiNode);
|
|
Packit |
022b05 |
if (elemCount >= 0) tEdge->connection = GRAPH_CON_DEPENDENCY;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* returns 1 if a new rerouting edge creates a loop and 0 otherwise
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
static int isloop(GraphEdge *tEdge, SmiNode *depTable)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
GraphEdge *loopEdge;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (loopEdge = graphGetFirstEdgeByNode(graph, tEdge->endNode);
|
|
Packit |
022b05 |
loopEdge;
|
|
Packit |
022b05 |
loopEdge = graphGetNextEdgeByNode(graph,loopEdge,tEdge->endNode)) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if ((cmpSmiNodes(loopEdge->startNode->smiNode, depTable)) ||
|
|
Packit |
022b05 |
(cmpSmiNodes(loopEdge->endNode->smiNode, depTable) &&
|
|
Packit |
022b05 |
(loopEdge != tEdge))) {
|
|
Packit |
022b05 |
return 1;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
return 0;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* subfunction of algCheckForDependency
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
static void rerouteDependencyEdge(GraphEdge *tEdge)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
SmiNode *startTable, *endTable, *depTable;
|
|
Packit |
022b05 |
SmiElement *smiElement;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
startTable = tEdge->startNode->smiNode;
|
|
Packit |
022b05 |
endTable = tEdge->endNode->smiNode;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (smiElement = smiGetFirstElement(
|
|
Packit |
022b05 |
smiGetFirstChildNode(endTable));
|
|
Packit |
022b05 |
smiElement;
|
|
Packit |
022b05 |
smiElement = smiGetNextElement(smiElement)) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/* look only at expanded indices (only present in endTable) */
|
|
Packit |
022b05 |
if (cmpSmiNodes(endTable, smiGetParentNode(
|
|
Packit |
022b05 |
smiGetParentNode(smiGetElementNode(smiElement)))) == 1) {
|
|
Packit |
022b05 |
depTable = algFindEqualType(startTable,
|
|
Packit |
022b05 |
smiGetElementNode(smiElement));
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/* depTable different to endTable? */
|
|
Packit |
022b05 |
if (depTable && !cmpSmiNodes(depTable, endTable)) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/* prevent loops */
|
|
Packit |
022b05 |
if (isloop(tEdge, depTable)) continue;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
algInsertEdge(depTable,
|
|
Packit |
022b05 |
startTable, SMI_INDEX_UNKNOWN,
|
|
Packit |
022b05 |
GRAPH_ENHINDEX_REROUTE);
|
|
Packit |
022b05 |
break;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* algCheckForDependency
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Tries to change connection types from association to dependency by
|
|
Packit |
022b05 |
* looking at the types.
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* 1. Supporting tables are revealed. Supporting tables consist only
|
|
Packit |
022b05 |
* index objects and RowStatus-Objects and/or Storage-Type/Objects.
|
|
Packit |
022b05 |
* 2. If a supporting table is found the connection type is changed to
|
|
Packit |
022b05 |
* dependency.
|
|
Packit |
022b05 |
* 3. Now the types of the index objects are checked (only in the end-table).
|
|
Packit |
022b05 |
* If the same type is found in an other table the start-table is going to
|
|
Packit |
022b05 |
* be connected with it (inserting a new edge).
|
|
Packit |
022b05 |
* The end-table is still connected to the start-table.
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
void algCheckForDependency()
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
GraphEdge *tEdge;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
createDependencies();
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (tEdge = graph->edges; tEdge; tEdge = tEdge->nextPtr) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (tEdge->connection == GRAPH_CON_DEPENDENCY) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
rerouteDependencyEdge(tEdge);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (XPLAIN) {
|
|
Packit |
022b05 |
printf("\n--- Fifth Phase - checking for dependency relationships\n\n");
|
|
Packit |
022b05 |
graphShowEdges(graph);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
static SmiNode *algFindTable(SmiNode *node)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
GraphNode *tNode;
|
|
Packit |
022b05 |
SmiNode *smiNode;
|
|
Packit |
022b05 |
SmiElement *smiElement;
|
|
Packit |
022b05 |
char *toFind;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (!node) return NULL;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
toFind = xstrdup(node->name
|
|
Packit |
022b05 |
+ strpfxlen(node->name, smiGetParentNode(node)->name));
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (tNode = graph->nodes; tNode; tNode = tNode->nextPtr) {
|
|
Packit |
022b05 |
if (tNode->smiNode->nodekind == SMI_NODEKIND_TABLE) {
|
|
Packit |
022b05 |
if (cmpSmiNodes(node, tNode->smiNode)) continue;
|
|
Packit |
022b05 |
smiNode = smiGetFirstChildNode(tNode->smiNode);
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (smiElement = smiGetFirstElement(smiNode);
|
|
Packit |
022b05 |
smiElement;
|
|
Packit |
022b05 |
smiElement = smiGetNextElement(smiElement)) {
|
|
Packit |
022b05 |
smiNode = smiGetElementNode(smiElement);
|
|
Packit |
022b05 |
if (strstr(smiNode->name, toFind)) {
|
|
Packit |
022b05 |
xfree(toFind);
|
|
Packit |
022b05 |
return smiGetParentNode(smiGetParentNode(smiNode));
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
xfree(toFind);
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
return NULL;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* Creates edges based on column-objects pointing to other tables.
|
|
Packit |
022b05 |
* Column-objects with a substring "Index" are examined.
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
void algCheckForPointerRels()
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
GraphNode *tNode;
|
|
Packit |
022b05 |
SmiModule *module;
|
|
Packit |
022b05 |
SmiNode *smiNode = NULL;
|
|
Packit |
022b05 |
SmiNode *ppNode, *table;
|
|
Packit |
022b05 |
int i;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (tNode = graph->nodes; tNode; tNode = tNode->nextPtr) {
|
|
Packit |
022b05 |
if (tNode->smiNode->nodekind == SMI_NODEKIND_TABLE) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
module = smiGetNodeModule(tNode->smiNode);
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (smiNode = smiGetFirstNode(module, SMI_NODEKIND_COLUMN);
|
|
Packit |
022b05 |
smiNode;
|
|
Packit |
022b05 |
smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_COLUMN)) {
|
|
Packit |
022b05 |
ppNode = smiGetParentNode(smiNode);
|
|
Packit |
022b05 |
ppNode = smiGetParentNode(ppNode);
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (!algIsIndexElement(tNode->smiNode, smiNode) &&
|
|
Packit |
022b05 |
cmpSmiNodes(tNode->smiNode, ppNode)) {
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
for (i = 0; pointer[i]; i++) {
|
|
Packit |
022b05 |
if (strstr(smiNode->name, pointer[i])) {
|
|
Packit |
022b05 |
/* printf("%s \n",smiNode->name); */
|
|
Packit |
022b05 |
table = algFindTable(smiNode);
|
|
Packit |
022b05 |
if (table) {
|
|
Packit |
022b05 |
algInsertEdge(table, tNode->smiNode,
|
|
Packit |
022b05 |
SMI_INDEX_UNKNOWN,
|
|
Packit |
022b05 |
GRAPH_ENHINDEX_POINTER);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (XPLAIN) {
|
|
Packit |
022b05 |
printf("\n--- Sixth Phase - checking for pointer relationships\n\n");
|
|
Packit |
022b05 |
graphShowEdges(graph);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|