* Copyright 2012 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Paweł Dziepak, pdziepak@quarnos.org
*/
#include "Request.h"
#include "FileSystem.h"
#include "Inode.h"
status_t
Request::Send(Cookie* cookie)
{
switch (fServer->ID().fProtocol) {
case IPPROTO_UDP: return _SendUDP(cookie);
case IPPROTO_TCP: return _SendTCP(cookie);
}
return B_BAD_VALUE;
}
status_t
Request::_SendUDP(Cookie* cookie)
{
RPC::Reply* rpl = NULL;
RPC::Request* rpc;
status_t result = fServer->SendCallAsync(fBuilder.Request(), &rpl, &rpc);
if (result != B_OK)
return result;
if (cookie != NULL)
cookie->RegisterRequest(rpc);
int requestTimeout = sSecToBigTime(60);
int retryLimit = 0;
bool hard = true;
if (fFileSystem != NULL) {
requestTimeout = fFileSystem->GetConfiguration().fRequestTimeout;
retryLimit = fFileSystem->GetConfiguration().fRetryLimit;
hard = fFileSystem->GetConfiguration().fHard;
}
if (fSingleAttempt) {
requestTimeout /= 10;
retryLimit = 0;
}
result = fServer->WaitCall(rpc, requestTimeout);
if (result != B_OK) {
int attempts = 1;
while (result != B_OK && (hard || attempts++ < retryLimit)) {
result = fServer->ResendCallAsync(fBuilder.Request(), rpc);
if (result != B_OK) {
if (cookie != NULL)
cookie->UnregisterRequest(rpc);
delete rpc;
return result;
}
result = fServer->WaitCall(rpc, requestTimeout);
}
if (result != B_OK) {
if (cookie != NULL)
cookie->UnregisterRequest(rpc);
fServer->CancelCall(rpc);
delete rpc;
return result;
}
}
if (cookie != NULL)
cookie->UnregisterRequest(rpc);
if (rpc->fError != B_OK) {
delete rpl;
result = rpc->fError;
delete rpc;
return result;
} else {
fReply.SetTo(rpl);
delete rpc;
return B_OK;
}
}
status_t
Request::_SendTCP(Cookie* cookie)
{
RPC::Reply* rpl = NULL;
RPC::Request* rpc;
status_t result;
int attempts = 0;
int requestTimeout = sSecToBigTime(60);
int retryLimit = 0;
bool hard = true;
if (fFileSystem != NULL) {
requestTimeout = fFileSystem->GetConfiguration().fRequestTimeout;
retryLimit = fFileSystem->GetConfiguration().fRetryLimit;
hard = fFileSystem->GetConfiguration().fHard;
}
if (fSingleAttempt) {
requestTimeout /= 10;
retryLimit = 0;
}
do {
result = fServer->SendCallAsync(fBuilder.Request(), &rpl, &rpc);
if (result == B_NO_MEMORY)
return result;
else if (result != B_OK) {
fServer->Repair();
continue;
}
if (cookie != NULL)
cookie->RegisterRequest(rpc);
result = fServer->WaitCall(rpc, requestTimeout);
if (result != B_OK) {
if (cookie != NULL)
cookie->UnregisterRequest(rpc);
fServer->CancelCall(rpc);
delete rpc;
fServer->Repair();
}
} while (result != B_OK && (hard || attempts++ < retryLimit));
if (result != B_OK)
return result;
if (cookie != NULL)
cookie->UnregisterRequest(rpc);
if (rpc->fError != B_OK) {
delete rpl;
result = rpc->fError;
delete rpc;
return result;
}
fReply.SetTo(rpl);
delete rpc;
return B_OK;
}
void
Request::Reset(uid_t uid, gid_t gid)
{
fBuilder.Reset(uid, gid);
fReply.Reset();
}