001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.io; 019 020import java.io.IOException; 021import java.io.OutputStream; 022import java.nio.ByteBuffer; 023 024import org.apache.hadoop.hbase.io.util.StreamUtils; 025import org.apache.hadoop.hbase.util.ByteBufferUtils; 026import org.apache.yetus.audience.InterfaceAudience; 027 028/** 029 * When deal with OutputStream which is not ByteBufferWriter type, wrap it with this class. We will 030 * have to write offheap ByteBuffer (DBB) data into the OS. This class is having a temp byte array 031 * to which we can copy the DBB data for writing to the OS. 032 * <br> 033 * This is used while writing Cell data to WAL. In case of AsyncWAL, the OS created there is 034 * ByteBufferWriter. But in case of FSHLog, the OS passed by DFS client, is not of type 035 * ByteBufferWriter. We will need this temp solution until DFS client supports writing ByteBuffer 036 * directly to the OS it creates. 037 * <br> 038 * Note: This class is not thread safe. 039 */ 040@InterfaceAudience.Private 041public class ByteBufferWriterOutputStream extends OutputStream 042 implements ByteBufferWriter { 043 044 private static final int TEMP_BUF_LENGTH = 4 * 1024; 045 private final OutputStream os; 046 private byte[] tempBuf = null; 047 048 public ByteBufferWriterOutputStream(OutputStream os) { 049 this.os = os; 050 } 051 052 @Override 053 public void write(ByteBuffer b, int off, int len) throws IOException { 054 byte[] buf = null; 055 if (len > TEMP_BUF_LENGTH) { 056 buf = new byte[len]; 057 } else { 058 if (this.tempBuf == null) { 059 this.tempBuf = new byte[TEMP_BUF_LENGTH]; 060 } 061 buf = this.tempBuf; 062 } 063 ByteBufferUtils.copyFromBufferToArray(buf, b, off, 0, len); 064 this.os.write(buf, 0, len); 065 } 066 067 @Override 068 public void writeInt(int i) throws IOException { 069 StreamUtils.writeInt(this.os, i); 070 } 071 072 @Override 073 public void write(int b) throws IOException { 074 this.os.write(b); 075 } 076 077 @Override 078 public void write(byte b[], int off, int len) throws IOException { 079 this.os.write(b, off, len); 080 } 081 082 @Override 083 public void flush() throws IOException { 084 this.os.flush(); 085 } 086 087 @Override 088 public void close() throws IOException { 089 this.os.close(); 090 } 091}