xref: /haiku/src/add-ons/kernel/file_systems/nfs4/Request.cpp (revision 21258e2674226d6aa732321b6f8494841895af5f)
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 
16 status_t
17 Request::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 
28 status_t
29 Request::_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 
91 status_t
92 Request::_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 
153 void
154 Request::Reset()
155 {
156 	fBuilder.Reset();
157 	fReply.Reset();
158 }
159 
160