blob: 199dd660ca58a23862e93109fa9827444728bf13 [file] [log] [blame]
/*
* 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 <decaf/lang/exceptions/NullPointerException.h>
#include <decaf/lang/exceptions/IllegalArgumentException.h>
#include <decaf/lang/exceptions/RuntimeException.h>
#include <decaf/util/Date.h>
#include <decaf/util/StringTokenizer.h>
#include <decaf/util/StlMap.h>
#include <decaf/util/concurrent/TimeUnit.h>
#include <decaf/util/Properties.h>
#include <apr.h>
#include <apr_errno.h>
#include <apr_env.h>
#include <apr_time.h>
#if HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_TIME_H
#include <time.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SYSCTL_H
#include <sys/sysctl.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#if defined(_HP_NAMESPACE_STD)
#include <sys/mpctl.h>
#endif
#include <cstdlib>
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<string, string> 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::setenv - ",
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<string, string>& System::getenv() {
System::sys->cachedEnvValues.clear();
StringTokenizer tokenizer("");
string key = "";
string value = "";
int tokens = 0;
std::vector<std::string> 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
std::size_t pos = 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 <windows.h>
////////////////////////////////////////////////////////////////////////////////
std::vector<std::string> System::getEnvArray() {
std::vector<std::string> 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 <crt_externs.h>
#define environ (*_NSGetEnviron())
#else
extern char** environ;
#endif
////////////////////////////////////////////////////////////////////////////////
std::vector<std::string> System::getEnvArray() {
std::vector<std::string> 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;
}