Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
os-util.cc
Go to the documentation of this file.
1 // Copyright 2012 Cloudera Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "util/os-util.h"
16 
17 #include <unistd.h>
18 #include <fstream>
19 #include <sstream>
20 #include <boost/filesystem.hpp>
21 #include <boost/algorithm/string.hpp>
22 #include <gutil/strings/substitute.h>
23 
24 #include "util/error-util.h"
25 #include "util/string-parser.h"
26 
27 #include "common/names.h"
28 
29 using boost::filesystem::exists;
30 using boost::algorithm::is_any_of;
31 using boost::algorithm::token_compress_on;
32 using boost::algorithm::split;
33 using namespace impala;
34 using namespace strings;
35 
36 // Ensure that Impala compiles on earlier kernels. If the target kernel does not support
37 // _SC_CLK_TCK, sysconf(_SC_CLK_TCK) will return -1.
38 #ifndef _SC_CLK_TCK
39 #define _SC_CLK_TCK 2
40 #endif
41 
42 static const int64_t TICKS_PER_SEC = sysconf(_SC_CLK_TCK);
43 
44 // Offsets into the ../stat file array of per-thread statistics
45 static const int64_t USER_TICKS = 13;
46 static const int64_t KERNEL_TICKS = 14;
47 static const int64_t IO_WAIT = 41;
48 
49 // Largest offset we are interested in, to check we get a well formed stat file.
50 static const int64_t MAX_OFFSET = IO_WAIT;
51 
53  DCHECK(stats != NULL);
54  if (TICKS_PER_SEC <= 0) return Status("ThreadStats not supported");
55 
56  stringstream proc_path;
57  proc_path << "/proc/self/task/" << tid << "/stat";
58  if (!exists(proc_path.str())) return Status("Thread path does not exist");
59 
60  ifstream proc_file(proc_path.str().c_str());
61  if (!proc_file.is_open()) return Status("Could not open ifstream");
62 
63  string buffer((std::istreambuf_iterator<char>(proc_file)),
64  std::istreambuf_iterator<char>());
65 
66  vector<string> splits;
67  split(splits, buffer, is_any_of(" "), token_compress_on);
68  if (splits.size() < MAX_OFFSET) return Status("Unrecognised /proc format");
69 
70  StringParser::ParseResult parse_result;
71  int64_t tmp = StringParser::StringToInt<int64_t>(splits[USER_TICKS].c_str(),
72  splits[USER_TICKS].size(), &parse_result);
73  if (parse_result == StringParser::PARSE_SUCCESS) {
74  stats->user_ns = tmp * (1e9 / TICKS_PER_SEC);
75  }
76 
77  tmp = StringParser::StringToInt<int64_t>(splits[KERNEL_TICKS].c_str(),
78  splits[KERNEL_TICKS].size(), &parse_result);
79  if (parse_result == StringParser::PARSE_SUCCESS) {
80  stats->kernel_ns = tmp * (1e9 / TICKS_PER_SEC);
81  }
82 
83  tmp = StringParser::StringToInt<int64_t>(splits[IO_WAIT].c_str(),
84  splits[IO_WAIT].size(), &parse_result);
85  if (parse_result == StringParser::PARSE_SUCCESS) {
86  stats->iowait_ns = tmp * (1e9 / TICKS_PER_SEC);
87  }
88 
89  return Status::OK;
90 }
91 
92 bool impala::RunShellProcess(const string& cmd, string* msg) {
93  DCHECK(msg != NULL);
94  FILE* fp = popen(cmd.c_str(), "r");
95  if (fp == NULL) {
96  *msg = Substitute("Failed to execute shell cmd: '$0', error was: $1", cmd,
97  GetStrErrMsg());
98  return false;
99  }
100  // Read the first 1024 bytes of any output before pclose() so we have some idea of what
101  // happened on failure.
102  char buf[1024];
103  size_t len = fread(buf, 1, 1024, fp);
104  string output;
105  output.assign(buf, len);
106 
107  // pclose() returns an encoded form of the sub-process' exit code.
108  int status = pclose(fp);
109  if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
110  *msg = output;
111  return true;
112  }
113 
114  *msg = Substitute("Shell cmd: '$0' exited with an error: '$1'. Output was: '$2'", cmd,
115  GetStrErrMsg(), output);
116  return false;
117 }
int64_t kernel_ns
Definition: os-util.h:29
bool RunShellProcess(const std::string &cmd, std::string *msg)
static const int64_t IO_WAIT
Definition: os-util.cc:47
int64_t user_ns
Definition: os-util.h:28
#define _SC_CLK_TCK
Definition: os-util.cc:39
static const int64_t USER_TICKS
Definition: os-util.cc:45
static const int64_t TICKS_PER_SEC
Definition: os-util.cc:42
string GetStrErrMsg()
Definition: error-util.cc:30
static const int64_t KERNEL_TICKS
Definition: os-util.cc:46
Container struct for statistics read from the /proc filesystem for a thread.
Definition: os-util.h:27
Status GetThreadStats(int64_t tid, ThreadStats *stats)
Definition: os-util.cc:52
static const int64_t MAX_OFFSET
Definition: os-util.cc:50
static const Status OK
Definition: status.h:87
int64_t iowait_ns
Definition: os-util.h:30