API and Developer Resources
These resources will help you integrate the VI to your project.
Table of Contents
API
The API consists of the following:
- An Input Message Stream from the Server which consists of UDP packages. Several such streams known as 'Data Sets' can be used simultaneously. These messages have a special formatting as explained in the section: 'API: Creating a Data Set'.
- Messages can be sent back to the Server from the VI GUI. How these messages will look is specified by the user in the 'vi_interface.xml' konfiguration file as explained in the section: 'API: XML Interface'.
- The 'vi_interface.xml' file also configures where the topology will be fetched from and many other settings. See: 'API: XML Interface'.
- The network topology is defined in a file with a special format as explained in the section: 'API: Topology File Structure'.
API: Creating a Data Set
A Data Set is a stream of data from the Server to the VI ynode. The stream is made up of UDP packets which have a special formatting. There are currently five different 'parsing strategies' with ID: 0-4 that you can choose from:
- This strategy is used for data which has only a singular value that will be plotted either as a color or a single bar on nodes. The format is:
dataParseName host value
...where dataParseName is a string used to identify this data set from other data sets, host is a host name associated with a node and the value is either an integer or floating point value.
- This strategy is used for data which is split up into several categories and will be plotted as cumulative bars on nodes. The format is:
dataParseName host category value
...where dataParseName is a string used to identify this data set from other data sets, host is a host name associated with a node and the value is either an integer or floating point value. Note that you need to send one such packet for each (category, value) pair.
- This strategy is used for data which is split up into categories and sub categories (multi-dimensional data) and will be plotted as cumulative bars on nodes. The format is:
dataParseName host category value1 value2 ... valueN
...where dataParseName is a string used to identify this data set from other data sets, host is a host name associated with a node and the valueX is either an integer or floating point value. N can be any positive integer. Note that you need to send one such packet for each (category, value1, value2, ... valueN) tuple.
- This strategy is used for data which has only a singular value that will be plotted as a color on relations/links. The format is:
dataParseName host1_host2 value
...where dataParseName is a string used to identify this data set from other data sets, host1 and host2 are the host names associated with the nodes which mke up the relation and the value is either an integer or floating point value. Note the 'underscore' which separates the two host names. The order of the two hostnames has no significance.
- This strategy is used for data which has two values that will be plotted on relations/links. The first value will be sent to the color component and the second will be sent to the weight component (sets the 'thickness') of the link. The format is:
dataParseName host1_host2 value1 value2
...where dataParseName is a string used to identify this data set from other data sets, host1 and host2 are the host names associated with the nodes which make up the relation and the value1 and value2 are either integer or floating point values. Note the 'underscore' which separates the two host names. The order of the two hostnames has no significance.
Examples of these parsing strategies are given in the following section where we use the 'vi_interface.xml' file to configure the Data Sets. In the TICTest Server you can see some examples of how these streams are constructed (look for the send() method). Also when you are playing around with the default 'vi_interface.xml' file and the TICTest Server you can use the keyboard shortcut: 'P' to toggle the printing of Server Messages.
You can create as many streams as you like and you can send as many packages as you want per time unit but limiting the rate at which these packages are sent is considered wise.
API: XML Interface
When the VI start up it reads and parses the content of a file named: 'vi_interface.xml'. This file needs to be located at the vi root directory. The VI software comes with a default 'vi_interface.xml' file which contains a working example that can be used with the TICTest Server software. There is also one other file named 'TEMPLATE.xml' which you can use to create your own 'vi_interface.xml' file. Both files are working examples and will load 'as is' to the VI software. Note that you need to rename it for the VI software to recognize it. The following will list every option that you can set in the 'vi_interface.xml' file and the examples used here are the once in the default 'vi_interface.xml' file.
The top-level element <Interface> ... </Interface> must contain the following elements:
The contents of these elements are defined below:
<Initialization> Must contain the following elements:
- <WindowTitle> String </WindowTitle> Used by the GUI. The title of the main window.
- <MasterHost> String </MasterHost> Host of the server.
- <MasterPort> Integer </MasterPort> Port number of the server.
- <SocketBufferSize> Integer </SocketBufferSize> Socket buffer size in bytes.
- <KeepAliveHost> String </KeepAliveHost> Host of the KeepAlive ynode.
- <KeepAlivePort> Integer </KeepAlivePort> Port number of the KeepAlive ynode.
- <InputPort> Integer </InputPort> The input port which is used for incoming data.
- <TimeOut> Integer </TimeOut> Timeout time in seconds. Setting this to zero sets timeout to infinity.
- <DefaultValue> Integer/Float </DefaultValue> The default value used when resetting the values on a time out.
- <DefaultBarType> Integer </DefaultBarType> Bar type. Try setting this to: 0, 1, 2, 3, 4, 5, 6, 7, 8 or 9.
- <AdvancedLighting> Boolean </AdvancedLighting> Enables the secondary light source. Global default rendering settings. Valid values: 'true' or 'false'.
- <Fog> Boolean </Fog> Enables the fog. Global default rendering settings. Valid values: 'true' or 'false'.
- <BarShading> Boolean </BarShading> Enables shading on bars. Global default rendering settings. Valid values: 'true' or 'false'.
- <NodeShading> Boolean </NodeShading> Enables shading on nodes. Global default rendering settings. Valid values: 'true' or 'false'. Note: This setting currently does nothing.
- <AntiAliasing> Boolean </AntiAliasing> Enables blending on links. Global default rendering settings. Valid values: 'true' or 'false'.
- <Skybox> Boolean </Skybox> Enables the skybox Global default rendering settings. Valid values: 'true' or 'false'.
Example from the default 'vi_interface.xml' file:
Window Title
localhost
8701
1048576
localhost
8602
8601
0
0
7
true
true
true
false
true
true
<Topology> Must contain the following elements:
- <File> String </File> A relative path from the vi root directory (vi/) to the topology save file.
- <NodeTypes> ... </NodeTypes> A list of all types of nodes. Must contain at least one <NodeType> element.
- <NodeType> ... </NodeType> Defines a type of node.
- <ID> Integer </ID> The ID of this node type. ID = 1, 2, 3,...
- <Name> String </Name> A string which is used in the GUI.
- <Level> Integer </Level> In a hierarchichal topology, level determines how high up in the tree the node is located. 0 is the top or root level.
- <Colors> ... </Colors> The default color used for nodes of this type when no data set is defined for the node. See definition below for the <Colors> element. Must contain one <Colors> element.
The following example shows how to set up three types of nodes in a typical tree hierarchy which will be colored green, white or blue depending on the type.
TopologyTool/topology.default16.save
1
Root
0
0.0
1.0
0.0
1
MiddleNode
1
1.0
1.0
1.0
3
Leaf
2
0.0
0.0
1.0
<Commands> Must contain the following elements:
- <Command> ... </command> Must contain the following:
- <ID> Integer </ID> The ID of this command. ID = 0, 1, 2,...
- <Name> String </Name> A string which is used in the GUI.
- <MessagePrefix> String </MessagePrefix> The message sent to the server is the content of <MessagePrefix> and <Message> separated by a space. The rationale behind having both the MessagePrefix and Message tags is that the intent was to create a more flexible system where the messages could also contain varaibles. This was never implemented.
- <Message> String </Message> The message sent to the server is the content of <MessagePrefix> and <Message> separated by a space. The rationale behind having both the MessagePrefix and Message tags is that the intent was to create a more flexible system where the messages could also contain varaibles. This was never implemented.
The following example sets up one command.
0
Hello World Command
Hello
World!
<Categories> Must contain the following elements:
- <Category> ... </Category> You can specify several category sets, however, currently only one category set is supported by the software. Must contain the following:
- <ID> Integer </ID> The ID of this category. ID = 1, 2, 3,...
- <Name> String </Name> A string which is used in the GUI.
- <CategoryItem> ... </CategoryItem> Each category must have at least one CategoryItem, however a category should have at least two for it to make any sense as a set of categories with only one category can be covered by Parsing Strategy 0.
- <Name> String </Name> A string which is used in the GUI.
- <ParseName> String </ParseName> Used for identifying the category in server messages.
- <Colors> ... </Colors> The default color used for that category. See definition below for the <Colors> element. Must contain one <Colors> element.
The following example sets up four categories based on a subset of HTTP status codes.
1
HTTP Status Codes
200 - OK
200
0.0
1.0
0.0
403 - Forbidden
403
1.0
0.0
0.0
404 - Not Found
404
1.0
0.0
0.5
All Other Status Codes
Other
0.5
0.5
0.5
<Data> Must contain the following elements:
- <DataSet> ... </DataSet> The null datasets must be defined and should not be modified. Besides the null data sets you can add as many data sets as you wish. Must contain the following:
- <ID> Integer </ID> The ID of this data set. ID = 0, 1, 2,...
- <Name> String </Name> Name is used in the GUI and should not be too long or it wont fit.
- <ParseName> String </ParseName> Used for identifying the data set in server messages.
- <Set> Integer </Set> Set is either 1 (nodes) or 2 (relations).
- <Category> Integer </Category> Category is either 0 (data not split by category) or 1, 2, 3... (referring to the ID of the categories defined above)
- <ParseStrat> Integer </ParseStrat> ParseStrat defines which parsing strategy to use. Valid values: 0, 1, 2, 3, 4
- <Dimension> Integer </Dimension> Dimension is the number of dimensions used. For ParseStrat 0, 1 and 3 it should always be 1. For ParseStrat 4 it should be 2. For ParseStrat 2 it should be the number of values N.
- <NodeType> Integer </NodeType> NodeType is a hint telling us which type of nodes this data set is intended for, refers to the ID used for the NodeType definitions above. The GUI will assume you want the DataSet tied to the datatype you specify here but this can be set in the GUI manually later and you may even plot data to any nodes you wish.
- <Max> Integer/Float </Max> Max is a value which is the expected maximum value in this data set. Sending higher values will not break the system.
- <Min> Integer/Float </Min> Min is the expected minimum value. Currently this is undefined for anything but 0
- <Colors> ... </Colors> Defines the start and end color for the gradient which is used for plotting singular data to nodes or relations/links. Ignored for ParseStrat 1, 2 and 4 but must be defined even in these cases. See definition below for the <Colors> element. Must contain two <Colors> elements.
The following example uses the NodeTypes and Categories defined in the examples above for defining a DataSet which plots comulative bars with different types of HTTP Status Codes sent from a node per time unit. The DataSet hints the GUI that it should be used for 'Leaf' nodes and that the maximum value is 16. Note that even though the Colors tag is not used the two colors must be defined as specified by the API.
0
HTTP Status Replies
httpStatus
1
1
1
1
3
16
0
1.0
1.0
1.0
1.0
1.0
1.0
<Colors> Must contain the following elements:
- <Color> ... </Color> You can define one or two Color elements as RGB values.
- <Red> Float </Red> A float value in the range: [0.0 1.0]
- <Green> Float </Green> A float value in the range: [0.0 1.0]
- <Blue> Float </Blue> A float value in the range: [0.0 1.0]
Example of a gradient from yellow to blue:
1.0
1.0
0.0
0.0
0.0
1.0
API: Topology File Structure
The topology file which is linked to by the 'vi_interface.xml' file is a simple text file which can have the file suffix '.save' and must have the following formatting:
C
node ID_N NODETYPE HOST_NAME_PART1 HOST_NAME_PART2 X_LOC Y_LOC
...
rel ID_R ID_A ID_B
...
- C Undefined. Can be any integer.
- ID_N The Node ID. (ID = 1, 2, 3,...)
- NODETYPE the ID for the node type as defined in the <Topology> definition in the 'vi_interface.xml'.
- HOST_NAME_PART1 First part of the host name.
- HOST_NAME_PART2 Second part of the host name.
- X_LOC X coordinate on the 2D-map view. X is in the interall: [-2.0 2.0].
- Y_LOC Y coordinate on the 2D-map view. Y is in the interall: [-1.0 1.0].
- ID_R The Relation ID.
- ID_A The ID of the first node of the relation.
- ID_B The ID of the second node of the relation.
Note that the full hostname of the node is the combination of the twop parts so if HOST_NAME_PART1 = 'sub' and HOST_NAME_PART2 = '.domain.com' the full hostname of the node is 'sub.domain.com'
Example file which creates a tree structure with the data types defined in the examples above in the previous section:
0
node 1 1 root 0
node 2 2 middle A
node 3 2 middle B
node 4 3 leaf AA
node 5 3 leaf AB
node 6 3 leaf BA
node 7 3 leaf BB
rel 1 1 2
rel 2 1 3
rel 3 2 4
rel 4 2 5
rel 5 3 6
rel 6 3 7
The VI software comes with an example software (TopologyTool) which can create this type of topology files for a very specific kind of topologies and a few example topology save files. It is provided 'as is' but may serve as inspiration for your own Topology Tool.
System Architecture Overview
The following illustration shows the overall system architecture and the main flow of data in the system.
- Some things are omitted in the above illustration. The GUI consists of several other components, but these are summarized here as a set of Listeners. The ViewPanel also consists of such GUI components, such as a pop-up menu which also may affect the sate of the ViewPanel.
- The user can create multiple Windows and Views. Each GUI Window has at least one ViewPanel and each ViewPanel has it's own set of AnimatorTimer, WorldTimer and Renderer as well as it's own state. All of these Windows and Views operate independently of each other.
- All ViewPanels read from the same Data Buffer and use the same topology information but can create their own subsets of the topology.
- The Initialization happens only once.
Source Code Overview
In this section I will guide you thrue the main parts of the source code. I suggest you have the javadoc and the source available as you read this section.
Program Execution starts in the VI.main() method which performs the following five sequential tasks:
- Reads the settings specified in the file 'vi_interface.xml' and prepares all of the datastructures according to these settings and the topology specified in the file pointed to by the 'vi_interface.xml' file.
- Starts reading the input socket and user input from the command line (BufferReader (source)).
- Starts the TimeOutTimer (source) which resets data which has timed out.
- Starts the main GUI (source) window (see below) and adds it to the list of windows.
- Starts the KeepAlive (source) class which gives feedback about the current up-state of the VI so that the server knows if it should be sending data or not.
The GUI sets up the main window (JFrame) and initializes the four main GUI components listed below and places these into split panes for flexible resizing of the different GUI components.
The GUI also sets up the menu and associated listeners.
The next class we will take a look at is a container class which may contain either one ViewPanel (source) or two SplitViewPanels (source) (which in turn may contain other SplitViewPanels or single ViewPanels). This makes up a tree hierarchy where the leafs are ViewPanels. If the SplitViewPanel contains two components they are placed inside a split pane which is either split vertically or horizontally.
One of the most important classes in the VI. This JPanel sets up the OpenGL rendering environment and canvas and keeps track of all View-specific data. It also creates a pop-up menu which contains options specific to that view.
The ViewPanel initiates two Timers: AnimatorTimer (source), which schedules calls to the Renderer.display() method and WorldTimer (source), which updates the state of the view (camera angle and node positions) at even intervals.
The Renderer is the real heart of the VI software. This class implements the GLEventListener interface and is responsible for calling the OpenGL pipeline to draw the 3D-scene on the canvas. The most important method is the Renderer.display() method which is called by the AnimatorTimer (source).
For extending the functionality of the Renderer class it is important to understand how the renderer relates to the ViewPanel (source) class. Each Renderer has a ViewPanel associated with it and it is from the pv object that the renderer pulls information about the topology and current state of the system. However, all the data is pulled from the global variables in the VI (source) class.
Other Important Classes
- BufferReader (source) Continuously reads both the socket input buffer and the user input buffer. The RawBuffer (source) class used to have a bigger role to play when it was used as a buffer for all kinds of messages. Now it is only used for buffering console commands.
- Camera (source) Keeps track of the camera state for one view.
- Category (source) This class forms a Category Set. A set consists of several CategoryItems (source).
- Data (source) This very important class stores all data in one DataSet as defined in the 'vi_interface.xml'-file.
- GraphNode (source) Defines one node in a network or a graph. The nodes positions are stored both using cartesian (x, y, z) as well as polar (latitutde, longitude, rad ( = distance from the center of the earth)) coordinates and the class contains many methods for converting between these and for moving the nodes to target locations on the plane and the globe. Note that this class implements the Cloaneable interface. We will discuss this in the following section.
- GraphNodeRel (source) Defines a relationsship between a pair of nodes. A link in a network. Note that this class implements the Cloaneable interface. We will discuss this in the following section.
- Parser (source) This class handles all parsing of messages from the Server. Messages can follow one of several so called 'parsing strategies' which is defined for each DataSet in the 'vi_interface.xml'-file.
- Pickable (source) All classes which inherit Pickable become so called 'pickable objects', which means they can be rendered onto the canvas using a color which acts as an id of that object. Detecting a mouse click on an object is then as simple as looking up which object had the same color as the point that was clicked. Black pid=(0, 0, 0) is used for non-pickable obscuring objects and background.
- XMLInterface (source) This class parses the 'vi_interface.xml'-file.
Global Variables
All global/static variables are located in the VI (source) class. The once which existence you should be aware of when digging into the source code are:
- public static Category[] categoryArr Lists all category sets specified by the 'vi_interface.xml'-file with the exception that VI.categoryArr[0] is the empty 'null category'.
- public static Command[] commandArr Lists all commands specified by the 'vi_interface.xml'-file.
- public static Data[] dataArr Lists all data sets specified by the 'vi_interface.xml'-file. This is the 'Encoded Data Buffer' as depicted in the System Architecture section above.
- public static Data[] nodeMultiData A subset of the VI.dataArr list whch contains only those data sets which has specified a more complex parsing strategy for data tied to Nodes.
- public static Data[] nodeSingularData A subset of the VI.dataArr list whch contains only those data sets which has specified a less complex parsing strategy for data tied to Nodes.
- public static Data[] relsData A subset of the VI.dataArr list which contains only those data sets which has specified a parsing strategy for data tied to Relations (links).
- public static GraphNode[] nodeArr Lists all nodes. This acts as a template and should not be called by the Renderer. The Renderer always calls a copy of this object located in the ViewPanel called pv.nodeArr.
- public static GraphNodeRel[] nodeRelArr Lists all relationships between nodes. This acts as a template and should not be called by the Renderer. The Renderer always calls a copy of this object located in the ViewPanel called pv.nodeRelArr.
- public static Hashtable<String, Integer> catID A hashtable which is used for category ID - hostname lookups.
- public static Hashtable<String, Integer> dataID A hashtable which is used for data set ID - hostname lookups.
- public static Hashtable<String, Integer> nodeID A hashtable which is used for node ID - hostname lookups.
- public static Hashtable<String, Integer> relID A hashtable which is used for relation ID - hostname lookups. Note that the hostname stored here is a pair in itself as it consists of the host names of the two nodes which the realtionship consists of separated by an underscore character.
- public static LinkedList<ViewPanel> viewList A list of all currently active ViewPanels.
- public static LinkedList<GUI> windowList A list of all currently active GUIs (windows/frames).
When a new ViewPanel is created the VI.nodeArr is cloned and the copy is stored in the ViewPanel as viewPanelObject.nodeArr. This is then accessed by the Renderer as pv.nodeArr. The same goes for VI.nodeRelArr. The new ViewPanel is also added to the VI.viewList.
This cloning is done because we want a separate world state for each view which means that when we navigate one view all other views are unaffected by these transformations. This is a result of previous design decisions and I realize that it is not optimal but this is what we have to deal with for now.
Hardware Considerations
The VI was developed on a Santa Rosa (2007) MacBook Pro 2.4Ghz and has been tested also on a HP Compaq nw8240 laptop. The conslusion of this evaluation is that the VI software runs better on the Mac and on a platform with faster CPU. The graphics card should generally not be the bottleneck of the system.
Performance Evaluation (PDF 372KB)