#ifndef MxNDataPort_h_seen #define MxNDataPort_h_seen // We use these AVIs #include "DistArrayDescriptor.h" #include "MxNDataHandle.h" namespace gov { namespace cca { /* $Id: MxNDataPort.h,v 1.4 2002/04/08 00:23:39 kohl Exp $ */ /** * MxN Parallel Data Redistribution Port * * Data Registry and Ready Methods * * CCA MxN Working Group */ class MxNDataPort : public virtual gov::cca::Port { public: /** * MxN Interface * * The purpose of this interface is to allow CCA components to * identify and exchange data elements among parallel, decomposed * data objects. One parallel component with "M" instances might * want to share or correlate data with another parallel component * with "N" instances. In some cases M == N, and the data mapping * is straightforward, although M and N could have different data * decompositions which would require remapping the data elements. * In other cases, N == 1, and the parallel data is collected into * a central location, such as for most visualization purposes. * When M != N, then a full "redistribution" of the parallel data * objects is required, to map each element of one data distribution * to a corresponding element in another data distribution. * * There is no implicit support for any data "munging" here, * such as spatial or temporal interpolation or units conversions. * These functions are outside the scope of MxN data exchange * and should be implemented in another interface, likely as a * "filter" service, component or port. * * As the CCA definitions for Data Objects becomes more complete, * this MxN interface should be expected to support a wide variety * of data organizations and decompositions, including both * structured and unstructured meshes. But for the purposes * of this initial interface description, the "Data Object" is * left open and unspecified. Ultimately, the MxN interface * will require sufficient information from a given Data Object * interface to be able to: * * 1. Identify the owner/location of any specific data element. * * 2. Extract and Assign the value(s) associated with a specific * data element. * * As long as all necessary information is available to support * these operations, then the MxN interface can function. Such * information includes, but may not be limited to: pointers to * actual data values, the data type(s), the dimensionality and * cardinality of any arrays, the allocated data size, leading * dimensions and boundary/ghost regions of any locally stored * subarrays, the data layout (as in Row Major or Column Major), * the element ids, coordinates, and vertex displacement of values * for an unstructured mesh, the spatial grid type and mapping, * some instantaneous temporal reference value, the units of the * data values, the processor topology, the decomposition types * along each axis for structured meshes, and the details of each * parallel instance's portion of a data distribution (logical * processor address, block or cycle size for rectangular * decompositions, and any explicit decomposition bounds or * patches). * * Note that some of the information above may be used purely for * error checking and validation purposes in the MxN interface * (e.g. spatial grid and units), but this information will be * essential for *other* support interfaces (such as interpolation * and units conversion) that must be present in any practical * implementation. * * Typical use of this interface will proceed as follows (see * interface specification below for method argument descriptions): * * Parallel components A and B "decide" to exchange parallel data. * How this happens is a mystery left up to the applications * programmer, but suffice to say that this could be done via * explicit component connections at composition time, to choose * which components / data objects should be coupled. Or this * could be arranged dynamically at run-time via some programmatic * control, given some method extensions to this MxN interface. * * To allow any sharing and exchange of parallel data, each * parallel data object must be registered with an instance of * the MxN implementation - say, an "MxN-er" (which could be a * port on a component or a system service, etc). Data objects * can be registered by any parallel component that has access * to a given MxN-er. Once all data objects have been registered, * the MxN-er can support a variety of dynamic MxN interconnections * among the parallel component instances. * * To register a data object with the MxN-er, a parallel component * must describe the data and any distributed decomposition (i.e. * who owns which pieces of it) and also make the actual data * elements themselves available for reading and/or writing as * part of subsequent MxN transfers. All of this information * about the data objects is currently encapsulated in the MxN * interface using a generic "Data" interface placeholder, while * the actual data interface is under development by the CCA Data * Working Group. The "registerData()" method takes this data * object information, along with some basic synchronization * and access mode settings, and produces an MxN data handle * for use in constructing MxN connections and transfers: * * Each A: Data Adata; * registerData( Adata, True, ReadOnly, Adhandle ); * * Each B: Data Bdata; * registerData( Bdata, False, WriteOnly, Bdhandle ); * * Once the MxN connection has been created and a transfer request * has been posted (see MxnCtrlPort.h), the data elements will * then be communicated from source to destination as each * parallel instance become "ready". The instances of A and B * must each indicate that their portion of the data object is * "ready" for the transfer, i.e. the parallel data object is * in some "consistent" state for reading or writing. The * "dataReady()" method is used to indicate this state. During * an invocation of dataReady(), (or between calls to the * non-blocking "dataReadyBegin()" and companion "dataReadyEnd()" * method), the MxN-er will process all pending transfers that * involve the given data object. (An integer flag to the * dataReady() and dataReadyBegin() methods indicates special * MxN connection and transfer functionality, such as not updating * the data objects time value ("dataReadyNoTimeUpdate") or * indicating that the data values are unchanged since the last * iteration ("dataReadyDataUnchanged"). * * All A: dataReady( Adhandle, ReadWrite, dataReadyDefault ); * * All B: dataReadyBegin( Bdhandle, ReadWrite, * dataReadyDefault ); * . . . * dataReadyEnd( Bdhandle ); * * The transfer of elements need not take place "en masse" as * a fully synchronized operation. As each "pair" of mapped * parallel instances (one from A, one from B - as specified in * the communication schedule) becomes "ready", the data elements * mapped between them can be transferred. * * Note that calls to dataReady() or dataReadyEnd() will *block* * under MxN "flow control" until ALL pending transfers involving * the given data object are completed. For "one-shot" connections * (frequency == 0) a single pending transfer will be posted for * each invocation of requestTransfer(). For "periodic" transfers * (frequency > 0), a series of pending transfers will be generated * from a single invocation of requestTransfer(); as the iteration * count or "time" associated with the given frequency elapses * (as counted by invocations of dataReady() or dataReadyBegin()), * a new transfer request is automatically posted. Calling the * requestTransfer() method again for a periodic connection will * reset the iteration count offset for triggering transfers at * the given frequency. * * More details of the methods in this interface are described * below. */ /** * AccessMode Enumerated Type * * Enumerated type for specifying the read/write access to data * objects that have been registered with the MxN system. * * Can have the values: * ReadOnly, WriteOnly and ReadWrite */ enum AccessMode { ReadOnly, WriteOnly, ReadWrite }; /** * int registerData( DistArrayDescriptor * & data, bool synch, * enum AccessMode access, mxnDataHandle &dHandle ) * * Registers a "Data Object" (whatever that is :-) with the MxN * System (a.k.a. the "MxN-er" - a generic moniker to cover the * component, port and service models :-). This makes the data * object available for "MxN parallel data redistribution," i.e. * when registered its elements can be extracted / overwritten * (see the "access" argument) with the values transferred from * another parallel distributed data object. The owner of the * data object may not want anyone to have MxN access to this * data object, so the owner has to specifically register the * object to allow this activity. * * To perform any data transfers with this data object, the MxN-er * will have to know the basic data organization and layout, and * how the local data allocation fits into the context of the * global data decomposition. It is assumed that the "Data" object * contains this decomposition information. * * @param data Input the "Data" object to be registered. * @param synch Input indicates whether the (potentially * distributed) data elements in "data" are inherently * "synchronized", i.e. the collection of decomposed * units constitute an overall global array that has * some periodic consistency as the data is computed * in parallel and then reconciled (usually this input * will be set to "True", unless it's an embarrassingly * parallel decomposition...). * @param access Input the access mode of the data object being * registered. Can be ReadOnly, WriteOnly or ReadWrite * to dictate whether the registered data object can * be read, written or both by the MxN-er. * @param dHandle Output a handle to this data object registration, * for subsequent use in unregistering the data via the * unregisterData() method. * @return execution status (0 if OK, !=0 if error) */ virtual int registerData( DistArrayDescriptor * & data, bool synch, enum AccessMode access, mxnDataHandle &dHandle ) = 0; /** * int unregisterData( mxnDataHandle dHandle ) * * Unregister a previously registered data object. This takes * the given data object "out of play" for MxN and breaks any * existing MxN connections to the data object. (It would be * "courteous" of the user to explicitly break any MxN data * connections using the releaseConn() method, but it is not * strictly necessary.) * * @param dHandle Input the handle returned by registerData(). * @return execution status (0 if OK, !=0 if error) */ virtual int unregisterData( mxnDataHandle dHandle ) = 0; /** * (Potential Method...?) * int reregisterData( mxnDataHandle dHandle, * DistArrayDescriptor *data, bool synch, * enum AccessMode access ) * * Re-register a previously registered data object. This could * invalidate existing MxN connections, depending on any changes * to the data object's registration. It is expected that any * such changes will be handled by a call to modifyConn(), else * the next requestTransfer() invocation will fail. * * @param dHandle Input the handle returned by registerData(). * @param data Input the "Data" object to be re-registered. * This re-registration allows changes in the data * object's size and any distributed decomposition. * @param synch Input the new synchronization property of the * registered data object (see registerData()). * @param access Input the new access mode of the registered data * object (see registerData()). * @return execution status (0 if OK, !=0 if error) */ /* virtual int reregisterData( mxnDataHandle dHandle, * DistArrayDescriptor *data, bool synch, * enum AccessMode access ) = 0; */ /** * int synch() * * Synchronize with all other parallel components who have * registered data with this MxN-er component. * * This is used to indicate a preliminary "ready" state for * an application component that uses the MxN-er, such that * all initial data fields have been registered for the given * component and normal execution can proceed. (This little * barrier can allow MxN coupling of components from the first * iteration and is considered generally a handy thing to have.) * * @return execution status (0 if OK, !=0 if error) */ virtual int synch() = 0; /** * dataReady*() Flag Constants * * Used to control extensible dataReady*() functionality. */ #define dataReadyDefault 0 /* dataReadyDefault is the default "business as usual" flag * setting for dataReadyFlags. */ #define dataReadyNoTimeUpdate 1 /* dataReadyNoTimeUpdate indicates that the internal iteration * count or "time" value for this data object should * NOT be incremented as part of this transfer cycle. * Setting this value allows multiple parallel data * transfers within a single iteration, as needed. */ #define dataReadyDataUnchanged 2 /* dataReadyDataUnchanged indicates that the data values associated * with this data object have not actually changed and * therefore do not need to be fully retransferred * (allows MxN caching of data values). */ /** * int dataReady( mxnDataHandle dHandle, AccessMode access, * int dataReadyFlags ) * * Set the MxN connection status to "Ready" for the data object * referred to by this MxN data handle. Any pending data transfers * that have been requested can now be executed (assuming that the * other side of the given connection is also in a "Ready" state). * The dataReady() method is a blocking call that will not return * until all pending data transfers have been processed. * * @param dHandle Input the data handle to the MxN-registered data * object that is ready for MxN data transfer. * @param access Input the access mode being activated for the * given data object. Can be ReadOnly, WriteOnly or * ReadWrite to dictate whether the data object can * now be read, written or both by the MxN-er to * execute parallel data transfers. * @param dataReadyFlags Input any extensible functionality options * to control the MxN connection & transfer handling. * (See dataReadyNoTimeUpdate & dataReadyDataUnchanged.) * @return execution status (0 if OK, !=0 if error) */ virtual int dataReady( mxnDataHandle dHandle, AccessMode access, int dataReadyFlags ) = 0; /** * int dataReadyBegin( mxnDataHandle dHandle, AccessMode access, * int dataReadyFlags ) * * Same as dataReady(), but in a Begin / End set of methods that * allow other processing while the pending data transfers are * in progress. * * Sets the MxN connection status to "Ready" for the data object * referred to by this MxN data handle. Any pending data transfers * that have been requested can now be executed (assuming that the * other side of the given connection is also in a "Ready" state). * The dataReadyBegin() method is a non-blocking call that will * return immediately, before any pending data transfers are * fully processed. * * @param dHandle Input the data handle to the MxN-registered data * object that is ready for MxN data transfer. * @param access Input the access mode being activated for the * given data object. Can be ReadOnly, WriteOnly or * ReadWrite to dictate whether the data object can * now be read, written or both by the MxN-er to * execute parallel data transfers. * @param dataReadyFlags Input any extensible functionality options * to control the MxN connection & transfer handling. * (See dataReadyNoTimeUpdate & dataReadyDataUnchanged.) * @return execution status (0 if OK, !=0 if error) */ virtual int dataReadyBegin( mxnDataHandle dHandle, AccessMode access, int dataReadyFlags ) = 0; /** * int dataReadyTest( mxnDataHandle dHandle ) * * Companion to dataReadyBegin(), tests whether all pending data * transfers have completed. * * This is a non-blocking call that returns True iff all pending * data transfers have completed. Otherwise, dataReadyTest() * returns False. * * The dataReadyTest() method does *not* change the MxN connection * status from "Ready" to "Not Ready" for the given data object. * The dataReadyEnd() method must still be called to complete * the iteration. * * @param dHandle Input the data handle to the MxN-registered data * object, as previously passed to dataReadyBegin(). * @return data transfer status (1 if completed, 0 if not, else * error) */ virtual int dataReadyTest( mxnDataHandle dHandle ) = 0; /** * int dataReadyEnd( mxnDataHandle dHandle ) * * Companion to dataReadyBegin(), waits for all pending data * transfers to complete. * * This is a blocking call, such that all pending data transfers * must complete before the dataReadyEnd() method returns. * Before returning, dataReadyEnd() un-sets the MxN connection * status from "Ready" to "Not Ready" for the given data object. * * @param dHandle Input the data handle to the MxN-registered data * object, as previously passed to dataReadyBegin(). * @return execution status (0 if OK, !=0 if error) */ virtual int dataReadyEnd( mxnDataHandle dHandle ) = 0; }; // MxNDataPort } // namespace cca } // namespace gov #endif // MxNDataPort_h_seen