This is an automated email from the ASF dual-hosted git repository.
yuqi1129 pushed a commit to branch branch-1.3
in repository https://gitbox.apache.org/repos/asf/gravitino.git
The following commit(s) were added to refs/heads/branch-1.3 by this push:
new e073d5eb0e [Cherry-pick to branch-1.3] [#11303] fix(gvfs): do not
close cached FileSystem on eviction (defer close to GVFS shutdown) (#11304)
(#11539)
e073d5eb0e is described below
commit e073d5eb0ed5de8656b32b3d136a2f9e5a3d941e
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Tue Jun 9 22:22:15 2026 +0800
[Cherry-pick to branch-1.3] [#11303] fix(gvfs): do not close cached
FileSystem on eviction (defer close to GVFS shutdown) (#11304) (#11539)
**Cherry-pick Information:**
- Original commit: 976cfa6d647bb491d905c63b20b2ff2afbe158c0
- Target branch: `branch-1.3`
- Status: ✅ Clean cherry-pick (no conflicts)
Co-authored-by: Gary Wang <[email protected]>
---
.../filesystem/hadoop/BaseGVFSOperations.java | 68 +++++--
.../GravitinoVirtualFileSystemConfiguration.java | 30 +++
.../gravitino/filesystem/hadoop/TestGvfsBase.java | 216 +++++++++++++++++++++
docs/how-to-use-gvfs.md | 3 +-
4 files changed, 304 insertions(+), 13 deletions(-)
diff --git
a/clients/filesystem-hadoop3/src/main/java/org/apache/gravitino/filesystem/hadoop/BaseGVFSOperations.java
b/clients/filesystem-hadoop3/src/main/java/org/apache/gravitino/filesystem/hadoop/BaseGVFSOperations.java
index ccfb8e29fa..06368c04c4 100644
---
a/clients/filesystem-hadoop3/src/main/java/org/apache/gravitino/filesystem/hadoop/BaseGVFSOperations.java
+++
b/clients/filesystem-hadoop3/src/main/java/org/apache/gravitino/filesystem/hadoop/BaseGVFSOperations.java
@@ -44,6 +44,7 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URI;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -51,6 +52,7 @@ import java.util.Objects;
import java.util.Optional;
import java.util.ServiceLoader;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
@@ -133,6 +135,15 @@ public abstract class BaseGVFSOperations implements
Closeable {
private final Cache<FileSystemCacheKey, FileSystem> fileSystemCache;
+ /**
+ * Tracks all {@link FileSystem} instances ever created by this operations
instance, including
+ * those already evicted from {@link #fileSystemCache}, so that {@link
#close()} can close them
+ * all at GVFS shutdown. See <a
+ * href="https://github.com/apache/gravitino/issues/11303">#11303</a>.
+ */
+ private final Set<FileSystem> allCreatedFileSystems =
+ Collections.newSetFromMap(new ConcurrentHashMap<>());
+
private final Map<String, FileSystemProvider> fileSystemProvidersMap;
private final String currentLocationEnvVar;
@@ -274,15 +285,18 @@ public abstract class BaseGVFSOperations implements
Closeable {
@Override
public void close() throws IOException {
- // close all actual FileSystems
- for (FileSystem fileSystem : fileSystemCache.asMap().values()) {
+ // Invalidate cache first so the removal listener can close cached
FileSystems,
+ // then close any remaining ones tracked in allCreatedFileSystems to avoid
double-close.
+ fileSystemCache.invalidateAll();
+
+ for (FileSystem fileSystem : allCreatedFileSystems) {
try {
fileSystem.close();
} catch (IOException e) {
- // ignore
+ LOG.warn("Failed to close FileSystem during GVFS shutdown: {}",
fileSystem, e);
}
}
- fileSystemCache.invalidateAll();
+ allCreatedFileSystems.clear();
try {
if (filesetMetadataCache != null && filesetMetadataCache.isPresent()) {
@@ -762,6 +776,11 @@ public abstract class BaseGVFSOperations implements
Closeable {
return fileSystemCache;
}
+ @VisibleForTesting
+ Set<FileSystem> allCreatedFileSystems() {
+ return allCreatedFileSystems;
+ }
+
/**
* Lazy initialization of GravitinoClient using double-checked locking
pattern. This ensures the
* expensive client creation only happens when actually needed.
@@ -824,11 +843,16 @@ public abstract class BaseGVFSOperations implements
Closeable {
// https://github.com/apache/gravitino/issues/5609
resetFileSystemServiceLoader(scheme);
+ FileSystem created;
if (scheme.equals(SCHEME_HDFS)) {
- return new HDFSFileSystemProxy(actualFilePath,
allProperties).getProxy();
+ created = new HDFSFileSystemProxy(actualFilePath,
allProperties).getProxy();
} else {
- return provider.getFileSystem(actualFilePath, allProperties);
+ created = provider.getFileSystem(actualFilePath, allProperties);
}
+ // Track every FS we create so we can guarantee close() at GVFS
shutdown,
+ // even if the entry is later evicted from the cache (see #11303).
+ allCreatedFileSystems.add(created);
+ return created;
} catch (IOException e) {
throw new GravitinoRuntimeException(
e, "Cannot get FileSystem for path: %s", actualFilePath);
@@ -877,6 +901,19 @@ public abstract class BaseGVFSOperations implements
Closeable {
GravitinoVirtualFileSystemConfiguration
.FS_GRAVITINO_FILESET_CACHE_EVICTION_MILLS_AFTER_ACCESS_KEY);
+ // Legacy fallback: close FS immediately on eviction (see #11303).
+ final boolean closeOnEviction =
+ configuration.getBoolean(
+ GravitinoVirtualFileSystemConfiguration
+ .FS_GRAVITINO_FILESET_CACHE_CLOSE_ON_EVICTION_KEY,
+ GravitinoVirtualFileSystemConfiguration
+ .FS_GRAVITINO_FILESET_CACHE_CLOSE_ON_EVICTION_DEFAULT);
+ if (closeOnEviction) {
+ LOG.warn(
+ "'{}' is enabled; FileSystem will be closed on cache eviction
(legacy behaviour, see #11303).",
+
GravitinoVirtualFileSystemConfiguration.FS_GRAVITINO_FILESET_CACHE_CLOSE_ON_EVICTION_KEY);
+ }
+
Caffeine<Object, Object> cacheBuilder =
Caffeine.newBuilder()
.maximumSize(maxCapacity)
@@ -888,14 +925,21 @@ public abstract class BaseGVFSOperations implements
Closeable {
1,
newDaemonThreadFactory("gvfs-filesystem-cache-cleaner"))))
.removalListener(
(key, value, cause) -> {
- FileSystem fs = (FileSystem) value;
- if (fs != null) {
- try {
- fs.close();
- } catch (IOException e) {
- LOG.error("Cannot close the file system for fileset:
{}", key, e);
+ if (closeOnEviction) {
+ FileSystem fs = (FileSystem) value;
+ if (fs != null) {
+ // Remove from allCreatedFileSystems first to avoid
double-close at shutdown.
+ allCreatedFileSystems.remove(fs);
+ try {
+ fs.close();
+ } catch (IOException e) {
+ LOG.error("Cannot close the file system for fileset:
{}", key, e);
+ }
}
+ return;
}
+ // Default: do not close on eviction; close is deferred to
GVFS shutdown.
+ LOG.debug("FileSystem evicted from cache (key={},
cause={})", key, cause);
});
cacheBuilder.expireAfterAccess(evictionMillsAfterAccess,
TimeUnit.MILLISECONDS);
return cacheBuilder.build();
diff --git
a/clients/filesystem-hadoop3/src/main/java/org/apache/gravitino/filesystem/hadoop/GravitinoVirtualFileSystemConfiguration.java
b/clients/filesystem-hadoop3/src/main/java/org/apache/gravitino/filesystem/hadoop/GravitinoVirtualFileSystemConfiguration.java
index 1c07ee7a53..3334e17b6e 100644
---
a/clients/filesystem-hadoop3/src/main/java/org/apache/gravitino/filesystem/hadoop/GravitinoVirtualFileSystemConfiguration.java
+++
b/clients/filesystem-hadoop3/src/main/java/org/apache/gravitino/filesystem/hadoop/GravitinoVirtualFileSystemConfiguration.java
@@ -98,6 +98,10 @@ public class GravitinoVirtualFileSystemConfiguration {
/**
* The configuration key for the eviction time of the Gravitino fileset
cache, measured in mills
* after access.
+ *
+ * <p>Note: an evicted {@code FileSystem} is not closed at eviction time; it
is closed when the
+ * owning GVFS instance is closed. See <a
+ * href="https://github.com/apache/gravitino/issues/11303">#11303</a>.
*/
public static final String
FS_GRAVITINO_FILESET_CACHE_EVICTION_MILLS_AFTER_ACCESS_KEY =
"fs.gravitino.fileset.cache.evictionMillsAfterAccess";
@@ -109,6 +113,32 @@ public class GravitinoVirtualFileSystemConfiguration {
public static final long
FS_GRAVITINO_FILESET_CACHE_EVICTION_MILLS_AFTER_ACCESS_DEFAULT =
1000L * 60 * 60;
+ /**
+ * Whether to close the underlying {@code FileSystem} immediately on cache
eviction. Default is
+ * {@code false}: close is deferred to GVFS shutdown to avoid breaking
long-lived streams (see <a
+ * href="https://github.com/apache/gravitino/issues/11303">#11303</a>). Set
to {@code true} to
+ * fall back to the legacy behaviour.
+ */
+ public static final String FS_GRAVITINO_FILESET_CACHE_CLOSE_ON_EVICTION_KEY =
+ "fs.gravitino.fileset.cache.closeOnEviction";
+
+ /**
+ * The default value for {@link
#FS_GRAVITINO_FILESET_CACHE_CLOSE_ON_EVICTION_KEY}.
+ *
+ * <p><b>Default behavior ({@code false})</b>: FileSystem instances are not
closed immediately
+ * when evicted from the cache. Instead, they remain open until the
Gravitino Virtual File System
+ * (GVFS) instance is closed. This prevents breaking long-lived streams and
connections that might
+ * still be active after cache eviction.
+ *
+ * <p><b>Legacy behavior ({@code true})</b>: FileSystem instances are closed
immediately upon
+ * cache eviction. This was the original behavior but can cause issues with
active streams.
+ *
+ * <p><b>Recommendation</b>: Keep the default value ({@code false}) unless
you have specific
+ * requirements for immediate resource cleanup and are certain that no
active streams will be
+ * affected.
+ */
+ public static final boolean
FS_GRAVITINO_FILESET_CACHE_CLOSE_ON_EVICTION_DEFAULT = false;
+
/**
* The configuration key for the fileset with multiple locations, on which
the file system will
* operate. If not set, the file system will operate on the default location.
diff --git
a/clients/filesystem-hadoop3/src/test/java/org/apache/gravitino/filesystem/hadoop/TestGvfsBase.java
b/clients/filesystem-hadoop3/src/test/java/org/apache/gravitino/filesystem/hadoop/TestGvfsBase.java
index d39bf26b3b..11779b1aab 100644
---
a/clients/filesystem-hadoop3/src/test/java/org/apache/gravitino/filesystem/hadoop/TestGvfsBase.java
+++
b/clients/filesystem-hadoop3/src/test/java/org/apache/gravitino/filesystem/hadoop/TestGvfsBase.java
@@ -474,6 +474,222 @@ public class TestGvfsBase extends GravitinoMockServerBase
{
}
}
+ /**
+ * Regression test for #11303: cache eviction must not close the underlying
{@link FileSystem};
+ * close is deferred to GVFS shutdown.
+ */
+ @Test
+ public void testFileSystemNotClosedOnEviction() throws IOException {
+ String filesetName = "fileset_evict_no_close";
+ Path localPath = FileSystemTestUtils.createLocalDirPrefix(catalogName,
schemaName, filesetName);
+ Path filesetPath =
+ FileSystemTestUtils.createFilesetPath(catalogName, schemaName,
filesetName, true);
+ String locationPath =
+ String.format(
+ "/api/metalakes/%s/catalogs/%s/schemas/%s/filesets/%s/location",
+ metalakeName, catalogName, schemaName, filesetName);
+ try (FileSystem fs = filesetPath.getFileSystem(conf)) {
+ FileLocationResponse fileLocationResponse = new
FileLocationResponse(localPath.toString());
+ Map<String, String> queryParams = new HashMap<>();
+ queryParams.put("sub_path", "");
+ buildMockResource(Method.GET, locationPath, queryParams, null,
fileLocationResponse, SC_OK);
+ buildMockResourceForCredential(filesetName, localPath.toString());
+
+ // Populate the cache by performing one operation.
+ FileSystemTestUtils.mkdirs(filesetPath, fs);
+
+ Cache<BaseGVFSOperations.FileSystemCacheKey, FileSystem> cache =
+ ((GravitinoVirtualFileSystem)
fs).getOperations().internalFileSystemCache();
+ assertEquals(1, cache.asMap().size());
+ FileSystem underlyingFs = cache.asMap().values().iterator().next();
+ assertNotNull(underlyingFs);
+
+ // Force an eviction; the underlying FS must NOT be closed.
+ cache.invalidateAll();
+ cache.cleanUp();
+ Awaitility.await()
+ .atMost(5, TimeUnit.SECONDS)
+ .pollInterval(100, TimeUnit.MILLISECONDS)
+ .untilAsserted(() -> assertTrue(cache.asMap().isEmpty()));
+
+ // The underlying FileSystem must still be usable after eviction.
+ Path probe = new Path(localPath, "probe_after_eviction");
+ FileSystemTestUtils.mkdirs(probe, underlyingFs);
+ assertTrue(underlyingFs.exists(probe));
+
+ // Evicted FS must still be tracked so GVFS#close() can release it.
+ assertTrue(
+ ((GravitinoVirtualFileSystem) fs)
+ .getOperations()
+ .allCreatedFileSystems()
+ .contains(underlyingFs),
+ "Evicted FileSystem must still be tracked for shutdown-time close");
+ }
+ }
+
+ /**
+ * Regression test for #11303: an evicted-but-not-yet-closed {@link
FileSystem} must be closed
+ * exactly once when the owning GVFS instance is closed.
+ */
+ @Test
+ public void testEvictedFileSystemClosedOnGvfsShutdown() throws IOException {
+ String filesetName = "fileset_evict_close_on_shutdown";
+ Path localPath = FileSystemTestUtils.createLocalDirPrefix(catalogName,
schemaName, filesetName);
+ Path filesetPath =
+ FileSystemTestUtils.createFilesetPath(catalogName, schemaName,
filesetName, true);
+ String locationPath =
+ String.format(
+ "/api/metalakes/%s/catalogs/%s/schemas/%s/filesets/%s/location",
+ metalakeName, catalogName, schemaName, filesetName);
+
+ FileSystem gvfs = filesetPath.getFileSystem(conf);
+ // Mock FS to verify close() is called at GVFS shutdown. Registered via
the test-only
+ // accessor to simulate an FS that was created earlier and (after the
#11303 fix) is no
+ // longer in the cache but must still be closed on shutdown.
+ FileSystem mockExtraFs = Mockito.mock(FileSystem.class);
+ try {
+ FileLocationResponse fileLocationResponse = new
FileLocationResponse(localPath.toString());
+ Map<String, String> queryParams = new HashMap<>();
+ queryParams.put("sub_path", "");
+ buildMockResource(Method.GET, locationPath, queryParams, null,
fileLocationResponse, SC_OK);
+ buildMockResourceForCredential(filesetName, localPath.toString());
+
+ FileSystemTestUtils.mkdirs(filesetPath, gvfs);
+
+ Cache<BaseGVFSOperations.FileSystemCacheKey, FileSystem> cache =
+ ((GravitinoVirtualFileSystem)
gvfs).getOperations().internalFileSystemCache();
+ assertEquals(1, cache.asMap().size());
+
+ // Inject a tracked-but-not-cached FS to model an "evicted but still
tracked" instance.
+ ((GravitinoVirtualFileSystem)
gvfs).getOperations().allCreatedFileSystems().add(mockExtraFs);
+
+ // Force eviction of the cache. Per the fix, this must NOT close any FS.
+ cache.invalidateAll();
+ cache.cleanUp();
+ Awaitility.await()
+ .atMost(5, TimeUnit.SECONDS)
+ .pollInterval(100, TimeUnit.MILLISECONDS)
+ .untilAsserted(() -> assertTrue(cache.asMap().isEmpty()));
+ Mockito.verify(mockExtraFs, Mockito.never()).close();
+ } finally {
+ gvfs.close();
+ }
+
+ // After GVFS shutdown, every FS that was ever tracked (including evicted
ones) must be
+ // closed exactly once.
+ Mockito.verify(mockExtraFs, Mockito.times(1)).close();
+
+ // The tracking set must be cleared on shutdown to avoid retaining stale
references.
+ assertTrue(
+ ((GravitinoVirtualFileSystem)
gvfs).getOperations().allCreatedFileSystems().isEmpty(),
+ "allCreatedFileSystems must be cleared after GVFS shutdown");
+ }
+
+ /**
+ * Regression test: the #11303 fix must not change cache hit/miss semantics;
the same key must
+ * still return the same {@link FileSystem} instance.
+ */
+ @Test
+ public void testCacheHitMissSemanticsUnchanged() throws IOException {
+ String filesetName = "fileset_cache_hit_miss";
+ Path localPath = FileSystemTestUtils.createLocalDirPrefix(catalogName,
schemaName, filesetName);
+ Path filesetPath =
+ FileSystemTestUtils.createFilesetPath(catalogName, schemaName,
filesetName, true);
+ String locationPath =
+ String.format(
+ "/api/metalakes/%s/catalogs/%s/schemas/%s/filesets/%s/location",
+ metalakeName, catalogName, schemaName, filesetName);
+ try (FileSystem fs = filesetPath.getFileSystem(conf)) {
+ FileLocationResponse fileLocationResponse = new
FileLocationResponse(localPath.toString());
+ Map<String, String> queryParams = new HashMap<>();
+ queryParams.put("sub_path", "");
+ buildMockResource(Method.GET, locationPath, queryParams, null,
fileLocationResponse, SC_OK);
+ buildMockResourceForCredential(filesetName, localPath.toString());
+
+ // First access -> cache miss, instantiate FS.
+ FileSystemTestUtils.mkdirs(filesetPath, fs);
+ Cache<BaseGVFSOperations.FileSystemCacheKey, FileSystem> cache =
+ ((GravitinoVirtualFileSystem)
fs).getOperations().internalFileSystemCache();
+ assertEquals(1, cache.asMap().size());
+ FileSystem firstHit = cache.asMap().values().iterator().next();
+
+ // Second access for the same fileset -> cache hit, must reuse the same
instance.
+ Path subDir = new Path(filesetPath, "sub");
+ FileSystemTestUtils.mkdirs(subDir, fs);
+ assertEquals(1, cache.asMap().size());
+ FileSystem secondHit = cache.asMap().values().iterator().next();
+
+ assertSame(
+ firstHit,
+ secondHit,
+ "Cache hit must return the same FileSystem instance for the same
key");
+ }
+ }
+
+ /**
+ * Verifies the legacy escape-hatch {@code closeOnEviction=true}: eviction
must close the FS
+ * immediately and remove it from {@code allCreatedFileSystems} to avoid
double-close on shutdown.
+ */
+ @Test
+ public void testCloseOnEvictionLegacyBehaviour() throws IOException {
+ Configuration legacyConf = new Configuration(conf);
+ legacyConf.setBoolean(
+
GravitinoVirtualFileSystemConfiguration.FS_GRAVITINO_FILESET_CACHE_CLOSE_ON_EVICTION_KEY,
+ true);
+
+ String filesetName = "fileset_evict_legacy_close";
+ Path localPath = FileSystemTestUtils.createLocalDirPrefix(catalogName,
schemaName, filesetName);
+ Path filesetPath =
+ FileSystemTestUtils.createFilesetPath(catalogName, schemaName,
filesetName, true);
+ String locationPath =
+ String.format(
+ "/api/metalakes/%s/catalogs/%s/schemas/%s/filesets/%s/location",
+ metalakeName, catalogName, schemaName, filesetName);
+
+ FileSystem mockFs = Mockito.mock(FileSystem.class);
+ try (FileSystem fs = filesetPath.getFileSystem(legacyConf)) {
+ FileLocationResponse fileLocationResponse = new
FileLocationResponse(localPath.toString());
+ Map<String, String> queryParams = new HashMap<>();
+ queryParams.put("sub_path", "");
+ buildMockResource(Method.GET, locationPath, queryParams, null,
fileLocationResponse, SC_OK);
+ buildMockResourceForCredential(filesetName, localPath.toString());
+
+ // Populate the cache with a real FS first so the cache is non-empty.
+ FileSystemTestUtils.mkdirs(filesetPath, fs);
+
+ Cache<BaseGVFSOperations.FileSystemCacheKey, FileSystem> cache =
+ ((GravitinoVirtualFileSystem)
fs).getOperations().internalFileSystemCache();
+ assertEquals(1, cache.asMap().size());
+
+ // Inject a mock FS with a fresh key so it doesn't collide with the real
entry.
+ BaseGVFSOperations.FileSystemCacheKey mockKey =
+ new BaseGVFSOperations.FileSystemCacheKey("file", "mock-authority",
null);
+ cache.put(mockKey, mockFs);
+ // Mirror the real loader so the legacy listener path can remove it.
+ ((GravitinoVirtualFileSystem)
fs).getOperations().allCreatedFileSystems().add(mockFs);
+
+ // Force eviction.
+ cache.invalidate(mockKey);
+ cache.cleanUp();
+
+ // Legacy path: close() called exactly once, and the FS removed from the
tracking set.
+ Awaitility.await()
+ .atMost(5, TimeUnit.SECONDS)
+ .pollInterval(100, TimeUnit.MILLISECONDS)
+ .untilAsserted(() -> Mockito.verify(mockFs,
Mockito.times(1)).close());
+ assertFalse(
+ ((GravitinoVirtualFileSystem) fs)
+ .getOperations()
+ .allCreatedFileSystems()
+ .contains(mockFs),
+ "Legacy mode must remove evicted FS from allCreatedFileSystems to
prevent "
+ + "double-close at GVFS shutdown");
+ }
+
+ // After GVFS#close(), close() must still have been called exactly once --
not twice.
+ Mockito.verify(mockFs, Mockito.times(1)).close();
+ }
+
@ParameterizedTest
@CsvSource({
"true, testCreate",
diff --git a/docs/how-to-use-gvfs.md b/docs/how-to-use-gvfs.md
index 4bce46da14..f0e192601f 100644
--- a/docs/how-to-use-gvfs.md
+++ b/docs/how-to-use-gvfs.md
@@ -62,7 +62,8 @@ the path mapping and convert automatically.
| `fs.gravitino.client.kerberos.keytabFilePath` | The auth keytab file
path for the Gravitino client when using `kerberos` auth type in the Gravitino
Virtual File System.
| (none)
| No [...]
| `fs.gravitino.fileset.cache.maxCapacity` | The cache capacity
of the Gravitino Virtual File System.
| `20`
| No [...]
| `fs.gravitino.fileset.cache.evictionMillsAfterAccess` | The value of time
that the cache expires after accessing in the Gravitino Virtual File System.
The value is in `milliseconds`.
| `3600000`
| No [...]
-| `fs.gravitino.current.location.name` | The configuration
used to select the location of the fileset. If this configuration is not set,
the value of environment variable configured by
`fs.gravitino.current.location.env.var` will be checked. If neither is set, the
value of fileset property `default-location-name` will be used as the location
name. | the value of fileset
property `default-location-name` | No [...]
+| `fs.gravitino.fileset.cache.closeOnEviction` | Whether to close the
underlying FileSystem immediately on cache eviction. Default is `false`: close
is deferred to GVFS shutdown to avoid breaking long-lived streams. Set to
`true` to fall back to the legacy behaviour (closing immediately on eviction).
| `false`
| No [...]
+| `fs.gravitino.current.location.name` | The configuration
used to select the location of the fileset. If this configuration is not set,
the value of environment variable configured by
`fs.gravitino.current.location.name.env.var` will be checked. If neither is
set, the value of fileset property `default-location-name` will be used as the
location name. | the value of
fileset property `default-location-name` | No [...]
| `fs.gravitino.current.location.name.env.var` | The environment
variable name to get the current location name.
| `CURRENT_LOCATION_NAME`
| No [...]
| `fs.gravitino.operations.class` | The operations class
to provide the FS operations for the Gravitino Virtual File System. Users can
extends `BaseGVFSOperations` to implement their own operations and configure
the class name in this conf to use custom FS operations.
|
`org.apache.gravitino.filesystem.hadoop.DefaultGVFSOperations` | No [...]
| `fs.gravitino.hook.class` | The hook class to
inject into the <br/>Gravitino Virtual File System. Users can implement their
own `GravitinoVirtualFileSystemHook` and configure the class name in this conf
to inject custom code.
| `org.apache.gravitino.filesystem.hadoop.NoOpHook`
| No [...]