public class InodeSyncStream extends Object
ExecutorService
which we submit inode paths to using
processSyncPath(AlluxioURI, RpcContext)
.
The processing of inode paths will discover new paths to
sync depending on the mDescendantType
. Syncing is finished when all submitted tasks
are completed and there are no new inodes left in the queue.
Syncing inode metadata requires making calls to the UFS. This implementation will schedule UFS
RPCs with the UfsStatusCache.prefetchChildren(AlluxioURI, MountTable)
. Then, once the
inode begins processing, it can retrieve the results. After processing, it can then remove its
UfsStatus
from the cache. This strategy helps reduce memory pressure on the master
while performing a sync for a large tree. Additionally, by using a prefetch mechanism we can
concurrently process other inodes while waiting for UFS RPCs to complete.
With regard to locking, this class expects to be able to take a write lock on any inode, and
then subsequently downgrades or unlocks after the sync is finished. Even though we use
ReentrantReadWriteLock
, because we concurrently process
inodes on separate threads, we cannot utilize the reentrant behavior. The implications of
that mean the caller of this class must not hold a write while calling sync()
.
A user of this class is expected to create a new instance for each path that they would like
to process. This is because the Lock on the mRootScheme
may be changed after calling
sync()
.
When a sync happens on a directory, only the sync timestamp of the directory itself will be
updated (including information if the sync was recursive) and not its children.
Then whenever a path checked it will also check its parent's sync time up to the root.
There are currently two reasons for this, the first is so that the sync cache will be
updated only on the parent directory level and not for every child synced meaning there will be
fewer entries in the cache. Second that updating the children times individually would require
a redesign because the sync paths are not tracked in a way currently where they know
when their children finish (apart from the root sync path).
When checking if a child of the root sync path needs to be synced, the following
two items are considered:
1. If a child directory does not need to be synced, then it will not be synced.
The parent will then update its sync time only to the oldest sync time of a child
that was not synced (or the current clock time if all children were synced).
2. If a child file does not need to be synced (but its updated state has already
been loaded from the UFS due to the listing of the parent directory) then the
sync is still performed (because no additional UFS operations are needed,
unless ACL is enabled for the UFS, then an additional UFS call would be
needed so the sync is skipped and the time is calculated as in 1.).
To go through an example (note I am assuming every path here is a directory).
If say the interval is 100s, and the last synced timestamps are:
/a 0
/a/b 10
/a/c 0
/a/d 0
/a/e 0
/a/f 0
Then the current timestamp is 100 and a sync will trigger with the sync for /a/b skipped.
Then the timestamps look like the following:
/a 10
/a/b 10
/a/c 0
/a/d 0
/a/e 0
/a/f 0
Now if we do a sync at timestamp 110, a metadata sync for /a will be triggered again,
all children are synced. After the operation, the timestamp looks like
(i.e. all paths have a sync time of 110):
/a 110
/a/b 10
/a/c 0
/a/d 0
/a/e 0
/a/f 0
Here is a second example:
If say the interval is 100s, the last synced timestamps are:
/a 0
/a/b 0
/a/c 0
/a/d 0
/a/e 0
/a/f 0
Now say at time 90 some children are synced individually.
Then the timestamps look like the following:
/a 0
/a/b 0
/a/c 90
/a/d 90
/a/e 90
/a/f 90
and if we do a sync at timestamp 100, a sync will only happen on /a/b,
and /a will get updated to 90
/a 90
/a/b 0
/a/c 90
/a/d 90
/a/e 90
/a/f 90
Note that we may consider different ways of deciding how to sync children
(see https://github.com/Alluxio/alluxio/pull/16081).Modifier and Type | Class and Description |
---|---|
static class |
InodeSyncStream.SyncStatus
Return status of a sync result.
|
Constructor and Description |
---|
InodeSyncStream(LockingScheme rootScheme,
DefaultFileSystemMaster fsMaster,
UfsSyncPathCache syncPathCache,
RpcContext rpcContext,
DescendantType descendantType,
FileSystemMasterCommonPOptions options,
boolean forceSync,
boolean loadOnly,
boolean loadAlways)
Create a new instance of
InodeSyncStream without any audit or permission checks. |
InodeSyncStream(LockingScheme rootPath,
DefaultFileSystemMaster fsMaster,
UfsSyncPathCache syncPathCache,
RpcContext rpcContext,
DescendantType descendantType,
FileSystemMasterCommonPOptions options,
FileSystemMasterAuditContext auditContext,
java.util.function.Function<LockedInodePath,Inode> auditContextSrcInodeFunc,
boolean forceSync,
boolean loadOnly,
boolean loadAlways)
Create a new instance of
InodeSyncStream . |
Modifier and Type | Method and Description |
---|---|
protected RpcContext |
getMetadataSyncRpcContext() |
static List<Journal.JournalEntry> |
mergeCreateComplete(List<Journal.JournalEntry> entries)
Merge inode entry with subsequent update inode and update inode file entries.
|
InodeSyncStream.SyncStatus |
sync()
Sync the metadata according the root path the stream was created with.
|
String |
toString() |
public InodeSyncStream(LockingScheme rootPath, DefaultFileSystemMaster fsMaster, UfsSyncPathCache syncPathCache, RpcContext rpcContext, DescendantType descendantType, FileSystemMasterCommonPOptions options, @Nullable FileSystemMasterAuditContext auditContext, @Nullable java.util.function.Function<LockedInodePath,Inode> auditContextSrcInodeFunc, boolean forceSync, boolean loadOnly, boolean loadAlways)
InodeSyncStream
.
The root path should be already locked with InodeTree.LockPattern.WRITE_EDGE
unless the user is
only planning on loading metadata. The desired pattern should always be
InodeTree.LockPattern.READ
.
It is an error to initiate sync without a WRITE_EDGE lock when loadOnly is false
.
If loadOnly is set to true
, then the root path may have a read lock.rootPath
- The root path to begin syncingfsMaster
- the FileSystemMaster
calling this methodsyncPathCache
- the UfsSyncPathCache
for the given pathrpcContext
- the caller's RpcContext
descendantType
- determines the number of descendant inodes to syncoptions
- the RPC's FileSystemMasterCommonPOptions
auditContext
- the audit context to use when loadingauditContextSrcInodeFunc
- the inode to set as the audit context sourceforceSync
- whether to sync inode metadata no matter whatloadOnly
- whether to only load new metadata, rather than update existing metadataloadAlways
- whether to always load new metadata from the ufs, even if a file or
directory has been previous found to not existpublic InodeSyncStream(LockingScheme rootScheme, DefaultFileSystemMaster fsMaster, UfsSyncPathCache syncPathCache, RpcContext rpcContext, DescendantType descendantType, FileSystemMasterCommonPOptions options, boolean forceSync, boolean loadOnly, boolean loadAlways)
InodeSyncStream
without any audit or permission checks.rootScheme
- The root path to begin syncingfsMaster
- the FileSystemMaster
calling this methodsyncPathCache
- the UfsSyncPathCache
for this pathrpcContext
- the caller's RpcContext
descendantType
- determines the number of descendant inodes to syncoptions
- the RPC's FileSystemMasterCommonPOptions
forceSync
- whether to sync inode metadata no matter whatloadOnly
- whether to only load new metadata, rather than update existing metadataloadAlways
- whether to always load new metadata from the ufs, even if a file or
directory has been previous found to not existpublic InodeSyncStream.SyncStatus sync() throws AccessControlException, InvalidPathException
AccessControlException
InvalidPathException
public static List<Journal.JournalEntry> mergeCreateComplete(List<Journal.JournalEntry> entries)
entries
- list of journal entriesprotected RpcContext getMetadataSyncRpcContext()
Copyright © 2023. All Rights Reserved.