Application on-boarding is the process of distributing computational logic to the grid and parallelizing the client logic so that the distributed logic can be run in parallel. The Symphony add-in and extensions for Visual Studio provide a developer with a simplified process for on-boarding their C# application to the grid from within the Visual Studio environment.
The add-in eases the task of grid-enabling and parallelizing compute-intensive portions of an existing application. A project wizard guides you through the on-boarding process. When on-boarding existing applications, the feature requires that the computational logic reside in a class library (DLL) file. After analyzing the DLL, a proxy of the exposed interfaces is generated and added to the client logic in Visual Studio. The proxy class enables you to interact with your grid-enabled object as if it was a local object.
Alternatively, if you choose to use the feature for on-boarding new applications, the project wizard creates a framework of generated code for the client and service. All you need to do is add the application logic.
The automation introduced by the add-in extends to the creation and maintenance of Symphony applications. For example, the tasks of deploying a service or updating an application profile is simplified through the Symphony Platform Management Console (PMC), which is integrated with the Visual Studio environment.
The add-in also features extensive online documentation to support your Symphony programming activities such as informative comments in the generated code, the Symphony .NET API reference documentation, and a tutorial.
This section highlights the key steps for on-boarding an existing application. Refer to the following diagram.
The wizard inspects the selected the .NET class library to determine the public classes, interfaces, and methods available. At this point, you have the opportunity to select which classes you intend to interact with once this library is placed on the grid. The method roles of the selected classes can also be customized.
The wizard creates and compiles the code to make the selected classes and their methods grid-enabled.
The wizard creates and deploys a package containing the class library to the grid. The application is also registered with Symphony.
The wizard updates any source code and project settings relevant to the on-boarding activity.
Once the wizard exits, you are able to review the contents of a generated readme file. The readme will contain a reference to the proxy interface and some examples of how to use it.
The client, at this point, can interact with the grid-enabled library that was previously deployed, i.e., your calculations would actually take place on the grid instead of inside your client process.
Parallelize the calculations on the grid by using the .NET Asynchronous Programming Model (APM) convention and the asynchronous methods generated in the proxy object.
Execute your code and verify that your calculations are performed in parallel on the grid.
The basic prerequisites for on-boarding new and existing applications are:
Existing applications must meet additional requirements before they can be successfully on-boarded.
The application has computational logic that can logically be executed in parallel
The computational logic resides in a .NET class library that can be packaged on its own so that it can be used in a stand-alone manner on the Symphony grid.
Only methods with serializable parameters can be used in the proxy object
The on-boarding feature also enables you to customize the logic produced during the on-boarding process by allowing access to the source code.
You must consider any application object state dependence between different application method calls and realize that when application methods are called in parallel on the grid, the state of the object cannot rely on a previous method being invoked on the object since there is no guarantee that subsequent calls will be made to the same object instance being hosted within the grid.
Since the setting of properties is achieved through the session update call (common data update feature), exceptions that occur during the setting of a property could cause the session associated with the proxy object to be aborted; refer to the Application Development Guide for details about common data updates.
Only items matching the following qualify for being generated in the proxy object:
Since stateful methods are implemented using the common data update feature, they cannot have a return value; for a definition of stateful methods, refer to the stateful role topic in this chapter.
Objects containing constructors that have output and reference parameters are allowed to be proxy objects, but once the constructor completes execution, the output and reference parameters will not be updated.
This feature does not support the construction of objects through the use of a private constructors from a static class method. This means only public constructors can be used to construct proxy objects.
All interfaces supported by the original object are supported by the proxy object, i.e., once you have constructed a proxy object, you are free to cast it to any of the interfaces supported on the original object.
The generated classes will use fully qualified names with namespace for all variable data types. In each case, the underlying types of the .NET framework will be used to generate method signatures instead of the value type aliases that may have been used when the class was originally coded. For example:
If an application was previously on-boarded, Visual Studio should be restarted before on-boarding the next application. This is necessary to clear Visual Studio’s memory of any on-boarded DLL assemblies. Here is a simple example of why you should restart Visual Studio. Suppose you have 2 DLLs to on-board: A and B, and B depends on A. If you on-board A.dll and then on-board B.dll without adding A.dll in the library dependency list box. the wizard will not report the missing dependent DLL since A.dll is still in Visual Studio’s memory. The on-boarded B.dll will not work because A.dll was not included during the on-boarding process.
As of .NET runtime 4.0, a change was made to no longer load mixed assemblies automatically. In order to load mixed assemblies, the runtime must be explicitly instructed through the use of a configuration file. Since all on-boarded applications still rely on the Symphony API (which is implemented as a mixed assembly), both the client and the service package to be deployed to the grid must be associated with a configuration file to instruct the runtime to load the mixed assembly. The configuration file must set the startup attribute useLegacyV2RuntimeActivationPolicy to true. For example;
<?xml version="1.0"?><configuration><startup useLegacyV2RuntimeActivationPolicy="true"><supportedRuntime version="v4.0"sku=".NETFramework,Version=v4.0"/></startup></configuration>
The configuration file name must match the name of the associated binary file. For example, the configuration file for the client executable CalculateInterest.exe must be named CalculateInterest.exe.config. Refer to Tutorial: On-boarding a Symphony application with Visual Studio for an example of how to associate configuration files with the client and service.
The on-boarding feature enhances the Visual Studio environment with the following menu extensions.
The application details window is only available within the context of a project that has been designated as a service project. The application details collected allow you to associate cluster and admin entry points and service packaging details that can be used multiple times by the add-in during development time instead of specifying them each time.
You can access the application details from any of the following locations:
When you create a new project in Visual Studio, the steps you take depend on whether you want to on-board an existing application or a new application from scratch.
If you want to on-board an existing application, you need to have your computational logic contained in a .NET class library. Create a new project in Visual Studio to launch the project wizard. Select the Grid Enabled Library template. The project wizard guides you through the rest of the on-boarding process. The wizard inspects the selected class library to determine the public classes, interfaces, and methods available in the library. This information is used to generate the proxy object that will be integrated with the client. The wizard enables the library to run on the grid without any changes to the library itself
The on-boarding process generates the following output:
a proxy class that the client can use to access the object on the grid
a transport class to serialize/de-serialize proxy calls to/from the service
a report file summarizing all the activities performed by the wizard during the on-boarding process including creating and building projects, deploying service packages, and registering the application.
a readme file providing details about the interface exposed by the generated proxy object and instructions.
In addition, the package containing our grid-enabled library and any of its dependencies specified in the wizard are deployed to the grid.
Once the grid-enabling stages are complete, the optional code update performed by the wizard is limited to simple redirection of any calls on the objects selected in the wizard to the generated proxy classes.
When you on-board a new application, you need to create code for the client and service. The Symphony add-in for Visual Studio provides client and service templates as a framework for code development. All you need to do is add your own logic to the framework.
Create a new project in Visual Studio to launch the project wizard. Select the Simple Console Client, Simple Console Client (with callback), or Simple Service template.
The on-boarding process generates the following output depending on the template chosen:
The feature creates a proxy containing the constructors and application methods from the class you selected with the on-boarding wizard. For every stateless application method selected, the proxy contains three related methods: (refer to Object roles topic for a definition of stateless methods)
For example, let’s look at a class with the following application method:
With this application method, you should have access to the following methods on the generated proxy:
double CalculateInterest(double amount);IAsyncResult BeginCalculateInterest(double amount,AsyncCallback cb, Object state);double EndCalculateInterest(IAsyncResult result);
You can either choose to use callback or block the current thread once all asynchronous operations have been started.
For stateful application methods, you only have access to a single method on the proxy that has the same signature as the original method. Since stateful updates are asynchronous in nature, no other methods are needed.
When a method call to a service-side object fails, the exception thrown from the grid-enabled library is preserved and thrown in the original form from within the proxy interface to the client. The client logic should be able to catch any application specific exception that can be thrown from the on-boarded .NET library running on the grid.
In the event that an exception occurs outside of the application logic, for example, a broken connection that cannot be resolved, a Symphony exception is propagated back to the client. This means that any try-catch block currently applied to a method in the proxy object must be extended to catch a GridException; otherwise, an unhandled exception may occur in your client logic.
Your code should be able to catch Symphony-specific exceptions that may be thrown from your proxy classes.
Any exceptions being propagated from the constructors of their classes in their service-side objects will not be preserved.
For stateless and property get methods, exceptions are preserved and thrown to the client.
Application methods in the proxy object can serve different roles. Although the role associated with a method is indicated by the on-boarding wizard when you review the libraries being grid-enabled, you have the option to customize the roles.
This role is only assigned to application methods that are identified as constructors of an application object. You cannot set this role explicitly. Constructor methods are called during the OnSessionEnter() call in the service.
This role is assigned only to properties of an application object. You cannot set this role explicitly.
Setting a property on the proxy object results in a common data update being dispatched for the session associated with the object. The setting of a property is executed on all service instances and takes effect on all object instances once the current method invocation on the service completes. You must consider and evaluate the need for synchronization between methods currently executing asynchronously and the state they need to set across all object instances in the grid. Service side object properties are set during the OnSessionUpdate() call.
Getting a property results in a task being created and dispatched to the session associated with the object to retrieve the value of the property from any object instance found on the grid. Service side object properties are retrieved during the OnInvoke() call.
You can assign this role to any application method (not including properties and constructors). Calling this application method results in a task being created and dispatched to the session associated with the object. The service side object stateless method is called during OnInvoke().
This role can be assigned to any application method that does not have an out or return value (not including properties and constructors). The behavior associated with this application method call is similar to the setting of a property, i.e., calling it results in a common data update being dispatched to the session associated with the object. It is intended for those cases where you want to optimize the setting of state for multiple items in the object at the same time. As with the setting of properties, you must consider and evaluate the need for synchronization between methods currently executing asynchronously and the state they need to set across all object instances in the grid. The service side stateful methods are called during OnSessionUpdate().
Since stateful methods are implemented using the common data update feature, they cannot have a return value. The wizard prevents you from associating a method that has a return value or out parameter from being assigned a stateful method role.
You can assign this role to any regular methods of the class (not including properties and constructors). This method is invoked by the service during OnSessionLeave() before the references for the proxy objects are released. Once a method has been assigned this role, it becomes unavailable for being called through the proxy since it has been assigned a special role on the service side. Only one method in the class can be assigned this role. If your object has already implemented the IDisposable interface, the dispose method will automatically be called so you do not need to select that method with this role. However, if you need any other method called, you can specify it with this role. The selected method cannot accept a parameter or return a value.
An interrupt is triggered whenever a task is suspended or killed, or a resource is reclaimed. You can assign this role to any regular methods of the class (not including properties and constructors). This method is invoked by the service during the OnServiceInterrupt(). Once a method has been assigned this role, it becomes unavailable for being called through the proxy since it has been assigned a special role on the service side. Only one method in the class can be assigned this role. The selected method cannot accept a parameter or return a value.
When each instance of a new object is created, it gets a dedicated session with the session name assigned the fully qualified name of the object. The session tag is assigned a modified form of the signature of the constructor used to create the object.
For example, take the following constructor in application MyApp:
double theInterest = 0.15;int theDuration = 10;Calculator obj = new Calculator (theInterest, theDuration);
If you call the Calculator constructor and view the session details, you would see the following:
Session name: MyApp_Basic_Calculator
Session tag: Calculator-_double_interest__int_duration_-
Each instance of a method call has a task dedicated to it with the task tag assigned a modified form of the signature of the method being called on the object.
For example, look at the following code:
If you call the CalculateInterest method and view the task details, you would see the following:
Task tag: CalculateInterest-_double_amount_-
The project wizard applies the following general rule for representing method calls as a session name, session tag or task tag:
When use of the proxy object is complete, call the Dispose() method for non-static classes and StaticDispose() for static classes before releasing the reference. This will guarantee that all Symphony resources are released before the .NET Garbage Collector gets a chance to clean up the object. If a disposal method is not called on the proxy object, there is a risk of having aborted sessions in the SSM when the client exits.