/** * Wait for sequence number to be assigned & return the assigned value. * * @param maxWaitForSeqId maximum time to wait in milliseconds for sequenceid * @return long the new assigned sequence number * @throws IOException */ public long getSequenceId(final long maxWaitForSeqId) throws IOException { // TODO: This implementation waiting on a latch is problematic because if a higher level // determines we should stop or abort, there is no global list of all these blocked WALKeys // waiting on a sequence id; they can't be cancelled... interrupted. See getNextSequenceId. // // UPDATE: I think we can remove the timeout now we are stamping all walkeys with sequenceid, // even those that have failed (previously we were not... so they would just hang out...). // St.Ack 20150910 try { if (maxWaitForSeqId < 0) { this.seqNumAssignedLatch.await(); } else if (!this.seqNumAssignedLatch.await(maxWaitForSeqId, TimeUnit.MILLISECONDS)) { throw new TimeoutIOException( "Failed to get sequenceid after " + maxWaitForSeqId + "ms; WAL system stuck or has gone away?"); } } catch (InterruptedException ie) { LOG.warn("Thread interrupted waiting for next log sequence number"); InterruptedIOException iie = new InterruptedIOException(); iie.initCause(ie); throw iie; } return this.logSeqNum; }
/** * Returns the stream's response headers, blocking if necessary if they have not been received * yet. */ public synchronized List<String> getResponseHeaders() throws IOException { long remaining = 0; long start = 0; if (readTimeoutMillis != 0) { start = (System.nanoTime() / 1000000); remaining = readTimeoutMillis; } try { while (responseHeaders == null && errorCode == null) { if (readTimeoutMillis == 0) { // No timeout configured. wait(); } else if (remaining > 0) { wait(remaining); remaining = start + readTimeoutMillis - (System.nanoTime() / 1000000); } else { throw new SocketTimeoutException( "Read response header timeout. readTimeoutMillis: " + readTimeoutMillis); } } if (responseHeaders != null) { return responseHeaders; } throw new IOException("stream was reset: " + errorCode); } catch (InterruptedException e) { InterruptedIOException rethrow = new InterruptedIOException(); rethrow.initCause(e); throw rethrow; } }
/** * Execute the passed <code>mutations</code> against <code>.META.</code> table. * * @param ct CatalogTracker on whose back we will ride the edit. * @param mutations Puts and Deletes to execute on .META. * @throws IOException */ static void mutateMetaTable(final CatalogTracker ct, final List<Mutation> mutations) throws IOException { HTable t = MetaReader.getMetaHTable(ct); try { t.batch(mutations); } catch (InterruptedException e) { InterruptedIOException ie = new InterruptedIOException(e.getMessage()); ie.initCause(e); throw ie; } finally { t.close(); } }
/** * Will block until a write entry has been assigned by they WAL subsystem. * * @return A WriteEntry gotten from local WAL subsystem. Must be completed by calling {@link * MultiVersionConcurrencyControl#complete(MultiVersionConcurrencyControl.WriteEntry)} or * {@link MultiVersionConcurrencyControl#complete(MultiVersionConcurrencyControl.WriteEntry)} * @see {@link #setWriteEntry(MultiVersionConcurrencyControl.WriteEntry)} */ @InterfaceAudience.Private // For internal use only. public MultiVersionConcurrencyControl.WriteEntry getWriteEntry() throws InterruptedIOException { try { this.seqNumAssignedLatch.await(); } catch (InterruptedException ie) { // If interrupted... clear out our entry else we can block up mvcc. MultiVersionConcurrencyControl mvcc = getMvcc(); LOG.debug("mvcc=" + mvcc + ", writeEntry=" + this.writeEntry); if (mvcc != null) { if (this.writeEntry != null) { mvcc.complete(this.writeEntry); } } InterruptedIOException iie = new InterruptedIOException(); iie.initCause(ie); throw iie; } return this.writeEntry; }
// non-javadoc, see interface ClientRequestDirector public HttpResponse execute(HttpHost target, HttpRequest request, HttpContext context) throws HttpException, IOException { HttpRequest orig = request; RequestWrapper origWrapper = wrapRequest(orig); origWrapper.setParams(params); HttpRoute origRoute = determineRoute(target, origWrapper, context); RoutedRequest roureq = new RoutedRequest(origWrapper, origRoute); long timeout = ConnManagerParams.getTimeout(params); int execCount = 0; boolean reuse = false; HttpResponse response = null; boolean done = false; try { while (!done) { // In this loop, the RoutedRequest may be replaced by a // followup request and route. The request and route passed // in the method arguments will be replaced. The original // request is still available in 'orig'. RequestWrapper wrapper = roureq.getRequest(); HttpRoute route = roureq.getRoute(); // See if we have a user token bound to the execution context Object userToken = context.getAttribute(ClientContext.USER_TOKEN); // Allocate connection if needed if (managedConn == null) { ClientConnectionRequest connRequest = connManager.requestConnection(route, userToken); if (orig instanceof AbortableHttpRequest) { ((AbortableHttpRequest) orig).setConnectionRequest(connRequest); } try { managedConn = connRequest.getConnection(timeout, TimeUnit.MILLISECONDS); } catch (InterruptedException interrupted) { InterruptedIOException iox = new InterruptedIOException(); iox.initCause(interrupted); throw iox; } if (HttpConnectionParams.isStaleCheckingEnabled(params)) { // validate connection this.log.debug("Stale connection check"); if (managedConn.isStale()) { this.log.debug("Stale connection detected"); // BEGIN android-changed try { managedConn.close(); } catch (IOException ignored) { // SSLSocket's will throw IOException // because they can't send a "close // notify" protocol message to the // server. Just supresss any // exceptions related to closing the // stale connection. } // END android-changed } } } if (orig instanceof AbortableHttpRequest) { ((AbortableHttpRequest) orig).setReleaseTrigger(managedConn); } // Reopen connection if needed if (!managedConn.isOpen()) { managedConn.open(route, context, params); } // BEGIN android-added else { // b/3241899 set the per request timeout parameter on reused connections managedConn.setSocketTimeout(HttpConnectionParams.getSoTimeout(params)); } // END android-added try { establishRoute(route, context); } catch (TunnelRefusedException ex) { if (this.log.isDebugEnabled()) { this.log.debug(ex.getMessage()); } response = ex.getResponse(); break; } // Reset headers on the request wrapper wrapper.resetHeaders(); // Re-write request URI if needed rewriteRequestURI(wrapper, route); // Use virtual host if set target = (HttpHost) wrapper.getParams().getParameter(ClientPNames.VIRTUAL_HOST); if (target == null) { target = route.getTargetHost(); } HttpHost proxy = route.getProxyHost(); // Populate the execution context context.setAttribute(ExecutionContext.HTTP_TARGET_HOST, target); context.setAttribute(ExecutionContext.HTTP_PROXY_HOST, proxy); context.setAttribute(ExecutionContext.HTTP_CONNECTION, managedConn); context.setAttribute(ClientContext.TARGET_AUTH_STATE, targetAuthState); context.setAttribute(ClientContext.PROXY_AUTH_STATE, proxyAuthState); // Run request protocol interceptors requestExec.preProcess(wrapper, httpProcessor, context); context.setAttribute(ExecutionContext.HTTP_REQUEST, wrapper); boolean retrying = true; while (retrying) { // Increment total exec count (with redirects) execCount++; // Increment exec count for this particular request wrapper.incrementExecCount(); if (wrapper.getExecCount() > 1 && !wrapper.isRepeatable()) { throw new NonRepeatableRequestException( "Cannot retry request " + "with a non-repeatable request entity"); } try { if (this.log.isDebugEnabled()) { this.log.debug("Attempt " + execCount + " to execute request"); } response = requestExec.execute(wrapper, managedConn, context); retrying = false; } catch (IOException ex) { this.log.debug("Closing the connection."); managedConn.close(); if (retryHandler.retryRequest(ex, execCount, context)) { if (this.log.isInfoEnabled()) { this.log.info( "I/O exception (" + ex.getClass().getName() + ") caught when processing request: " + ex.getMessage()); } if (this.log.isDebugEnabled()) { this.log.debug(ex.getMessage(), ex); } this.log.info("Retrying request"); } else { throw ex; } // If we have a direct route to the target host // just re-open connection and re-try the request if (route.getHopCount() == 1) { this.log.debug("Reopening the direct connection."); managedConn.open(route, context, params); } else { // otherwise give up throw ex; } } } // Run response protocol interceptors response.setParams(params); requestExec.postProcess(response, httpProcessor, context); // The connection is in or can be brought to a re-usable state. reuse = reuseStrategy.keepAlive(response, context); if (reuse) { // Set the idle duration of this connection long duration = keepAliveStrategy.getKeepAliveDuration(response, context); managedConn.setIdleDuration(duration, TimeUnit.MILLISECONDS); } RoutedRequest followup = handleResponse(roureq, response, context); if (followup == null) { done = true; } else { if (reuse) { this.log.debug("Connection kept alive"); // Make sure the response body is fully consumed, if present HttpEntity entity = response.getEntity(); if (entity != null) { entity.consumeContent(); } // entity consumed above is not an auto-release entity, // need to mark the connection re-usable explicitly managedConn.markReusable(); } else { managedConn.close(); } // check if we can use the same connection for the followup if (!followup.getRoute().equals(roureq.getRoute())) { releaseConnection(); } roureq = followup; } userToken = this.userTokenHandler.getUserToken(context); context.setAttribute(ClientContext.USER_TOKEN, userToken); if (managedConn != null) { managedConn.setState(userToken); } } // while not done // check for entity, release connection if possible if ((response == null) || (response.getEntity() == null) || !response.getEntity().isStreaming()) { // connection not needed and (assumed to be) in re-usable state if (reuse) managedConn.markReusable(); releaseConnection(); } else { // install an auto-release entity HttpEntity entity = response.getEntity(); entity = new BasicManagedEntity(entity, managedConn, reuse); response.setEntity(entity); } return response; } catch (HttpException ex) { abortConnection(); throw ex; } catch (IOException ex) { abortConnection(); throw ex; } catch (RuntimeException ex) { abortConnection(); throw ex; } } // execute