Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
disk-info.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/disk-info.h"
16 
17 #include <sys/vfs.h>
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <unistd.h>
21 
22 #include <boost/algorithm/string.hpp>
23 #include <boost/algorithm/string/join.hpp>
24 #include <iostream>
25 #include <fstream>
26 #include <sstream>
27 
28 #include "util/debug-util.h"
29 
30 #include "common/names.h"
31 
32 using boost::algorithm::is_any_of;
33 using boost::algorithm::split;
34 using boost::algorithm::token_compress_on;
35 using boost::algorithm::trim;
36 using boost::algorithm::trim_right_if;
37 
38 namespace impala {
39 
41 vector<DiskInfo::Disk> DiskInfo::disks_;
42 map<dev_t, int> DiskInfo::device_id_to_disk_id_;
43 map<string, int> DiskInfo::disk_name_to_disk_id_;
45 
46 // Parses /proc/partitions to get the number of disks. A bit of looking around
47 // seems to indicate this as the best way to do this.
48 // TODO: is there not something better than this?
50  // Format of this file is:
51  // major, minor, #blocks, name
52  // We are only interesting in name which is formatted as device_name<partition #>
53  // The same device will show up multiple times for each partition (e.g. sda1, sda2).
54  ifstream partitions("/proc/partitions", ios::in);
55  while (partitions.good() && !partitions.eof()) {
56  string line;
57  getline(partitions, line);
58  trim(line);
59 
60  vector<string> fields;
61  split(fields, line, is_any_of(" "), token_compress_on);
62  if (fields.size() != 4) continue;
63  string name = fields[3];
64  if (name == "name") continue;
65 
66  // Remove the partition# from the name. e.g. sda2 --> sda
67  trim_right_if(name, is_any_of("0123456789"));
68 
69  // Create a mapping of all device ids (one per partition) to the disk id.
70  int major_dev_id = atoi(fields[0].c_str());
71  int minor_dev_id = atoi(fields[1].c_str());
72  dev_t dev = makedev(major_dev_id, minor_dev_id);
73  DCHECK(device_id_to_disk_id_.find(dev) == device_id_to_disk_id_.end());
74 
75  int disk_id = -1;
76  map<string, int>::iterator it = disk_name_to_disk_id_.find(name);
77  if (it == disk_name_to_disk_id_.end()) {
78  // First time seeing this disk
79  disk_id = disks_.size();
80  disks_.push_back(Disk(name, disk_id));
82  } else {
83  disk_id = it->second;
84  }
86  }
87 
88  if (partitions.is_open()) partitions.close();
89 
90  if (disks_.empty()) {
91  // If all else fails, return 1
92  LOG(WARNING) << "Could not determine number of disks on this machine.";
93  disks_.push_back(Disk("sda", 0));
94  return;
95  }
96 
97  // Determine if the disk is rotational or not.
98  for (int i = 0; i < disks_.size(); ++i) {
99  // We can check if it is rotational by reading:
100  // /sys/block/<device>/queue/rotational
101  // If the file is missing or has unexpected data, default to rotational.
102  stringstream ss;
103  ss << "/sys/block/" << disks_[i].name << "/queue/rotational";
104  ifstream rotational(ss.str().c_str(), ios::in);
105  if (rotational.good()) {
106  string line;
107  getline(rotational, line);
108  if (line == "0") disks_[i].is_rotational = false;
109  }
110  if (rotational.is_open()) rotational.close();
111  }
112 }
113 
115  GetDeviceNames();
116  initialized_ = true;
117 }
118 
119 int DiskInfo::disk_id(const char* path) {
120  struct stat s;
121  stat(path, &s);
122  map<dev_t, int>::iterator it = device_id_to_disk_id_.find(s.st_dev);
123  if (it == device_id_to_disk_id_.end()) return -1;
124  return it->second;
125 }
126 
128  DCHECK(initialized_);
129  stringstream stream;
130  stream << "Disk Info: " << endl;
131  stream << " Num disks " << num_disks() << ": " << endl;
132  for (int i = 0; i < disks_.size(); ++i) {
133  stream << " " << disks_[i].name
134  << " (rotational=" << (disks_[i].is_rotational ? "true" : "false") << ")\n";
135  }
136  stream << endl;
137  return stream.str();
138 }
139 
140 
141 }
string path("/usr/lib/sasl2:/usr/lib64/sasl2:/usr/local/lib/sasl2:/usr/lib/x86_64-linux-gnu/sasl2")
static bool initialized_
Definition: disk-info.h:79
static int num_disks()
Returns the number of (logical) disks on the system.
Definition: disk-info.h:38
static void Init()
Initialize DiskInfo. Just be called before any other functions.
Definition: disk-info.cc:114
static std::vector< Disk > disks_
All disks.
Definition: disk-info.h:96
static std::string DebugString()
Definition: disk-info.cc:127
static int num_datanode_dirs_
Definition: disk-info.h:104
static std::map< dev_t, int > device_id_to_disk_id_
mapping of dev_ts to disk ids
Definition: disk-info.h:99
static void GetDeviceNames()
Definition: disk-info.cc:49
string name
Definition: cpu-info.cc:50
static int disk_id(const char *path)
Definition: disk-info.cc:119
static std::map< std::string, int > disk_name_to_disk_id_
mapping of devices names to disk ids
Definition: disk-info.h:102