To start with, go to the the server machine and start the OpenLC server. To do this, simply run this command:
$ OLCServer Initialization done. Ready to serve requests. On UNIX, type 'q' and 'Return' to exit. On Windows, kill this python process.
The server initializes the run database then enters a loop and waits for IP connections. By default it listens in the 43434 port (you can change it by using the -p <port> option). You can halt the server by pressing 'q' and <return>. On Windows your only chance to stop OpenLC server is by killing that python process using the process management tool (hot-key: ctrl-alt-supr).
Once the server is up and running, run (in a different window or machine) the sample commander (OLCCommander) together with a scenario to do some tests. This client reads the scenario file passed in the command line, and some calls to the microkernel API are made using XML-RPC. You can start a test run, by issuin the next command line:
$ OLCCommander -s 1 sdf/local-config.xml
This is a completely automatic test so no interaction is needed from the user except optional modification of scenario file. Now, look at the output of this example and the Scenario Definition File (SDF) used; then read some explanations on what has happened.
Scenario file: local-config.xml Preparing the server: ['OK', 'Mon Jun 17 18:06:28 2002'] sending start: ['OK', 'Mon Jun 17 18:06:28 2002'] { 'Local/test/constant': { 'commandNumber': 1, 'dataTransferred': 10.082274999999999, 'threadNumber': 3, 'timeSpent': 0.0098460000000000006, 'wallClock': 0.99921199999999999}, 'Local/test/linear': { 'commandNumber': 3, 'dataTransferred': 10.573729999999999, 'threadNumber': 3, 'timeSpent': 0.010326, 'wallClock': 0.98901300000000003}} { 'Local/test/constant': { 'commandNumber': 1, 'dataTransferred': 9.8293459999999993, 'threadNumber': 3, 'timeSpent': 0.0095989999999999999, 'wallClock': 1.9887189999999999}, 'Local/test/linear': { 'commandNumber': 3, 'dataTransferred': 10.418213, 'threadNumber': 3, 'timeSpent': 0.010174000000000001, 'wallClock': 1.9787710000000001}} { 'Local/test/constant': { 'commandNumber': 1, 'dataTransferred': 9.8078610000000008, 'threadNumber': 3, 'timeSpent': 0.0095779999999999997, 'wallClock': 2.9786049999999999}, 'Local/test/linear': { 'commandNumber': 3, 'dataTransferred': 10.838013, 'threadNumber': 3, 'timeSpent': 0.010584, 'wallClock': 2.999555}} { 'Local/test/constant': { 'commandNumber': 1, 'dataTransferred': 10.085326999999999, 'threadNumber': 3, 'timeSpent': 0.0098490000000000001, 'wallClock': 3.9992260000000002}, 'Local/test/linear': { 'commandNumber': 3, 'dataTransferred': 10.590210000000001, 'threadNumber': 3, 'timeSpent': 0.010342, 'wallClock': 3.989023}} { 'Local/test/constant': { 'commandNumber': 1, 'dataTransferred': 10.493895999999999, 'threadNumber': 3, 'timeSpent': 0.010248, 'wallClock': 4.9981999999999998}, 'Local/test/linear': { 'commandNumber': 3, 'dataTransferred': 9.5662839999999996, 'threadNumber': 3, 'timeSpent': 0.0093419999999999996, 'wallClock': 4.987603}} sending Stop: ['OK', 'Mon Jun 17 18:06:33 2002'] sending Finish: ['OK', 85] sending getStatistics: [OK] -- Some statistical results coming from post-processing run data -- -- Grand total for the entire run (runID --> 85) -- Elapsed Time: 5.01 s Cummulated Elapsed Time: 24.01 s Number of Transactions: 2475 Response Time (mean): 0.00970 s Transaction Rate: 494.06 trans/s Total Data Transferred 24586.67 (KB)
Let's have a look at the scenario definition file (sdf/local-config.xml):
<configuration> <clients number="5"></clients> <time max="5"></time> <sample small="yes" period="2.0"></sample> <!-- The number of bins of the resulting reduced data --> <reduction minElementsPerBin="10" maxBins="100"></reduction> <!-- Here begins the protocol-specific definition --> <runProtocol name="Local" mode="random"> <!-- Maximum number of iterations for this protocol and for each client --> <!-- All the cmd's hanging from here are considered one single iteration --> <iterations max="1000"></iterations> <!-- values we are interested in --> <retValues> <wallClock units="s" sta="mean" typecode="Float"></wallClock> <timeSpent units="s" spyplot="yes" sta="vds" typecode="Float"></timeSpent> <dataTransferred units="KB" sta="vds" typecode="Float"></dataTransferred> <commandNumber units=" " typecode="Int"></commandNumber> <threadNumber units=" " sta="minimal" typecode="Int"></threadNumber> </retValues> <cmdGroup name="test"> <cmd spy="yes" name="constant"> constant(range=0.01) </cmd> <cmd spy="no" name="random"> random(range=0.01) </cmd> <cmd spy="yes" name="linear"> linear(range=0.01) </cmd> </cmdGroup> </runProtocol> </configuration>
Before a command is issued into the server, a message is printed telling what the commander is about to do. For example, the first thing it does is to send a getReady RPC to the server (indicated by a Preparing the server message). The next line prints the results from this RPC call. Right now, this is a 2 elements tuple, telling you if the call has been ok ("OK") or not ok ("NO"), and a timestamp of when the command has been executed in the server.
After getReady, a startRun command is sent ("sending start"). We can see that it was executed without problems in the server.
Then, as we called the OLCCommander with the -s 1 option which means that we wanted to spy the data every 1 seconds, the client sent a getSampleData RPC command each 1 seconds. Please, don't confuse this time period with the period attribute of the <sample> scenario tag. This will be used in the server in future releases, but not now. For every getSampleData command issued, a hash is printed with information about the very last commands executed on the server. In this example, we collect information about the Local/test/constant and Local/test/linear commands, because we asked for this info in the scenario definition (see the spy attribute for these commands). For each measurement collected, it will be displayed all its attributes, which are selected on the <retValues> tag subtree (see chapter 4).
If you choose sample.small="no", you would get the pure raw data for each measurement, which would be quite a lot of information. The small attribute is introduced to easy the management of big quantities of data for spying purposes on the client side. If you select the "no" value, be sure to redirect the standard output of OLCCommander to a file so as to not mess too much your shell terminal.
Next, a stopRun command is sent, followed by an finishRun. The return value for the finishRun call tell us the run number assigned to this run (instead of a normal timestamp). Note it down for future references to this run because right now no functionality to retrieve past run data from the client is implemented, so you will have to go to the server and look at the data on the run database.
Then, a getStats is sent to the server to collect some statistics of this last run. They are printed nicely by the printStatistics() method. This information is normally what the user want to have a quick idea of what happened on the stress test and to extract preliminary conclusions. If you want more information you can always go to the rundata repository (on the server side) and look carefully at the raw data and reduced data files (see chapter 5).
It is worth noting that this sample commander is a real commander. It basically uses all the present microkernel API, but, of course, its functionality is limited. If you browse the OLCCommander source you will find how easy is to talk with the OpenLC server.
Feel free to modify the parameters in the scenario definition file and experiment with different values, then save the file and rerun the client to see the changes. Try also with the http-config.xml scenario sample. Read chapter 4 for more information about the different parameters and its values.