src/IplPaws/PawsDataConnect.cpp

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 /***************************************************************************
00003  *
00004  * The IPPL Framework
00005  * 
00006  * This program was prepared by PSI. 
00007  * All rights in the program are reserved by PSI.
00008  * Neither PSI nor the author(s)
00009  * makes any warranty, express or implied, or assumes any liability or
00010  * responsibility for the use of this software
00011  *
00012  * Visit http://www.acl.lanl.gov/POOMS for more details
00013  *
00014  ***************************************************************************/
00015 
00016 // -*- C++ -*-
00017 /***************************************************************************
00018  *
00019  * The IPPL Framework
00020  * 
00021  *
00022  * Visit http://people.web.psi.ch/adelmann/ for more details
00023  *
00024  ***************************************************************************/
00025 
00026 #include <iostream.h>
00027 #include "IpplPaws/PawsDataConnect.h"
00028 #include "Paws/PawsApplication.h"
00029 #include "Message/Message.h"
00030 #include "Utility/IpplInfo.h"
00031 
00032 
00033 // static data members of this class
00034 PawsApplication *PawsDataConnect::PawsApp   = 0;
00035 bool             PawsDataConnect::PawsReady = false;
00036 int              PawsDataConnect::NumPawsConnect = 0;
00037 
00038 
00040 // constructor: initialize PAWS application by connecting with controller
00041 PawsDataConnect::PawsDataConnect(const char *nm, int n)
00042   : DataConnect(nm, "paws", DataSource::OUTPUT, n) {
00043 
00044   // do initialization the first time this application is started under paws
00045   if (PawsApp == 0) {
00046     PawsApp  = new PawsApplication;
00047     PawsApp->initialize(nm, Ippl::getArgc(), Ippl::getArgv(),
00048                         Ippl::myNode(), Ippl::getNodes());
00049   }
00050 
00051   // indicate we're one more object using this PawsApp
00052   if (PawsApp != 0)
00053     NumPawsConnect++;
00054 }
00055 
00056 
00058 // destructor: disconnect all data objects, and close window
00059 PawsDataConnect::~PawsDataConnect() {
00060   //Inform dbgmsg("PawsDataConnect::~PawsDataConnect", INFORM_ALL_NODES);
00061   //dbgmsg << "In PawsDataConnect destructor, wtih NumPawsConnect = ";
00062   //dbgmsg << NumPawsConnect << endl;
00063 
00064   if (PawsApp != 0) {
00065     // disconnect any remaining data objects
00066     //dbgmsg << "Calling disconnectConnections from the destructor" << endl;
00067     disconnectConnections();
00068 
00069     // and then shut down our application
00070     if (--NumPawsConnect == 0) {
00071       //dbgmsg << "Waiting at barrier before deleting PawsApplication" << endl;
00072       barrier();
00073 
00074       //dbgmsg << "Deleting the PawsApplication object ..." << endl;
00075       delete PawsApp; 
00076 
00077       PawsApp = 0;
00078       PawsReady = false;
00079     }
00080   }
00081 }
00082 
00083 
00085 // perform a "paws-aware" barrier, where we do not do a
00086 // communicate barrier, but instead do it through messages to/from
00087 // node zero in a loop that also does a poll.
00088 void PawsDataConnect::barrier() {
00089 
00090   // If there is only one node, just do a poll and exit
00091   if (Ippl::getNodes() == 1) {
00092     poll();
00093     return;
00094   }
00095 
00096   // Get to/from tags
00097   int stag = Ippl::Comm->next_tag(COMM_REDUCE_SEND_TAG, COMM_REDUCE_CYCLE);
00098   int rtag = Ippl::Comm->next_tag(COMM_REDUCE_RECV_TAG, COMM_REDUCE_CYCLE);
00099 
00100   // All nodes except node zero send to node zero
00101   if (Ippl::myNode() != 0) {
00102     // Put our node number in a message and send it to node zero
00103     Message *msg = new Message;
00104     msg->put(Ippl::myNode());
00105     Ippl::Comm->send(msg, 0, stag);
00106 
00107     // Wait for the reply, polling as we go
00108     Message *rmsg = 0;
00109     int sender = 0;
00110     while (rmsg == 0) {
00111       // Do a PAWS poll
00112 
00113       poll();
00114 
00115       // ... and then look for a message
00116 
00117       rmsg = Ippl::Comm->receive(sender, rtag);
00118     }
00119 
00120     // Get the replies node number, delete it, and we're done on this node
00121     rmsg->get(sender);
00122     if (sender != 0) {
00123       ERRORMSG("Bad reply node " << sender << " in PawsDataConnect::barrier");
00124       ERRORMSG(endl);
00125     }
00126     delete rmsg;
00127 
00128   } else {
00129 
00130     // On node zero, we wait for messages from all other nodes, while
00131     // doing polls as well.  As a sanity check, we can add all the
00132     // received node numbers, it should be == sum(n), where n = 1 ... N-1
00133     // so it should be (N-1)(N)/2
00134 
00135     int nodetotal = 0;
00136     int received = 1;           // we don't worry about ourselves
00137     while (received < Ippl::getNodes()) {
00138       // Do a PAWS poll
00139 
00140       poll();
00141 
00142       // ... and then look for a message
00143 
00144       int sender = COMM_ANY_NODE;
00145       Message *msg = Ippl::Comm->receive(sender, stag);
00146       while (msg != 0) {
00147         // We did receive a message, so get the sender's node number,
00148         // make sure it is correct, and add it in
00149         int s;
00150         msg->get(s);
00151         if (s != sender) {
00152           ERRORMSG("Bad sender's node " << s << " (should be " << sender);
00153           ERRORMSG(") in PawsDataConnect::barrier" << endl);
00154         }
00155         delete msg;
00156         msg = 0;
00157         nodetotal += s;
00158         received += 1;
00159 
00160         // Look for another message, if we still need more
00161         if (received < Ippl::getNodes()) {
00162           sender = COMM_ANY_NODE;
00163           msg = Ippl::Comm->receive(sender, stag);
00164         }
00165       }
00166     }
00167 
00168     // Sanity check
00169     if (nodetotal != (Ippl::getNodes() * (Ippl::getNodes()-1))/2) {
00170       ERRORMSG("Not all nodes reported properly in PawsDataConnect::barrier");
00171       ERRORMSG(" (nodetotal is " << nodetotal << ")" << endl);
00172     }
00173 
00174     // Now, send a reply back to all the others
00175     Message *rmsg = new Message;
00176     rmsg->put(0);
00177     Ippl::Comm->broadcast_others(rmsg, rtag);
00178   }
00179 }
00180 
00181 
00183 // perform a poll 
00184 void PawsDataConnect::poll() {
00185   if (PawsApp != 0)
00186     PawsApp->poll();
00187 }
00188 
00190 // perform a ready
00191 void PawsDataConnect::ready() {
00192   if (PawsApp != 0)
00193     PawsApp->ready();
00194 }
00195 
00196 
00198 // are we currently connected to a receiver?  The base-class default
00199 // behavior for this is to indicate that we're not connected.
00200 bool PawsDataConnect::connected() const {
00201   return (PawsApp != 0);
00202 }
00203 
00204 
00205 /***************************************************************************
00206  * $RCSfile: PawsDataConnect.cpp,v $   $Author: adelmann $
00207  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:32 $
00208  * IPPL_VERSION_ID: $Id: PawsDataConnect.cpp,v 1.1.1.1 2003/01/23 07:40:32 adelmann Exp $ 
00209  ***************************************************************************/

Generated on Mon Jan 16 13:23:49 2006 for IPPL by  doxygen 1.4.6