/*** * Framework independent implementation file for utils... * * Implement the utils component here. * * // TODO: WRITE YOUR DESCRIPTION HERE! * * @author * @version ***/ #include <iostream> #include <fstream> #include <stdcasa/record.h> #include <stdcasa/version.h> #include <utils_cmpt.h> #include <tools/utils/stdBaseInterface.h> #if ! defined(CASATOOLS) #include <tools/xerces/stdcasaXMLUtil.h> #endif #include <casa/Logging/LogIO.h> #include <casa/BasicSL/String.h> #include <casa/OS/File.h> #include <casa/OS/DOos.h> #include <tables/Tables/Table.h> #include <casa/System/Aipsrc.h> #include <casa/OS/HostInfo.h> #ifndef NO_CRASH_REPORTER #include <stdcasa/StdCasa/CrashReporter.h> #endif #include <stdlib.h> #include <signal.h> #include <string> #include <vector> #include <cstdlib> #include <casacore/casa/Quanta/UnitMap.h> #include <casatools/Config/State.h> #ifdef CASATOOLS #include <asdmstman/AsdmStMan.h> #include <toolversion.h> #endif using namespace std; using namespace casacore; using namespace casa; using namespace casacore; namespace casac { utils::utils() { myConstraints = 0; itsLog = new casacore::LogIO; } utils::~utils() { if(myConstraints) delete myConstraints; delete itsLog; } #if ! defined(CASATOOLS) // These parameter/XML processing routines are no longer needed with // CASA 6 because Cereberus is used for type checking based upon // generated JSON parameter descriptions... bool utils::verify(const ::casac::record& input, const ::casac::variant& xmldescriptor, bool throwexcept) { bool rstat(true); record *constraints(0); *itsLog << LogOrigin("utils", "verify") << LogIO::NORMAL3 << "Verifying arguments...."; switch(xmldescriptor.type()){ case variant::STRING : constraints = torecord(xmldescriptor.getString()); //std::cerr << "constraints record: "; //dumpRecord(std::cerr, *constraints); break; case variant::RECORD : constraints = new record(xmldescriptor.getRecord()); break; default : rstat = false; break; } if(rstat){ rstat = stdBaseInterface::verify(const_cast<record &>(input), *constraints, *itsLog); if(constraints) delete constraints; if(rstat){ *itsLog << LogOrigin("utils", "verify") << LogIO::NORMAL3 << "verified." << LogIO::POST; }else{ if(throwexcept){ throw(AipsError("Parameter verification failed")); } else { *itsLog << LogIO::POST; *itsLog << LogOrigin("utils", "verify") << LogIO::WARN << "Some arguments failed to verify!" << LogIO::POST; } } } //std::cerr << "return from verify is " << rstat << std::endl; return rstat; } bool utils::setconstraints(const ::casac::variant& xmldescriptor) { bool rstat(true); if(myConstraints) delete myConstraints; *itsLog << LogOrigin("utils", "setconstraints") << LogIO::NORMAL3 << "Setting constraints ..."; switch(xmldescriptor.type()){ case variant::STRING : myConstraints = torecord(xmldescriptor.getString()); // std::cerr << "constraints record: "; // dumpRecord(std::cerr, *constraints); break; case variant::RECORD : myConstraints = new record(xmldescriptor.getRecord()); break; default : rstat = false; } *itsLog << LogIO::NORMAL3 << "Constraints set." << LogIO::POST; //std::cerr << "constraints record: "; //dumpRecord(std::cerr, *myConstraints); return rstat; } bool utils::verifyparam(const ::casac::record& param) { bool rstat(true); if(myConstraints && !param.empty()){ //dumpRecord(std::cerr, param); rec_map::iterator iter = myConstraints->begin(); // We need the underlying record... /* cerr << "Constraints Record " << endl; dumpRecord(std::cerr, *myConstraints); cerr << "Param Record " << endl; dumpRecord(std::cerr, param); */ rstat = stdBaseInterface::verifyOne(const_cast<record &>(param), (*iter).second.asRecord(), *itsLog); } else { if(param.empty()){ *itsLog << LogOrigin("utils", "verifyparam") << LogIO::WARN << "parameter not set, unable to verify parameter" << LogIO::POST; }else{ *itsLog << LogOrigin("utils", "verifyparam") << LogIO::WARN << "Constraints record not set, unable to verify parameter" << LogIO::POST; } } return rstat; } ::casac::variant* utils::expandparam(const std::string& name , const ::casac::variant& value ) { ::casac::variant *rstat(0); if(myConstraints){ rec_map::iterator iter = myConstraints->begin(); // We need the underlying record... //dumpRecord(std::cerr, (*iter).second.asRecord()["parameters"].asRecord()[name].asRecord()); if((*iter).second.asRecord()["parameters"].asRecord().count(name) && (*iter).second.asRecord()["parameters"].asRecord()[name].asRecord().count("allowed")){ rstat = stdBaseInterface::expandEnum((*iter).second.asRecord()["parameters"].asRecord()[name].asRecord()["allowed"], value, *itsLog); } else{ rstat = new variant(value); } } else { rstat = new variant(casac::initialize_variant(""));; *itsLog << LogOrigin("utils", "expandparam") << LogIO::WARN << "Constraints record not set, unable to expand parameter" << LogIO::POST; } return rstat; } ::casac::record* utils::torecord(const std::string& input) { stdcasaXMLUtil xmlUtils; casac::record *rstat = new casac::record; if(!input.find("<?xml version")){ xmlUtils.toCasaRecord(*rstat, input); }else{ if(!input.find("file:///")){ Bool ok = xmlUtils.readXMLFile(*rstat, input.substr(7)); if(!ok){ *itsLog << LogIO::SEVERE << "Unable to read XML file " << input << ", unable to verify input" << LogIO::POST; } } else { *itsLog << LogIO::SEVERE << "Defaults specified are not an XML string, unable to verify input" << LogIO::POST; } } return rstat; } std::string utils::toxml(const ::casac::record& input, const bool asfile, const std::string& filename) { string rstat; stdcasaXMLUtil xmlUtils; if(asfile){ std::ofstream xmlout(filename.c_str(), ios::out); xmlUtils.fromCasaRecord(xmlout, input); rstat = filename; } else { ostringstream xmlout; xmlUtils.fromCasaRecord(xmlout, input); rstat = xmlout.str(); } return rstat; } #endif std::string utils::getrc(const std::string& rcvar) { String rstat1; if(!rcvar.length()){ rstat1 = Aipsrc::aipsRoot(); } else { if(!Aipsrc::find(rstat1, rcvar)) rstat1 = "Unknown value"; } string rstat(rstat1.c_str()); return rstat; } bool utils::removetable(const std::vector<std::string> &tablenames) { bool rstat(true); try { *itsLog << LogOrigin("utils", "removetable"); for(vector<std::string>::const_iterator iter = tablenames.begin(); iter != tablenames.end(); iter++){ String fileName(*iter); if (fileName.empty()) { *itsLog << LogIO::WARN << "Empty filename" << LogIO::POST; rstat = false; } File f(fileName); if (! f.exists()) { *itsLog << LogIO::WARN << fileName << " does not exist." << LogIO::POST; rstat = false; } // Now try and blow it away. If it's open, tabledelete won't delete it. String message; if(rstat && Table::isReadable(fileName)){ if (Table::canDeleteTable(message, fileName, true)) { Table::deleteTable(fileName, true); } else { *itsLog << LogIO::WARN << "Cannot delete file " << fileName << " because " << message << LogIO::POST; } } else { *itsLog << LogIO::WARN << "Cannot delete file " << fileName << " because it's not a table." << LogIO::POST; } } } catch (AipsError x) { *itsLog << LogIO::SEVERE << "Exception Reported: " << x.getMesg() << LogIO::POST; RETHROW(x); } return rstat; } ::casac::record *utils::tableinfo(const std::string &tablename) { Vector<Int> info = casacore::DOos::lockInfo(tablename); ::casac::record *result = new record( ); switch( info[0] ) { case 3: result->insert("lockstatus", "write"); break; case 2: result->insert("lockstatus", "read"); break; case 1: result->insert("lockstatus", "open"); break; case 0: result->insert("lockstatus", "not in use"); break; default: result->insert("lockstatus", "unknown"); } result->insert("lockpid", info[1]); result->insert("lockperm", info[2] ? true : false); return result; } std::vector<std::string> utils::lockedtables( ) { Vector<String> locks = Table::getLockedTables( ); std::vector<std::string> result; for (unsigned int x = 0; x < locks.nelements(); ++x ) { result.push_back(locks[x]); } return result; } typedef int SIZETCAST; ::casac::record *utils::hostinfo( ) { ::casac::record *result = new record( ); ::casac::record *swap = new record( ); swap->insert( "total", (SIZETCAST) HostInfo::swapTotal( ) ); swap->insert( "used", (SIZETCAST) HostInfo::swapUsed( ) ); swap->insert( "free", (SIZETCAST) HostInfo::swapFree( ) ); result->insert( "swap", swap ); ::casac::record *memory = new record( ); memory->insert( "total", (SIZETCAST) HostInfo::memoryTotal( ) ); memory->insert( "available", (SIZETCAST) HostInfo::memoryTotal(true) ); memory->insert( "used", (SIZETCAST) HostInfo::memoryUsed( ) ); memory->insert( "free", (SIZETCAST) HostInfo::memoryFree( ) ); result->insert( "memory", memory ); ::casac::record *cpus = new record( ); cpus->insert( "total", HostInfo::numCPUs( ) ); cpus->insert( "available", HostInfo::numCPUs(true) ); result->insert( "cpus", cpus ); result->insert( "endian", HostInfo::bigEndian( ) ? "big" : "little" ); result->insert( "hostname", HostInfo::hostName( ) ); result->insert( "pid", HostInfo::processID( ) ); result->insert( "seconds", HostInfo::secondsFrom1970( ) ); return result; } std::string utils::c_exception () { String lastMessage, lastStackTrace; AipsError::getLastInfo (lastMessage, lastStackTrace); String result = lastMessage + "\n" + lastStackTrace; return result; } void utils::c_exception_clear () { AipsError::clearLastInfo (); } void bogusHandler (int, siginfo_t *, void *) { // Do nothing } string utils::_crash_reporter_initialize (const string & crashDirectory, const string & crashPosterApplication, const string & crashPostingUrl, const string & logFile) { #ifndef NO_CRASH_REPORTER // *NOTE*: Not intended for casual use! string status = casa::CrashReporter::initialize(crashDirectory, crashPosterApplication, crashPostingUrl, logFile); return status; #else return "no-op"; #endif } bool utils::_trigger_segfault (int faultType) { // *NOTE*: Not intended for casual use! switch (faultType) { case 0:{ bool * p; long zero = 0; p = (bool *) zero; return * p; break; } default: case 1:{ throw exception(); break; } } return false; } // ------------------------------------------------------------ // -------------------- initialize CASAtools ------------------ static std::vector<std::string> default_data_path; static std::string python_path; #ifdef CASATOOLS // CASA 6 bool utils::initialize(const std::string &pypath, const std::vector<std::string> &default_path) { #else // CASA 5 bool utils::initialize(const std::vector<std::string> &default_path) { std::string pypath; #endif static bool initialized = false; if ( initialized ) return false; default_data_path = default_path; python_path = pypath; casatools::get_state( ).setDataPath(default_data_path); casatools::get_state( ).setPythonPath(python_path); // configure quanta/measures customizations... UnitMap::putUser( "pix", UnitVal(1.0), "pixel units" ); #ifdef CASATOOLS casa::AsdmStMan::registerClass( ); #endif initialized = true; return true; } // ------------------------------------------------------------ // -------------------- handling data path -------------------- std::vector<std::string> utils::defaultpath( ) { return default_data_path; } bool utils::setpath(const std::vector<std::string> &dirs) { casatools::get_state( ).setDataPath(dirs); return casatools::get_state( ).dataPath( ).size( ) == dirs.size( ); } std::vector<std::string> utils::getpath( ) { std::vector<std::string> result; const std::list<std::string> &path = casatools::get_state( ).dataPath( ); std::copy( path.begin( ), path.end( ), std::back_inserter(result) ); return result; } #ifdef CASATOOLS std::string utils::getpython( ) { return casatools::get_state( ).pythonPath( ); } #endif void utils::clearpath( ) { casatools::get_state( ).clearDataPath( ); } std::string utils::resolve(const std::string &subdir) { return casatools::get_state( ).resolve(subdir); } // ------------------------------------------------------------ // ------------------------------------------------------------ // -------------- handling service registry ------------------- ::casac::record *utils::registry( ) { casac::record *regrec = new casac::record; regrec->insert("uri",casatools::get_state( ).registryURI( )); return regrec; } ::casac::record *utils::services( ) { std::list<casatools::ServiceId> servs = casatools::get_state( ).services( ); casac::record *regrec = new casac::record; unsigned int count = 1; for ( std::list<casatools::ServiceId>::const_iterator it=servs.begin( ); it != servs.end( ); ++it ) { casac::record *sub = new casac::record; sub->insert("id",it->id( )); sub->insert("uri",it->uri( )); sub->insert("types",std::vector<std::string>(it->types( ).begin( ),it->types( ).end( ))); sub->insert("priority",it->priority( )); regrec->insert(std::to_string(count++),sub); } return regrec; } void utils::shutdown( ) { casatools::get_state( ).shutdown( ); // this will result in the deletion of casacore state object casacore::AppStateSource::initialize(0); } // ------------------------------------------------------------ std::vector<int> utils::version( ) { std::vector<int> result = { VersionInfo::major( ), VersionInfo::minor( ), VersionInfo::patch( ), VersionInfo::feature( ) }; return result; } std::string utils::version_desc( ) { return VersionInfo::desc( ); } std::string utils::version_variant( ) { return VersionInfo::variant( ); } std::string utils::version_info( ) { return VersionInfo::info( ); } std::string utils::version_string( ) { return VersionInfo::str( ); } bool utils::compare_version(const string& comparitor, const std::vector<int>& vec) { return VersionInfo::compare(comparitor,vec); } std::vector<int> utils::toolversion( ) { std::vector<int> result = { #ifdef CASATOOLS ToolVersionInfo::major( ), ToolVersionInfo::minor( ), ToolVersionInfo::patch( ), ToolVersionInfo::feature( ), #endif }; return result; } std::string utils::toolversion_string( ) { #ifdef CASATOOLS return ToolVersionInfo::version( ); #else return ""; #endif } } // casac namespace