Locking Files and Folders in Virtual File System

The User File System sample provides a sample code to lock items in your remote storage, to protect it from modifications by other users. Locking may also serve as a visual indication that somebody else is working on the document. You can implement both automatic and manual locking. 

This article is about the legacy version of the User File System. For the latest version please refer to the articles in this section.

If the AutoLock option is enabled in appsettings.json, the file will be automatically locked when a file handle is opened for writing and unlocked when the handle is released. The file will be also locked before the content is sent to the remote storage and unlocked when the operation completes. The Windows File Manager will display the "Locked" iconLocked icon in the Status column.

The sample code also provides additional support for MS Office document editing. When you edit MS Office documents the file will be automatically locked when the document is opened and unlocked then the document is closed. 

Microsoft Office documents are automatically locked when a document is opened and unlocked when closed

Locking

When the item in the remote storage must be locked, the UserFileSystemItem.LockAsync() method is called. In this method implementation, you will lock the item in your remote storage and receive the lock-token from your server. You must return this lock token from the LockAsync() method as part of the LockInfo object. The LockInfo object will be serialized and stored in the local file system, in the folder specified in the Settings.ServerDataFolderPath property. You can also store additional data associated with the lock, such as lock expiration time, inside the LockInfo class.

public async Task<LockInfo> LockAsync()
{
    string lockToken = LockServerItem(RemoteStoragePath);
    return new LockInfo { LockToken = lockToken };
}

Note that when locking/unlocking the file in the remote storage, the file ETag and modification date of your remote storage file typically should NOT change.

To manually lock the item, for example from your Windows Shell Extension context menu, call the RemoteStorageRawItem.LockAsync() method. This method will call the UserFileSystemItem.LockAsync() method, update the lock icon in the Windows File Manager Status column, and then will store the LockInfo object. The RemoteStorageRawItem.LockAsync() method provides the LockMode parameter which you will use to indicate if the item should be unlocked automatically after the item update:

await new RemoteStorageRawItem(userFileSystemPath, Logger).LockAsync(LockMode.Manual);

Note that in your log you can find a number of messages that the file lock can not be opened or created. This is the normal behavior of the sample code. Because of the concurrent nature of file operations, the file handle is concurrently opened by multiple threads, but only the first thread will be able to obtain the file lock, causing all other lock attempts to fail. Regardless of the number of attempts, the UserFileSystemItem.LockAsync() method will be called only one time.

Item Update

When the item needs to be sent from the user file system to the remote storage, you can retrieve the LockInfo object from the UserFileSystemItem.Lock property and sent the lock-token to the server as part of the update request:

protected async Task<string> CreateOrUpdateFileAsync(
    string remoteStoragePath, IFolderBasicInfo newInfo, FileMode mode)
{
    if (mode == FileMode.Open)
    {
        // Get ETag.
        string eTag = await ETag.GetETagAsync(UserFileSystemPath);
                
        // Get lock-token.
        string lockToken = Lock?.LockToken;
    }

    ...
}

For Microsoft Office documents, to reduce the number of file updates in the remote storage, the document content is being sent to the remote storage only when the document is closed, before the unlock.

Unlocking

When the item in the remote storage must be unlocked, the UserFileSystemItem.LockAsync() method is called with a lock-token saved during the lock operation:

public async Task UnlockAsync(string lockToken)
{
    UnlockServerItem(RemoteStoragePath, lockToken);
}

To manually unlock the item, call the RemoteStorageRawItem.UnlockAsync() method. It will call the UserFileSystemItem.UnlockAsync() method, update the lock icon in the Windows File Manager Status column, and delete the file storing information about the lock from the local file system.

await new RemoteStorageRawItem(userFileSystemPath, Logger).UnlockAsync();

Displaying the Lock Status

To show that the item is locked by a third party in Windows File Manager set the FileSystemItemBasicInfo.LockedByAnotherUser property to true in Mapping.GetUserFileSysteItemBasicInfo() method implementation:

public static FileSystemItemBasicInfo GetUserFileSysteItemBasicInfo(
    FileSystemInfo remoteStorageItem)
{
    FileSystemItemBasicInfo userFileSystemItem = new FileBasicInfo();
    ...
    userFileSystemItem.LockedByAnotherUser = true;
    ...
    return userFileSystemItem;
}

This will show the lock icon in the Status column as well as will set the read-only attribute on files. When the user opens a Microsoft Office document it will be opened as read-only in this case.

As soon as setting read-only attribute marks the item as not In-sync, the StorageProviderInSyncPolicy.FileReadOnlyAttribute must NOT be included into the StorageProviderSyncRootInfo.InSyncPolicy when registering the file system root:

storageInfo.InSyncPolicy =
    StorageProviderInSyncPolicy.FileCreationTime    | 
    StorageProviderInSyncPolicy.DirectoryCreationTime |
    StorageProviderInSyncPolicy.FileLastWriteTime   | 
    StorageProviderInSyncPolicy.DirectoryLastWriteTime |
    StorageProviderInSyncPolicy.FileHiddenAttribute | 
    StorageProviderInSyncPolicy.DirectoryHiddenAttribute |
    StorageProviderInSyncPolicy.FileSystemAttribute | 
    StorageProviderInSyncPolicy.DirectorySystemAttribute;

 

Next Article:

User File System Engine for .NET Programming Guide