All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.daos.dfs.DaosFsClient Maven / Gradle / Ivy

There is a newer version: 2.4.1
Show newest version
/*
 * (C) Copyright 2018-2021 Intel Corporation.
 *
 * SPDX-License-Identifier: BSD-2-Clause-Patent
 */

package io.daos.dfs;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import io.daos.*;
import org.apache.commons.lang.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A shareable Java DAOS DFS client to wrap all DFS related operations, including
 * 
  • mount/unmount DAOS FS on container
  • *
  • call DFS methods, including release DFS files in the cleaner executor
  • *
  • construct {@link DaosFile} instance
  • * It registers itself to shutdown manager in {@link DaosClient} to release resources in case of abnormal shutdown. * *

    * If you have poolId specified, but no containerId, DAOS FS will be mounted on * non-readonly root container with UUID {@link #ROOT_CONT_UUID}. Thus, you need to make sure the pool * doesn't have root container yet. * *

    * User cannot instantiate this class directly since we need to make sure single instance of * {@linkplain DaosFsClient client} per pool and container. User should get this object from * {@link DaosFsClientBuilder}. * *

    * After getting {@linkplain DaosFsClient client}, user usually get {@link DaosFile} object via {@linkplain #getFile} * methods. * *

    * For example, user can simply create {@linkplain DaosFsClient client} and {@link DaosFile} with all default values * by following code. * * DaosFsClient.DaosFsClientBuilder builder = new DaosFsClient.DaosFsClientBuilder(); * builder.poolId(poolId).containerId(contId); * DaosFsClient client = builder.build(); * * DaosFile daosFile = client.getFile("/path"); * if (!daosFile.exists()){ * daosFile.mkdir(); * } * * *

    * User can also call some utility methods directly in this object for convenience without creating new * {@link DaosFile}. User should prefer these utility methods to {@link DaosFile} if it's only one-shot DAOS file * operation. Whilst {@link DaosFile} should be created for multiple DAOS file operations because DAOS FS object is * cached inside. We don't need to query/open DAOS FS object for each DAOS operation. * * @see DaosFsClientBuilder * @see DaosFile * @see Cleaner */ public final class DaosFsClient extends ShareableClient implements ForceCloseable { private long dfsPtr; private long contPtr; public static final String ROOT_CONT_UUID = "ffffffff-ffff-ffff-ffff-ffffffffffff"; private static final Logger log = LoggerFactory.getLogger(DaosFsClient.class); static { DaosClient.initClient(); } private final ExecutorService cleanerExe = Executors.newSingleThreadExecutor((r) -> { Thread thread = new Thread(r, "DAOS file object cleaner thread"); thread.setDaemon(true); return thread; }); // keyed by poolId+contId private static final Map pcFsMap = new ConcurrentHashMap<>(); private DaosFsClient(String poolId, String contId, DaosFsClientBuilder builder) { super(poolId, contId, builder); } private void init() throws IOException { if (isInited()) { return; } DaosFsClientBuilder builder = getBuilder(); setClient(builder.buildDaosClient()); DaosClient client = getClient(); if (builder.getContId() != null && !ROOT_CONT_UUID.equals(builder.getContId())) { contPtr = client.getContPtr(); dfsPtr = mountFileSystem(client.getPoolPtr(), contPtr, builder.readOnlyFs); if (log.isDebugEnabled()) { log.debug("mounted FS {}", dfsPtr); } } else { setContId(ROOT_CONT_UUID); contPtr = -1; dfsPtr = mountFileSystem(client.getPoolPtr(), -1, builder.readOnlyFs); if (log.isDebugEnabled()) { log.debug("mounted FS {} on root container", dfsPtr); } } cleanerExe.execute(new Cleaner.CleanerTask()); if (log.isDebugEnabled()) { log.debug("cleaner task running"); } client.registerForShutdown(this); setInited(true); log.info("DaosFsClient for {}, {} initialized", builder.getPoolId(), builder.getContId()); } public long getDfsPtr() { return dfsPtr; } @Override protected DaosFsClientBuilder getBuilder() { return (DaosFsClientBuilder)super.getBuilder(); } /** * mount DAOS FS on specific pool and container. * * @param poolPtr * pointer to pool object * @param contPtr * pointer to container object * @param readOnly * is read only file system * @return pointer of native mounted DAOS FS object. * @throws IOException * {@link DaosIOException} */ public static synchronized long mountFileSystem(long poolPtr, long contPtr, boolean readOnly) throws IOException { if (contPtr != -1) { return dfsMountFs(poolPtr, contPtr, readOnly); } return dfsMountFsOnRoot(poolPtr); } /** * Decrement reference first. If there is no more reference, then disconnect this client from DAOS server. * After actual disconnect, * - DAOS FS is unmounted * - container is closed * - pool is closed * - cleaner task is stopped * - this instance is removed from cache * *

    * User should call this method before application exiting to release resources. It's synchronized method * so that the two synchronized methods, {@link #incrementRef()} and {@link #decrementRef()}, for maintaining * references can be safely called. * *

    * If there are still references to this object, no actual disconnect will be called. User can call * {@link #getRefCnt()} method to double-check the reference count of this object. * * @param force * close client forcibly? * @throws IOException * {@link DaosIOException} */ @Override protected synchronized void disconnect(boolean force) throws IOException { decrementRef(); DaosFsClientBuilder builder = getBuilder(); if (force || getRefCnt() <= 0) { if (isInited() && dfsPtr != 0) { log.debug("dfsptr: " + dfsPtr); cleanerExe.shutdownNow(); if (log.isDebugEnabled()) { log.debug("cleaner stopped"); } log.debug("dfsptr: " + dfsPtr); if (contPtr == -1) { dfsUnmountFsOnRoot(dfsPtr); if (log.isDebugEnabled()) { log.debug("FS unmounted {} from root container", dfsPtr); } } else { dfsUnmountFs(dfsPtr); if (log.isDebugEnabled()) { log.debug("FS unmounted {}", dfsPtr); } } if (force) { getClient().forceClose(); } else { getClient().close(); } log.info("DaosFsClient for {}, {} disconnected", builder.getPoolId(), builder.getContId()); } setInited(false); pcFsMap.remove(builder.getPoolId() + builder.getContId()); } } /** * Get {@link DaosFile} denoted by path. * * @param path * path of file * @return DaosFile */ public DaosFile getFile(String path) { return getFile(path, getBuilder().defaultFileAccessFlags); } /** * Get {@link DaosFile} denoted by path with giving accessFlags. * * @param path * path of file * @param accessFlags * file access flags, see {@link DaosFsClientBuilder#defaultFileAccessFlags(int)} for its possible values * @return DaosFile */ public DaosFile getFile(String path, int accessFlags) { return new DaosFile(path, accessFlags, this); } /** * Get {@link DaosFile} denoted by parent and path. * * @param parent * parent path of file * @param path * path of file * @return DaosFile */ public DaosFile getFile(String parent, String path) { return getFile(parent, path, getBuilder().defaultFileAccessFlags); } /** * Get {@link DaosFile} denoted by parent and path with giving accessFlags. * * @param parent * parent path of file * @param path * path of file * @param accessFlags * file access flags, see {@link DaosFsClientBuilder#defaultFileAccessFlags(int)} for its possible values * @return DaosFile */ public DaosFile getFile(String parent, String path, int accessFlags) { return new DaosFile(parent, path, accessFlags, this); } /** * Get {@link DaosFile} denoted by parent object and path. * * @param parent * parent file object * @param path * path of file * @return DaosFile */ public DaosFile getFile(DaosFile parent, String path) { return getFile(parent, path, getBuilder().defaultFileAccessFlags); } /** * Get {@link DaosFile} denoted by parent object and path with giving * accessFlags. * * @param parent * parent file object * @param path * path of file * @param accessFlags * file access flags, see {@link DaosFsClientBuilder#defaultFileAccessFlags(int)} for its possible values * @return DaosFile */ public DaosFile getFile(DaosFile parent, String path, int accessFlags) { return new DaosFile(parent, path, accessFlags, this); } /** * move file from srcPath to destPath. * * @param srcPath * source path * @param destPath * destination path * @throws IOException * {@link DaosIOException} */ public void move(String srcPath, String destPath) throws IOException { String src = DaosUtils.normalize(srcPath); String dest = DaosUtils.normalize(destPath); if (dest.length() > src.length() && dest.startsWith(src + '/')) { throw new IOException("cannot move to subdirectory of itself. " + src + " to " + dest); } move(dfsPtr, src, dest); } /** * move file from srcName under directory denoted by srcParentObjId * to destName under directory denoted by destParentObjId. * This method is more efficient than {@link #move(String, String)} since we don't need to open * both source directory and destination directory. * * @param srcParentObjId * object id of source directory * @param srcName * source file name without any path * @param destParentObjId * object id of destination directory * @param destName * destination file name without any path * @throws IOException * {@link DaosIOException} */ public void move(long srcParentObjId, String srcName, long destParentObjId, String destName) throws IOException { srcName = DaosUtils.normalize(srcName); if (srcName.indexOf('/') >= 0) { throw new IllegalArgumentException("srcName should not contain any path"); } if (destName.indexOf('/') >= 0) { throw new IllegalArgumentException("destName should not contain any path"); } move(dfsPtr, srcParentObjId, srcName, destParentObjId, destName); } /** * delete file or directory denoted by path. Non-empty directory will be deleted * if force is true. * * @param path * path of file to be deleted * @param force * force delete if directory is not empty * @return true for deleted successfully, false for other cases, like not existed or failed to delete * @throws IOException * {@link DaosIOException} */ public boolean delete(String path, boolean force) throws IOException { path = DaosUtils.normalize(path); String[] pc = DaosUtils.parsePath(path); return delete(dfsPtr, pc.length == 2 ? pc[0] : null, pc[1], force); } /** * delete file or directory denoted by path without force deletion. * * @param path * path of file to be deleted * @return true for deleted successfully, false for other cases, like not existed or failed to delete * @throws IOException * {@link DaosIOException} */ public boolean delete(String path) throws IOException { return delete(DaosUtils.normalize(path), false); } /** * create directory denoted by path. * If recursive is true, ancestor path will be created if they don't exist. * * @param path * path of directory * @param recursive * create directories recursively * @throws IOException * {@link DaosIOException} */ public void mkdir(String path, boolean recursive) throws IOException { mkdir(DaosUtils.normalize(path), getBuilder().defaultFileMode, recursive); } /** * create directory denoted by path with giving mode. * If recursive is true, ancestor path will be created if they don't exist. * * @param path * path of directory * @param mode * file mode, see {@link DaosFsClientBuilder#defaultFileMode(int)} for its possible values * @param recursive * create directories recursively * @throws IOException * {@link DaosIOException} */ public void mkdir(String path, int mode, boolean recursive) throws IOException { try { mkdir(dfsPtr, DaosUtils.normalize(path), mode, recursive); } catch (IOException e) { if (recursive && (e instanceof DaosIOException)) { if (((DaosIOException) e).getErrorCode() == Constants.ERROR_CODE_FILE_EXIST) { return; } } throw e; } } /** * check existence of file denoted by path. * * @param path * path of file * @return true if exists. false otherwise * @throws IOException * {@link DaosIOException} */ public boolean exists(String path) throws IOException { long objId = 0; try { objId = dfsLookup(dfsPtr, DaosUtils.normalize(path), getBuilder().defaultFileAccessFlags, -1); return true; } catch (Exception e) { if (!(e instanceof DaosIOException)) { //unexpected exception throw new DaosIOException(e); } //verify error code to determine existence, if it's other error code, throw it anyway. DaosIOException de = (DaosIOException) e; if (de.getErrorCode() != Constants.ERROR_CODE_NOT_EXIST) { throw de; } return false; } finally { if (objId > 0) { dfsRelease(objId); } } } // ------------------native methods------------------ /** * move file object denoted by srcPath to new path denoted by destPath. * * @param dfsPtr * pointer of dfs object * @param srcPath * full path of source * @param destPath * full path of destination * @throws IOException * {@link DaosIOException} */ native void move(long dfsPtr, String srcPath, String destPath) throws IOException; /** * move file from srcName under directory denoted by srcParentObjId * to destName under directory denoted by destParentObjId. * This method is more efficient than {@link #move(String, String)} since we don't need to open * both source directory and destination directory. * * @param dfsPtr * pointer of dfs object * @param srcParentObjId * object id of source directory * @param srcName * source name * @param destParentObjId * object id of destination directory * @param destName * destination name * @throws IOException * {@link DaosIOException} */ native void move(long dfsPtr, long srcParentObjId, String srcName, long destParentObjId, String destName) throws IOException; /** * make directory denoted by path. * * @param dfsPtr * pointer of dfs object * @param path * full path * @param mode * file mode, see {@link DaosFsClientBuilder#defaultFileMode(int)} for possible values * @param recursive * true to create all ancestors, false to create just itself * @throws IOException * {@link DaosIOException} */ native void mkdir(long dfsPtr, String path, int mode, boolean recursive) throws IOException; /** * create new file. * * @param dfsPtr * pointer of dfs object * @param parentPath * null for root * @param name * file name * @param mode * file mode, see {@link DaosFsClientBuilder#defaultFileMode(int)} for possible values * @param accessFlags * file access flags, see {@link DaosFsClientBuilder#defaultFileAccessFlags(int)} for its possible values * @param objType * object type in string, see {@link DaosFsClientBuilder#defaultFileObjType} for its possible values * @param chunkSize * file chunk size * @param createParent * if create directory if parent doesn't exist * @return DAOS FS object id * @throws IOException * {@link DaosIOException} */ native long createNewFile(long dfsPtr, String parentPath, String name, int mode, int accessFlags, String objType, int chunkSize, boolean createParent) throws IOException; /** * delete file with name from parentPath. * * @param dfsPtr * pointer of dfs object * @param parentPath * null for root * @param name * file name * @param force * true to delete directory if it's not empty * @return true for deleted successfully, false for other cases, like not existed or failed to delete * @throws IOException * {@link DaosIOException} */ native boolean delete(long dfsPtr, String parentPath, String name, boolean force) throws IOException; // DAOS FS corresponding methods /** * set prefix. * * @param dfsPtr * pointer to dfs object * @param prefix * path prefix * @throws IOException * {@link DaosIOException} */ native void dfsSetPrefix(long dfsPtr, String prefix) throws IOException; /** * open a file with opened parent specified by parentObjId. * *

    * @param dfsPtr * pointer of dfs object * @param parentObjId * parent object id * @param name * file name * @param flags * file flags * @param bufferAddress address of direct {@link java.nio.ByteBuffer} for holding all information of * {@link StatAttributes}, -1 if you don't want to get {@link StatAttributes} * @return DAOS FS object id * @throws IOException * {@link DaosIOException} */ native long dfsLookup(long dfsPtr, long parentObjId, String name, int flags, long bufferAddress) throws IOException; /** * Same as {@link #dfsLookup(long, long, String, int, long)} except parent file is not opened. * * @param dfsPtr * pointer of dfs object * @param path * file path * @param flags * file flags * @param bufferAddress address of direct {@link java.nio.ByteBuffer} for holding all information of * {@link StatAttributes} * @return DAOS FS object id * @throws IOException * {@link DaosIOException} */ native long dfsLookup(long dfsPtr, String path, int flags, long bufferAddress) throws IOException; /** * get file length for opened FS object. * * @param dfsPtr * pointer of dfs object * @param objId * object id * @return file length * @throws IOException * {@link DaosIOException} */ native long dfsGetSize(long dfsPtr, long objId) throws IOException; /** * duplicate opened FS object. * * @param dfsPtr * pointer of dfs object * @param objId * object id * @param flags * file flags * @return FS object id of duplication * @throws IOException * {@link DaosIOException} */ native long dfsDup(long dfsPtr, long objId, int flags) throws IOException; /** * release opened FS object. * * @param objId * object id * @throws IOException * {@link DaosIOException} */ native void dfsRelease(long objId) throws IOException; /** * allocate native dfs desc struct. * * @param descBufAddress * memory address of desc buffer. * @return handle of native dfs desc */ native static long allocateDfsDesc(long descBufAddress); /** * release native dfs desc struct. * * @param nativeHandle * handle of native dfs desc */ native static void releaseDfsDesc(long nativeHandle); /** * read data from file to buffer. * * @param dfsPtr * pointer of dfs object * @param objId * object id * @param bufferAddress * address of direct buffer * @param offset * file offset * @param len * length in byte to read from file * @return number of bytes actual read * @throws IOException * {@link DaosIOException} */ native long dfsRead(long dfsPtr, long objId, long bufferAddress, long offset, long len) throws IOException; native void dfsReadAsync(long dfsPtr, long objId, long memoryAddress) throws IOException; /** * write data from buffer to file. * * @param dfsPtr * pointer of dfs object * @param objId * object id * @param bufferAddress * address of direct buffer * @param offset * file offset * @param len * length in byte to write to file * @return number of bytes actual written * @throws IOException * {@link DaosIOException} */ native long dfsWrite(long dfsPtr, long objId, long bufferAddress, long offset, long len) throws IOException; native void dfsWriteAsync(long dfsPtr, long objId, long memoryAddress) throws IOException; /** * read children. * * @param dfsPtr * pointer of dfs object * @param objId * object id * @param maxEntries * -1 for no limit * @return file names separated by ',' */ native String dfsReadDir(long dfsPtr, long objId, int maxEntries) throws IOException; /** * get FS object status attribute into direct {@link java.nio.ByteBuffer}. * Order of fields to be read. * objId = buffer.getLong(); * mode = buffer.getInt(); * uid = buffer.getInt(); * gid = buffer.getInt(); * blockCnt = buffer.getLong(); * blockSize = buffer.getLong(); * length = buffer.getLong(); * accessTime = buffer.getLong() buffer.getLong(); * modifyTime = buffer.getLong() buffer.getLong(); * createTime = buffer.getLong() buffer.getLong(); * file = buffer.get() > 0; * * @param dfsPtr * pointer of dfs object * @param objId * object id * @param bufferAddress memory address of direct buffer. -1 if you don't want to retrieve stat actually. It's usually * for checking file existence. * @throws IOException * {@link DaosIOException} */ native void dfsOpenedObjStat(long dfsPtr, long objId, long bufferAddress) throws IOException; /** * set extended attribute. * * @param dfsPtr * pointer of dfs object * @param objId * object id * @param name * attribute name * @param value * attribute value * @param flags * attribute flags, possible values are, * {@link Constants#SET_XATTRIBUTE_REPLACE} * {@link Constants#SET_XATTRIBUTE_CREATE} * {@link Constants#SET_XATTRIBUTE_NO_CHECK} * @throws IOException * {@link DaosIOException} */ native void dfsSetExtAttr(long dfsPtr, long objId, String name, String value, int flags) throws IOException; /** * get extended attribute. * * @param dfsPtr * pointer of dfs object * @param objId * object id * @param name * attribute name * @param expectedValueLen * expected value length * @return attribute value * @throws IOException * {@link DaosIOException} */ native String dfsGetExtAttr(long dfsPtr, long objId, String name, int expectedValueLen) throws IOException; /** * remove extended attribute. * * @param dfsPtr * pointer of dfs object * @param objId * object id * @param name * attribute name * @throws IOException * {@link DaosIOException} */ native void dfsRemoveExtAttr(long dfsPtr, long objId, String name) throws IOException; /** * get chunk size. * * @param objId * object id * @return chunk size * @throws IOException * {@link DaosIOException} */ static native long dfsGetChunkSize(long objId) throws IOException; /** * get mode. * * @param objId * object id * @return file mode * @throws IOException * {@link DaosIOException} */ static native int dfsGetMode(long objId) throws IOException; /** * check if it's directory by providing mode. * * @param mode * file mode * @return true if directory. false otherwise * @throws IOException * {@link DaosIOException} */ static native boolean dfsIsDirectory(int mode) throws IOException; /** * mount FS on container. * * @param poolPtr * pointer to pool * @param contPtr * pointer to container * @param readOnly * read only filesystem * @return FS client pointer */ static native long dfsMountFs(long poolPtr, long contPtr, boolean readOnly) throws IOException; /** * mount FS on non-readonly root container. * * @param poolPtr * pointer to pool * @return pointer to dfs object * @throws IOException * {@link DaosIOException} */ static native long dfsMountFsOnRoot(long poolPtr) throws IOException; /** * unmount FS from root container. * * @param poolPtr * pointer to pool * @throws IOException * {@link DaosIOException} */ static native void dfsUnmountFsOnRoot(long poolPtr) throws IOException; /** * unmount FS. * * @param dfsPtr * pointer to dfs object * @throws IOException * {@link DaosIOException} */ static native void dfsUnmountFs(long dfsPtr) throws IOException; /** * create UNS path with given data in bufferAddress in pool poolHandle. * A new container will be created with some properties from attribute. * Object type, pool UUID and container UUID are set to extended attribute of path. * * @param poolHandle * handle of pool * @param path * OS file path to set duns attributes. make sure file not existing * @param bufferAddress * buffer memory address of direct buffer which holds DunsAttribute data serialized by * protocol buffer * @param buffLen * length of buffer * @return UUID of container * @throws IOException * {@link DaosIOException} */ static native String dunsCreatePath(long poolHandle, String path, long bufferAddress, int buffLen) throws IOException; /** * extract and parse extended attributes from given path. * * @param path * OS file path * @return UNS attribute info in binary get from path, including object type, pool UUID and container UUID. * user should deserialize the data by {@link io.daos.dfs.uns.DunsAttribute} * @throws IOException * {@link DaosIOException} */ static native byte[] dunsResolvePath(String path) throws IOException; /** * get application info stored in attrName from path. * * @param path * OS file path * @param attrName * app-specific attribute name * @param maxLen * maximum length of attribute value * @return application info in string, key1=value1;key2=value2... * @throws IOException * {@link DaosIOException} */ static native String dunsGetAppInfo(String path, String attrName, int maxLen) throws IOException; /** * set application info to attrName on path. * * @param path * OS file path * @param attrName * app-specific attribute name * @param value * application info in string, key1=value1;key2=value2... * @throws IOException * {@link DaosIOException} */ static native void dunsSetAppInfo(String path, String attrName, String value) throws IOException; /** * Destroy a container and remove the path associated with it in the UNS. * * @param poolHandle * pool handle * @param path * OS file path * @throws IOException * {@link DaosIOException} */ static native void dunsDestroyPath(long poolHandle, String path) throws IOException; /** * parse input string to UNS attribute. * * @param input * attribute string * @return UNS attribute info in binary. * user should deserialize the data by {@link io.daos.dfs.uns.DunsAttribute} * @throws IOException * {@link DaosIOException} */ static native byte[] dunsParseAttribute(String input) throws IOException; /** * finalize DAOS client. * * @throws IOException * {@link DaosIOException} */ static synchronized native void daosFinalize() throws IOException; //------------------native methods end------------------ int getDefaultFileAccessFlags() { return getBuilder().defaultFileAccessFlags; } int getDefaultFileMode() { return getBuilder().defaultFileMode; } DaosObjectType getDefaultFileObjType() { return getBuilder().defaultFileObjType; } int getDefaultFileChunkSize() { return getBuilder().defaultFileChunkSize; } /** * A builder for constructing Java DAOS FS Client. All parameters should be specified here. This builder * makes sure single instance of {@link DaosFsClient} per pool and container. * *

    * poolId should be set at least. ROOT container will be used if containerId is not set. */ public static class DaosFsClientBuilder extends DaosClient.DaosClientBuilder { private int defaultFileChunkSize = Constants.FILE_DEFAULT_CHUNK_SIZE; private int defaultFileAccessFlags = Constants.ACCESS_FLAG_FILE_READWRITE; private int defaultFileMode = Constants.FILE_DEFAULT_FILE_MODE; private DaosObjectType defaultFileObjType = DaosObjectType.OC_SX; private boolean readOnlyFs = false; private boolean shareFsClient = true; /** * set default file access flag. * * @param defaultFileAccessFlags should be one of * {@link Constants#ACCESS_FLAG_FILE_CREATE} * {@link Constants#ACCESS_FLAG_FILE_READONLY} * {@link Constants#ACCESS_FLAG_FILE_READWRITE} * {@link Constants#ACCESS_FLAG_FILE_EXCL} * default is {@link Constants#ACCESS_FLAG_FILE_READWRITE} * @return DaosFsClientBuilder */ public DaosFsClientBuilder defaultFileAccessFlags(int defaultFileAccessFlags) { this.defaultFileAccessFlags = defaultFileAccessFlags; return this; } /** * set default file mode. You can override this value when create new file by * Scalling {@link DaosFile#createNewFile(int, DaosObjectType, int, boolean)}. * * @param defaultFileMode * should be octal value. Default is 0755 * @return DaosFsClientBuilder */ public DaosFsClientBuilder defaultFileMode(int defaultFileMode) { this.defaultFileMode = defaultFileMode; return this; } /** * set default file type. You can override this value when create new file by * calling {@link DaosFile#createNewFile(int, DaosObjectType, int, boolean)}. * * @param defaultFileObjType * default is {@link DaosObjectType#OC_SX} * @return DaosFsClientBuilder */ public DaosFsClientBuilder defaultFileType(DaosObjectType defaultFileObjType) { this.defaultFileObjType = defaultFileObjType; return this; } /** * set default file chunk size. You can override this value when create new file by * calling {@link DaosFile#createNewFile(int, DaosObjectType, int, boolean)}. * * @param defaultFileChunkSize * default is 0. DAOS will decide what default is. 1MB for now. * @return DaosFsClientBuilder */ public DaosFsClientBuilder defaultFileChunkSize(int defaultFileChunkSize) { this.defaultFileChunkSize = defaultFileChunkSize; return this; } /** * set FS readonly. * * @param readOnlyFs * default is false * @return DaosFsClientBuilder */ public DaosFsClientBuilder readOnlyFs(boolean readOnlyFs) { this.readOnlyFs = readOnlyFs; return this; } /** * share {@link DaosFsClient} instance or not. * * @param shareFsClient * default is true * @return DaosFsClientBuilder */ public DaosFsClientBuilder shareFsClient(boolean shareFsClient) { this.shareFsClient = shareFsClient; return this; } @Override public DaosFsClientBuilder clone() throws CloneNotSupportedException { return (DaosFsClientBuilder) super.clone(); } /** * Either return existing {@link DaosFsClient} instance or create new instance. Reference count of returned client * is increased by one. * * @return DaosFsClient * @throws IOException * {@link DaosIOException} */ @Override public DaosFsClient build() throws IOException { String poolId = getPoolId(); String contId = getContId(); DaosFsClientBuilder builder = (DaosFsClientBuilder) ObjectUtils.clone(this); DaosFsClient fsClient; if (!builder.shareFsClient) { fsClient = new DaosFsClient(poolId, contId, builder); } else { //check existing client if (poolId == null) { throw new IllegalArgumentException("need pool UUID."); } if (contId == null) { contId = ROOT_CONT_UUID; } String key = poolId + contId; fsClient = pcFsMap.get(key); if (fsClient == null) { fsClient = new DaosFsClient(poolId, contId, builder); pcFsMap.putIfAbsent(key, fsClient); } fsClient = pcFsMap.get(key); } synchronized (fsClient) { fsClient.init(); fsClient.incrementRef(); } return fsClient; } protected DaosClient buildDaosClient() throws IOException { return (DaosClient) super.build(); } } }





    © 2015 - 2024 Weber Informatics LLC | Privacy Policy