Search in sources :

Example 1 with DirListPlus3

use of org.apache.hadoop.nfs.nfs3.response.READDIRPLUS3Response.DirListPlus3 in project hadoop by apache.

the class READDIRPLUS3Response method deserialize.

public static READDIRPLUS3Response deserialize(XDR xdr) {
    int status = xdr.readInt();
    xdr.readBoolean();
    Nfs3FileAttributes postOpDirAttr = Nfs3FileAttributes.deserialize(xdr);
    long cookieVerf = 0;
    ArrayList<EntryPlus3> entries = new ArrayList<EntryPlus3>();
    DirListPlus3 dirList = null;
    if (status == Nfs3Status.NFS3_OK) {
        cookieVerf = xdr.readHyper();
        while (xdr.readBoolean()) {
            EntryPlus3 e = EntryPlus3.deseralize(xdr);
            entries.add(e);
        }
        boolean eof = xdr.readBoolean();
        EntryPlus3[] allEntries = new EntryPlus3[entries.size()];
        entries.toArray(allEntries);
        dirList = new DirListPlus3(allEntries, eof);
    }
    return new READDIRPLUS3Response(status, postOpDirAttr, cookieVerf, dirList);
}
Also used : Nfs3FileAttributes(org.apache.hadoop.nfs.nfs3.Nfs3FileAttributes) ArrayList(java.util.ArrayList)

Example 2 with DirListPlus3

use of org.apache.hadoop.nfs.nfs3.response.READDIRPLUS3Response.DirListPlus3 in project hadoop by apache.

the class RpcProgramNfs3 method readdirplus.

@VisibleForTesting
READDIRPLUS3Response readdirplus(XDR xdr, SecurityHandler securityHandler, SocketAddress remoteAddress) {
    if (!checkAccessPrivilege(remoteAddress, AccessPrivilege.READ_ONLY)) {
        return new READDIRPLUS3Response(Nfs3Status.NFS3ERR_ACCES);
    }
    DFSClient dfsClient = clientCache.getDfsClient(securityHandler.getUser());
    if (dfsClient == null) {
        return new READDIRPLUS3Response(Nfs3Status.NFS3ERR_SERVERFAULT);
    }
    READDIRPLUS3Request request = null;
    try {
        request = READDIRPLUS3Request.deserialize(xdr);
    } catch (IOException e) {
        LOG.error("Invalid READDIRPLUS request");
        return new READDIRPLUS3Response(Nfs3Status.NFS3ERR_INVAL);
    }
    FileHandle handle = request.getHandle();
    long cookie = request.getCookie();
    if (cookie < 0) {
        LOG.error("Invalid READDIRPLUS request, with negative cookie: " + cookie);
        return new READDIRPLUS3Response(Nfs3Status.NFS3ERR_INVAL);
    }
    long dirCount = request.getDirCount();
    if (dirCount <= 0) {
        LOG.info("Nonpositive dircount in invalid READDIRPLUS request: " + dirCount);
        return new READDIRPLUS3Response(Nfs3Status.NFS3ERR_INVAL);
    }
    int maxCount = request.getMaxCount();
    if (maxCount <= 0) {
        LOG.info("Nonpositive maxcount in invalid READDIRPLUS request: " + maxCount);
        return new READDIRPLUS3Response(Nfs3Status.NFS3ERR_INVAL);
    }
    if (LOG.isDebugEnabled()) {
        LOG.debug("NFS READDIRPLUS fileId: " + handle.getFileId() + " cookie: " + cookie + " dirCount: " + dirCount + " maxCount: " + maxCount + " client: " + remoteAddress);
    }
    HdfsFileStatus dirStatus;
    DirectoryListing dlisting;
    Nfs3FileAttributes postOpDirAttr;
    long dotdotFileId = 0;
    HdfsFileStatus dotdotStatus = null;
    try {
        String dirFileIdPath = Nfs3Utils.getFileIdPath(handle);
        dirStatus = dfsClient.getFileInfo(dirFileIdPath);
        if (dirStatus == null) {
            LOG.info("Can't get path for fileId: " + handle.getFileId());
            return new READDIRPLUS3Response(Nfs3Status.NFS3ERR_STALE);
        }
        if (!dirStatus.isDir()) {
            LOG.error("Can't readdirplus for regular file, fileId: " + handle.getFileId());
            return new READDIRPLUS3Response(Nfs3Status.NFS3ERR_NOTDIR);
        }
        long cookieVerf = request.getCookieVerf();
        if ((cookieVerf != 0) && (cookieVerf != dirStatus.getModificationTime())) {
            if (aixCompatMode) {
                // The AIX NFS client misinterprets RFC-1813 and will repeatedly send
                // the same cookieverf value even across VFS-level readdir calls,
                // instead of getting a new cookieverf for every VFS-level readdir
                // call. This means that whenever a readdir call is made by an AIX NFS
                // client for a given directory, and that directory is subsequently
                // modified, thus changing its mtime, no later readdir calls will
                // succeed for that directory from AIX until the FS is
                // unmounted/remounted. See HDFS-6549 for more info.
                LOG.warn("AIX compatibility mode enabled, ignoring cookieverf " + "mismatches.");
            } else {
                LOG.error("cookieverf mismatch. request cookieverf: " + cookieVerf + " dir cookieverf: " + dirStatus.getModificationTime());
                return new READDIRPLUS3Response(Nfs3Status.NFS3ERR_BAD_COOKIE, Nfs3Utils.getFileAttr(dfsClient, dirFileIdPath, iug), 0, null);
            }
        }
        if (cookie == 0) {
            // Get dotdot fileId
            String dotdotFileIdPath = dirFileIdPath + "/..";
            dotdotStatus = dfsClient.getFileInfo(dotdotFileIdPath);
            if (dotdotStatus == null) {
                // This should not happen
                throw new IOException("Can't get path for handle path: " + dotdotFileIdPath);
            }
            dotdotFileId = dotdotStatus.getFileId();
        }
        // Get the list from the resume point
        byte[] startAfter;
        if (cookie == 0) {
            startAfter = HdfsFileStatus.EMPTY_NAME;
        } else {
            String inodeIdPath = Nfs3Utils.getFileIdPath(cookie);
            startAfter = inodeIdPath.getBytes(Charset.forName("UTF-8"));
        }
        dlisting = listPaths(dfsClient, dirFileIdPath, startAfter);
        postOpDirAttr = Nfs3Utils.getFileAttr(dfsClient, dirFileIdPath, iug);
        if (postOpDirAttr == null) {
            LOG.info("Can't get path for fileId: " + handle.getFileId());
            return new READDIRPLUS3Response(Nfs3Status.NFS3ERR_STALE);
        }
    } catch (IOException e) {
        LOG.warn("Exception ", e);
        int status = mapErrorStatus(e);
        return new READDIRPLUS3Response(status);
    }
    // Set up the dirents in the response
    HdfsFileStatus[] fstatus = dlisting.getPartialListing();
    int n = (int) Math.min(fstatus.length, dirCount - 2);
    boolean eof = (n >= fstatus.length) && !dlisting.hasMore();
    READDIRPLUS3Response.EntryPlus3[] entries;
    if (cookie == 0) {
        entries = new READDIRPLUS3Response.EntryPlus3[n + 2];
        entries[0] = new READDIRPLUS3Response.EntryPlus3(postOpDirAttr.getFileId(), ".", 0, postOpDirAttr, new FileHandle(postOpDirAttr.getFileId()));
        entries[1] = new READDIRPLUS3Response.EntryPlus3(dotdotFileId, "..", dotdotFileId, Nfs3Utils.getNfs3FileAttrFromFileStatus(dotdotStatus, iug), new FileHandle(dotdotFileId));
        for (int i = 2; i < n + 2; i++) {
            long fileId = fstatus[i - 2].getFileId();
            FileHandle childHandle = new FileHandle(fileId);
            Nfs3FileAttributes attr;
            try {
                attr = writeManager.getFileAttr(dfsClient, childHandle, iug);
            } catch (IOException e) {
                LOG.error("Can't get file attributes for fileId: " + fileId, e);
                continue;
            }
            entries[i] = new READDIRPLUS3Response.EntryPlus3(fileId, fstatus[i - 2].getLocalName(), fileId, attr, childHandle);
        }
    } else {
        // Resume from last readdirplus. If the cookie is "..", the result
        // list is up the directory content since HDFS uses name as resume point.
        entries = new READDIRPLUS3Response.EntryPlus3[n];
        for (int i = 0; i < n; i++) {
            long fileId = fstatus[i].getFileId();
            FileHandle childHandle = new FileHandle(fileId);
            Nfs3FileAttributes attr;
            try {
                attr = writeManager.getFileAttr(dfsClient, childHandle, iug);
            } catch (IOException e) {
                LOG.error("Can't get file attributes for fileId: " + fileId, e);
                continue;
            }
            entries[i] = new READDIRPLUS3Response.EntryPlus3(fileId, fstatus[i].getLocalName(), fileId, attr, childHandle);
        }
    }
    DirListPlus3 dirListPlus = new READDIRPLUS3Response.DirListPlus3(entries, eof);
    return new READDIRPLUS3Response(Nfs3Status.NFS3_OK, postOpDirAttr, dirStatus.getModificationTime(), dirListPlus);
}
Also used : DFSClient(org.apache.hadoop.hdfs.DFSClient) DirectoryListing(org.apache.hadoop.hdfs.protocol.DirectoryListing) FileHandle(org.apache.hadoop.nfs.nfs3.FileHandle) Nfs3FileAttributes(org.apache.hadoop.nfs.nfs3.Nfs3FileAttributes) READDIRPLUS3Response(org.apache.hadoop.nfs.nfs3.response.READDIRPLUS3Response) IOException(java.io.IOException) READDIRPLUS3Request(org.apache.hadoop.nfs.nfs3.request.READDIRPLUS3Request) HdfsFileStatus(org.apache.hadoop.hdfs.protocol.HdfsFileStatus) DirListPlus3(org.apache.hadoop.nfs.nfs3.response.READDIRPLUS3Response.DirListPlus3) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Aggregations

Nfs3FileAttributes (org.apache.hadoop.nfs.nfs3.Nfs3FileAttributes)2 VisibleForTesting (com.google.common.annotations.VisibleForTesting)1 IOException (java.io.IOException)1 ArrayList (java.util.ArrayList)1 DFSClient (org.apache.hadoop.hdfs.DFSClient)1 DirectoryListing (org.apache.hadoop.hdfs.protocol.DirectoryListing)1 HdfsFileStatus (org.apache.hadoop.hdfs.protocol.HdfsFileStatus)1 FileHandle (org.apache.hadoop.nfs.nfs3.FileHandle)1 READDIRPLUS3Request (org.apache.hadoop.nfs.nfs3.request.READDIRPLUS3Request)1 READDIRPLUS3Response (org.apache.hadoop.nfs.nfs3.response.READDIRPLUS3Response)1 DirListPlus3 (org.apache.hadoop.nfs.nfs3.response.READDIRPLUS3Response.DirListPlus3)1