/*
* The Alluxio Open Foundation licenses this work under the Apache License, version 2.0
* (the "License"). You may not use this work except in compliance with the License, which is
* available at www.apache.org/licenses/LICENSE-2.0
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied, as more fully set forth in the License.
*
* See the NOTICE file distributed with this work for information regarding copyright ownership.
*/
package alluxio.client.file;
import alluxio.AbstractMasterClient;
import alluxio.AlluxioURI;
import alluxio.Constants;
import alluxio.client.file.options.CheckConsistencyOptions;
import alluxio.client.file.options.CompleteFileOptions;
import alluxio.client.file.options.CreateDirectoryOptions;
import alluxio.client.file.options.CreateFileOptions;
import alluxio.client.file.options.DeleteOptions;
import alluxio.client.file.options.FreeOptions;
import alluxio.client.file.options.GetStatusOptions;
import alluxio.client.file.options.ListStatusOptions;
import alluxio.client.file.options.LoadMetadataOptions;
import alluxio.client.file.options.MountOptions;
import alluxio.client.file.options.SetAttributeOptions;
import alluxio.thrift.AlluxioService;
import alluxio.thrift.FileSystemMasterClientService;
import alluxio.thrift.GetNewBlockIdForFileTOptions;
import alluxio.thrift.LoadMetadataTOptions;
import alluxio.thrift.RenameTOptions;
import alluxio.thrift.ScheduleAsyncPersistenceTOptions;
import alluxio.thrift.UnmountTOptions;
import alluxio.wire.ThriftUtils;
import org.apache.thrift.TException;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.concurrent.ThreadSafe;
import javax.security.auth.Subject;
/**
* A wrapper for the thrift client to interact with the file system master, used by alluxio clients.
*
* Since thrift clients are not thread safe, this class is a wrapper to provide thread safety, and
* to provide retries.
*/
@ThreadSafe
public final class RetryHandlingFileSystemMasterClient extends AbstractMasterClient
implements FileSystemMasterClient {
private FileSystemMasterClientService.Client mClient = null;
/**
* Creates a new {@link RetryHandlingFileSystemMasterClient} instance.
*
* @param subject the subject
* @param masterAddress the master address
*/
protected static RetryHandlingFileSystemMasterClient create(Subject subject,
InetSocketAddress masterAddress) {
return new RetryHandlingFileSystemMasterClient(subject, masterAddress);
}
private RetryHandlingFileSystemMasterClient(Subject subject, InetSocketAddress masterAddress) {
super(subject, masterAddress);
}
@Override
protected AlluxioService.Client getClient() {
return mClient;
}
@Override
protected String getServiceName() {
return Constants.FILE_SYSTEM_MASTER_CLIENT_SERVICE_NAME;
}
@Override
protected long getServiceVersion() {
return Constants.FILE_SYSTEM_MASTER_CLIENT_SERVICE_VERSION;
}
@Override
protected void afterConnect() {
mClient = new FileSystemMasterClientService.Client(mProtocol);
}
@Override
public synchronized List<AlluxioURI> checkConsistency(final AlluxioURI path,
final CheckConsistencyOptions options) throws IOException {
return retryRPC(new RpcCallable<List<AlluxioURI>>() {
@Override
public List<AlluxioURI> call() throws TException {
List<String> inconsistentPaths =
mClient.checkConsistency(path.getPath(), options.toThrift()).getInconsistentPaths();
List<AlluxioURI> inconsistentUris = new ArrayList<>(inconsistentPaths.size());
for (String path : inconsistentPaths) {
inconsistentUris.add(new AlluxioURI(path));
}
return inconsistentUris;
}
});
}
@Override
public synchronized void createDirectory(final AlluxioURI path,
final CreateDirectoryOptions options) throws IOException {
retryRPC(new RpcCallable<Void>() {
@Override
public Void call() throws TException {
mClient.createDirectory(path.getPath(), options.toThrift());
return null;
}
});
}
@Override
public synchronized void createFile(final AlluxioURI path, final CreateFileOptions options)
throws IOException {
retryRPC(new RpcCallable<Void>() {
@Override
public Void call() throws TException {
mClient.createFile(path.getPath(), options.toThrift());
return null;
}
});
}
@Override
public synchronized void completeFile(final AlluxioURI path, final CompleteFileOptions options)
throws IOException {
retryRPC(new RpcCallable<Void>() {
@Override
public Void call() throws TException {
mClient.completeFile(path.getPath(), options.toThrift());
return null;
}
});
}
@Override
public synchronized void delete(final AlluxioURI path, final DeleteOptions options)
throws IOException {
retryRPC(new RpcCallable<Void>() {
@Override
public Void call() throws TException {
mClient.remove(path.getPath(), options.isRecursive(), options.toThrift());
return null;
}
});
}
@Override
public synchronized void free(final AlluxioURI path, final FreeOptions options)
throws IOException {
retryRPC(new RpcCallable<Void>() {
@Override
public Void call() throws TException {
mClient.free(path.getPath(), options.isRecursive(), options.toThrift());
return null;
}
});
}
@Override
public synchronized URIStatus getStatus(final AlluxioURI path, final GetStatusOptions options)
throws IOException {
return retryRPC(new RpcCallable<URIStatus>() {
@Override
public URIStatus call() throws TException {
return new URIStatus(ThriftUtils
.fromThrift(mClient.getStatus(path.getPath(), options.toThrift()).getFileInfo()));
}
});
}
@Override
public synchronized long getNewBlockIdForFile(final AlluxioURI path) throws IOException {
return retryRPC(new RpcCallable<Long>() {
@Override
public Long call() throws TException {
return mClient.getNewBlockIdForFile(path.getPath(), new GetNewBlockIdForFileTOptions())
.getId();
}
});
}
@Override
public synchronized List<URIStatus> listStatus(final AlluxioURI path,
final ListStatusOptions options) throws IOException {
return retryRPC(new RpcCallable<List<URIStatus>>() {
@Override
public List<URIStatus> call() throws TException {
List<URIStatus> result = new ArrayList<URIStatus>();
for (alluxio.thrift.FileInfo fileInfo : mClient
.listStatus(path.getPath(), options.toThrift()).getFileInfoList()) {
result.add(new URIStatus(ThriftUtils.fromThrift(fileInfo)));
}
return result;
}
});
}
@Override
public synchronized void loadMetadata(final AlluxioURI path,
final LoadMetadataOptions options) throws IOException {
retryRPC(new RpcCallable<Long>() {
@Override
public Long call() throws TException {
return mClient
.loadMetadata(path.toString(), options.isRecursive(), new LoadMetadataTOptions())
.getId();
}
});
}
@Override
public synchronized void mount(final AlluxioURI alluxioPath, final AlluxioURI ufsPath,
final MountOptions options) throws IOException {
retryRPC(new RpcCallable<Void>() {
@Override
public Void call() throws TException {
mClient.mount(alluxioPath.toString(), ufsPath.toString(), options.toThrift());
return null;
}
});
}
@Override
public synchronized void rename(final AlluxioURI src, final AlluxioURI dst) throws IOException {
retryRPC(new RpcCallable<Void>() {
@Override
public Void call() throws TException {
mClient.rename(src.getPath(), dst.getPath(), new RenameTOptions());
return null;
}
});
}
@Override
public synchronized void setAttribute(final AlluxioURI path, final SetAttributeOptions options)
throws IOException {
retryRPC(new RpcCallable<Void>() {
@Override
public Void call() throws TException {
mClient.setAttribute(path.getPath(), options.toThrift());
return null;
}
});
}
@Override
public synchronized void scheduleAsyncPersist(final AlluxioURI path) throws IOException {
retryRPC(new RpcCallable<Void>() {
@Override
public Void call() throws TException {
mClient.scheduleAsyncPersistence(path.getPath(), new ScheduleAsyncPersistenceTOptions());
return null;
}
});
}
@Override
public synchronized void unmount(final AlluxioURI alluxioPath) throws IOException {
retryRPC(new RpcCallable<Void>() {
@Override
public Void call() throws TException {
mClient.unmount(alluxioPath.toString(), new UnmountTOptions());
return null;
}
});
}
}