• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

HDFGroup / hermes / 4851036339

pending completion
4851036339

Pull #515

github

GitHub
Merge aee741046 into 87672e106
Pull Request #515: v1.0

5501 of 5501 new or added lines in 117 files covered. (100.0%)

4997 of 7299 relevant lines covered (68.46%)

6131966.73 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

70.0
/src/rpc.cc
1
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2
 * Distributed under BSD 3-Clause license.                                   *
3
 * Copyright by The HDF Group.                                               *
4
 * Copyright by the Illinois Institute of Technology.                        *
5
 * All rights reserved.                                                      *
6
 *                                                                           *
7
 * This file is part of Hermes. The full Hermes copyright notice, including  *
8
 * terms governing use, modification, and redistribution, is contained in    *
9
 * the COPYING file, which can be found at the top directory. If you do not  *
10
 * have access to the file, you may request a copy from help@hdfgroup.org.   *
11
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12

13
#include "rpc.h"
14
#include "hermes.h"
15
#include <netinet/in.h>
16
#include <sys/socket.h>
17
#include <ifaddrs.h>
18
#include <functional>
19
#include <iostream>
20
#include <fstream>
21

22
namespace hermes {
23

24
/** parse hostfile */
25
std::vector<std::string> RpcContext::ParseHostfile(const std::string &path) {
×
26
  std::vector<std::string> hosts;
×
27
  std::ifstream file(path);
×
28
  if (file.is_open()) {
×
29
    std::string line;
×
30
    while (std::getline(file, line)) {
×
31
      hshm::ConfigParse::ParseHostNameString(line, hosts);
×
32
    }
33
    file.close();
×
34
  } else {
35
    HELOG(kFatal, "Could not open the hostfile: {}", path)
×
36
  }
37
  return hosts;
×
38
}
39

40
/**
41
 * initialize host info list
42
 * Requires the MetadataManager to be initialized.
43
 * */
44
void RpcContext::InitRpcContext() {
161✔
45
  config_ = &HERMES->server_config_;
161✔
46
  mdm_ = &HERMES->mdm_;
161✔
47
  port_ = config_->rpc_.port_;
161✔
48
  mode_ = HERMES->mode_;
161✔
49
  if (hosts_.size()) { return; }
161✔
50
  // Uses hosts produced by host_names
51
  auto &hosts = config_->rpc_.host_names_;
105✔
52
  // Load hosts from hostfile
53
  if (!config_->rpc_.host_file_.empty()) {
105✔
54
    hosts = ParseHostfile(config_->rpc_.host_file_);
×
55
  }
56

57
  // Get all host info
58
  hosts_.reserve(hosts.size());
105✔
59
  for (const auto& name : hosts) {
210✔
60
    hosts_.emplace_back(name, _GetIpAddress(name));
210✔
61
  }
62

63
  // Get id of current host
64
  if (HERMES->mode_ == HermesType::kServer) {
105✔
65
    node_id_ = _FindThisHost();
28✔
66
  } else {
67
    node_id_ = mdm_->header_->node_id_;
77✔
68
  }
69
  if (node_id_ == 0 || node_id_ > (i32)hosts_.size()) {
105✔
70
    HELOG(kFatal, "Couldn't identify this host.")
×
71
  }
72
}
73

74
/** Check if we should skip an RPC and call a function locally */
75
bool RpcContext::ShouldDoLocalCall(i32 node_id) {
×
76
  switch (mode_) {
×
77
    case HermesType::kClient: {
78
      return false;
79
    }
80
    case HermesType::kServer: {
×
81
      return node_id == node_id_;
×
82
    }
83
    default: {
×
84
      HELOG(kFatal, "Invalid HermesType.")
×
85
      exit(1);
×
86
    }
87
  }
88
}
89

90
/** get RPC address */
91
std::string RpcContext::GetRpcAddress(i32 node_id, int port) {
28✔
92
  std::string result = config_->rpc_.protocol_ + "://";
28✔
93
  if (!config_->rpc_.domain_.empty()) {
28✔
94
    result += config_->rpc_.domain_ + "/";
×
95
  }
96
  std::string host_name = GetHostNameFromNodeId(node_id);
28✔
97
  result += host_name + ":" + std::to_string(port);
56✔
98
  return result;
28✔
99
}
100

101
/** Get RPC address for this node */
102
std::string RpcContext::GetMyRpcAddress() {
28✔
103
  return GetRpcAddress(node_id_, port_);
28✔
104
}
105

106
/** get host name from node ID */
107
std::string RpcContext::GetHostNameFromNodeId(i32 node_id) {
161✔
108
  // NOTE(llogan): node_id 0 is reserved as the NULL node
109
  if (node_id <= 0 || node_id > (i32)hosts_.size()) {
161✔
110
    HELOG(kFatal, "Attempted to get from node {}, which is out of "
×
111
          "the range 1-{}", node_id, hosts_.size() + 1)
112
  }
113
  u32 index = node_id - 1;
161✔
114
  return hosts_[index].hostname_;
161✔
115
}
116

117
/** get host name from node ID */
118
std::string RpcContext::GetIpAddressFromNodeId(i32 node_id) {
3,332✔
119
  // NOTE(llogan): node_id 0 is reserved as the NULL node
120
  if (node_id <= 0 || node_id > (i32)hosts_.size()) {
3,332✔
121
    HELOG(kFatal, "Attempted to get from node {}, which is out of "
×
122
          "the range 1-{}", node_id, hosts_.size() + 1)
123
  }
124
  u32 index = node_id - 1;
3,332✔
125
  return hosts_[index].ip_addr_;
3,332✔
126
}
127

128
/** Get RPC protocol */
129
std::string RpcContext::GetProtocol() {
133✔
130
  return config_->rpc_.protocol_;
133✔
131
}
132

133
/** Get the node ID of this machine according to hostfile */
134
int RpcContext::_FindThisHost() {
28✔
135
  int node_id = 1;
28✔
136
  for (HostInfo &host : hosts_) {
28✔
137
    if (_IsAddressLocal(host.ip_addr_)) {
28✔
138
      return node_id;
28✔
139
    }
140
    ++node_id;
×
141
  }
142
  HELOG(kFatal, "Could not identify this host");
×
143
  return -1;
×
144
}
145

146
/** Check if an IP address is local to this machine */
147
bool RpcContext::_IsAddressLocal(const std::string &addr) {
28✔
148
  struct ifaddrs* ifAddrList = nullptr;
28✔
149
  bool found = false;
28✔
150

151
  if (getifaddrs(&ifAddrList) == -1) {
28✔
152
    perror("getifaddrs");
×
153
    return false;
×
154
  }
155

156
  for (struct ifaddrs* ifAddr = ifAddrList;
28✔
157
       ifAddr != nullptr; ifAddr = ifAddr->ifa_next) {
112✔
158
    if (ifAddr->ifa_addr == nullptr ||
112✔
159
        ifAddr->ifa_addr->sa_family != AF_INET) {
112✔
160
      continue;
84✔
161
    }
162

163
    struct sockaddr_in* sin =
28✔
164
        reinterpret_cast<struct sockaddr_in*>(ifAddr->ifa_addr);
165
    char ipAddress[INET_ADDRSTRLEN] = {0};
28✔
166
    inet_ntop(AF_INET, &(sin->sin_addr), ipAddress, INET_ADDRSTRLEN);
28✔
167

168
    if (addr == ipAddress) {
28✔
169
      found = true;
28✔
170
      break;
28✔
171
    }
172
  }
173

174
  freeifaddrs(ifAddrList);
28✔
175
  return found;
28✔
176
}
177

178
/** Get IPv4 address from the host with "host_name" */
179
std::string RpcContext::_GetIpAddress(const std::string &host_name) {
105✔
180
  struct hostent hostname_info = {};
105✔
181
  struct hostent *hostname_result;
105✔
182
  int hostname_error = 0;
105✔
183
  char hostname_buffer[4096] = {};
105✔
184
#ifdef __APPLE__
185
  hostname_result = gethostbyname(host_name.c_str());
186
  in_addr **addr_list = (struct in_addr **)hostname_result->h_addr_list;
187
#else
188
  int gethostbyname_result =
105✔
189
      gethostbyname_r(host_name.c_str(), &hostname_info, hostname_buffer,
105✔
190
                      4096, &hostname_result, &hostname_error);
191
  if (gethostbyname_result != 0) {
105✔
192
    HELOG(kFatal, hstrerror(h_errno))
×
193
  }
194
  in_addr **addr_list = (struct in_addr **)hostname_info.h_addr_list;
105✔
195
#endif
196
  if (!addr_list[0]) {
105✔
197
    HELOG(kFatal, hstrerror(h_errno))
×
198
  }
199

200
  char ip_address[INET_ADDRSTRLEN] = {0};
105✔
201
  const char *inet_result =
105✔
202
      inet_ntop(AF_INET, addr_list[0], ip_address, INET_ADDRSTRLEN);
105✔
203
  if (!inet_result) {
105✔
204
    FailedLibraryCall("inet_ntop");
×
205
  }
206
  return ip_address;
105✔
207
}
208

209
}  // namespace hermes
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc