1/*
2 * Copyright 2012 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Pawe�� Dziepak, pdziepak@quarnos.org
7 */
8
9
10#include "Request.h"
11
12#include "FileSystem.h"
13#include "Inode.h"
14
15
16status_t
17Request::Send(Cookie* cookie)
18{
19	switch (fServer->ID().fProtocol) {
20		case IPPROTO_UDP:	return _SendUDP(cookie);
21		case IPPROTO_TCP:	return _SendTCP(cookie);
22	}
23
24	return B_BAD_VALUE;
25}
26
27
28status_t
29Request::_SendUDP(Cookie* cookie)
30{
31	RPC::Reply* rpl = NULL;
32	RPC::Request* rpc;
33
34	status_t result = fServer->SendCallAsync(fBuilder.Request(), &rpl, &rpc);
35	if (result != B_OK)
36		return result;
37
38	if (cookie != NULL)
39		cookie->RegisterRequest(rpc);
40
41	int requestTimeout = sSecToBigTime(60);
42	int retryLimit = 0;
43	bool hard = true;
44
45	if (fFileSystem != NULL) {
46		requestTimeout = fFileSystem->GetConfiguration().fRequestTimeout;
47		retryLimit = fFileSystem->GetConfiguration().fRetryLimit;
48		hard = fFileSystem->GetConfiguration().fHard;
49	}
50
51	result = fServer->WaitCall(rpc, requestTimeout);
52	if (result != B_OK) {
53		int attempts = 1;
54		while (result != B_OK && (hard || attempts++ < retryLimit)) {
55			result = fServer->ResendCallAsync(fBuilder.Request(), rpc);
56			if (result != B_OK) {
57				if (cookie != NULL)
58					cookie->UnregisterRequest(rpc);
59				delete rpc;
60				return result;
61			}
62
63			result = fServer->WaitCall(rpc, requestTimeout);
64		}
65
66		if (result != B_OK) {
67			if (cookie != NULL)
68				cookie->UnregisterRequest(rpc);
69			fServer->CancelCall(rpc);
70			delete rpc;
71			return result;
72		}
73	}
74
75	if (cookie != NULL)
76		cookie->UnregisterRequest(rpc);
77
78	if (rpc->fError != B_OK) {
79		delete rpl;
80		result = rpc->fError;
81		delete rpc;
82		return result;
83	} else {
84		fReply.SetTo(rpl);
85		delete rpc;
86		return B_OK;
87	}
88}
89
90
91status_t
92Request::_SendTCP(Cookie* cookie)
93{
94	RPC::Reply* rpl = NULL;
95	RPC::Request* rpc;
96
97	status_t result;
98	int attempts = 0;
99
100	int requestTimeout = sSecToBigTime(60);
101	int retryLimit = 0;
102	bool hard = true;
103
104	if (fFileSystem != NULL) {
105		requestTimeout = fFileSystem->GetConfiguration().fRequestTimeout;
106		retryLimit = fFileSystem->GetConfiguration().fRetryLimit;
107		hard = fFileSystem->GetConfiguration().fHard;
108	}
109
110	do {
111		result = fServer->SendCallAsync(fBuilder.Request(), &rpl, &rpc);
112		if (result == B_NO_MEMORY)
113			return result;
114		else if (result != B_OK) {
115			fServer->Repair();
116			continue;
117		}
118
119		if (cookie != NULL)
120			cookie->RegisterRequest(rpc);
121
122		result = fServer->WaitCall(rpc, requestTimeout);
123		if (result != B_OK) {
124			if (cookie != NULL)
125				cookie->UnregisterRequest(rpc);
126
127			fServer->CancelCall(rpc);
128			delete rpc;
129
130			fServer->Repair();
131		}
132	} while (result != B_OK && (hard || attempts++ < retryLimit));
133
134	if (result != B_OK)
135		return result;
136
137	if (cookie != NULL)
138		cookie->UnregisterRequest(rpc);
139
140	if (rpc->fError != B_OK) {
141		delete rpl;
142		result = rpc->fError;
143		delete rpc;
144		return result;
145	}
146
147	fReply.SetTo(rpl);
148	delete rpc;
149	return B_OK;
150}
151
152
153void
154Request::Reset()
155{
156	fBuilder.Reset();
157	fReply.Reset();
158}
159
160