blob: 0103e7627cc52f566708fd1c5258c91c5302cbc3 [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 "util/os-info.h"
#include <stdlib.h>
#include <string.h>
#include <fstream>
#include <iostream>
#include <sstream>
#include <unistd.h>
#include <boost/algorithm/string.hpp>
#include <sys/stat.h>
#include "common/names.h"
using boost::algorithm::is_any_of;
using boost::algorithm::split;
using boost::algorithm::token_compress_on;
namespace impala {
bool OsInfo::initialized_ = false;
string OsInfo::os_distribution_ = "Unknown";
string OsInfo::os_version_ = "Unknown";
clockid_t OsInfo::fast_clock_ = CLOCK_MONOTONIC;
std::string OsInfo::clock_name_ =
"Unknown clocksource, clockid_t defaulting to CLOCK_MONOTONIC";
// CLOCK_MONOTONIC_COARSE was added in Linux 2.6.32. For now we still want to support
// older kernels by falling back to CLOCK_MONOTONIC.
#ifdef CLOCK_MONOTONIC_COARSE
#define HAVE_CLOCK_MONOTONIC_COARSE true
#else
#define HAVE_CLOCK_MONOTONIC_COARSE false
#define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC
#endif
void OsInfo::Init() {
DCHECK(!initialized_);
struct stat info;
// Read from /etc/os-release
if (stat("/etc/os-release", &info) == 0) {
ifstream os_distribution("/etc/os-release", ios::in);
string line;
while (os_distribution.good() && !os_distribution.eof()) {
getline(os_distribution, line);
vector<string> fields;
split(fields, line, is_any_of("="), token_compress_on);
if (fields[0].compare("PRETTY_NAME") == 0) {
os_distribution_ = fields[1].data();
// remove quotes around os distribution
os_distribution_.erase(
remove(os_distribution_.begin(), os_distribution_.end(), '\"'),
os_distribution_.end());
break;
}
}
if (os_distribution.is_open()) os_distribution.close();
} else if (stat("/etc/redhat-release", &info) == 0) {
// Only old distributions like centos 6, redhat 6
ifstream os_distribution("/etc/redhat-release", ios::in);
if (os_distribution.good()) getline(os_distribution, os_distribution_);
if (os_distribution.is_open()) os_distribution.close();
}
// Read from /proc/version
ifstream os_version("/proc/version", ios::in);
if (os_version.good()) getline(os_version, os_version_);
if (os_version.is_open()) os_version.close();
// Read the current clocksource to see if CLOCK_MONOTONIC is known to be fast. "tsc" is
// fast, while "xen" is slow (40 times slower than "tsc" on EC2). If CLOCK_MONOTONIC is
// known to be slow, we use CLOCK_MONOTONIC_COARSE, which uses jiffies, with a
// resolution measured in milliseconds, rather than nanoseconds.
std::ifstream clocksource_file(
"/sys/devices/system/clocksource/clocksource0/current_clocksource");
if (clocksource_file.good()) {
std::string clocksource;
clocksource_file >> clocksource;
clock_name_ = "clocksource: '" + clocksource + "', clockid_t: ";
if (HAVE_CLOCK_MONOTONIC_COARSE && clocksource != "tsc") {
clock_name_ += "CLOCK_MONOTONIC_COARSE";
fast_clock_ = CLOCK_MONOTONIC_COARSE;
} else {
clock_name_ += "CLOCK_MONOTONIC";
fast_clock_ = CLOCK_MONOTONIC;
}
}
initialized_ = true;
}
string OsInfo::DebugString() {
DCHECK(initialized_);
stringstream stream;
stream << "OS distribution: " << os_distribution_ << endl
<< "OS version: " << os_version_ << endl
<< "Clock: " << clock_name_ << endl;
return stream.str();
}
} // namespace impala