1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.mapreduce;
20
21 import java.io.IOException;
22
23 import org.apache.commons.logging.Log;
24 import org.apache.commons.logging.LogFactory;
25 import org.apache.hadoop.hbase.classification.InterfaceAudience;
26 import org.apache.hadoop.hbase.classification.InterfaceStability;
27 import org.apache.hadoop.conf.Configurable;
28 import org.apache.hadoop.conf.Configuration;
29 import org.apache.hadoop.hbase.HBaseConfiguration;
30 import org.apache.hadoop.hbase.HConstants;
31 import org.apache.hadoop.hbase.TableName;
32 import org.apache.hadoop.hbase.client.BufferedMutator;
33 import org.apache.hadoop.hbase.client.Connection;
34 import org.apache.hadoop.hbase.client.ConnectionFactory;
35 import org.apache.hadoop.hbase.client.Delete;
36 import org.apache.hadoop.hbase.client.HTable;
37 import org.apache.hadoop.hbase.client.Mutation;
38 import org.apache.hadoop.hbase.client.Put;
39 import org.apache.hadoop.mapreduce.JobContext;
40 import org.apache.hadoop.mapreduce.OutputCommitter;
41 import org.apache.hadoop.mapreduce.OutputFormat;
42 import org.apache.hadoop.mapreduce.RecordWriter;
43 import org.apache.hadoop.mapreduce.TaskAttemptContext;
44
45
46
47
48
49
50 @InterfaceAudience.Public
51 @InterfaceStability.Stable
52 public class TableOutputFormat<KEY> extends OutputFormat<KEY, Mutation>
53 implements Configurable {
54
55 private static final Log LOG = LogFactory.getLog(TableOutputFormat.class);
56
57
58 public static final String OUTPUT_TABLE = "hbase.mapred.outputtable";
59
60
61
62
63
64
65
66
67
68 public static final String OUTPUT_CONF_PREFIX = "hbase.mapred.output.";
69
70
71
72
73
74
75
76 public static final String QUORUM_ADDRESS = OUTPUT_CONF_PREFIX + "quorum";
77
78
79 public static final String QUORUM_PORT = OUTPUT_CONF_PREFIX + "quorum.port";
80
81
82 public static final String
83 REGION_SERVER_CLASS = OUTPUT_CONF_PREFIX + "rs.class";
84
85 public static final String
86 REGION_SERVER_IMPL = OUTPUT_CONF_PREFIX + "rs.impl";
87
88
89 private Configuration conf = null;
90
91
92
93
94 protected class TableRecordWriter
95 extends RecordWriter<KEY, Mutation> {
96
97 private Connection connection;
98 private BufferedMutator mutator;
99
100
101
102
103
104 public TableRecordWriter() throws IOException {
105 String tableName = conf.get(OUTPUT_TABLE);
106 this.connection = ConnectionFactory.createConnection(conf);
107 this.mutator = connection.getBufferedMutator(TableName.valueOf(tableName));
108 LOG.info("Created table instance for " + tableName);
109 }
110
111
112
113
114
115
116
117 @Override
118 public void close(TaskAttemptContext context) throws IOException {
119 try {
120 if (mutator != null) {
121 mutator.close();
122 }
123 } finally {
124 if (connection != null) {
125 connection.close();
126 }
127 }
128 }
129
130
131
132
133
134
135
136
137
138 @Override
139 public void write(KEY key, Mutation value)
140 throws IOException {
141 if (!(value instanceof Put) && !(value instanceof Delete)) {
142 throw new IOException("Pass a Delete or a Put");
143 }
144 mutator.mutate(value);
145 }
146 }
147
148
149
150
151
152
153
154
155
156 @Override
157 public RecordWriter<KEY, Mutation> getRecordWriter(TaskAttemptContext context)
158 throws IOException, InterruptedException {
159 return new TableRecordWriter();
160 }
161
162
163
164
165
166
167
168
169
170 @Override
171 public void checkOutputSpecs(JobContext context) throws IOException,
172 InterruptedException {
173
174
175 }
176
177
178
179
180
181
182
183
184
185
186 @Override
187 public OutputCommitter getOutputCommitter(TaskAttemptContext context)
188 throws IOException, InterruptedException {
189 return new TableOutputCommitter();
190 }
191
192 @Override
193 public Configuration getConf() {
194 return conf;
195 }
196
197 @Override
198 public void setConf(Configuration otherConf) {
199 String tableName = otherConf.get(OUTPUT_TABLE);
200 if(tableName == null || tableName.length() <= 0) {
201 throw new IllegalArgumentException("Must specify table name");
202 }
203
204 String address = otherConf.get(QUORUM_ADDRESS);
205 int zkClientPort = otherConf.getInt(QUORUM_PORT, 0);
206 String serverClass = otherConf.get(REGION_SERVER_CLASS);
207 String serverImpl = otherConf.get(REGION_SERVER_IMPL);
208
209 try {
210 this.conf = HBaseConfiguration.createClusterConf(otherConf, address, OUTPUT_CONF_PREFIX);
211
212 if (serverClass != null) {
213 this.conf.set(HConstants.REGION_SERVER_IMPL, serverImpl);
214 }
215 if (zkClientPort != 0) {
216 this.conf.setInt(HConstants.ZOOKEEPER_CLIENT_PORT, zkClientPort);
217 }
218 } catch(IOException e) {
219 LOG.error(e);
220 throw new RuntimeException(e);
221 }
222 }
223 }