package org.dcache.chimera.nfsv41.mover;
import diskCacheV111.util.CacheException;
import diskCacheV111.util.PnfsId;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Map;
import org.dcache.chimera.FsInodeType;
import org.dcache.nfs.ChimeraNFSException;
import org.dcache.nfs.nfsstat;
import org.dcache.nfs.status.BadHandleException;
import org.dcache.nfs.status.NfsIoException;
import org.dcache.nfs.v4.AbstractNFSv4Operation;
import org.dcache.nfs.v4.CompoundContext;
import org.dcache.nfs.v4.xdr.COMMIT4res;
import org.dcache.nfs.v4.xdr.COMMIT4resok;
import org.dcache.nfs.v4.xdr.nfs_argop4;
import org.dcache.nfs.v4.xdr.nfs_opnum4;
import org.dcache.nfs.v4.xdr.nfs_resop4;
import org.dcache.nfs.vfs.Inode;
import org.dcache.pool.repository.RepositoryChannel;
import org.dcache.xdr.OncRpcException;
public class EDSOperationCOMMIT extends AbstractNFSv4Operation {
private final Map<PnfsId, NfsMover> _activeWrites;
public EDSOperationCOMMIT(nfs_argop4 args, Map<PnfsId, NfsMover> activeMovers) {
super(args, nfs_opnum4.OP_COMMIT);
_activeWrites = activeMovers;
}
@Override
public void process(CompoundContext cc, nfs_resop4 result) throws ChimeraNFSException, IOException, OncRpcException {
try {
Inode inode = cc.currentInode();
PnfsId pnfsId = toPnfsid(inode);
NfsMover mover = _activeWrites.get(pnfsId);
if (mover == null) {
throw new BadHandleException("can't find mover for pnfsid : " + pnfsId);
}
RepositoryChannel fc = mover.getMoverChannel();
fc.sync();
mover.commitFileSize(fc.size());
final COMMIT4res res = result.opcommit;
res.status = nfsstat.NFS_OK;
res.resok4 = new COMMIT4resok();
res.resok4.writeverf = mover.getBootVerifier();
} catch (CacheException e) {
throw new NfsIoException(e.getMessage());
}
}
/*
* this is shameless light copy-paste form JdbcFs.
*/
private static PnfsId toPnfsid(Inode inode) throws ChimeraNFSException {
ByteBuffer b = ByteBuffer.wrap(inode.getFileId());
int fsid = b.get();
int type = b.get();
FsInodeType inodeType = FsInodeType.valueOf(type);
if (inodeType != FsInodeType.INODE) {
throw new BadHandleException("Not a regular pnfsid");
}
int idLen = b.get();
byte[] id = new byte[idLen];
b.get(id);
int opaqueLen = b.get();
if (opaqueLen > b.remaining()) {
throw new BadHandleException("Bad pnfsid size");
}
return new PnfsId(id);
}
}