1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.util;
20
21 import static org.apache.hadoop.hbase.util.test.LoadTestDataGenerator.INCREMENT;
22 import static org.apache.hadoop.hbase.util.test.LoadTestDataGenerator.MUTATE_INFO;
23
24 import java.io.IOException;
25 import java.io.PrintWriter;
26 import java.io.StringWriter;
27 import java.util.Arrays;
28 import java.util.HashSet;
29 import java.util.Set;
30
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33 import org.apache.hadoop.conf.Configuration;
34 import org.apache.hadoop.hbase.HConstants;
35 import org.apache.hadoop.hbase.TableName;
36 import org.apache.hadoop.hbase.client.HTableInterface;
37 import org.apache.hadoop.hbase.client.Put;
38 import org.apache.hadoop.hbase.client.RetriesExhaustedWithDetailsException;
39 import org.apache.hadoop.hbase.client.Table;
40 import org.apache.hadoop.hbase.util.test.LoadTestDataGenerator;
41 import org.apache.hadoop.util.StringUtils;
42
43
44 public class MultiThreadedWriter extends MultiThreadedWriterBase {
45 private static final Log LOG = LogFactory.getLog(MultiThreadedWriter.class);
46
47 protected Set<HBaseWriterThread> writers = new HashSet<HBaseWriterThread>();
48
49 protected boolean isMultiPut = false;
50
51 public MultiThreadedWriter(LoadTestDataGenerator dataGen, Configuration conf,
52 TableName tableName) throws IOException {
53 super(dataGen, conf, tableName, "W");
54 }
55
56
57 public void setMultiPut(boolean isMultiPut) {
58 this.isMultiPut = isMultiPut;
59 }
60
61 @Override
62 public void start(long startKey, long endKey, int numThreads) throws IOException {
63 super.start(startKey, endKey, numThreads);
64
65 if (verbose) {
66 LOG.debug("Inserting keys [" + startKey + ", " + endKey + ")");
67 }
68
69 createWriterThreads(numThreads);
70
71 startThreads(writers);
72 }
73
74 protected void createWriterThreads(int numThreads) throws IOException {
75 for (int i = 0; i < numThreads; ++i) {
76 HBaseWriterThread writer = new HBaseWriterThread(i);
77 Threads.setLoggingUncaughtExceptionHandler(writer);
78 writers.add(writer);
79 }
80 }
81
82 public class HBaseWriterThread extends Thread {
83 private final Table table;
84
85 public HBaseWriterThread(int writerId) throws IOException {
86 setName(getClass().getSimpleName() + "_" + writerId);
87 table = createTable();
88 }
89
90 protected HTableInterface createTable() throws IOException {
91 return connection.getTable(tableName);
92 }
93
94 @Override
95 public void run() {
96 try {
97 long rowKeyBase;
98 byte[][] columnFamilies = dataGenerator.getColumnFamilies();
99 while ((rowKeyBase = nextKeyToWrite.getAndIncrement()) < endKey) {
100 byte[] rowKey = dataGenerator.getDeterministicUniqueKey(rowKeyBase);
101 Put put = new Put(rowKey);
102 numKeys.addAndGet(1);
103 int columnCount = 0;
104 for (byte[] cf : columnFamilies) {
105 byte[][] columns = dataGenerator.generateColumnsForCf(rowKey, cf);
106 for (byte[] column : columns) {
107 byte[] value = dataGenerator.generateValue(rowKey, cf, column);
108 put.add(cf, column, value);
109 ++columnCount;
110 if (!isMultiPut) {
111 insert(table, put, rowKeyBase);
112 numCols.addAndGet(1);
113 put = new Put(rowKey);
114 }
115 }
116 long rowKeyHash = Arrays.hashCode(rowKey);
117 put.add(cf, MUTATE_INFO, HConstants.EMPTY_BYTE_ARRAY);
118 put.add(cf, INCREMENT, Bytes.toBytes(rowKeyHash));
119 if (!isMultiPut) {
120 insert(table, put, rowKeyBase);
121 numCols.addAndGet(1);
122 put = new Put(rowKey);
123 }
124 }
125 if (isMultiPut) {
126 if (verbose) {
127 LOG.debug("Preparing put for key = [" + Bytes.toString(rowKey) + "], " + columnCount
128 + " columns");
129 }
130 insert(table, put, rowKeyBase);
131 numCols.addAndGet(columnCount);
132 }
133 if (trackWroteKeys) {
134 wroteKeys.add(rowKeyBase);
135 }
136 }
137 } finally {
138 closeHTable();
139 numThreadsWorking.decrementAndGet();
140 }
141 }
142
143 public void insert(Table table, Put put, long keyBase) {
144 long start = System.currentTimeMillis();
145 try {
146 put = (Put) dataGenerator.beforeMutate(keyBase, put);
147 table.put(put);
148 totalOpTimeMs.addAndGet(System.currentTimeMillis() - start);
149 } catch (IOException e) {
150 failedKeySet.add(keyBase);
151 String exceptionInfo;
152 if (e instanceof RetriesExhaustedWithDetailsException) {
153 RetriesExhaustedWithDetailsException aggEx = (RetriesExhaustedWithDetailsException)e;
154 exceptionInfo = aggEx.getExhaustiveDescription();
155 } else {
156 StringWriter stackWriter = new StringWriter();
157 PrintWriter pw = new PrintWriter(stackWriter);
158 e.printStackTrace(pw);
159 pw.flush();
160 exceptionInfo = StringUtils.stringifyException(e);
161 }
162 LOG.error("Failed to insert: " + keyBase + " after " + (System.currentTimeMillis() - start)
163 + "ms; region information: " + getRegionDebugInfoSafe(table, put.getRow())
164 + "; errors: " + exceptionInfo);
165 }
166 }
167 protected void closeHTable() {
168 try {
169 if (table != null) {
170 table.close();
171 }
172 } catch (IOException e) {
173 LOG.error("Error closing table", e);
174 }
175 }
176 }
177
178 @Override
179 public void waitForFinish() {
180 super.waitForFinish();
181 System.out.println("Failed to write keys: " + failedKeySet.size());
182 for (Long key : failedKeySet) {
183 System.out.println("Failed to write key: " + key);
184 }
185 }
186 }