/** * Initiates a call by sending the parameter to the remote server. * Note: this is not called from the Connection thread, but by other * threads. * @param call * @param priority * @see #readResponse() */ protected void writeRequest(Call call, final int priority) { if (shouldCloseConnection.get()) return; try { RequestHeader.Builder builder = RequestHeader.newBuilder(); builder.setCallId(call.id); if (Trace.isTracing()) { Span s = Trace.currentSpan(); builder.setTraceInfo(RPCTInfo.newBuilder(). setParentId(s.getSpanId()).setTraceId(s.getTraceId())); } builder.setMethodName(call.md.getName()); builder.setRequestParam(call.param != null); ByteBuffer cellBlock = ipcUtil.buildCellBlock(this.codec, this.compressor, call.cells); if (cellBlock != null) { CellBlockMeta.Builder cellBlockBuilder = CellBlockMeta.newBuilder(); cellBlockBuilder.setLength(cellBlock.limit()); builder.setCellBlockMeta(cellBlockBuilder.build()); } // Only pass priority if there one. Let zero be same as no priority. if (priority != 0) builder.setPriority(priority); //noinspection SynchronizeOnNonFinalField RequestHeader header = builder.build(); synchronized (this.out) { // FindBugs IS2_INCONSISTENT_SYNC IPCUtil.write(this.out, header, call.param, cellBlock); } if (LOG.isDebugEnabled()) { LOG.debug(getName() + ": wrote request header " + TextFormat.shortDebugString(header)); } } catch(IOException e) { markClosed(e); } }
protected synchronized void setResponse(Object m, final CellScanner cells, Throwable t, String errorMsg) { if (this.isError) return; if (t != null) this.isError = true; BufferChain bc = null; try { ResponseHeader.Builder headerBuilder = ResponseHeader.newBuilder(); // Presume it a pb Message. Could be null. Message result = (Message)m; // Call id. headerBuilder.setCallId(this.id); if (t != null) { ExceptionResponse.Builder exceptionBuilder = ExceptionResponse.newBuilder(); exceptionBuilder.setExceptionClassName(t.getClass().getName()); exceptionBuilder.setStackTrace(errorMsg); exceptionBuilder.setDoNotRetry(t instanceof DoNotRetryIOException || t instanceof NeedUnmanagedConnectionException); if (t instanceof RegionMovedException) { // Special casing for this exception. This is only one carrying a payload. // Do this instead of build a generic system for allowing exceptions carry // any kind of payload. RegionMovedException rme = (RegionMovedException)t; exceptionBuilder.setHostname(rme.getHostname()); exceptionBuilder.setPort(rme.getPort()); } // Set the exception as the result of the method invocation. headerBuilder.setException(exceptionBuilder.build()); } // Pass reservoir to buildCellBlock. Keep reference to returne so can add it back to the // reservoir when finished. This is hacky and the hack is not contained but benefits are // high when we can avoid a big buffer allocation on each rpc. this.cellBlock = ipcUtil.buildCellBlock(this.connection.codec, this.connection.compressionCodec, cells, reservoir); if (this.cellBlock != null) { CellBlockMeta.Builder cellBlockBuilder = CellBlockMeta.newBuilder(); // Presumes the cellBlock bytebuffer has been flipped so limit has total size in it. cellBlockBuilder.setLength(this.cellBlock.limit()); headerBuilder.setCellBlockMeta(cellBlockBuilder.build()); } Message header = headerBuilder.build(); // Organize the response as a set of bytebuffers rather than collect it all together inside // one big byte array; save on allocations. ByteBuffer bbHeader = IPCUtil.getDelimitedMessageAsByteBuffer(header); ByteBuffer bbResult = IPCUtil.getDelimitedMessageAsByteBuffer(result); int totalSize = bbHeader.capacity() + (bbResult == null? 0: bbResult.limit()) + (this.cellBlock == null? 0: this.cellBlock.limit()); ByteBuffer bbTotalSize = ByteBuffer.wrap(Bytes.toBytes(totalSize)); bc = new BufferChain(bbTotalSize, bbHeader, bbResult, this.cellBlock); if (connection.useWrap) { bc = wrapWithSasl(bc); } } catch (IOException e) { LOG.warn("Exception while creating response " + e); } this.response = bc; }
/** * Initiates a call by sending the parameter to the remote server. * Note: this is not called from the Connection thread, but by other * threads. * @see #readResponse() */ @edu.umd.cs.findbugs.annotations.SuppressWarnings(value="IS2_INCONSISTENT_SYNC", justification="Findbugs is misinterpreting locking missing fact that this.outLock is held") private void writeRequest(Call call, final int priority, Span span) throws IOException { RequestHeader.Builder builder = RequestHeader.newBuilder(); builder.setCallId(call.id); if (span != null) { builder.setTraceInfo( RPCTInfo.newBuilder().setParentId(span.getSpanId()).setTraceId(span.getTraceId())); } builder.setMethodName(call.md.getName()); builder.setRequestParam(call.param != null); ByteBuffer cellBlock = ipcUtil.buildCellBlock(this.codec, this.compressor, call.cells); if (cellBlock != null) { CellBlockMeta.Builder cellBlockBuilder = CellBlockMeta.newBuilder(); cellBlockBuilder.setLength(cellBlock.limit()); builder.setCellBlockMeta(cellBlockBuilder.build()); } // Only pass priority if there one. Let zero be same as no priority. if (priority != 0) builder.setPriority(priority); RequestHeader header = builder.build(); setupIOstreams(); // Now we're going to write the call. We take the lock, then check that the connection // is still valid, and, if so we do the write to the socket. If the write fails, we don't // know where we stand, we have to close the connection. checkIsOpen(); IOException writeException = null; synchronized (this.outLock) { if (Thread.interrupted()) throw new InterruptedIOException(); calls.put(call.id, call); // We put first as we don't want the connection to become idle. checkIsOpen(); // Now we're checking that it didn't became idle in between. try { call.callStats.setRequestSizeBytes(IPCUtil.write(this.out, header, call.param, cellBlock)); } catch (IOException e) { // We set the value inside the synchronized block, this way the next in line // won't even try to write. Otherwise we might miss a call in the calls map? shouldCloseConnection.set(true); writeException = e; interrupt(); } } // call close outside of the synchronized (outLock) to prevent deadlock - HBASE-14474 if (writeException != null) { markClosed(writeException); close(); } // We added a call, and may be started the connection close. In both cases, we // need to notify the reader. doNotify(); // Now that we notified, we can rethrow the exception if any. Otherwise we're good. if (writeException != null) throw writeException; }
protected synchronized void setResponse(Object m, final CellScanner cells, Throwable t, String errorMsg) { if (this.isError) return; if (t != null) this.isError = true; BufferChain bc = null; try { ResponseHeader.Builder headerBuilder = ResponseHeader.newBuilder(); // Presume it a pb Message. Could be null. Message result = (Message)m; // Call id. headerBuilder.setCallId(this.id); if (t != null) { ExceptionResponse.Builder exceptionBuilder = ExceptionResponse.newBuilder(); exceptionBuilder.setExceptionClassName(t.getClass().getName()); exceptionBuilder.setStackTrace(errorMsg); exceptionBuilder.setDoNotRetry(t instanceof DoNotRetryIOException); if (t instanceof RegionMovedException) { // Special casing for this exception. This is only one carrying a payload. // Do this instead of build a generic system for allowing exceptions carry // any kind of payload. RegionMovedException rme = (RegionMovedException)t; exceptionBuilder.setHostname(rme.getHostname()); exceptionBuilder.setPort(rme.getPort()); } // Set the exception as the result of the method invocation. headerBuilder.setException(exceptionBuilder.build()); } ByteBuffer cellBlock = ipcUtil.buildCellBlock(this.connection.codec, this.connection.compressionCodec, cells); if (cellBlock != null) { CellBlockMeta.Builder cellBlockBuilder = CellBlockMeta.newBuilder(); // Presumes the cellBlock bytebuffer has been flipped so limit has total size in it. cellBlockBuilder.setLength(cellBlock.limit()); headerBuilder.setCellBlockMeta(cellBlockBuilder.build()); } Message header = headerBuilder.build(); // Organize the response as a set of bytebuffers rather than collect it all together inside // one big byte array; save on allocations. ByteBuffer bbHeader = IPCUtil.getDelimitedMessageAsByteBuffer(header); ByteBuffer bbResult = IPCUtil.getDelimitedMessageAsByteBuffer(result); int totalSize = bbHeader.capacity() + (bbResult == null? 0: bbResult.limit()) + (cellBlock == null? 0: cellBlock.limit()); ByteBuffer bbTotalSize = ByteBuffer.wrap(Bytes.toBytes(totalSize)); bc = new BufferChain(bbTotalSize, bbHeader, bbResult, cellBlock); if (connection.useWrap) { bc = wrapWithSasl(bc); } } catch (IOException e) { LOG.warn("Exception while creating response " + e); } this.response = bc; }
/** * Initiates a call by sending the parameter to the remote server. * Note: this is not called from the Connection thread, but by other * threads. * @see #readResponse() */ private void writeRequest(Call call, final int priority, Span span) throws IOException { RequestHeader.Builder builder = RequestHeader.newBuilder(); builder.setCallId(call.id); if (span != null) { builder.setTraceInfo( RPCTInfo.newBuilder().setParentId(span.getSpanId()).setTraceId(span.getTraceId())); } builder.setMethodName(call.md.getName()); builder.setRequestParam(call.param != null); ByteBuffer cellBlock = ipcUtil.buildCellBlock(this.codec, this.compressor, call.cells); if (cellBlock != null) { CellBlockMeta.Builder cellBlockBuilder = CellBlockMeta.newBuilder(); cellBlockBuilder.setLength(cellBlock.limit()); builder.setCellBlockMeta(cellBlockBuilder.build()); } // Only pass priority if there one. Let zero be same as no priority. if (priority != 0) builder.setPriority(priority); RequestHeader header = builder.build(); setupIOstreams(); // Now we're going to write the call. We take the lock, then check that the connection // is still valid, and, if so we do the write to the socket. If the write fails, we don't // know where we stand, we have to close the connection. checkIsOpen(); IOException writeException = null; synchronized (this.outLock) { if (Thread.interrupted()) throw new InterruptedIOException(); calls.put(call.id, call); // We put first as we don't want the connection to become idle. checkIsOpen(); // Now we're checking that it didn't became idle in between. try { IPCUtil.write(this.out, header, call.param, cellBlock); } catch (IOException e) { // We set the value inside the synchronized block, this way the next in line // won't even try to write shouldCloseConnection.set(true); writeException = e; interrupt(); } } // We added a call, and may be started the connection close. In both cases, we // need to notify the reader. synchronized (this) { notifyAll(); } // Now that we notified, we can rethrow the exception if any. Otherwise we're good. if (writeException != null) throw writeException; }
/** * Initiates a call by sending the parameter to the remote server. * Note: this is not called from the Connection thread, but by other * threads. * @see #readResponse() */ private void writeRequest(Call call, final int priority, Span span) throws IOException { RequestHeader.Builder builder = RequestHeader.newBuilder(); builder.setCallId(call.id); if (span != null) { builder.setTraceInfo( RPCTInfo.newBuilder().setParentId(span.getSpanId()).setTraceId(span.getTraceId())); } builder.setMethodName(call.md.getName()); builder.setRequestParam(call.param != null); ByteBuffer cellBlock = ipcUtil.buildCellBlock(this.codec, this.compressor, call.cells); if (cellBlock != null) { CellBlockMeta.Builder cellBlockBuilder = CellBlockMeta.newBuilder(); cellBlockBuilder.setLength(cellBlock.limit()); builder.setCellBlockMeta(cellBlockBuilder.build()); } // Only pass priority if there one. Let zero be same as no priority. if (priority != 0) builder.setPriority(priority); RequestHeader header = builder.build(); setupIOstreams(); // Now we're going to write the call. We take the lock, then check that the connection // is still valid, and, if so we do the write to the socket. If the write fails, we don't // know where we stand, we have to close the connection. checkIsOpen(); IOException writeException = null; synchronized (this.out) { if (Thread.interrupted()) throw new InterruptedIOException(); calls.put(call.id, call); // We put first as we don't want the connection to become idle. checkIsOpen(); // Now we're checking that it didn't became idle in between. try { IPCUtil.write(this.out, header, call.param, cellBlock); } catch (IOException e) { // We set the value inside the synchronized block, this way the next in line // won't even try to write shouldCloseConnection.set(true); writeException = e; } } // We added a call, and may be started the connection close. In both cases, we // need to notify the reader. synchronized (this) { notifyAll(); } // Now that we notified, we can rethrow the exception if any. Otherwise we're good. if (writeException != null) throw writeException; if (LOG.isDebugEnabled()) { LOG.debug(getName() + ": wrote request header " + TextFormat.shortDebugString(header)); } }