/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "System.h" #include #include #include #include #include #include #include #include #include #include #include #include #if HAVE_SYS_TIME_H #include #endif #if HAVE_UNISTD_H #include #endif #ifdef HAVE_TIME_H #include #endif #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_SYS_SYSCTL_H #include #endif #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_STRINGS_H #include #endif #if defined(_HP_NAMESPACE_STD) #include #endif #include using namespace std; using namespace decaf; using namespace decaf::lang; using namespace decaf::util; using namespace decaf::util::concurrent; using namespace decaf::internal; using namespace decaf::lang::exceptions; //////////////////////////////////////////////////////////////////////////////// namespace decaf { namespace lang { class SystemData { public: StlMap cachedEnvValues; AprPool aprPool; Properties systemProperties; public: SystemData() : cachedEnvValues(), aprPool(), systemProperties() {} ~SystemData() {} }; }} //////////////////////////////////////////////////////////////////////////////// SystemData* System::sys = NULL; //////////////////////////////////////////////////////////////////////////////// System::System() { } //////////////////////////////////////////////////////////////////////////////// void System::initSystem( int argc DECAF_UNUSED, char **argv DECAF_UNUSED ) { // TODO - Parse out properties specified at the Command Line level. // Create the System Data class. System::sys = new SystemData(); } //////////////////////////////////////////////////////////////////////////////// void System::shutdownSystem() { // Destroy the System Data class. delete System::sys; } //////////////////////////////////////////////////////////////////////////////// AprPool& System::getAprPool() { return System::sys->aprPool; } //////////////////////////////////////////////////////////////////////////////// void System::arraycopy( const char* src, std::size_t srcPos, char* dest, std::size_t destPos, std::size_t length ) { if( src == NULL ) { throw NullPointerException( __FILE__, __LINE__, "Given Source Pointer was null." ); } if( src == NULL ) { throw NullPointerException( __FILE__, __LINE__, "Given Source Pointer was null." ); } // Now we try and copy, could still segfault. if( src != dest ) { ::memcpy( dest + destPos, src + srcPos, length ); } else { ::memmove( dest + destPos, src + srcPos, length ); } } //////////////////////////////////////////////////////////////////////////////// void System::arraycopy( const unsigned char* src, std::size_t srcPos, unsigned char* dest, std::size_t destPos, std::size_t length ) { if( src == NULL ) { throw NullPointerException( __FILE__, __LINE__, "Given Source Pointer was null." ); } if( src == NULL ) { throw NullPointerException( __FILE__, __LINE__, "Given Source Pointer was null." ); } // Now we try and copy, could still segfault. if( src != dest ) { ::memcpy( dest + destPos, src + srcPos, length ); } else { ::memmove( dest + destPos, src + srcPos, length ); } } //////////////////////////////////////////////////////////////////////////////// void System::arraycopy( const short* src, std::size_t srcPos, short* dest, std::size_t destPos, std::size_t length ) { if( src == NULL ) { throw NullPointerException( __FILE__, __LINE__, "Given Source Pointer was null." ); } if( src == NULL ) { throw NullPointerException( __FILE__, __LINE__, "Given Source Pointer was null." ); } // Now we try and copy, could still segfault. if( src != dest ) { ::memcpy( dest + destPos, src + srcPos, length * sizeof( short ) ); } else { ::memmove( dest + destPos, src + srcPos, length * sizeof( short ) ); } } //////////////////////////////////////////////////////////////////////////////// void System::arraycopy( const int* src, std::size_t srcPos, int* dest, std::size_t destPos, std::size_t length ) { if( src == NULL ) { throw NullPointerException( __FILE__, __LINE__, "Given Source Pointer was null." ); } if( src == NULL ) { throw NullPointerException( __FILE__, __LINE__, "Given Source Pointer was null." ); } // Now we try and copy, could still segfault. if( src != dest ) { ::memcpy( dest + destPos, src + srcPos, length * sizeof( int ) ); } else { ::memmove( dest + destPos, src + srcPos, length * sizeof( int ) ); } } //////////////////////////////////////////////////////////////////////////////// void System::arraycopy( const long long* src, std::size_t srcPos, long long* dest, std::size_t destPos, std::size_t length ) { if( src == NULL ) { throw NullPointerException( __FILE__, __LINE__, "Given Source Pointer was null." ); } if( src == NULL ) { throw NullPointerException( __FILE__, __LINE__, "Given Source Pointer was null." ); } // Now we try and copy, could still segfault. if( src != dest ) { ::memcpy( dest + destPos, src + srcPos, length * sizeof( long long ) ); } else { ::memmove( dest + destPos, src + srcPos, length * sizeof( long long ) ); } } //////////////////////////////////////////////////////////////////////////////// void System::arraycopy( const float* src, std::size_t srcPos, float* dest, std::size_t destPos, std::size_t length ) { if( src == NULL ) { throw NullPointerException( __FILE__, __LINE__, "Given Source Pointer was null." ); } if( src == NULL ) { throw NullPointerException( __FILE__, __LINE__, "Given Source Pointer was null." ); } // Now we try and copy, could still segfault. if( src != dest ) { ::memcpy( dest + destPos, src + srcPos, length * sizeof( float ) ); } else { ::memmove( dest + destPos, src + srcPos, length * sizeof( float ) ); } } //////////////////////////////////////////////////////////////////////////////// void System::arraycopy( const double* src, std::size_t srcPos, double* dest, std::size_t destPos, std::size_t length ) { if( src == NULL ) { throw NullPointerException( __FILE__, __LINE__, "Given Source Pointer was null." ); } if( src == NULL ) { throw NullPointerException( __FILE__, __LINE__, "Given Source Pointer was null." ); } // Now we try and copy, could still segfault. if( src != dest ) { ::memcpy( dest + destPos, src + srcPos, length * sizeof( double ) ); } else { ::memmove( dest + destPos, src + srcPos, length * sizeof( double ) ); } } //////////////////////////////////////////////////////////////////////////////// void System::unsetenv( const std::string& name ) { apr_status_t result = APR_SUCCESS; // Clear the value, errors are thrown out as an exception result = apr_env_delete( name.c_str(), getAprPool().getAprPool() ); getAprPool().cleanup(); if( result != APR_SUCCESS ) { char buffer[256] = {0}; throw NullPointerException( __FILE__, __LINE__, "System::getenv - ", apr_strerror( result, buffer, 255 ) ); } } //////////////////////////////////////////////////////////////////////////////// std::string System::getenv( const std::string& name ) { char* value = NULL; apr_status_t result = APR_SUCCESS; // Read the value, errors are thrown out as an exception result = apr_env_get( &value, name.c_str(), getAprPool().getAprPool() ); if( result != APR_SUCCESS ) { char buffer[256] = {0}; throw NullPointerException( __FILE__, __LINE__, "System::getenv - ", apr_strerror( result, buffer, 255 ) ); } // Copy and cleanup if( value == NULL ) { return ""; } std::string envVal( value ); getAprPool().cleanup(); return value; } //////////////////////////////////////////////////////////////////////////////// void System::setenv( const std::string& name, const std::string& value ) { apr_status_t result = APR_SUCCESS; // Write the value, errors are thrown out as an exception result = apr_env_set( name.c_str(), value.c_str(), getAprPool().getAprPool() ); getAprPool().cleanup(); if( result != APR_SUCCESS ) { char buffer[256] = {0}; throw NullPointerException( __FILE__, __LINE__, "System::getenv - ", apr_strerror( result, buffer, 255 ) ); } } //////////////////////////////////////////////////////////////////////////////// long long System::currentTimeMillis() { #ifdef _WIN32 /* Number of micro-seconds between the beginning of the Windows epoch * (Jan. 1, 1601) and the Unix epoch (Jan. 1, 1970) */ static const unsigned long long DELTA_EPOCH_IN_USEC = 116444736000000000ULL; unsigned long long time = 0; ::GetSystemTimeAsFileTime( (FILETIME*)&time ); return ( time - DELTA_EPOCH_IN_USEC ) / 10000; #else struct timeval tv; gettimeofday( &tv, NULL ); return ( ( (long long)tv.tv_sec * 1000000 ) + tv.tv_usec ) / 1000; #endif } //////////////////////////////////////////////////////////////////////////////// long long System::nanoTime() { #ifdef _WIN32 LARGE_INTEGER freq, i, multiplier; long long result; if( !::QueryPerformanceFrequency( &freq ) ) { return ::GetTickCount(); } multiplier.QuadPart = freq.QuadPart / 1000000; ::QueryPerformanceCounter( &i ); result = i.QuadPart / multiplier.QuadPart; return result * 1000; #else struct timeval tv; gettimeofday( &tv, NULL ); return ( ( (long long)tv.tv_sec * 1000000 ) + tv.tv_usec ) * 1000; #endif } //////////////////////////////////////////////////////////////////////////////// const Map& System::getenv() { System::sys->cachedEnvValues.clear(); StringTokenizer tokenizer( "" ); string key = ""; string value = ""; int tokens = 0; std::vector env = getEnvArray(); for( std::size_t i = 0; i < env.size(); i++ ){ tokenizer.reset( env[i], "=" ); tokens = tokenizer.countTokens(); if( tokens == 1 ) { // special case, no value set, store empty string as value key = tokenizer.nextToken(); value = string(""); } else if( tokens > 2 ) { // special case: first equals delimits the key value, the rest are // part of the variable int pos = (int)env[i].find( "=" ); key = env[i].substr( 0, pos ); value = env[i].substr( pos + 1, string::npos ); } else if( tokens == 0 ) { // Odd case, got a string with no equals sign. throw IllegalArgumentException( __FILE__, __LINE__, "System::getenv - Invalid env string. %s", env[i].c_str() ); } else { // Normal case. key = tokenizer.nextToken(); value = tokenizer.nextToken(); } // Store the env var System::sys->cachedEnvValues.put( key, value ); } return System::sys->cachedEnvValues; } #if defined(_WIN32) #include //////////////////////////////////////////////////////////////////////////////// std::vector System::getEnvArray() { std::vector buffer; int count = 0; LPTSTR lpszVars; LPVOID lpvEnv; lpvEnv = GetEnvironmentStrings(); if( NULL == lpvEnv ){ return buffer; } lpszVars = (LPTSTR)lpvEnv; while( *lpszVars != NULL ) { count++; lpszVars += strlen(lpszVars)+1; } lpszVars = (LPTSTR)lpvEnv; int index = 0; while( *lpszVars != NULL ) { buffer.push_back( lpszVars ); lpszVars += strlen(lpszVars)+1; } FreeEnvironmentStrings( (LPTCH)lpvEnv ); return buffer; } #else #if defined(__APPLE__) #include #define environ (*_NSGetEnviron()) #else extern char** environ; #endif //////////////////////////////////////////////////////////////////////////////// std::vector System::getEnvArray() { std::vector buffer; for( int i = 0; *(environ + i); i++ ){ buffer.push_back( environ[i] ); } return buffer; } #endif //////////////////////////////////////////////////////////////////////////////// int System::availableProcessors() { int numCpus = 1; #if defined(_WIN32) SYSTEM_INFO sysInfo; ::GetSystemInfo( &sysInfo ); numCpus = sysInfo.dwNumberOfProcessors; #elif defined(__APPLE__) // derived from examples in the sysctl(3) man page from FreeBSD int mib[2]; std::size_t len; mib[0] = CTL_HW; mib[1] = HW_NCPU; len = sizeof(numCpus); sysctl(mib, 2, &numCpus, &len, NULL, 0); #elif defined(_HP_NAMESPACE_STD) numCpus = (int)mpctl(MPC_GETNUMSPUS, NULL, NULL); #else // returns number of online(_SC_NPROCESSORS_ONLN) processors, number configured(_SC_NPROCESSORS_CONF) // may be more than online numCpus = (int)sysconf( _SC_NPROCESSORS_ONLN ); #endif if( numCpus < 1 ) { numCpus = 1; } return numCpus; } //////////////////////////////////////////////////////////////////////////////// decaf::util::Properties& System::getProperties() { return System::sys->systemProperties; } //////////////////////////////////////////////////////////////////////////////// std::string System::getProperty( const std::string& key ) { if( key.empty() ) { throw IllegalArgumentException( __FILE__, __LINE__, "Cannot pass an empty key to getProperty." ); } return System::sys->systemProperties.getProperty( key, "" ); } //////////////////////////////////////////////////////////////////////////////// std::string System::getProperty( const std::string& key, const std::string& defaultValue ) { if( key.empty() ) { throw IllegalArgumentException( __FILE__, __LINE__, "Cannot pass an empty key to getProperty." ); } return System::sys->systemProperties.getProperty( key, defaultValue ); } //////////////////////////////////////////////////////////////////////////////// std::string System::setProperty( const std::string& key, const std::string& value ) { if( key.empty() ) { throw IllegalArgumentException( __FILE__, __LINE__, "Cannot pass an empty key to setProperty." ); } if( value == "" ) { return System::clearProperty( key ); } return System::sys->systemProperties.setProperty( key, value ); } //////////////////////////////////////////////////////////////////////////////// std::string System::clearProperty( const std::string& key ) { if( key.empty() ) { throw IllegalArgumentException( __FILE__, __LINE__, "Cannot pass an empty key to clearProperty." ); } std::string oldValue = System::sys->systemProperties.getProperty( key, "" ); System::sys->systemProperties.remove( key ); return oldValue; }