This chapter discusses the example applications contained in the SDK. An example application ("OIC") is presented in multiple implementations in different programming language environments.
| File | Description |
|---|---|
| UDsdk_v4.1/ | SDK home directory |
| README.txt | Introductory file that points to this document |
| uduserconf.sample | Sample config file for SDK scripts |
| UDsdk_v4.1/doc/ | SDK documentation directory |
| appdev-guide.pdf | Application Developer's Guide |
| appuser-quickguide.pdf | Application User's Quick Guide |
| index.html | This document |
| style.css | Style sheet for this document |
| TestAgent.html | Test Agent documentation |
| TestAgent.png | Graphic for TestAgent.html document |
| mgsi-reference.html | MGSI function reference |
| UDsdk_v4.1/external/ | External third party libraries |
| build.cmd | Windows command file to build libraries |
| build.sh | Shell command file to build libraries |
| curl-7.11.1.tar.gz | CURL library |
| EasySoap++-0.6.tar.gz | EasySoap++ library |
| EasySoap++-0.6-patch-aa | Patch for EasySoap++ |
| EasySoap++-0.6-patch-ab | Patch for EasySoap++ |
| EasySoap++-0.6-patch-ac | Patch for EasySoap++ |
| EasySoap++-0.6-win-patch-aa | Patch for EasySoap++ |
| EasySoap++-0.6-win-patch-ab | Patch for EasySoap++ |
| expat-1.95.2.tar.gz | expat library |
| openssl-0.9.6m.tar.gz | OpenSSL library |
| zlib-1.1.4.tar.gz | zlib library |
| install/include/*.h | Header files for precompiled libraries |
| install/lib/*.lib | Library files for precompiled libraries |
| UDsdk_v4.1/mgsi/ | Various MGSI related files |
| udmgsi.wsdl | WSDL specification of the MGSI SOAP interface |
| i686-pc-linux-gnu/*_i686-pc-linux-gnu | Precompiled MGSI utilities for Linux |
| win32/*.exe | Precompiled MGSI utilities for Windows |
| sparc-sun-solaris2.8/*_sparc-sun-solaris2.8 | Precompiled MGSI utilities for Solaris |
| powerpc-ibm-aix5.2.0.0/*_powerpc-ibm-aix5.2.0.0 | Precompiled MGSI utilities for AIX |
| UDsdk_v4.1/mgsi/perl/ | MGSI utilities |
| create-app.pl | Create an application in the system |
| dumpsec.pl | Dump access control information for an object |
| mgsicall.pl | Execute arbitrary MGSI calls through the commandline |
| mgsifile.pl | Upload and download files from the file server |
| setcredential.pl | Set login credentials for job execution |
| submit-job.pl | Submit a job to the system |
| UDsdk_v4.1/mgsi/cpp/ | C++ library for the MGSI |
| build.cmd | Windows command file to build udmgsi.dll |
| build.sh | Shell command file to build libudmgsi.so |
| include/*.h | Header files for C++ MGSI library |
| lib/udmgsi.dll | Windows library for MGSI C++ functions |
| lib/udmgsi.lib | Windows import library file for udmgsi.dll |
| lib/udmgsid.dll | Windows library for MGSI C++ functions (debug version) |
| lib/udmgsid.lib | Windows import library file for udmgsi.dll (debug version) |
| src/mgsi_client.cpp | MGSI C++ library source code |
| src/mgsi_client_valuefuncs.cpp | MGSI C++ library source code |
| src/mgsi_file_transfer.cpp | MGSI C++ library source code, file transfer |
| src/Makefile.* | GNU build files |
| Makefile.* | GNU build files |
| configure.in | GNU build files |
| configure | GNU build files |
| config.* | GNU build files |
| ltmain.sh | GNU build files |
| aclocal.m4 | GNU build files |
| install-sh | GNU build files |
| mkinstalldirs | GNU build files |
| missing | GNU build files |
| UDsdk_v4.1/mgsi/patches/ | Patches for libraries for the MGSI |
| frontier-rpc.patch | Patch for the Perl Frontier::RPC module |
| frontier-rpc.txt | Documentation for the patch for the Perl Frontier::RPC module |
| UDsdk_v4.1/mgsi/java/ | |
| Makefile | Makefile for Java MGSI library |
| com/ud/mgsi/*.java | Source files for Java MGSI library |
| com/ud/mgsi/*.class | Compiled class files for Java MGSI library |
| javadoc/* | Documentation for Java MGSI library |
| lib/*.jar | Apache Axis libraries |
| fix-axis-generated-source.pl | Script to correct Axis-generated source code |
| UDsdk_v4.1/tools/build/ | Tools for building Program modules |
| buildmodule.c | Buildmodule utility source code |
| buildmodule* | Tool to build Program modules |
| buildpkg.c | Buildpkg utility source code |
| buildpkg* | Tool to build data package files |
| loader* | Program loader executable for Program modules |
| CLRLoader.exe | Windows additional program loader for CLR (.NET) modules |
| untar.exe | Utility to extract .tar.gz files |
| patch.exe | GNU patch for applying source patches |
| UDsdk_v4.1/tools/mpbatch/ | Tools for batch-queueing programs |
| mpinit.pl | Initialization script for mpbatch |
| mpsub.pl | Main mpbatch-submission script |
| mpresult.pl | Script for retrieving mpbatch results |
| batchmodule_* | Support modules for batch submission |
| *_i686-pc-linux-gnu | Precompiled batch utilities for Linux |
| *.exe | Precompiled batch utilities for Windows |
| *_sparc-sun-solaris2.8 | Precompiled batch utilities for Solaris |
| *_powerpc-ibm-aix5.2.0.0 | Precompiled batch utilities for AIX |
| UDsdk_v4.1/tools/mpi/ | Tools for MPI support |
| ud_mpirun.pl | Grid MP implementation of MPICH's mpirun |
| mpich-1.2.5-1a-patch-aa | Patch for MPICH 1.2.5 |
| ud_mpirun* | Precompiled ud_mpirun for various platforms |
| UDsdk_v4.1/tools/testagent/ | Tools for testing Program modules |
| ta* | CLI tool for testing Program modules |
| TestAgent.exe | GUI tool for testing Windows Program modules |
| udtapi.dll | Runtime windows UDTAPI library neccessary for TestAgent |
| UDsdk_v4.1/examples/oic/ | Example OIC application and Program modules |
| mkpackages.bat | Windows script for building sample datas |
| mkpackages.sh | Shell script for building sample datas |
| exclusion.txt | Sample input for OIC example |
| fragment.txt | Sample input for OIC example |
| oic_data_text.tar | Sample input datapackage for OIC example |
| oic_data_excl.tar | Sample input datapackage for OIC example |
| UDsdk_v4.1/examples/oic/program/cpp/ | C++ example application |
| Makefile.gcc | GCC makefile for OIC example |
| Makefile.vc | Windows makefile for OIC example |
| Makefile.cyg | Cygwin makefile for OIC example |
| oic.cpp | OIC example source file |
| oic-mpi.cpp | OIC example source file with MPICH support |
| oic.exe | Original Windows OIC binary |
| oic-module.exe | Windows OIC Program Module |
| UDsdk_v4.1/examples/oic/program/dotnet/ | C# .NET example application |
| Makefile | Makefile for C# OIC example |
| oic.cs | Source file for C# OIC |
| oic_dotnet.exe | Precompiled C# oic example |
| oic_wrapped_dotnet.exe | Precompiled C# oic example after buildmodule |
| UDsdk_v4.1/examples/oic/appserv/perl/ | Example Perl Application Service |
| oic-submitjob.pl | OIC Perl job submission script |
| oic-retrievejob.pl | OIC Perl result retrieval script |
| UDsdk_v4.1/examples/oic/appserv/cpp/ | Example C++ Application Service |
| Makefile.gcc | GCC makefile for OIC C++ Application Service |
| Makefile.vc | Windows makefile for OIC C++ Application Service |
| oic-submitjob.cpp | Precompiled OIC C++ job submission program |
| oic-submitjob.exe | Precompiled OIC C++ job submission program windows binary |
| oic-retrievejob.cpp | Precompiled OIC C++ result retrieval program |
| oic-retrievejob.exe | Precompiled OIC C++ result retrieval program windows binary |
| UDsdk_v4.1/examples/oic/appserv/mfc/ | Example C++ Application Service |
| gui.dsp | MSVC 6 project file |
| gui.cpp | Example C++ MFC source file |
| gui.h | Example C++ MFC header file |
| gui.rc | Example C++ MFC resource file |
| guiDlg.cpp | Example C++ MFC source file |
| guiDlg.h | Example C++ MFC header file |
| resource.h | Example C++ MFC header file |
| StdAfx.cpp | Example C++ MFC source file |
| StdAfx.h | Example C++ MFC source file |
| res/ud.ico | Example C++ MFC icon file |
| OICgui.exe | Precompiled example C++ MFC application |
| UDsdk_v4.1/examples/oic/appserv/java/ | Example Java Application Service |
| Makefile | Makefile for OIC Java Application Service |
| com/ud/*.java | Source files |
| com/ud/*.class | Precompiled class files |
| config/ErrorMessages.msg | Error message data file |
| config/oicadmin.properties | Configuration file for Java example |
| scripts/oicadmin | Startup script |
| scripts/oicadmin.bat | Startup command file |
Because the MGSI service is implemented using standard SOAP web services, many programming environments can call MGSI functions directly, with or without the udmgsi.wsdl file.
In many situations it is desirable to have a small extra layer of functionality on the client side.
In particular, for programs that expect to run for more than one hour, care must be taken to renew the MGSI authentication token when necessary.
The MGSI authentication token is only good for one hour from the time the login function is called.
The client side interface classes automatically call the login function whenever it is necessary to do so.
This relieves the calling code from having to catch and handle this common type of exception.
However, the calling code should always handle exceptions that might be thrown from MGSI functions.
Failure to handle such exceptions will cause an immediate program abort in most programming environments.
C++ does not offer standard support for SOAP, so we have provided a helper library that uses the third party EasySoap++ library for communications. This helper library takes care of the details of interfacing with the EasySoap library, and provides an easy to use C++ interface to MGSI.
The udmgsi library interface is provided in two header files:
#include <mgsi_client.h> #include <mgsi_file_transfer.h>
The MgsiClient class is constructed with a factory method.
It is destroyed with a call to the standard C++ delete operator.
static MgsiClient *MgsiClient::create(const char *url);
The MgsiClient class provides two management methods:
// Get the current authentication token std::string getAuthToken() const; // Get the URL used to initialize this instance std::string getUrl() const;
There is an automatic retry feature in the udmgsi library. In case of a transient network failure, it will automatically try to contact the server a short time later without returning an exception to the caller. The default number of retries is 3, with a default maximum time between retries of 60 seconds. The following methods modify the retry parameters:
// Set the maximum number of times to retry a failed call. // Use a negative value to indicate infinite retries. void setRetryLimit(int retries); // Get the current retry limit. int getRetryLimit() const; // Set the maximum time between retry attempts. bool setRetryDelay(int seconds); // Get the current maximum retry delay. int getRetryDelay() const;
Data structures from the MGSI are implemented as C structures, and fields in a MGSI structure are members of these C structures.
Arrays are implemented with std::vector. MGSI functions are implemented as member functions (see mgsi-reference.html for a complete list).
The MgsiClient functions will throw a MgsiException exception when a MGSI exception is returned from the server.
The Code and String members will be filled with the numeric error code and a descriptive error message.
You should be sure to catch these exceptions, because an uncaught exception in C++ will cause an immediate program abort.
When a connection is lost, either due to SSL keepalive timeouts (in https mode) or transient network errors (in either http or https), EasySoap will cause a SIGPIPE to be sent to the program. This signal should be ignored when possible. See OIC in UDsdk_v4.1/examples/oic/as-cpp for an example of this. Additionally, be sure to set the MgsiClient retry limit to something greater than zero if you want your program to recover.
Simple code example:
#include "mgsi_client.h"
int main()
{
ud::mgsi::MgsiClient *mgsi = ud::mgsi::MgsiClient::create(
"https://server:18443/mgsi/rpc_soap.cgi"
);
std::string auth = mgsi->login("username", "password");
ud::mgsi::Job myjob;
// Fill in myjob here
ud::uuid job_gid = mgsi->createJob(myjob);
std::vector<ud::mgsi::JobStep> jobsteps = mgsi->getJobStepsByJob(job_gid);
// Add work here
delete mgsi;
}
The MgsiFileTransfer class constructor takes an url to the file service and a pointer to an existing MgsiClient:
MgsiFileTransfer(const std::string &url, MgsiClient *mgsi);
There are two methods for downloading data. One writes data directly to disk, and the other uses a user allocated buffer:
// Only one of "tarfile" or "subfile" can be non-empty at a time.
// The file is transfered directly to a file named "file_name".
void download_file(const std::string &file_name,
const std::string &hash,
const std::string &subfile="",
const std::string &tarfile="");
// Only one of "tarfile" or "subfile" can be non-empty at a time.
// The caller allocates buffer, which must be at least len bytes.
void download_data(char *buffer,
size_t len,
const std::string &hash,
const std::string &subfile="",
const std::string &tarfile="");
The difference between tarfile and subfile is that subfile will look in the pmf.xml for files and possibly uncompress it, whereas tarfile will just obtain the file directly from the tarball. For example, if you have a pmf.xml line like:
<file name="foofile" internalname="foofile.bz2" encoding="bzip2" />
then you can retrieve the compressed foofile.bz2 through the tarfile option, and the uncompressed foofile through the subfile option. The tarfile option is particularly useful for retrieving the pmf.xml file itself.
The methods for uploading return a Response struct with the hash of the data and its size.
struct Response {
std::string hash;
off_t size;
};
// Reads from a file named "file_name".
Response upload_file(const std::string &file_name, const std::string &hash = "");
// Reads "len" bytes from "buffer".
Response upload_data(const char *buffer, size_t len, const std::string &hash = "");
The "hash" parameter is the SHA1 of the uploaded file. Normally you can leave this empty and the file server will automatically compute the hash and return it in the response. If you already know the hash, passing it here will help ensure that the file arrives intact at the server.
The Java interface library is provided in the com.ud.mgsi package.
The majority of the classes in this package are created automatically using the Apache Axis tools.
The one class that is not automatically generated by Axis is the com.ud.mgsi.Retry class.
The com.ud.mgsi.Retry class provides a transparent layer on top of the generated Axis interface.
Normal use of the Axis interface is something like this:
UdMgsiPortType mgsi = new UdMgsiLocator().getUdMgsiPort(new URL(address));
To use the Retry class, change this as follows:
UdMgsiPortType mgsi = (UdMgsiPortType)new Retry(
new UdMgsiLocator().getUdMgsiPort(new URL(address)),
UdmgsiPortType.class).create();
To take advantage of the automatic relogin feature, pass null to the auth parameter of each MGSI function.
If you pass a non-null authentication token value, that value will be explicitly used and not refreshed even if it has expired.
If you pass a null value, the authentication token obtained from the last successfull call to login (or login2) will be used, and refreshed if necessary.
Some of the tools in the SDK use a small bit of Perl code that provides automatic an automatic reauthentication feature. This code is not packaged in a Perl module but is instead included at the end of a script that uses it. For convenience, the code is reproduced here:
package MgsiAuthenticator;
use vars qw($AUTOLOAD);
sub new {
my ($class, $server) = @_;
my $r = {server => $server};
return bless($r, $class);
}
sub call {
my $self = shift;
my $f = shift;
my $r;
if ($f !~ /^login/) {
splice(@_, 0, 0, $self->{auth});
$r = $self->{server}->call($f, @_);
if ($r->fault && $r->faultstring =~ /^\(-1\)/) {
my $rr = $self->{server}->call("login", @{$self->{loginparams}});
if ($rr->fault) {
return $r;
}
$self->{auth} = $rr->result;
$_[0] = $self->{auth};
$r = $self->{server}->call($f, @_);
}
} else {
$r = $self->{server}->call($f, @_);
$self->{loginparams} = \@_;
if ($f eq 'login') {
$self->{auth} = $r->result;
} elsif ($f eq 'login2') {
$self->{auth} = $r->result->{auth};
}
}
return $r;
}
sub AUTOLOAD {
my $self = shift;
my $f = $AUTOLOAD;
$f =~ s/.*:://;
return if $f eq 'DESTROY';
return call($self, $f, @_);
}
Normal use of the Perl SOAP::Lite module looks like this:
my $mgsi = new SOAP::Lite
-> uri('urn://ud.com/mgsi')
-> proxy(address);
To use the MgsiAuthenticator layer, change this as follows:
my $mgsi = new MgsiAuthenticator(new SOAP::Lite
-> uri('urn://ud.com/mgsi')
-> proxy(address));
When calling MGSI functions using this class, do not include the first auth parameter.
This parameter will automatically be added by the MgsiAuthenticator class.
All the SDK example programs are supplied with 'make' scripts that automate the building process for each example. Since many of the build steps refer to files in other directories in the SDK, the environment variable UD_SDK_HOME is used to indicate where the root of the SDK is. For example, if the SDK is extracted into /home/mpuser (Linux) or c:\home\mpuser (Windows), then the UD_SDK_HOME environment variable would be set as follows:
export UD_SDK_HOME=/home/mpuser/UDsdk_v4.1
set UD_SDK_HOME=c:\home\mpuser\UDsdk_v4.1
The first step that needs to be done is to build the third-party libraries included in the SDK. To do this, change to the 'external' directory and run:
sh build.sh
build.cmd
This step may take a few minutes and will build the necessary third-party libraries. The last line printed should be: external build successful.
The next step is to build the libudmgsi library. Change to the 'mgsi/cpp' directory and run:
sh build.sh
build.cmd
If all goes well, the libudmgsi.so library will be installed in mgsi/cpp/lib.
All the functionality of the examples are based around the Ordered Item Count (OIC) application. OIC is a simple application designed to illustrate most of the aspects of developing distributed applications for the Grid MP platform.
OIC accepts a text file as input, and counts the number of times each word occurs in the input file. The output is a list of all words encountered in the input file, with the number of times each word is seen, sorted by frequency. To demonstrate workload splitting, a large text file can be split into smaller fragments, each fragment processed on a separate device, and the result combined later after each fragment has been processed. Additionally, an exclusion list allows selected words to be ommitted from the count.
The postprocessing functionality demonstrates how the MGSI is used to submit work into the system and retrieve results.
The OIC program module is the core of the OIC functionality. It is an executable program that accepts its arguments on the command line, reads its input from disk files, and writes its output to a disk file. It performs the work of tokenizing the input file into individual words and counting the number of times each word occurs.
The general command line format of the OIC program module is:
oic textfile outputfile exclusionsfile [sleep [-r]]
The input file 'textfile' is the file containing text whose words will be counted. The output file 'outputfile' is the file where the output will be written. The file 'exclusionsfile' is a list of words, one to a line, that will be excluded from the final count. The 'sleep' parameter is the number of seconds to wait between lines of the input file. The '-r' option reverses the sense of the exclusion file, so that it becomes an inclusion file and only the words appearing in that file will be counted.
The OIC application service manages the submission of work into the system, splitting of input files into smaller workunits, collection of results, and combining of result files.
The example application services are in two parts - submitjob and retrievejob. The submitjob portion reads the input file, and splits it into smaller files for each device to work on. A job is created to represent the work needed by a single large input file. Each portion of the input file is created as an individual workunit inside the job. The retrievejob portion gets the results for each workunit within the job, and assembles a single output file. This output file represents the same output file that would be produced by a single run of oic against the original input file.
Each workunit consists of a portion of the original input file, plus the complete exclusion list.
There are three different versions of the OIC program module in the SDK examples. Two of them are the same program implemented in different programming languages: C++ and C#. The third is a C++ example that uses the Message Passing Interface (MPI) for parallel computation.
The C++ implementation of OIC is found in the examples/oic/program/cpp directory. To build this example, change to the examples/oic/program/cpp directory and run:
make -fMakefile.gcc
nmake -fMakefile.vc
make -fMakefile.cyg
This will make the file "oic-module" (or "oic-module.exe") which is the program module ready for uploading into the platform.
The C# implementation of OIC is found in the examples/oic/program/dotnet directory. To build this example, change to the examples/oic/program/dotnet directory and run:
nmake
This will make the file "oic_wrapped_dotnet.exe" which is the program module ready for uploading into the platform.
The MPI implementation of OIC is also found in the examples/oic/program/cpp directory. To build this example, change to the examples/oic/program/cpp directory and run:
make -fMakefile.gcc oic-mpi
nmake -fMakefile.vc oic-mpi.exe
This will make the file "oic-mpi" (or "oic-mpi.exe") which is suitable for use with ud_mpirun.
There are four different versions of the OIC application service in the SDK examples. They are implemented in three different programming languages: C++ (command line), C++ (MFC), Java, and Perl.
The C++ command line application service implementation is found in the examples/oic/appserv/cpp directory. To build this example, change to the examples/oic/appserv/cpp directory and run:
make -fMakefile.gcc
nmake -fMakefile.vc
This example requires the use of shared libraries at runtime. To run this executable, use:
export LD_LIBRARY_PATH=$UD_SDK_HOME/external/install/lib:$UD_SDK_HOME/mgsi/cpp/lib ./oic-submitjob
set PATH=%UD_SDK_HOME%\mgsi\cpp\lib;%PATH% oic-submitjob
The C++ MFC application service implementation is found in the examples/oic/appserv/mfc directory. To build this example, change to the examples/oic/appserv/mfc directory and run:
msdev gui.dsp /make
devenv gui.dsp
[ follow the prompts to convert the project, then exit devenv and save the gui.sln file when prompted ]
devenv gui.sln /build release
For the real work, the GUI delegates the work to the oic-retrievejob.exe and oic-submitjob.exe (SDK location UDsdk_v4.1\examples\oic\appserv/cpp). Their location, and several other parameters, must be set through environment variables prior to launching the oicgui.exe executable. These environment variables are:
Also, for execution, the udmgsi.dll library must be present in either the directory where oicgui.exe is located, or in a directory in the %PATH%.
Start the GUI by typing "oicgui.exe".
Fill out the correct MGSI constants, such as rpc url, fileserver url, username and password. Then click "Login".
If the login was successful, the Application pulldown list will contain all applications in your Grid MP installation.
You can now Submit a job by filling out the relevant fields in the 'Submit Job' area, and press submit. At that point, control will be passed to the oic-submitjob.exe utility, and its output will be displayed in a window.
You can monitor jobs and retrieve the results for jobs through the "Monitor Jobs" area. Click "Update now" to refresh the list of jobs for your application, or click "Start" to automatically refresh the list. Highlight a job and click "View" to retrieve the results for that job and display them in notepad.exe. Highlight a job and click "Delete" to delete that job.
Clicking "Exit" will exit the GUI Application.
The Java application service implementation is found in the examples/oic/appserv/java directory. To build this example, change to the examples/oic/appserv/java directory and run:
make
nmake
The Java MGSI library uses the Axis library, which uses the standard Java HTTP classes. When connecting to an HTTPS server with SSL, the Java HTTP classes require that the server certificate be trusted in order to connect successfully. This certificate must be imported into a local "keystore" file. To do this, execute a command such as the following:
keytool -import -alias mpserver -file /usr/local/UD/inetpub/etc/ssl/crt/mpservice.crt -keystore ~/.cacerts
[ enter any password to create a new keystore file ]
[ copy mpservice.crt file from MGSI server computer ]
keytool -import -alias mpserver -file mpservice.crt -keystore cacerts
[ enter any password to create a new keystore file ]
The cacerts (or ~/.cacerts) file will now contain a trusted copy of the server certificate. The oicadmin script will use this file when connecting to the HTTPS server so that the connection will succeed.
Note that in order for the connection to succeed, the address used by the client must match the DNS name of the server computer. This means that the client should not be configured to use an IP address (for example, https://192.168.0.1:18443/mgsi/rpc_soap.cgi), but should use a specific DNS name instead (for example, https://mgsiserver.grid.example.com/mgsi/rpc_soap.cgi).
To execute the oicadmin sample, change to the examples/oic/appserv/java/scripts directory and run:
./oicadmin
set OIC_CERTFILE=\path\to\cacerts oicadmin
The Perl application service implementation is found in the examples/oic/appserv/perl directory.