
Co-authored-by: Charles0429 <xiezhenjiang@gmail.com> Co-authored-by: tino247 <tino247@126.com> Co-authored-by: chaser-ch <chaser.ch@antgroup.com>
170 lines
5.0 KiB
C++
170 lines
5.0 KiB
C++
/**
|
|
* Copyright (c) 2021 OceanBase
|
|
* OceanBase CE is licensed under Mulan PubL v2.
|
|
* You can use this software according to the terms and conditions of the Mulan PubL v2.
|
|
* You may obtain a copy of Mulan PubL v2 at:
|
|
* http://license.coscl.org.cn/MulanPubL-2.0
|
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
* See the Mulan PubL v2 for more details.
|
|
*/
|
|
|
|
#ifndef OCEANBASE_UNITTEST_CLUSTER_OB_UTILS_H
|
|
#define OCEANBASE_UNITTEST_CLUSTER_OB_UTILS_H
|
|
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <gmock/gmock.h>
|
|
#include <unistd.h>
|
|
#include <sys/types.h> /* See NOTES */
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include "lib/oblog/ob_log.h"
|
|
#include "lib/oblog/ob_log_module.h"
|
|
#include "lib/utility/ob_macro_utils.h"
|
|
#include "lib/time/ob_time_utility.h"
|
|
|
|
namespace oceanbase
|
|
{
|
|
namespace unittest
|
|
{
|
|
|
|
std::string __attribute__ ((weak)) _executeShellCommand(std::string command)
|
|
{
|
|
char buffer[256];
|
|
std::string result = "";
|
|
const char * cmd = command.c_str();
|
|
FILE* pipe = popen(cmd, "r");
|
|
if (!pipe) throw std::runtime_error("popen() failed!");
|
|
try {
|
|
while (!feof(pipe))
|
|
if (fgets(buffer, 128, pipe) != NULL)
|
|
result += buffer;
|
|
} catch (...) {
|
|
pclose(pipe);
|
|
throw;
|
|
}
|
|
pclose(pipe);
|
|
return result;
|
|
}
|
|
|
|
bool __attribute__ ((weak)) _isAvailablePort(unsigned short usPort)
|
|
{
|
|
char shellCommand[256], pcPort[6];
|
|
sprintf(shellCommand, "netstat -lntu | awk '{print $4}' | grep ':' | cut -d \":\" -f 2 | sort | uniq | grep %hu", usPort);
|
|
sprintf(pcPort, "%hu", usPort);
|
|
|
|
std::string output = _executeShellCommand(std::string(shellCommand));
|
|
|
|
if(output.find(std::string(pcPort)) != std::string::npos)
|
|
return false;
|
|
else
|
|
return true;
|
|
}
|
|
|
|
int __attribute__ ((weak)) listen_occupy_port(int port, int &server_fd_ret)
|
|
{
|
|
struct sockaddr_in address;
|
|
int opt = 1;
|
|
int server_fd;
|
|
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
|
|
perror("socket failed");
|
|
return -1;
|
|
}
|
|
memset(&address, '0', sizeof(address));
|
|
|
|
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR,
|
|
&opt, sizeof(opt))) {
|
|
perror("setsockopt");
|
|
return -1;
|
|
}
|
|
address.sin_family = AF_INET;
|
|
address.sin_addr.s_addr = INADDR_ANY;
|
|
address.sin_port = htons(port);
|
|
|
|
if (bind(server_fd, (struct sockaddr *)&address,
|
|
sizeof(address))<0) {
|
|
perror("bind failed");
|
|
return -1;
|
|
}
|
|
if (listen(server_fd, 3) < 0) {
|
|
perror("listen");
|
|
return -1;
|
|
}
|
|
server_fd_ret = server_fd;
|
|
return 0;
|
|
}
|
|
|
|
void __attribute__ ((weak)) get_netport_range(int &start_port, int &end_port)
|
|
{
|
|
char *mit_network_start_port_env = getenv("mit_network_start_port");
|
|
char *mit_network_port_num_env = getenv("mit_network_port_num");
|
|
if (mit_network_start_port_env != nullptr && mit_network_port_num_env != nullptr) {
|
|
start_port = atoi(mit_network_start_port_env);
|
|
end_port = atoi(mit_network_port_num_env) + start_port;
|
|
start_port = (start_port+3) / 3 * 3;
|
|
STORAGE_LOG(INFO, "get netport from env", K(start_port), K(end_port));
|
|
} else {
|
|
//srand(oceanbase::common::ObTimeUtility::current_time());
|
|
start_port = 11000;
|
|
end_port = start_port + 100;
|
|
STORAGE_LOG(INFO, "get netport rand", K(start_port), K(end_port));
|
|
}
|
|
}
|
|
|
|
int64_t __attribute__ ((weak)) get_rpc_port(int &server_fd_ret)
|
|
{
|
|
int find_port = 0;
|
|
server_fd_ret = 0;
|
|
int server_fd = -1;
|
|
int server_fd1 = -1;
|
|
int server_fd2 = -1;
|
|
int start_port = 0;
|
|
int end_port = 0;
|
|
get_netport_range(start_port, end_port);
|
|
for (int port = start_port; port + 2 < end_port; port = port + 3) {
|
|
if (_isAvailablePort(port) && _isAvailablePort(port + 1) && _isAvailablePort(port + 2)) {
|
|
bool can_use = false;
|
|
bool can_use1 = false;
|
|
bool can_use2 = false;
|
|
can_use = (listen_occupy_port(port, server_fd) == 0);
|
|
if (can_use) {
|
|
can_use1 = (listen_occupy_port(port+1, server_fd1) == 0);
|
|
if (can_use1) {
|
|
can_use2 = (listen_occupy_port(port+2, server_fd2) == 0);
|
|
}
|
|
}
|
|
if (can_use && can_use1 && can_use2) {
|
|
find_port = port + 1;
|
|
server_fd_ret = server_fd;
|
|
close(server_fd1);
|
|
close(server_fd2);
|
|
break;
|
|
} else {
|
|
STORAGE_LOG(INFO, "find port fail continue try", K(can_use), K(can_use1), K(can_use2), K(port));
|
|
if (can_use) {
|
|
close(server_fd);
|
|
}
|
|
if (can_use1) {
|
|
close(server_fd1);
|
|
}
|
|
if (can_use2) {
|
|
close(server_fd2);
|
|
}
|
|
sleep(1);
|
|
}
|
|
}
|
|
}
|
|
STORAGE_LOG(INFO, "find port", K(find_port));
|
|
if (find_port == 0) {
|
|
STORAGE_LOG_RET(WARN, OB_ERR_UNEXPECTED, "find port fail", K(find_port));
|
|
STORAGE_LOG_RET(WARN, OB_ERR_UNEXPECTED, "net", "ss", _executeShellCommand("ss -antlp").c_str());
|
|
OB_ASSERT(false);
|
|
}
|
|
return find_port;
|
|
}
|
|
}
|
|
}
|
|
#endif
|