nfs4: Make RPC calls asynchronous

This commit is contained in:
Pawel Dziepak
2012-06-29 02:14:39 +02:00
parent 01d6381d20
commit 3ce57b347f
4 changed files with 67 additions and 15 deletions
@@ -119,8 +119,26 @@ Server::_StartListening()
status_t
Server::SendCall(Call* call, Reply** reply)
{
status_t result;
Request* req;
status_t result = SendCallAsync(call, reply, &req);
if (result != B_OK)
return result;
result = WaitCall(req);
if (result != B_OK) {
CancelCall(req);
delete req;
return result;
}
delete req;
return B_OK;
}
status_t
Server::SendCallAsync(Call* call, Reply** reply, Request** request)
{
if (fThreadError != B_OK)
return fThreadError;
@@ -137,21 +155,15 @@ Server::SendCall(Call* call, Reply** reply)
fRequests.AddRequest(req);
XDR::WriteStream& stream = call->Stream();
result = fConnection->Send(stream.Buffer(), stream.Size());
if (result != B_OK)
goto out_cancel;
status_t result = fConnection->Send(stream.Buffer(), stream.Size());
if (result != B_OK) {
fRequests.FindRequest(xid);
delete req;
return result;
}
result = req->fEvent.Wait(B_RELATIVE_TIMEOUT, kWaitTime);
if (result != B_OK)
goto out_cancel;
delete req;
*request = req;
return B_OK;
out_cancel:
fRequests.FindRequest(xid);
delete req;
return result;
}
@@ -50,6 +50,12 @@ public:
status_t SendCall(Call* call, Reply** reply);
status_t SendCallAsync(Call* call, Reply** reply,
Request** request);
inline status_t WaitCall(Request* request,
bigtime_t time = kWaitTime);
inline status_t CancelCall(Request* request);
status_t Repair();
inline const ServerAddress& ID() const;
@@ -75,6 +81,22 @@ private:
static const bigtime_t kWaitTime = 1000000;
};
inline status_t
Server::WaitCall(Request* request, bigtime_t time)
{
return request->fEvent.Wait(B_RELATIVE_TIMEOUT, time);
}
inline status_t
Server::CancelCall(Request* request)
{
fRequests.FindRequest(request->fXID);
return B_OK;
}
inline const ServerAddress&
Server::ID() const
{
@@ -12,12 +12,28 @@
status_t
Request::Send()
{
return _TrySend();
}
status_t
Request::_TrySend()
{
RPC::Reply *rpl;
status_t result = fServer->SendCall(fBuilder.Request(), &rpl);
RPC::Request *rpc;
status_t result = fServer->SendCallAsync(fBuilder.Request(), &rpl, &rpc);
if (result != B_OK)
return result;
result = fServer->WaitCall(rpc);
if (result != B_OK) {
fServer->CancelCall(rpc);
delete rpc;
return result;
}
return fReply.SetTo(rpl);
}
@@ -25,6 +25,8 @@ public:
void Reset();
private:
status_t _TrySend();
RPC::Server* fServer;
RequestBuilder fBuilder;