Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CB-5390 use remote file system for storage #2945

Merged
merged 7 commits into from
Oct 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ server/test/io.cloudbeaver.test.platform/workspace/.data/
.classpath
.settings/

## Eclipse PDE
*.product.launch

workspace-dev-ce/
deploy/cloudbeaver
server/**/target
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,32 @@
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.registry.fs.FileSystemProviderRegistry;
import org.jkiss.utils.IOUtils;

import java.net.URI;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Path;

/**
* Abstract class that contains methods for loading configuration with gson.
*/
public abstract class BaseServerConfigurationController<T extends WebServerConfiguration>
implements WebServerConfigurationController<T> {
private static final Log log = Log.getLog(BaseServerConfigurationController.class);
@NotNull
private final Path homeDirectory;

protected Path workspacePath;

protected BaseServerConfigurationController(@NotNull Path homeDirectory) {
this.homeDirectory = homeDirectory;
//default workspaceLocation
this.workspacePath = homeDirectory.resolve("workspace");
}

@NotNull
public Gson getGson() {
Expand All @@ -34,4 +54,50 @@ public Gson getGson() {
protected abstract GsonBuilder getGsonBuilder();

public abstract T getServerConfiguration();


@NotNull
protected synchronized void initWorkspacePath() throws DBException {
if (workspacePath != null && !IOUtils.isFileFromDefaultFS(workspacePath)) {
log.warn("Workspace directory already initialized: " + workspacePath);
}
String workspaceLocation = getWorkspaceLocation();
URI workspaceUri = URI.create(workspaceLocation);
if (workspaceUri.getScheme() == null) {
// default filesystem
this.workspacePath = getHomeDirectory().resolve(workspaceLocation);
} else {
var externalFsProvider =
FileSystemProviderRegistry.getInstance().getFileSystemProviderBySchema(workspaceUri.getScheme());
if (externalFsProvider == null) {
throw new DBException("File system not found for scheme: " + workspaceUri.getScheme());
}
ClassLoader fsClassloader = externalFsProvider.getInstance().getClass().getClassLoader();
try (FileSystem externalFileSystem = FileSystems.newFileSystem(workspaceUri,
System.getenv(),
fsClassloader);) {
this.workspacePath = externalFileSystem.provider().getPath(workspaceUri);
} catch (Exception e) {
throw new DBException("Failed to initialize workspace path: " + workspaceUri, e);
}
}
log.info("Workspace path initialized: " + workspacePath);
}

@NotNull
protected abstract String getWorkspaceLocation();

@NotNull
protected Path getHomeDirectory() {
return homeDirectory;
}

@NotNull
@Override
public Path getWorkspacePath() {
if (workspacePath == null) {
throw new RuntimeException("Workspace path not initialized");
}
return workspacePath;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,12 @@ public String getWorkspaceIdProperty() throws DBException {
return BaseWorkspaceImpl.readWorkspaceIdProperty();
}

@Override
public Path getWorkspaceDirectory() {
return getServerConfigurationController().getWorkspacePath();
}


public String getApplicationId() {
try {
return getApplicationInstanceId();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@
return Map.of();
}

@NotNull

Check warning on line 42 in server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/app/WebServerConfigurationController.java

View check run for this annotation

Jenkins-CI-integration / CheckStyle Java Report

server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/app/WebServerConfigurationController.java#L42

Missing a Javadoc comment.
Path getWorkspacePath();

@NotNull
Gson getGson();

void validateFinalServerConfiguration() throws DBException;

Check warning on line 48 in server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/app/WebServerConfigurationController.java

View check run for this annotation

Jenkins-CI-integration / CheckStyle Java Report

server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/app/WebServerConfigurationController.java#L48

Missing a Javadoc comment.
}
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,7 @@ public String moveResource(
throw new DBException("Resource '" + oldTargetPath + "' doesn't exists");
}
Path newTargetPath = getTargetPath(projectId, normalizedNewResourcePath);
validateResourcePath(newTargetPath.toString());
validateResourcePath(rootPath.relativize(newTargetPath).toString());
if (Files.exists(newTargetPath)) {
throw new DBException("Resource with name %s already exists".formatted(newTargetPath.getFileName()));
}
Expand Down Expand Up @@ -881,7 +881,7 @@ private Path getTargetPath(@NotNull String projectId, @NotNull String resourcePa
if (!targetPath.startsWith(projectPath)) {
throw new DBException("Invalid resource path");
}
return WebAppUtils.getWebApplication().getHomeDirectory().relativize(targetPath);
return targetPath;
} catch (InvalidPathException e) {
throw new DBException("Resource path contains invalid characters");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.app.DBPWorkspace;
import org.jkiss.utils.IOUtils;

import java.io.IOException;
import java.io.Reader;
Expand Down Expand Up @@ -73,18 +74,23 @@ public RMFileLockController(WebApplication application, int maxLockTime) throws
* @return - lock
*/
@NotNull
public RMLock lockProject(@NotNull String projectId,@NotNull String operationName) throws DBException {
public RMLock lockProject(@NotNull String projectId, @NotNull String operationName) throws DBException {
synchronized (RMFileLockController.class) {
try {
createLockFolderIfNeeded();
createProjectFolder(projectId);
Path projectLockFile = getProjectLockFilePath(projectId);

RMLockInfo lockInfo = new RMLockInfo.Builder(projectId, UUID.randomUUID().toString())
.setApplicationId(applicationId)
.setOperationName(operationName)
.setOperationStartTime(System.currentTimeMillis())
.build();
Path projectLockFile = getProjectLockFilePath(projectId);

if (!IOUtils.isFileFromDefaultFS(lockFolderPath)) {
// fake lock for external file system?
return new RMLock(projectLockFile);
}
createLockFolderIfNeeded();
createProjectFolder(projectId);

createLockFile(projectLockFile, lockInfo);
return new RMLock(projectLockFile);
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package io.cloudbeaver.server;

import io.cloudbeaver.DBWConstants;
import io.cloudbeaver.model.app.WebApplication;
import org.eclipse.core.runtime.Plugin;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.Log;
Expand All @@ -33,14 +34,16 @@
import org.jkiss.dbeaver.runtime.qm.QMLogFileWriter;
import org.jkiss.dbeaver.runtime.qm.QMRegistryImpl;
import org.jkiss.dbeaver.utils.ContentUtils;
import org.jkiss.utils.CommonUtils;
import org.jkiss.utils.StandardConstants;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

public abstract class BaseGQLPlatform extends BasePlatformImpl {
private static final Log log = Log.getLog(BaseGQLPlatform.class);
public static final String WORK_DATA_FOLDER_NAME = ".work-data";
public static final String BASE_TEMP_DIR = "dbeaver";

private Path tempFolder;

Expand All @@ -55,7 +58,7 @@
SecurityProviderUtils.registerSecurityProvider();

// Register properties adapter
this.workspace = new WebGlobalWorkspace(this);
this.workspace = new WebGlobalWorkspace(this, (WebApplication) getApplication());
this.workspace.initializeProjects();
QMUtils.initApplication(this);

Expand Down Expand Up @@ -92,16 +95,12 @@

@NotNull
public Path getTempFolder(@NotNull DBRProgressMonitor monitor, @NotNull String name) {

if (tempFolder == null) {
// Make temp folder
monitor.subTask("Create temp folder");
tempFolder = workspace.getAbsolutePath().resolve(DBWConstants.WORK_DATA_FOLDER_NAME);
}
if (!Files.exists(tempFolder)) {
try {
Files.createDirectories(tempFolder);
} catch (IOException e) {
log.error("Can't create temp directory " + tempFolder, e);
synchronized (this) {
if (tempFolder == null) {
initTempFolder(monitor);
}
}
}
Path folder = tempFolder.resolve(name);
Expand All @@ -115,6 +114,21 @@
return folder;
}

private void initTempFolder(@NotNull DBRProgressMonitor monitor) {
// Make temp folder
monitor.subTask("Create temp folder");
String sysTempFolder = System.getProperty(StandardConstants.ENV_TMP_DIR);
if (CommonUtils.isNotEmpty(sysTempFolder)) {
tempFolder = Path.of(sysTempFolder).resolve(BASE_TEMP_DIR).resolve(DBWConstants.WORK_DATA_FOLDER_NAME);
} else {
//we do not use workspace because it can be in external file system
tempFolder = getApplication().getHomeDirectory().resolve(DBWConstants.WORK_DATA_FOLDER_NAME);
}
}

@NotNull

Check warning on line 129 in server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/server/BaseGQLPlatform.java

View check run for this annotation

Jenkins-CI-integration / CheckStyle Java Report

server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/server/BaseGQLPlatform.java#L129

Missing a Javadoc comment.
public abstract WebApplication getApplication();

@Override
public synchronized void dispose() {
super.dispose();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import io.cloudbeaver.WebProjectImpl;
import io.cloudbeaver.model.app.WebApplication;
import io.cloudbeaver.utils.WebAppUtils;
import org.eclipse.core.runtime.Platform;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.Log;
Expand All @@ -30,8 +29,6 @@
import org.jkiss.utils.CommonUtils;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
Expand All @@ -49,21 +46,14 @@ public class WebGlobalWorkspace extends BaseWorkspaceImpl {
protected final Map<String, WebProjectImpl> projects = new LinkedHashMap<>();
private WebGlobalProject globalProject;

public WebGlobalWorkspace(DBPPlatform platform) {
super(platform,
platform.getApplication().isMultiuser()
? Path.of(getWorkspaceURI())
: ((WebApplication) platform.getApplication()).getWorkspaceDirectory());
}
private final WebApplication application;

@NotNull
private static URI getWorkspaceURI() {
String workspacePath = Platform.getInstanceLocation().getURL().toString();
try {
return new URI(workspacePath);
} catch (URISyntaxException e) {
throw new IllegalStateException("Workspace path is invalid: " + workspacePath, e);
}
public WebGlobalWorkspace(
@NotNull DBPPlatform platform,
@NotNull WebApplication application
) {
super(platform, application.getWorkspaceDirectory());
this.application = application;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;

import java.io.File;
import java.io.PrintStream;

/**
Expand All @@ -33,7 +32,6 @@ public class WebPlatformActivator extends Plugin {

// The shared instance
private static WebPlatformActivator instance;
private static File configDir;
private PrintStream debugWriter;
private DBPPreferenceStore preferences;

Expand Down
Loading
Loading