Initializing help system before first use

Introduction

Topics covered in this chapter:

The Mosel remote invocation library (XPRD) makes it possible to build applications requiring the Xpress technology that run from environments where Xpress is not installed—including architectures for which Xpress is not available. Relying on the Mosel Distributed Framework (see Mosel module mmjobs), this self-contained library (i.e. with no dependency on the usual Xpress libraries) provides the necessary routines to start Mosel instances either on the local machine or on remote hosts and control them in a similar way as if they were invoked through the Mosel libraries. In particular, the published functionality includes

  • redirection of standard streams (input, output and errors);
  • compiling and loading of models;
  • running and interrupting models.
In addition to these standard operations, the library supports the file handling mechanisms of mmjobs (transparent file access between instances) as well as its event signaling system (events can be exchanged between the application and running models).

Overview

Thanks to the Mosel Distributed Framework a Mosel model can start Mosel instances and use them to compile and run other models. The XPRD package implements the protocol used by the Mosel Distributed Framework such that an application using this library can perform the same general operations as a model using the mmjobs module: connect a new instance, compile models, load and run bim files, as well as access remote files and exchange events with running models. The following example shows the typical structure of a program using XPRD (for the sake of clarity error handling is not included):

{
 XPRDcontext xprd;
 XPRDmosel mosel;
 XPRDmodel model;

 /* Create an XPRD context */
 xprd=XPRDinit();

 /* Start an instance on host 'xpserver' */
 mosel=XPRDconnect(xprd, "xpserver", NULL, NULL, NULL, 0);

 /* Compile model from local source - bim file saved on remote instance */
 XPRDcompmod(mosel, "", "rmt:mymod.mos", "mymod.bim", "");

 /* Load bim file */
 model=XPRDloadmod(mosel, "mymod.bim");

 /* Run model */
 XPRDrunmod(model, "");

 /* Wait for termination of model before finishing */
 XPRDwaitevent(xprd,-1);
 printf("status: %d exit code:%d\n",
        XPRDgetstatus(model), XPRDgetexitcode(model));
 XPRDunloadmod(model);
 XPRDdisconnect(mosel);
 XPRDfinish(xprd);
}

The obvious use of XPRD is when Xpress is not installed on the host running the application: in this case one (or several) remote Mosel instance(s) can be launched on host(s) supporting Xpress. This is a requirement if the application is running on an architecture for which Xpress is not available but may also be useful if the application is executed on a machine with insufficient computational resources. In this scenario, the execution of models may be transfered to dedicated servers or even to some cloud computing facility.

XPRD can also be helpful when the models are to be run on the same host as the application calling the models. In this case, the program could of course use directly the usual Mosel libraries for its optimisation tasks and run models from the same process as the application itself. However, in certain cases it might be preferable to run the optimisation tasks in a separate process in order to preserve the application when resources required by the solution process cannot be predicted or if the models to be run are not coming from a trusted source. For example, an application using XPRD can start Mosel from a process with a limited amount of memory or CPU.

The XPRD package has no dependency on any external library and the Java version is written in pure Java (as opposed to the Mosel Java libraries that rely on native calls): as a consequence, an application using XPRD does not require any supplementary installation task and can be written in pure Java.

File managers

XPRD acts as a master model, and therefore has to process file operations requested from its remote instances (i.e. when a model opens a file using the "rmt:" driver). By default, the library handles file requests using the standard operating system routines looking for files from the process' current working directory. For example, if a remote instance asks for the file "rmt:myfile.txt", the library will look for "myfile.txt" in the current directory. In addition to accessing physical files, the I/O driver "sysfd:" is also supported by the library: typically a remote instance uses "rmt:sysfd:1" for its default output and "rmt:sysfd:2" for its default error stream. These streams are automatically routed to the corresponding local file descriptors such that output from remote instances is sent to the usual streams on the calling process.

At the time of creating a Mosel instance using function XPRDconnect it is possible to specify a file manager in order to complement or replace the default file handling mechanism. The entry point for this user-provided manager is a function of the following type:

void *fmgr(void *fctx, char *fname, int mode,
   XPRDfct_data* sync, XPRDfct_close *close, XPRDfct_skip *skip,
   char *errmsg, int msgsize);

This function is called instead of the default file manager whenever a request for opening a file is received from the corresponding instance. The first argument is the data pointer provided when creating the instance; fname is the file to open and mode its opening mode (e.g. XPRD_F_INPUT for reading). If this routine returns NULL, the file request is processed using the default procedure as described above. If the value XPRD_FMGR_ERR is returned, the request is rejected and an error message (NUL terminated) may be copied into buffer errmsg of size msgsize. Any other value is interpreted as a file descriptor pointer to be used with the provided I/O routines sync, skip and close.

The user functions sync, skip and close are used to transfer data from/to the local file and release the resources used by the file descriptor when the file is closed. Only the first function is mandatory (i.e. the others can be set to NULL). The signature of these routines is as follows:

int sync(void *fd, int buf, int bufsize);
int skip(void *fd,int nbtoskip);
int close(void *fd);

When the file is open for reading, the function sync is expected to copy into buffer buf up to bufsize bytes of data. The return value should be the number of bytes copied (0 indicating an end of file) or a negative value to report an error condition.
In the case of writing to the file, this function has to get bufsize bytes from buffer buf. The return value should be bufsize if writing is successful, any other value is interpreted as an I/O error.
The optional routine skip may be used to skip a number of bytes from a file open for reading (the function is not used on an output stream). Its return value must be positive or 0 in case of success; the special value -2 indicates the operation is not supported (in which case bytes to skip are read using the sync routine) and any other value is interpreted as an I/O error.

In the following example, the file manager my_open redirects the pseudo file "outremote" to the function outremote (that simply displays the text it receives) and keeps the default behaviour for files open for reading and through "sysfd:" (redirection to standard streams). Any other queries are rejected.

void* XPRD_RTC my_open(void *ctx, char *filename,
    int mode, XPRDfct_data* fct_data, XPRDfct_close* fct_close,
    char *msg, int msglen)
{
 if(strcmp(filename,"outremote")==0)
 {
  if((mode&(XPRD_F_READ|XPRD_F_WRITE))!=XPRD_F_WRITE)
  {
   strncpy(msg, "'outremote' is write only!", msglen);
   return XPRD_FMGR_ERR;
  }
  else
  {
   *fct_data=outremote;
   *fct_close=NULL;
   return (void*)1;
  }
 }
 else
  if((strncmp(filename,"sysfd:",6)==0)||
     ((mode&(XPRD_F_READ|XPRD_F_WRITE))==XPRD_F_READ))
   return NULL;
  else
  {
   strncpy(msg, "access denied", msglen);
   return XPRD_FMGR_ERR;
  }
}

int XPRD_RTC outremote(void *data, char *buf, int size)
{
 printf("REMOTE: %.*s", size, buf);
 return size;
}

The above manager has to be passed to XPRD at the time of creating a new instance. In the example below, the error stream of the instance is redirected to the pseudo file "outremote":

mosel=XPRDconnect(xprd, "", my_open, NULL, msg, sizeof(msg));
XPRDsetdefstream(mosel, NULL, XPRD_F_ERROR, "rmt:outremote");

© 2001-2024 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.