blob: f20d15ff08f2990ea6863dde5721a0037c36078b [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 "Utils.hpp"
#include <chrono>
#include <cstdio>
#include <cstdlib>
#include <iomanip>
#include <ace/INET_Addr.h>
#include <ace/OS.h>
#include <boost/asio.hpp>
#include <boost/dll/import.hpp>
#include <boost/dll/runtime_symbol_info.hpp>
namespace apache {
namespace geode {
namespace client {
std::string Utils::getEnv(const char* varName) {
std::string env;
if (const auto varValue = std::getenv(varName)) {
env = varValue;
}
return env;
}
void Utils::parseEndpointString(const char* endpoints, std::string& host,
uint16_t& port) {
std::string endpointsStr(endpoints);
LOGFINE("Parsing endpoint string [%s]", endpointsStr.c_str());
// Parse this string to get all hostnames and port numbers.
std::string endpoint;
std::string::size_type length = endpointsStr.size();
std::string::size_type pos = 0;
pos = endpointsStr.find(':', 0);
if (pos != std::string::npos) {
endpoint = endpointsStr.substr(0, pos);
pos += 1; // skip ':'
length -= (pos);
endpointsStr = endpointsStr.substr(pos, length);
} else {
host = "";
port = 0;
return;
}
// trim white spaces.
std::string::size_type wpos = endpoint.find_last_not_of(' ');
if (wpos != std::string::npos) {
endpoint.erase(wpos + 1);
wpos = endpoint.find_first_not_of(' ');
if (wpos != std::string::npos) endpoint.erase(0, wpos);
}
host = endpoint;
port = atoi(endpointsStr.c_str());
}
std::string Utils::convertHostToCanonicalForm(const char* endpoints) {
if (endpoints == nullptr) return nullptr;
std::string hostString("");
uint16_t port = 0;
std::string endpointsStr(endpoints);
std::string endpointsStr1(endpoints);
// Parse this string to get all hostnames and port numbers.
std::string endpoint;
std::string::size_type length = endpointsStr.size();
std::string::size_type pos = 0;
ACE_TCHAR hostName[256], fullName[512];
pos = endpointsStr.find(':', 0);
if (pos != std::string::npos) {
endpoint = endpointsStr.substr(0, pos);
pos += 1; // skip ':'
length -= (pos);
endpointsStr = endpointsStr.substr(pos, length);
} else {
hostString = "";
return "";
}
hostString = endpoint;
port = atoi(endpointsStr.c_str());
if (strcmp(hostString.c_str(), "localhost") == 0) {
ACE_OS::hostname(hostName, sizeof(hostName) - 1);
struct hostent* host;
host = ACE_OS::gethostbyname(hostName);
if (host) {
std::snprintf(fullName, sizeof(fullName), "%s:%d", host->h_name, port);
return fullName;
}
} else {
pos = endpointsStr1.find('.', 0);
if (pos != std::string::npos) {
ACE_INET_Addr addr(endpoints);
addr.get_host_name(hostName, 256);
std::snprintf(fullName, sizeof(fullName), "%s:%d", hostName, port);
return fullName;
}
}
return endpoints;
}
void Utils::parseEndpointNamesString(
std::string endpoints, std::unordered_set<std::string>& endpointNames) {
// Parse this string to get all hostnames and port numbers.
std::string endpoint;
std::string::size_type length = endpoints.size();
std::string::size_type pos = 0;
do {
pos = endpoints.find(',', 0);
if (pos != std::string::npos) {
endpoint = endpoints.substr(0, pos);
pos += 1; // skip ','
length -= (pos);
endpoints = endpoints.substr(pos, length);
} else {
endpoint = endpoints;
}
// trim white spaces.
std::string::size_type wpos = endpoint.find_last_not_of(' ');
if (wpos != std::string::npos) {
endpoint.erase(wpos + 1);
wpos = endpoint.find_first_not_of(' ');
if (wpos != std::string::npos) endpoint.erase(0, wpos);
endpointNames.insert(endpoint);
}
} while (pos != std::string::npos);
}
char* Utils::copyString(const char* str) {
char* resStr = nullptr;
if (str != nullptr) {
size_t strSize = strlen(str) + 1;
resStr = new char[strSize];
memcpy(resStr, str, strSize);
}
return resStr;
}
/**
* Finds, loads and keeps a copy of requested shared library. Future
* improvements should use the boost::dll::import to maintain references to
* shared libraries rather than a synchronized global structure.
*
* Uses similar options ans search patterns to the original ACE_DLL
* implementation.
*
* @param libraryName to find or load
* @return found or loaded shared library
* @throws IllegalArgumentException if library is not found or otherwise
* unloadable.
*/
const boost::dll::shared_library& getSharedLibrary(
const std::string& libraryName) {
static std::mutex sharedLibrariesMutex;
static std::unordered_map<std::string,
std::shared_ptr<boost::dll::shared_library>>
sharedLibraries;
std::lock_guard<decltype(sharedLibrariesMutex)> lock(sharedLibrariesMutex);
const auto& find = sharedLibraries.find(libraryName);
if (find == sharedLibraries.end()) {
auto path = libraryName.empty() ? boost::dll::program_location()
: boost::dll::fs::path{libraryName};
try {
return *sharedLibraries
.emplace(
libraryName,
std::make_shared<boost::dll::shared_library>(
path,
boost::dll::load_mode::rtld_global |
boost::dll::load_mode::rtld_lazy |
boost::dll::load_mode::append_decorations |
boost::dll::load_mode::search_system_folders))
.first->second;
} catch (const boost::dll::fs::system_error& e) {
throw IllegalArgumentException("cannot open library: \"" + path.string() +
"\": reason: " + e.what());
}
}
return *find->second;
}
void* Utils::getFactoryFunctionVoid(const std::string& lib,
const std::string& funcName) {
try {
const auto& sharedLibrary = getSharedLibrary(lib);
return reinterpret_cast<void*>(sharedLibrary.get<void*()>(funcName));
} catch (const boost::dll::fs::system_error&) {
std::string location =
lib.empty() ? "the application" : "library \"" + lib + "\"";
throw IllegalArgumentException("cannot find factory function " + funcName +
" in " + location);
}
}
std::string Utils::convertBytesToString(const uint8_t* bytes, size_t length,
size_t maxLength) {
if (bytes != nullptr) {
length = std::min(length, maxLength);
std::stringstream ss;
ss << std::setfill('0') << std::hex;
for (size_t i = 0; i < length; ++i) {
ss << std::setw(2) << static_cast<int>(bytes[i]);
}
return ss.str();
}
return "";
}
std::string Utils::convertBytesToString(const int8_t* bytes, size_t length,
size_t maxLength) {
return Utils::convertBytesToString(reinterpret_cast<const uint8_t*>(bytes),
length, maxLength);
}
int64_t Utils::startStatOpTime() {
return std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::steady_clock::now().time_since_epoch())
.count();
}
void Utils::updateStatOpTime(statistics::Statistics* m_regionStats,
int32_t statId, int64_t start) {
m_regionStats->incLong(statId, startStatOpTime() - start);
}
} // namespace client
} // namespace geode
} // namespace apache