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 */ 018 package org.apache.hadoop.fs; 019 020 import java.io.*; 021 import java.io.DataOutputStream; 022 import java.io.FilterOutputStream; 023 import java.io.IOException; 024 import java.io.OutputStream; 025 026 import org.apache.hadoop.classification.InterfaceAudience; 027 import org.apache.hadoop.classification.InterfaceStability; 028 029 /** Utility that wraps a {@link OutputStream} in a {@link DataOutputStream}, 030 * buffers output through a {@link BufferedOutputStream} and creates a checksum 031 * file. */ 032 @InterfaceAudience.Public 033 @InterfaceStability.Stable 034 public class FSDataOutputStream extends DataOutputStream 035 implements Syncable, CanSetDropBehind { 036 private final OutputStream wrappedStream; 037 038 private static class PositionCache extends FilterOutputStream { 039 private FileSystem.Statistics statistics; 040 long position; 041 042 public PositionCache(OutputStream out, 043 FileSystem.Statistics stats, 044 long pos) throws IOException { 045 super(out); 046 statistics = stats; 047 position = pos; 048 } 049 050 public void write(int b) throws IOException { 051 out.write(b); 052 position++; 053 if (statistics != null) { 054 statistics.incrementBytesWritten(1); 055 } 056 } 057 058 public void write(byte b[], int off, int len) throws IOException { 059 out.write(b, off, len); 060 position += len; // update position 061 if (statistics != null) { 062 statistics.incrementBytesWritten(len); 063 } 064 } 065 066 public long getPos() throws IOException { 067 return position; // return cached position 068 } 069 070 public void close() throws IOException { 071 out.close(); 072 } 073 } 074 075 @Deprecated 076 public FSDataOutputStream(OutputStream out) throws IOException { 077 this(out, null); 078 } 079 080 public FSDataOutputStream(OutputStream out, FileSystem.Statistics stats) 081 throws IOException { 082 this(out, stats, 0); 083 } 084 085 public FSDataOutputStream(OutputStream out, FileSystem.Statistics stats, 086 long startPosition) throws IOException { 087 super(new PositionCache(out, stats, startPosition)); 088 wrappedStream = out; 089 } 090 091 /** 092 * Get the current position in the output stream. 093 * 094 * @return the current position in the output stream 095 */ 096 public long getPos() throws IOException { 097 return ((PositionCache)out).getPos(); 098 } 099 100 /** 101 * Close the underlying output stream. 102 */ 103 public void close() throws IOException { 104 out.close(); // This invokes PositionCache.close() 105 } 106 107 /** 108 * Get a reference to the wrapped output stream. Used by unit tests. 109 * 110 * @return the underlying output stream 111 */ 112 @InterfaceAudience.LimitedPrivate({"HDFS"}) 113 public OutputStream getWrappedStream() { 114 return wrappedStream; 115 } 116 117 @Override // Syncable 118 @Deprecated 119 public void sync() throws IOException { 120 if (wrappedStream instanceof Syncable) { 121 ((Syncable)wrappedStream).sync(); 122 } 123 } 124 125 @Override // Syncable 126 public void hflush() throws IOException { 127 if (wrappedStream instanceof Syncable) { 128 ((Syncable)wrappedStream).hflush(); 129 } else { 130 wrappedStream.flush(); 131 } 132 } 133 134 @Override // Syncable 135 public void hsync() throws IOException { 136 if (wrappedStream instanceof Syncable) { 137 ((Syncable)wrappedStream).hsync(); 138 } else { 139 wrappedStream.flush(); 140 } 141 } 142 143 @Override 144 public void setDropBehind(Boolean dropBehind) throws IOException { 145 try { 146 ((CanSetDropBehind)wrappedStream).setDropBehind(dropBehind); 147 } catch (ClassCastException e) { 148 throw new UnsupportedOperationException("the wrapped stream does " + 149 "not support setting the drop-behind caching setting."); 150 } 151 } 152 }