mirror of
https://review.haiku-os.org/haiku
synced 2025-02-07 06:16:11 +01:00
nfs4: Correctly handle timeouts and other rpc errors
This commit is contained in:
parent
3ce57b347f
commit
5945c55ae4
@ -154,15 +154,28 @@ Server::SendCallAsync(Call* call, Reply** reply, Request** request)
|
||||
|
||||
fRequests.AddRequest(req);
|
||||
|
||||
*request = req;
|
||||
return ResendCallAsync(call, req);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Server::ResendCallAsync(Call* call, Request* req)
|
||||
{
|
||||
if (fThreadError != B_OK) {
|
||||
fRequests.FindRequest(req->fXID);
|
||||
delete req;
|
||||
return fThreadError;
|
||||
}
|
||||
|
||||
XDR::WriteStream& stream = call->Stream();
|
||||
status_t result = fConnection->Send(stream.Buffer(), stream.Size());
|
||||
if (result != B_OK) {
|
||||
fRequests.FindRequest(xid);
|
||||
fRequests.FindRequest(req->fXID);
|
||||
delete req;
|
||||
return result;
|
||||
}
|
||||
|
||||
*request = req;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@ -198,7 +211,9 @@ Server::_Listener()
|
||||
|
||||
while (!fThreadCancel) {
|
||||
result = fConnection->Receive(&buffer, &size);
|
||||
if (result != B_OK) {
|
||||
if (result == B_NO_MEMORY)
|
||||
continue;
|
||||
else if (result != B_OK) {
|
||||
fThreadError = result;
|
||||
return result;
|
||||
}
|
||||
@ -206,8 +221,7 @@ Server::_Listener()
|
||||
Reply* reply = new(std::nothrow) Reply(buffer, size);
|
||||
if (reply == NULL) {
|
||||
free(buffer);
|
||||
fThreadError = result;
|
||||
return B_NO_MEMORY;
|
||||
continue;
|
||||
}
|
||||
|
||||
Request* req = fRequests.FindRequest(reply->GetXID());
|
||||
|
@ -52,6 +52,7 @@ public:
|
||||
|
||||
status_t SendCallAsync(Call* call, Reply** reply,
|
||||
Request** request);
|
||||
status_t ResendCallAsync(Call* call, Request* req);
|
||||
inline status_t WaitCall(Request* request,
|
||||
bigtime_t time = kWaitTime);
|
||||
inline status_t CancelCall(Request* request);
|
||||
|
@ -13,12 +13,17 @@
|
||||
status_t
|
||||
Request::Send()
|
||||
{
|
||||
return _TrySend();
|
||||
switch (fServer->ID().fProtocol) {
|
||||
case ProtocolUDP: return _SendUDP();
|
||||
case ProtocolTCP: return _SendTCP();
|
||||
}
|
||||
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Request::_TrySend()
|
||||
Request::_SendUDP()
|
||||
{
|
||||
RPC::Reply *rpl;
|
||||
RPC::Request *rpc;
|
||||
@ -29,15 +34,51 @@ Request::_TrySend()
|
||||
|
||||
result = fServer->WaitCall(rpc);
|
||||
if (result != B_OK) {
|
||||
fServer->CancelCall(rpc);
|
||||
delete rpc;
|
||||
return result;
|
||||
int attempts = 1;
|
||||
while (result != B_OK && attempts++ < kRetryLimit)
|
||||
result = fServer->ResendCallAsync(fBuilder.Request(), rpc);
|
||||
|
||||
if (attempts == kRetryLimit) {
|
||||
fServer->CancelCall(rpc);
|
||||
delete rpc;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return fReply.SetTo(rpl);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Request::_SendTCP()
|
||||
{
|
||||
RPC::Reply *rpl;
|
||||
RPC::Request *rpc;
|
||||
|
||||
status_t result;
|
||||
int attempts = 0;
|
||||
do {
|
||||
result = fServer->SendCallAsync(fBuilder.Request(), &rpl, &rpc);
|
||||
if (result == B_NO_MEMORY)
|
||||
return result;
|
||||
else if (result != B_OK) {
|
||||
fServer->Repair();
|
||||
continue;
|
||||
}
|
||||
|
||||
result = fServer->WaitCall(rpc);
|
||||
if (result != B_OK) {
|
||||
fServer->CancelCall(rpc);
|
||||
delete rpc;
|
||||
|
||||
fServer->Repair();
|
||||
}
|
||||
} while (result != B_OK && attempts++ < kRetryLimit);
|
||||
|
||||
return fReply.SetTo(rpl);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Request::Reset()
|
||||
{
|
||||
|
@ -25,12 +25,15 @@ public:
|
||||
void Reset();
|
||||
|
||||
private:
|
||||
status_t _TrySend();
|
||||
status_t _SendUDP();
|
||||
status_t _SendTCP();
|
||||
|
||||
RPC::Server* fServer;
|
||||
|
||||
RequestBuilder fBuilder;
|
||||
ReplyInterpreter fReply;
|
||||
|
||||
static const int kRetryLimit = 5;
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user