XPRD Java
For the remote execution of Mosel models we need to augment the standard execution sequence for Mosel models (that we have seen, for example, in Section Java) of compile load run to the sequence connect – compile load run wait (this remark equally applies to submodels launched via mmjobs). The meaning of these additions is the following:
- We need to connect to a remote machine and create a new Mosel instance (XPRDmosel) prior to working with any Mosel models. Remote machines are specified by their name or IP address, the empty string in the example below indicates that we want to use the local machine.
- The submodel is executed in an independent process and we therefore need to wait for its termination.
The program example runprimedistr.java below shows how to run the model prime.mos using the XPRD Java library. If the submodel has not terminated after 2 seconds (i.e., not termination message has been received from this model), then it is stopped by the application. After termination of the submodel (either by finishing its calculations within less than 2 seconds or stopped by the parent model) the application reports the full event information and also displays the termination status and the exit value of the Mosel model. Unloading a model explicitly as shown here is only really necessary in larger applications that continue after the termination of the submodel, so as to free the memory used by it.
import com.dashoptimization.*; import java.lang.*; import java.io.*; public class runprimedistr { public static void main(String[] args) throws Exception { XPRD xprd=new XPRD(); XPRDMosel moselInst; XPRDModel modPrime; XPRDEvent event; moselInst=xprd.connect(""); // Open connection to remote nodes // "" means the node running this program // Compile the model file on remote instance moselInst.compile("", "rmt:prime.mos", "rmt:prime.bim"); // Load the bim file into remote instance modPrime=moselInst.loadModel("rmt:prime.bim"); modPrime.execParams = "LIMIT=50000"; modPrime.run(); // Start execution and xprd.waitForEvent(2); // wait 2 seconds for an event if (xprd.isQueueEmpty()) // No event has been sent... { System.out.println("Model too slow: stopping it!"); modPrime.stop(); // ... stop the model, then wait xprd.waitForEvent(); } // An event is available: model finished event=xprd.getNextEvent(); System.out.println("Event value: " + event.value + " sent by model " + event.sender.getNumber()); System.out.println("Exit status: " + modPrime.getExecStatus()); System.out.println("Exit code : " + modPrime.getResult()); moselInst.unloadModel(modPrime); // Unload the submodel moselInst.disconnect(); // Terminate the connection new File("prime.bim").delete(); // Clean up temporary files } }
The model source file prime.mos used by this example is saved on the local machine running XPRD, and the BIM file is written back to this machine (indicated by the I/O driver prefix rmt: in the 'compile' and 'load' function calls that are executed on the remote instance). Alternatively, we might choose to save the BIM file on the remote machine, e.g. in memory (shmem:primebim) or in Mosel's temporary directory (tmp:prime.bim).
Exchanging data with the model
An application that processes a Mosel model typically needs to retrieve some (result) data from the model for reporting or further treatment. Besides exchanging data via external sources (e.g. databases), Mosel offers a number of possibilities for directly retrieving data into an XPRD program. The choice of the method for exchanging data usually depends on the particular system setup (write access rights) and the volume of data to be communicated (memory usage). Data in Mosel format written in an initializations block can be output
- on the remote machine running Mosel
- in memory
- as a physical file
- on the local machine running XPRD
- in memory
- as a physical file
Case 1a is implemented in the program version runprimeiodistr.java printed below. Case 1b is obtained by removing the shmem: prefix from the file name, for example, the setting
OUTPUTFILE=bin:tmp:resdata
will create a file resdata in Mosel's temporary directory. Cases 2a and 2b could use the setting
OUTPUTFILE=bin:rmt:resdata
For the implementation of case 2b we simply replace the XPRD remote file access by standard Java file access, for example
resdata=new FileInputStream("resdata");Somewhat more work is required for the implementation of case 2a: the program needs to define an XPRD file manager to handle the data in memory—an example implementation is provided in the file runprimeiodistr2.java.
All implementation versions share the use of the bin: I/O driver and they all define the same function showSolution that decodes Mosel's binary format and displays the solution values. Using Mosel's binary format is recommended (though not a necessity) in distributed applications—it is platform-independent and uses less space than the standard text format.
The program version printed below introduces two user events to achieve more precise time measures for the remote process: the hard stop of the Mosel model is replaced by sending the user event `STOPMOD' to the submodel: instead of immediately terminating the submodel this event is intercepted by the submodel and makes it interrupt its calculations and write out the current solution. To make sure that the submodel is actually running at the point where we sent the `STOPMOD' event, we have also introduced a 'MODREADY' event sent from the submodel to its parent to indicate the point of time when it starts the calculations (with heavy operating system loads the actual submodel start may be delayed).
We work with the Mosel model primeio.mos from Section Exchanging data between models.
import com.dashoptimization.*; import java.lang.*; import java.util.*; import java.io.*; public class runprimeiodistr { static final int STOPMOD = 2; // Identifier for "Stop submodel" user event static final int MODREADY = 3; // Identifier for "Submodel ready" user event public static void main(String[] args) throws Exception { XPRD xprd=new XPRD(); // Initialize XPRD XPRDMosel moselInst; XPRDModel modPrime; XPRDEvent event; InputStream resdata; moselInst=xprd.connect(""); // Open connection to remote nodes // "" means the node running this program // Compile the model file on remote instance moselInst.compile("", "rmt:primeio.mos", "tmp:primeio.bim"); // Load the bim file into remote instance modPrime=moselInst.loadModel("tmp:primeio.bim"); // Disable submodel output modPrime.setDefaultStream(modPrime.F_OUTPUT, "null:"); modPrime.execParams = "LIMIT=50000,OUTPUTFILE=bin:shmem:resdata"; modPrime.run(); // Start execution and xprd.waitForEvent(); // ...wait for an event event=xprd.getNextEvent(); // Retrieve the event if (event.eventClass != MODREADY) // Check the event class { System.out.println("Problem with submodel run"); System.exit(1); } xprd.waitForEvent(2); // Let the submodel run for 2 seconds if (xprd.isQueueEmpty()) // No event has been sent... { System.out.println("Model too slow: stopping it!"); modPrime.sendEvent(STOPMOD, 0); // ... stop the model, then xprd.waitForEvent(); // wait for its termination } // Open the output file, retrieve and display the solution data resdata=moselInst.openForReading("shmem:resdata", moselInst.F_BINARY); showSolution(resdata); resdata.close(); moselInst.unloadModel(modPrime); // Unload the submodel moselInst.disconnect(); // Terminate the connection } }
After termination of the model run, the XPRD application reads the solution data from the location specified in the model parameter OUTPUTFILE and displays the results. Below follows the implementation of the function showSolution that uses an instance of BinDrvReader to decode Mosel's binary format (the bindrv library is provided with XPRD). A binary format files has the same structure as the correponding text file in Mosel format, for example:
NumP: 6 SPrime: [ 2 3 5 7 11 13 ]
Each data entry starts with a label (string followed by a colon), followed either by a single, scalar data value, or a list of data values surrounded by square brackets.
// **** Decode the binary stream and display its contents **** static void showSolution(InputStream inbuf) throws Exception { BinDrvReader bdrv=new BinDrvReader(inbuf); // Initialize binreader String label; ArrayList<Integer> setP=new ArrayList<Integer>(); while(bdrv.nextToken()>=0) { bdrv.getControl(); // 'label' (marker) label=bdrv.getString(); // Read a string if(label.equals("NumP")) { // Read an integer System.out.println("(" + bdrv.getInt() + " prime numbers.)"); } else if(label.equals("SPrime")) { bdrv.getControl(); // [ (start marker) while(bdrv.nextToken()==BinDrvReader.TYP_INT) // or ] at end of list { // Read integers setP.add(Integer.valueOf(bdrv.getInt())); } bdrv.getControl(); // ] (end marker) } else { System.out.println("Unexpected label: "+label); System.exit(0); } } // Display the contents of the set 'SPrime' Iterator<Integer> iprime=setP.iterator(); System.out.print("Prime numbers={"); while(iprime.hasNext()) { Integer p=iprime.next(); System.out.print(" "+p); } System.out.println(" }"); }
© 2001-2025 Fair Isaac Corporation. All rights reserved. This documentation is the property of Fair Isaac Corporation (“FICO”). Receipt or possession of this documentation does not convey rights to disclose, reproduce, make derivative works, use, or allow others to use it except solely for internal evaluation purposes to determine whether to purchase a license to the software described in this documentation, or as otherwise set forth in a written software license agreement between you and FICO (or a FICO affiliate). Use of this documentation and the software described in it must conform strictly to the foregoing permitted uses, and no other use is permitted.