CB-423 Connection search on local host improvements (docker)

This commit is contained in:
Serge Rider
2020-10-13 17:11:16 +03:00
parent ffcfd1f39b
commit 60baff3f93
9 changed files with 145 additions and 30 deletions
+4
View File
@@ -1,4 +1,8 @@
#!/bin/bash
# Detect host machine IP Address (we need this when run in docker container)
export CB_LOCAL_HOST_ADDR=$(ifconfig | grep -E "([0-9]{1,3}\.){3}[0-9]{1,3}" | grep -v 127.0.0.1 | awk '{ print $2 }' | cut -f2 -d: | head -n1)
launcherJar=( server/plugins/org.eclipse.equinox.launcher*.jar )
echo "Starting Cloudbeaver Server"
@@ -83,6 +83,7 @@ type ServerConfig {
supportsConnectionBrowser: Boolean
supportsWorkspaces: Boolean
sessionExpireTime: Int
localHostAddress: String
configurationMode: Boolean
developmentMode: Boolean
@@ -92,6 +92,11 @@ public class WebServerConfig {
return application.getMaxSessionIdleTime();
}
@Property
public String getLocalHostAddress() {
return application.getLocalHostAddress();
}
@Property
public WebServerLanguage[] getSupportedLanguages() {
List<PlatformLanguageDescriptor> langs = PlatformLanguageRegistry.getInstance().getLanguages();
@@ -46,10 +46,11 @@ import org.jkiss.utils.CommonUtils;
import org.jkiss.utils.StandardConstants;
import java.io.*;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.*;
/**
* This class controls all aspects of the application's execution
@@ -93,6 +94,8 @@ public class CBApplication extends BaseApplicationImpl {
private boolean develMode = false;
private boolean configurationMode = false;
private String localHostAddress;
private final List<InetAddress> localInetAddresses = new ArrayList<>();
public CBApplication() {
}
@@ -181,6 +184,15 @@ public class CBApplication extends BaseApplicationImpl {
configurationMode = CommonUtils.isEmpty(serverName);
//|| CommonUtils.isEmpty(databaseConfiguration.getUser()) || CommonUtils.isEmpty(databaseConfiguration.getPassword());
// Determine address for local host
localHostAddress = System.getenv(CBConstants.VAR_CB_LOCAL_HOST_ADDR);
if (CommonUtils.isEmpty(localHostAddress)) {
localHostAddress = System.getProperty(CBConstants.VAR_CB_LOCAL_HOST_ADDR);
}
if (CommonUtils.isEmpty(localHostAddress) || "127.0.0.1".equals(localHostAddress) || "::0".equals(localHostAddress)) {
localHostAddress = "localhost";
}
final Runtime runtime = Runtime.getRuntime();
Location instanceLoc = Platform.getInstanceLocation();
@@ -222,6 +234,13 @@ public class CBApplication extends BaseApplicationImpl {
if (configurationMode) {
log.debug("\tServer is in configuration mode!");
}
{
log.debug("\tLocal host addresses:");
determineLocalAddresses();
for (InetAddress ia : localInetAddresses) {
log.debug("\t\t" + ia.getHostAddress() + " (" + ia.getCanonicalHostName() + ")");
}
}
{
try {
@@ -248,6 +267,33 @@ public class CBApplication extends BaseApplicationImpl {
return null;
}
private void determineLocalAddresses() {
try {
// InetAddress localHost = InetAddress.getLocalHost();
// InetAddress[] allMyIps = InetAddress.getAllByName(localHost.getCanonicalHostName());
// for (InetAddress addr : allMyIps) {
// System.out.println("Local addr: " + addr);
// }
boolean hasLoopbackAddress = false;
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface intf = en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
InetAddress localInetAddress = enumIpAddr.nextElement();
boolean loopbackAddress = localInetAddress.isLoopbackAddress();
if (loopbackAddress ? !hasLoopbackAddress : !localInetAddress.isLinkLocalAddress()) {
if (loopbackAddress) {
hasLoopbackAddress = true;
}
localInetAddresses.add(localInetAddress);
}
}
}
} catch (Exception e) {
log.error(e);
}
}
@NotNull
private File getRuntimeConfigFile() {
return new File(getDataDirectory(false), CBConstants.RUNTIME_CONFIG_FILE_NAME);
@@ -403,6 +449,23 @@ public class CBApplication extends BaseApplicationImpl {
return configurationMode;
}
public String getLocalHostAddress() {
return localHostAddress;
}
public boolean isLocalInetAddress(String hostName) {
for (InetAddress addr : localInetAddresses) {
if (addr.getHostAddress().equals(hostName)) {
return true;
}
}
return false;
}
public List<InetAddress> getLocalInetAddresses() {
return localInetAddresses;
}
public synchronized void finishConfiguration(
String newServerName,
String adminName,
@@ -65,4 +65,7 @@ public class CBConstants {
public static final String DEFAUL_APP_ANONYMOUS_ROLE_NAME = "user";
public static final String VAR_CB_LOCAL_HOST_ADDR = "CB_LOCAL_HOST_ADDR";
}
@@ -81,7 +81,6 @@ public class CBPlatform extends BasePlatformImpl {
private WebSessionManager sessionManager;
private final List<DBPDriver> applicableDrivers = new ArrayList<>();
public static CBPlatform getInstance() {
if (instance == null) {
synchronized (CBPlatform.class) {
@@ -20,18 +20,28 @@ import java.util.ArrayList;
import java.util.List;
public class AdminConnectionSearchInfo {
private final String host;
private final String displayName;
private final String hostAddr;
private final int port;
private List<String> possibleDrivers = new ArrayList<>();
private String defaultDriver;
public AdminConnectionSearchInfo(String host, int driverPort) {
this.host = host;
public AdminConnectionSearchInfo(String displayName, String hostAddr, int driverPort) {
this.displayName = displayName;
this.hostAddr = hostAddr;
this.port = driverPort;
}
public String getDisplayName() {
return displayName;
}
public String getHostAddr() {
return hostAddr;
}
public String getHost() {
return host;
return hostAddr;
}
public int getPort() {
@@ -20,14 +20,13 @@ import io.cloudbeaver.WebServiceUtils;
import io.cloudbeaver.model.session.WebSession;
import io.cloudbeaver.server.CBPlatform;
import io.cloudbeaver.service.admin.AdminConnectionSearchInfo;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.model.connection.DBPDriver;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.runtime.DBRRunnableWithProgress;
import org.jkiss.dbeaver.registry.DataSourceRegistry;
import org.jkiss.utils.CommonUtils;
import java.lang.reflect.InvocationTargetException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
@@ -44,7 +43,7 @@ public class ConnectionSearcher implements DBRRunnableWithProgress {
private final WebSession webSession;
private final String[] hostNames;
private final DataSourceRegistry tempRegistry;
private List<AdminConnectionSearchInfo> foundConnections = new ArrayList<>();
private final List<AdminConnectionSearchInfo> foundConnections = new ArrayList<>();
private List<DBPDriver> availableDrivers = new ArrayList<>();
public ConnectionSearcher(WebSession webSession, String[] hostNames) {
@@ -53,47 +52,83 @@ public class ConnectionSearcher implements DBRRunnableWithProgress {
CBPlatform platform = CBPlatform.getInstance();
this.tempRegistry = new DataSourceRegistry(platform, platform.getWorkspace().getActiveProject());
availableDrivers.addAll(CBPlatform.getInstance().getApplicableDrivers());
this.availableDrivers.addAll(CBPlatform.getInstance().getApplicableDrivers());
}
public List<AdminConnectionSearchInfo> getFoundConnections() {
return foundConnections;
synchronized (foundConnections) {
return new ArrayList<>(foundConnections);
}
}
@Override
public void run(DBRProgressMonitor monitor) throws InvocationTargetException {
monitor.beginTask("Search connections", hostNames.length * availableDrivers.size());
public void run(DBRProgressMonitor monitor) {
List<String> finalHostNames = new ArrayList<>();
Map<String, String> localHostNames = new HashMap<>();
for (String hostName : hostNames) {
monitor.subTask("Search connections on '" + hostName + "'");
if (hostName.equals("localhost") || hostName.equals("local") || hostName.equals("127.0.0.1")) {
for (InetAddress addr : CBPlatform.getInstance().getApplication().getLocalInetAddresses()) {
String localHostAddress = addr.getHostAddress();
finalHostNames.add(localHostAddress);
localHostNames.put(localHostAddress, hostName);
}
} else {
finalHostNames.add(hostName);
}
}
monitor.beginTask("Search connections", finalHostNames.size());
try {
for (String hostName : hostNames) {
ThreadGroup tg = new ThreadGroup("Connection search");
List<Thread> threadList = new ArrayList<>();
for (String hostName : finalHostNames) {
monitor.subTask("Search connections on '" + hostName + "'");
searchConnections(monitor, hostName);
String localName = localHostNames.get(hostName);
if (localName == null) {
localName = hostName;
}
String finalLocalName = localName;
Runnable searchFunc = () -> searchConnections(monitor, hostName, finalLocalName);
Thread t = new Thread(tg, searchFunc, "Search connection @" + hostName);
threadList.add(t);
t.start();
}
for (Thread t : threadList) {
try {
t.join();
} catch (InterruptedException e) {
// ignore
}
}
} catch (DBException e) {
throw new InvocationTargetException(e);
} finally {
monitor.done();
}
}
private void searchConnections(DBRProgressMonitor monitor, String hostName) throws DBException {
int checkTimeout = 250;
private void searchConnections(DBRProgressMonitor monitor, String hostName, String displayName) {
int checkTimeout = 150;
Map<Integer, AdminConnectionSearchInfo> portCache = new HashMap<>();
for (DBPDriver driver : availableDrivers) {
monitor.subTask("Check '" + driver.getName() + "' on '" + hostName + "'");
if (!CommonUtils.isEmpty(driver.getDefaultPort())) {
updatePortInfo(portCache, hostName, driver, checkTimeout);
updatePortInfo(portCache, hostName, displayName, driver, checkTimeout);
}
monitor.worked(1);
}
for (AdminConnectionSearchInfo si : portCache.values()) {
if (si.getDefaultDriver() != null) {
foundConnections.add(si);
synchronized (foundConnections) {
if (foundConnections.stream().noneMatch(fsi -> fsi.getDisplayName().equals(displayName) && fsi.getPort() == si.getPort())) {
foundConnections.add(si);
}
}
}
}
}
private void updatePortInfo(Map<Integer, AdminConnectionSearchInfo> portCache, String hostName, DBPDriver driver, int timeout) {
private void updatePortInfo(Map<Integer, AdminConnectionSearchInfo> portCache, String hostName, String displayName, DBPDriver driver, int timeout) {
int driverPort = CommonUtils.toInt(driver.getDefaultPort());
if (driverPort <= 0) {
return;
@@ -105,7 +140,7 @@ public class ConnectionSearcher implements DBRRunnableWithProgress {
searchInfo.getPossibleDrivers().add(driverId);
return;
}
searchInfo = new AdminConnectionSearchInfo(hostName, driverPort);
searchInfo = new AdminConnectionSearchInfo(displayName, hostName, driverPort);
portCache.put(driverPort, searchInfo);
try {
@@ -41,7 +41,6 @@ import org.jkiss.dbeaver.model.exec.DBCException;
import org.jkiss.dbeaver.model.navigator.DBNBrowseSettings;
import org.jkiss.utils.CommonUtils;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -250,11 +249,7 @@ public class WebServiceAdmin implements DBWServiceAdmin {
@Override
public List<AdminConnectionSearchInfo> searchConnections(@NotNull WebSession webSession, @NotNull List<String> hostNames) throws DBWebException {
ConnectionSearcher searcher = new ConnectionSearcher(webSession, hostNames.toArray(new String[0]));
try {
searcher.run(webSession.getProgressMonitor());
} catch (InvocationTargetException e) {
throw new DBWebException("Error searching connections", e.getTargetException());
}
searcher.run(webSession.getProgressMonitor());
return searcher.getFoundConnections();
}