#include "xios_spl.hpp" #include "cxios.hpp" #include "client.hpp" #include "server.hpp" #include "xml_parser.hpp" #include #include "mpi.hpp" #include "memory.hpp" #include #include "memtrack.hpp" #include "registry.hpp" namespace xios { string CXios::rootFile="./iodef.xml" ; string CXios::xiosCodeId="xios.x" ; string CXios::clientFile="./xios_client"; string CXios::serverFile="./xios_server"; bool CXios::isClient ; bool CXios::isServer ; MPI_Comm CXios::globalComm ; bool CXios::usingOasis ; bool CXios::usingServer = false; double CXios::bufferSizeFactor = 1.0; const double CXios::defaultBufferSizeFactor = 1.0; StdSize CXios::minBufferSize = 1024 * sizeof(double); bool CXios::printLogs2Files; bool CXios::isOptPerformance = true; CRegistry* CXios::globalRegistry = 0; //! Parse configuration file and create some objects from it void CXios::initialize() { set_new_handler(noMemory); #pragma omp critical { parseFile(rootFile); } parseXiosConfig(); } /*! \brief Parse xios part of configuration file (.iodef.xml) Both client and server need information returned from this function */ void CXios::parseXiosConfig() { usingOasis=getin("using_oasis",false) ; usingServer=getin("using_server",false) ; info.setLevel(getin("info_level",0)) ; report.setLevel(getin("info_level",50)); printLogs2Files=getin("print_file",false); StdString bufMemory("memory"); StdString bufPerformance("performance"); StdString bufOpt = getin("optimal_buffer_size", bufPerformance); std::transform(bufOpt.begin(), bufOpt.end(), bufOpt.begin(), ::tolower); if (0 == bufOpt.compare(bufMemory)) isOptPerformance = false; else if (0 != bufOpt.compare(bufPerformance)) { ERROR("CXios::parseXiosConfig()", << "optimal_buffer_size must be memory or performance "<< endl ); } bufferSizeFactor = getin("buffer_size_factor", defaultBufferSizeFactor); minBufferSize = getin("min_buffer_size", 1024 * sizeof(double)); int num_ep; if(isClient) { num_ep = omp_get_num_threads(); printf("Client %d: num_ep = %d\n", omp_get_thread_num(), num_ep); } if(isServer) { num_ep = omp_get_num_threads(); printf("Server %d: num_ep = %d\n", omp_get_thread_num(), num_ep); } MPI_Info info; #pragma omp master { MPI_Comm *ep_comm; MPI_Comm_create_endpoints(MPI_COMM_WORLD, num_ep, info, ep_comm); // servers should reach here too. passage = ep_comm; } #pragma omp barrier globalComm = passage[omp_get_thread_num()]; int tmp_rank; MPI_Comm_rank(globalComm, &tmp_rank); if(isClient) printf("client thread %d/%d\n", omp_get_thread_num(), tmp_rank); if(isServer) printf("server thread %d/%d\n", omp_get_thread_num(), tmp_rank); } /*! Initialize client \param [in] codeId identity of context \param [in] localComm local communicator \param [in/out] returnComm communicator corresponding to group of client with same codeId */ void CXios::initClientSide(const string& codeId, MPI_Comm& localComm, MPI_Comm& returnComm) { isClient = true; initialize() ; CClient::initialize(codeId,localComm,returnComm) ; if (CClient::getRank()==0) globalRegistry = new CRegistry(returnComm) ; // If there are no server processes then we are in attached mode // and the clients are also servers isServer = !usingServer; printf("CXios::initClientSide OK, printLogs2Files = %d\n", printLogs2Files); if (printLogs2Files) { CClient::openInfoStream(clientFile); CClient::openErrorStream(clientFile); } else { CClient::openInfoStream(); CClient::openErrorStream(); } } void CXios::clientFinalize(void) { CClient::finalize() ; if (CClient::getRank()==0) { info(80)<<"Write data base Registry"<toString()<toFile("xios_registry.bin") ; delete globalRegistry ; } CClient::closeInfoStream(); #ifdef XIOS_MEMTRACK MemTrack::TrackListMemoryUsage() ; MemTrack::TrackDumpBlocks(); #endif } //! Init server by parsing only xios part of config file void CXios::initServer() { int initialized; MPI_Initialized(&initialized); if (initialized) CServer::is_MPI_Initialized=true ; else CServer::is_MPI_Initialized=false ; if(!CServer::is_MPI_Initialized) { MPI_Init(NULL, NULL); } set_new_handler(noMemory); std::set parseList; parseList.insert("xios"); xml::CXMLParser::ParseFile(rootFile, parseList); parseXiosConfig(); } //! Initialize server then put it into listening state void CXios::initServerSide(void) { isClient = false; isServer = true; initServer(); // Initialize all aspects MPI CServer::initialize(); if (CServer::getRank()==0) globalRegistry = new CRegistry(CServer::intraComm) ; if (printLogs2Files) { CServer::openInfoStream(serverFile); CServer::openErrorStream(serverFile); } else { CServer::openInfoStream(); CServer::openErrorStream(); } // Enter the loop to listen message from Client CServer::eventLoop(); // Finalize if (CServer::getRank()==0) { info(80)<<"Write data base Registry"<toString()<toFile("xios_registry.bin") ; delete globalRegistry ; } CServer::finalize(); CServer::closeInfoStream(); } //! Parse configuration file void CXios::parseFile(const string& filename) { xml::CXMLParser::ParseFile(filename); } //! Set using server void CXios::setUsingServer() { usingServer = true; } //! Unset using server void CXios::setNotUsingServer() { usingServer = false; } }