/** * Copyright 2014 NetApp Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.hadoop.fs.nfs; import java.io.IOException; import java.nio.ByteBuffer; import java.util.LinkedList; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.nfs.NfsTime; import org.apache.hadoop.nfs.nfs3.FileHandle; import org.apache.hadoop.nfs.nfs3.Nfs3Constant; import org.apache.hadoop.nfs.nfs3.Nfs3Constant.WriteStableHow; import org.apache.hadoop.nfs.nfs3.Nfs3DirList; import org.apache.hadoop.nfs.nfs3.Nfs3DirList.Nfs3DirEntry; import org.apache.hadoop.nfs.nfs3.Nfs3FileAttributes; import org.apache.hadoop.nfs.nfs3.Nfs3FileHandle; import org.apache.hadoop.nfs.nfs3.Nfs3Info; import org.apache.hadoop.nfs.nfs3.Nfs3Status; import org.apache.hadoop.nfs.nfs3.response.COMMIT3Response; import org.apache.hadoop.nfs.nfs3.response.CREATE3Response; import org.apache.hadoop.nfs.nfs3.response.FSINFO3Response; import org.apache.hadoop.nfs.nfs3.response.GETATTR3Response; import org.apache.hadoop.nfs.nfs3.response.LOOKUP3Response; import org.apache.hadoop.nfs.nfs3.response.MKDIR3Response; import org.apache.hadoop.nfs.nfs3.response.READ3Response; import org.apache.hadoop.nfs.nfs3.response.READDIR3Response; import org.apache.hadoop.nfs.nfs3.response.READDIR3Response.DirList3; import org.apache.hadoop.nfs.nfs3.response.READDIR3Response.Entry3; import org.apache.hadoop.nfs.nfs3.response.REMOVE3Response; import org.apache.hadoop.nfs.nfs3.response.RENAME3Response; import org.apache.hadoop.nfs.nfs3.response.RMDIR3Response; import org.apache.hadoop.nfs.nfs3.response.SETATTR3Response; import org.apache.hadoop.nfs.nfs3.response.WRITE3Response; import org.apache.hadoop.nfs.nfs3.response.WccAttr; import org.apache.hadoop.nfs.nfs3.response.WccData; import org.apache.hadoop.oncrpc.XDR; public class NFSv3ResponseBuilder { public final static Log LOG = LogFactory.getLog(NFSv3ResponseBuilder.class); public static COMMIT3Response buildCOMMIT3Response(XDR xdr) throws IOException { int status = xdr.readInt(); if(status == Nfs3Status.NFS3_OK) { WccData fileWcc; long verf; fileWcc = buildWccData(xdr); verf = xdr.readHyper(); return new COMMIT3Response(status, fileWcc, verf); } else { WccData fileWcc; fileWcc = buildWccData(xdr); return new COMMIT3Response(status, fileWcc, Nfs3Constant.WRITE_COMMIT_VERF); } } public static CREATE3Response buildCREATE3Response(XDR xdr) throws IOException { int status = xdr.readInt(); if(status == Nfs3Status.NFS3_OK) { FileHandle handle = null; Nfs3FileAttributes postOpObjAttr; WccData dirWcc; if(xdr.readBoolean()) { handle = buildFileHandle(xdr); } postOpObjAttr = buildPostOpAttributes(xdr); dirWcc = buildWccData(xdr); return new CREATE3Response(status, handle, postOpObjAttr, dirWcc); } else { WccData dirWcc; dirWcc = buildWccData(xdr); return new CREATE3Response(status, null, null, dirWcc); } } public static FSINFO3Response buildFSINFO3Response(XDR xdr) throws IOException { int status = xdr.readInt(); if(status == Nfs3Status.NFS3_OK) { Nfs3FileAttributes postOpAttr; int rtmax, rtperf, rtmult, wtmax, wtperf, wtmult, dtperf; long maxFileSize; NfsTime timeDelta; int properties; postOpAttr = buildPostOpAttributes(xdr); rtmax = xdr.readInt(); rtperf = xdr.readInt(); rtmult = xdr.readInt(); wtmax = xdr.readInt(); wtperf = xdr.readInt(); wtmult = xdr.readInt(); dtperf = xdr.readInt(); maxFileSize = xdr.readHyper(); timeDelta = NfsTime.deserialize(xdr); properties = xdr.readInt(); return new FSINFO3Response(status, postOpAttr, rtmax, rtperf, rtmult, wtmax, wtperf, wtmult, dtperf, maxFileSize, timeDelta, properties); } else { Nfs3FileAttributes postOpAttr; postOpAttr = buildPostOpAttributes(xdr); return new FSINFO3Response(status, postOpAttr, 0, 0, 0, 0, 0, 0, 0, 0, null, 0); } } public static GETATTR3Response buildGETATTR3Response(XDR xdr) throws IOException { int status = xdr.readInt(); if(status == Nfs3Status.NFS3_OK) { Nfs3FileAttributes attrs; attrs = Nfs3FileAttributes.deserialize(xdr); return new GETATTR3Response(status, attrs); } else { return new GETATTR3Response(status); } } public static LOOKUP3Response buildLOOKUP3Response(XDR xdr) throws IOException { int status = xdr.readInt(); if(status == Nfs3Status.NFS3_OK) { FileHandle fileHandle = buildFileHandle(xdr); Nfs3FileAttributes postOpObjAttr = buildPostOpAttributes(xdr); Nfs3FileAttributes postOpDirAttributes = buildPostOpAttributes(xdr); return new LOOKUP3Response(status, fileHandle, postOpObjAttr, postOpDirAttributes); } else { return new LOOKUP3Response(status); } } public static MKDIR3Response buildMKDIR3Response(XDR xdr) throws IOException { int status = xdr.readInt(); if(status == Nfs3Status.NFS3_OK) { boolean hasFileHandle; FileHandle handle = null; Nfs3FileAttributes attr; WccData dirWcc; hasFileHandle = xdr.readBoolean(); if(hasFileHandle) { handle = new Nfs3FileHandle(); handle.deserialize(xdr); } attr = Nfs3FileAttributes.deserialize(xdr); dirWcc = buildWccData(xdr); return new MKDIR3Response(status, handle, attr, dirWcc); } else { return new MKDIR3Response(status); } } public static READ3Response buildREAD3Response(XDR xdr) throws IOException { int status = xdr.readInt(); if(status == Nfs3Status.NFS3_OK) { Nfs3FileAttributes postOpAttr; int count; boolean eof; ByteBuffer data; postOpAttr = buildPostOpAttributes(xdr); count = xdr.readInt(); eof = xdr.readBoolean(); data = ByteBuffer.wrap(xdr.readVariableOpaque()); return new READ3Response(status, postOpAttr, count, eof, data); } else { Nfs3FileAttributes postOpAttr = buildPostOpAttributes(xdr); return new READ3Response(status, postOpAttr, 0, false, null); } } public static READDIR3Response buildREADDIR3Response(XDR xdr) throws IOException { int status = xdr.readInt(); if(status == Nfs3Status.NFS3_OK) { Nfs3FileAttributes postOpAttr; long cookieVerf; List<Entry3> entries; DirList3 dirList; boolean eof; postOpAttr = buildPostOpAttributes(xdr); cookieVerf = xdr.readHyper(); entries = buildDirEntryList(xdr); eof = xdr.readBoolean(); dirList = new DirList3(entries.toArray(new Entry3[] {}), eof); return new READDIR3Response(status, postOpAttr, cookieVerf, dirList); } else { Nfs3FileAttributes postOpAttr; postOpAttr = Nfs3FileAttributes.deserialize(xdr); return new READDIR3Response(status, postOpAttr); } } public static REMOVE3Response buildREMOVE3Response(XDR xdr) throws IOException { int status = xdr.readInt(); WccData wccData = buildWccData(xdr); return new REMOVE3Response(status, wccData); } public static RENAME3Response buildRENAME3Response(XDR xdr) throws IOException { int status = xdr.readInt(); WccData fromWccData, toWccData; fromWccData = buildWccData(xdr); toWccData = buildWccData(xdr); return new RENAME3Response(status, fromWccData, toWccData); } public static RMDIR3Response buildRMDIR3Response(XDR xdr) throws IOException { int status = xdr.readInt(); WccData wccData = buildWccData(xdr); return new RMDIR3Response(status, wccData); } public static SETATTR3Response buildSETATTR3Response(XDR xdr) throws IOException { int status = xdr.readInt(); WccData wccData = buildWccData(xdr); return new SETATTR3Response(status, wccData); } public static WRITE3Response buildWRITE3Response(XDR xdr) throws IOException { int status = xdr.readInt(); if(status == Nfs3Status.NFS3_OK) { WccData fileWcc; int count; WriteStableHow stableHow; long verifier; fileWcc = buildWccData(xdr); count = xdr.readInt(); stableHow = WriteStableHow.fromValue(xdr.readInt()); verifier = xdr.readHyper(); return new WRITE3Response(status, fileWcc, count, stableHow, verifier); } else { WccData fileWcc; fileWcc = buildWccData(xdr); return new WRITE3Response(status, fileWcc, 0, WriteStableHow.UNSTABLE, Nfs3Constant.WRITE_COMMIT_VERF); } } public static FileHandle buildFileHandle(XDR xdr) throws IOException { FileHandle handle = new Nfs3FileHandle(); handle.deserialize(xdr); return handle; } public static Nfs3Info buildFilesystemInfo(XDR xdr) throws IOException { int status = xdr.readInt(); if(status == Nfs3Status.NFS3_OK) { int rtmax, rtperf, rtmult, wtmax, wtperf, wtmult, dtperf; long maxFileSize; NfsTime timeDelta; int properties; buildPostOpAttributes(xdr); rtmax = xdr.readInt(); rtperf = xdr.readInt(); rtmult = xdr.readInt(); wtmax = xdr.readInt(); wtperf = xdr.readInt(); wtmult = xdr.readInt(); dtperf = xdr.readInt(); maxFileSize = xdr.readHyper(); timeDelta = NfsTime.deserialize(xdr); properties = xdr.readInt(); return new Nfs3Info(rtmax, rtperf, rtmult, wtmax, wtperf, wtmult, dtperf, maxFileSize, timeDelta, properties); } else { buildPostOpAttributes(xdr); return null; } } public static Nfs3DirList buildDirectoryList(XDR xdr) throws IOException { int status = xdr.readInt(); if(status == Nfs3Status.NFS3_OK) { List<Nfs3DirEntry> entries; Nfs3DirList dirList; boolean eof; long cookieVerf; buildPostOpAttributes(xdr); cookieVerf = xdr.readHyper(); entries = new LinkedList<Nfs3DirEntry>(); while(xdr.readBoolean()) { long fileId = xdr.readHyper(); byte[] name = xdr.readVariableOpaque(); long cookie = xdr.readHyper(); Nfs3DirEntry entry = new Nfs3DirEntry(fileId, new String(name), cookie); entries.add(entry); } eof = xdr.readBoolean(); dirList = new Nfs3DirList(entries.toArray(new Nfs3DirEntry[] {}), cookieVerf, eof); return dirList; } else { Nfs3FileAttributes.deserialize(xdr); return null; } } public static WccData buildWccData(XDR xdr) throws IOException { WccAttr preOpAttr; Nfs3FileAttributes postOpAttr; boolean b1 = xdr.readBoolean(); if(b1 == true) { preOpAttr = buildWccAttr(xdr); } else { preOpAttr = null; } boolean b2 = xdr.readBoolean(); if(b2 == true) { postOpAttr = Nfs3FileAttributes.deserialize(xdr); } else { postOpAttr = null; } return new WccData(preOpAttr, postOpAttr); } public static WccAttr buildWccAttr(XDR xdr) throws IOException { long size; NfsTime mtime; NfsTime ctime; size = xdr.readHyper(); mtime = NfsTime.deserialize(xdr); ctime = NfsTime.deserialize(xdr); return new WccAttr(size, mtime, ctime); } public static Nfs3FileAttributes buildPostOpAttributes(XDR xdr) throws IOException { boolean hasPostOpAttr; Nfs3FileAttributes postOpAttributes; hasPostOpAttr = xdr.readBoolean(); if(hasPostOpAttr == true) { postOpAttributes = Nfs3FileAttributes.deserialize(xdr); } else { postOpAttributes = null; } return postOpAttributes; } public static List<Entry3> buildDirEntryList(XDR xdr) throws IOException { List<Entry3> entries = new LinkedList<Entry3>(); boolean haveMore = xdr.readBoolean(); while(haveMore) { long fileId = xdr.readHyper(); byte[] name = xdr.readVariableOpaque(); long cookie = xdr.readHyper(); Entry3 entry = new Entry3(fileId, new String(name), cookie); entries.add(entry); haveMore = xdr.readBoolean(); } return entries; } }