use std::io::{Read, Write};
use tracing::debug;
use crate::protocol::rpc;
use crate::protocol::xdr::{self, deserialize, nfs3, Serialize};
pub async fn nfsproc3_commit(
xid: u32,
input: &mut impl Read,
output: &mut impl Write,
context: &rpc::Context,
) -> Result<(), anyhow::Error> {
let args = deserialize::<nfs3::file::COMMIT3args>(input)?;
debug!("nfsproc3_commit({:?}, {:?}) ", xid, args);
let id = context.vfs.fh_to_id(&args.file);
if let Err(stat) = id {
xdr::rpc::make_success_reply(xid).serialize(output)?;
stat.serialize(output)?;
nfs3::wcc_data::default().serialize(output)?;
return Ok(());
}
let id = id.unwrap();
let pre_obj_attr = context
.vfs
.getattr(id)
.await
.map(|v| nfs3::wcc_attr { size: v.size, mtime: v.mtime, ctime: v.ctime })
.ok();
match context.vfs.commit(id, args.offset, args.count).await {
Ok(fattr) => {
let post_obj_attr = nfs3::post_op_attr::Some(fattr);
let res = nfs3::file::COMMIT3resok {
file_wcc: nfs3::wcc_data { before: pre_obj_attr, after: post_obj_attr },
verf: context.vfs.server_id(),
};
debug!("nfsproc3_commit success");
xdr::rpc::make_success_reply(xid).serialize(output)?;
nfs3::nfsstat3::NFS3_OK.serialize(output)?;
res.serialize(output)?;
}
Err(stat) => {
let post_obj_attr = context.vfs.getattr(id).await.ok();
let wcc_data = nfs3::wcc_data { before: pre_obj_attr, after: post_obj_attr };
debug!("nfsproc3_commit error: {:?}", stat);
xdr::rpc::make_success_reply(xid).serialize(output)?;
stat.serialize(output)?;
wcc_data.serialize(output)?;
}
}
Ok(())
}