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 files 00027 #include "DataSource/DataSource.h" 00028 #include "DataSource/DataSourceObject.h" 00029 #include "DataSource/DataConnect.h" 00030 #include "DataSource/DataConnectCreator.h" 00031 #include "Utility/IpplInfo.h" 00032 00033 00035 // constructor 00036 DataSource::DataSource() { 00037 // nothing to do 00038 } 00039 00040 00042 // destructor 00043 DataSource::~DataSource() { 00044 //Inform dbgmsg("DataSource::~DataSource", INFORM_ALL_NODES); 00045 //dbgmsg << "Calling disconnect() from DataSource destructor." << endl; 00046 00047 // disconnect from all existing connections, if we still have any 00048 disconnect(); 00049 } 00050 00051 00053 // find the first DataSourceObject which is connected to the given DataConnect, 00054 // and return it; otherwise, return 0 00055 DataSourceObject *DataSource::findDataSourceObject(DataConnect *dc) const { 00056 container_t::const_iterator a = ConnectionList.begin(); 00057 for ( ; a != ConnectionList.end(); ++a) 00058 if (dc == (*a)->getConnection()) 00059 return (*a); 00060 00061 // if we're here, we're not connected 00062 return 0; 00063 } 00064 00065 00067 // Are we connected to the given DataConnect? If not specified, just return 00068 // whether we're connected to anything. 00069 bool DataSource::connected(DataConnect *dataconn) const { 00070 if (dataconn == 0) 00071 return ( ! ConnectionList.empty() ); 00072 else 00073 return (findDataSourceObject(dataconn) != 0); 00074 } 00075 00076 00078 // Register an object as something that can be a source of data. Return 00079 // success. Arguments = name of item, connection to use, and type of 00080 // connection (INPUT, OUTPUT, or BOTH). If the connection 00081 // has not been created yet (e.g., it is NULL), create a new default 00082 // connection (or use the existing default one). Return the connection. 00083 DataConnect *DataSource::connect(const char *nm,DataConnect *dataconn,int tm) { 00084 //Inform dbgmsg("DataSource::connect", INFORM_ALL_NODES); 00085 //dbgmsg << "Connecting '" << nm << "'" << endl; 00086 //if (dataconn != 0) 00087 // dbgmsg << " to '" << dataconn->name() << "'"; 00088 //dbgmsg << endl; 00089 00090 // figure out which connection to use ... if none given, we must get a 00091 // new one 00092 if (dataconn == 0) { 00093 //dbgmsg << "Creating new connection ..." << endl; 00094 dataconn = DataConnectCreator::create(); 00095 } 00096 00097 // make sure we're not already connected to this object 00098 if (connected(dataconn)) { 00099 ERRORMSG("Cannot connect '" << nm << "' to the same agency twice." <<endl); 00100 ERRORMSG("dataconn = " << (void *)dataconn << endl); 00101 return 0; 00102 } 00103 00104 // set the transfer method properly, if we are requested to use the default 00105 if (tm == DataSource::DEFAULT) 00106 tm = dataconn->getDefaultTransferMethod(); 00107 00108 // OK, connect away ... create new DataSourceObject, which establishes 00109 // the connection. If we fail to connect, delete the created Obj 00110 DataSourceObject *dso = createDataSourceObject(nm, dataconn, tm); 00111 if (dso != 0 && !connect(dso)) { 00112 delete dso; 00113 return 0; 00114 } 00115 00116 // if we're here, everything was ok ... return the connection we used 00117 return dataconn; 00118 } 00119 00120 00122 // Register the given DataSourceObject directly. This is simpler than 00123 // the above version of connect, since the DataSourceObject has already 00124 // been created. It can be used to register most any type of connection, 00125 // even one using DataConnect objects that are not part of IPPL itself. 00126 // Return success. 00127 bool DataSource::connect(DataSourceObject *dso) { 00128 00129 // make sure the connection is OK 00130 if (dso != 0 && dso->connected() && dso->getSource() == this) { 00131 ConnectionList.push_back(dso); 00132 dso->getConnection()->checkin(this); 00133 return true; 00134 } 00135 00136 // if we're here, there was a problem 00137 return false; 00138 } 00139 00140 00142 // Disconnect an object from the given receiver. Return success. 00143 bool DataSource::disconnect(DataConnect *dataconn) { 00144 //Inform dbgmsg("DataSource::disconnect", INFORM_ALL_NODES); 00145 //dbgmsg << "Disconnecting source from connection(s) '"; 00146 //dbgmsg << (dataconn != 0 ? dataconn->name() : "(all)")<< "' ..." << endl; 00147 00148 container_t::iterator a = ConnectionList.begin(); 00149 for ( ; a != ConnectionList.end(); ++a) { 00150 DataConnect *dc = (*a)->getConnection(); 00151 if (dataconn == 0 || dataconn == dc) { 00152 //dbgmsg << "Calling checkout from the DataSource ..." << endl; 00153 dc->checkout(this, false); 00154 //dbgmsg << "Deleting DSO '" << (*a)->name() << "' ..." << endl; 00155 delete (*a); 00156 if (dataconn == dc) { 00157 ConnectionList.erase(a); 00158 return true; 00159 } 00160 } 00161 } 00162 00163 // if we've removed all, we can erase all 00164 if (dataconn == 0 && ConnectionList.size() > 0) { 00165 //dbgmsg<<"Erasing all " << ConnectionList.size() << " DSO's ..." << endl; 00166 ConnectionList.erase(ConnectionList.begin(), ConnectionList.end()); 00167 } 00168 00169 return (dataconn == 0); 00170 } 00171 00172 00174 // Update the object, that is, make sure the receiver of the data has a 00175 // current and consistent snapshot of the current state. Return success. 00176 bool DataSource::updateConnection(DataConnect *dataconn) { 00177 container_t::iterator a = ConnectionList.begin(); 00178 for ( ; a != ConnectionList.end(); ++a) { 00179 if (dataconn == 0) 00180 (*a)->update(); 00181 else if (dataconn == (*a)->getConnection()) 00182 return (*a)->update(); 00183 } 00184 00185 // if we're here, we were successful only if we tried to disconnect all 00186 return (dataconn == 0); 00187 } 00188 00189 00191 // Indicate to the receiver that we're allowing them time to manipulate the 00192 // data (e.g., for a viz program, to rotate it, change representation, etc.) 00193 // This should only return when the manipulation is done. For some cases, 00194 // this will be a no-op. 00195 void DataSource::interact(DataConnect *dataconn) { 00196 container_t::iterator a = ConnectionList.begin(); 00197 for ( ; a != ConnectionList.end(); ++a) { 00198 if (dataconn == 0 || dataconn == (*a)->getConnection()) 00199 (*a)->interact(); 00200 } 00201 } 00202 00203 00205 // Pass on a string to the connection, most likely to give it a 00206 // command to do some action. Similar to the above interact, except 00207 // the request for interaction involves the given string 00208 void DataSource::interact(const char *str, DataConnect *dataconn) { 00209 container_t::iterator a = ConnectionList.begin(); 00210 for ( ; a != ConnectionList.end(); ++a) { 00211 if (dataconn == 0 || dataconn == (*a)->getConnection()) 00212 (*a)->interact(str); 00213 } 00214 } 00215 00216 00217 /*************************************************************************** 00218 * $RCSfile: DataSource.cpp,v $ $Author: adelmann $ 00219 * $Revision: 1.1.1.1 $ $Date: 2003/01/23 07:40:25 $ 00220 * IPPL_VERSION_ID: $Id: DataSource.cpp,v 1.1.1.1 2003/01/23 07:40:25 adelmann Exp $ 00221 ***************************************************************************/