This method sends a request to the replicas, and returns the related reply. If the servers take more than invokeTimeout seconds the method returns null. This method is thread-safe. @param request Request to be sent @param reqType ORDERED_REQUEST/ORDERED_HASHED_REQUEST/UNORDERED_REQUEST/UNORDERED_HA
(byte[] request, TOMMessageType reqType)
| 197 | * @return The reply from the replicas related to request |
| 198 | */ |
| 199 | public byte[] invoke(byte[] request, TOMMessageType reqType) { |
| 200 | try { |
| 201 | canSendLock.lock(); |
| 202 | |
| 203 | requestHandler = createRequestHandler(reqType); |
| 204 | |
| 205 | TOMMessage requestMessage = requestHandler.createRequest(request); |
| 206 | |
| 207 | logger.debug("Sending request ({}) with seqId = {}", reqType, requestHandler.getSequenceId()); |
| 208 | TOMulticast(requestMessage); |
| 209 | |
| 210 | logger.debug("Expected number of matching replies: {}", requestHandler.getReplyQuorumSize()); |
| 211 | |
| 212 | // This instruction blocks the thread, until a response is obtained. |
| 213 | // The thread will be unblocked when the method replyReceived is invoked |
| 214 | // by the client side communication system |
| 215 | requestHandler.waitForResponse(); |
| 216 | |
| 217 | if (requestHandler.isRequestTimeout()) { |
| 218 | logger.info("###### TIMEOUT ({}s) OF REQUEST {} | seqId: {} | replies received: {} ######", |
| 219 | invokeTimeout, reqType, requestHandler.getSequenceId(), |
| 220 | requestHandler.getNumberReceivedReplies()); |
| 221 | if (reqType == TOMMessageType.UNORDERED_HASHED_REQUEST || reqType == TOMMessageType.UNORDERED_REQUEST) { |
| 222 | return invoke(request, TOMMessageType.ORDERED_REQUEST); |
| 223 | } else { |
| 224 | return null; |
| 225 | } |
| 226 | } |
| 227 | |
| 228 | TOMMessage response = requestHandler.getResponse(); |
| 229 | logger.debug("Response extracted: " + response); |
| 230 | |
| 231 | if (response == null) { |
| 232 | //the response can be null if n-f replies are received but there isn't |
| 233 | //a replyQuorumSize of matching replies |
| 234 | logger.debug("Received n-f replies and no response could be extracted."); |
| 235 | |
| 236 | if (reqType == TOMMessageType.UNORDERED_REQUEST || reqType == TOMMessageType.UNORDERED_HASHED_REQUEST) { |
| 237 | //invoke the operation again, whitout the read-only flag |
| 238 | logger.debug("###################RETRY#######################"); |
| 239 | return invokeOrdered(request); |
| 240 | } else { |
| 241 | requestHandler.printState(); |
| 242 | throw new RuntimeException("Received n-f replies without f+1 of them matching."); |
| 243 | } |
| 244 | } else { |
| 245 | if (response.getViewID() == getViewManager().getCurrentViewId()) {// normal operation |
| 246 | return response.getContent(); |
| 247 | } else if (response.getViewID() > getViewManager().getCurrentViewId()) { |
| 248 | if (reqType == TOMMessageType.ORDERED_REQUEST) { |
| 249 | reconfigureTo((View) TOMUtil.getObject(response.getContent())); |
| 250 | return invokeOrdered(request); |
| 251 | } else if (reqType == TOMMessageType.UNORDERED_REQUEST |
| 252 | || reqType == TOMMessageType.UNORDERED_HASHED_REQUEST) { |
| 253 | // Ignore the response and request again because servers are in a later view |
| 254 | return invokeOrdered(request); |
| 255 | } else {// Reply to a reconfigure request! |
| 256 | logger.debug("Reconfiguration request' reply received!"); |
no test coverage detected