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 }