 f8c5c2647f
			
		
	
	f8c5c2647f
	
	
	
		
			
			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
 |