1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.util;
19
20 import java.io.IOException;
21 import java.io.PrintWriter;
22 import java.io.StringWriter;
23 import java.security.PrivilegedExceptionAction;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.apache.hadoop.conf.Configuration;
31 import org.apache.hadoop.hbase.TableName;
32 import org.apache.hadoop.hbase.client.Append;
33 import org.apache.hadoop.hbase.client.Delete;
34 import org.apache.hadoop.hbase.client.Get;
35 import org.apache.hadoop.hbase.client.HTable;
36 import org.apache.hadoop.hbase.client.Increment;
37 import org.apache.hadoop.hbase.client.Mutation;
38 import org.apache.hadoop.hbase.client.Put;
39 import org.apache.hadoop.hbase.client.Result;
40 import org.apache.hadoop.hbase.client.RetriesExhaustedWithDetailsException;
41 import org.apache.hadoop.hbase.security.User;
42 import org.apache.hadoop.hbase.util.test.LoadTestDataGenerator;
43 import org.apache.hadoop.security.UserGroupInformation;
44 import org.apache.hadoop.util.StringUtils;
45
46
47
48
49 public class MultiThreadedUpdaterWithACL extends MultiThreadedUpdater {
50 private static final Log LOG = LogFactory.getLog(MultiThreadedUpdaterWithACL.class);
51 private final static String COMMA= ",";
52 private User userOwner;
53
54
55
56
57 private Map<String, HTable> userVsTable = new HashMap<String, HTable>();
58 private Map<String, User> users = new HashMap<String, User>();
59 private String[] userNames;
60
61 public MultiThreadedUpdaterWithACL(LoadTestDataGenerator dataGen, Configuration conf,
62 TableName tableName, double updatePercent, User userOwner) {
63 super(dataGen, conf, tableName, updatePercent);
64 this.userOwner = userOwner;
65 userNames = dataGenerator.getArgs()[0].split(COMMA);
66 }
67
68 @Override
69 protected void addUpdaterThreads(int numThreads) throws IOException {
70 for (int i = 0; i < numThreads; ++i) {
71 HBaseUpdaterThread updater = new HBaseUpdaterThreadWithACL(i);
72 updaters.add(updater);
73 }
74 }
75
76 public class HBaseUpdaterThreadWithACL extends HBaseUpdaterThread {
77
78 private HTable table;
79 private MutateAccessAction mutateAction = new MutateAccessAction();
80
81 public HBaseUpdaterThreadWithACL(int updaterId) throws IOException {
82 super(updaterId);
83 }
84
85 @Override
86 protected HTable createTable() throws IOException {
87 return null;
88 }
89
90 @Override
91 protected void closeHTable() {
92 try {
93 if (table != null) {
94 table.close();
95 }
96 for (HTable table : userVsTable.values()) {
97 try {
98 table.close();
99 } catch (Exception e) {
100 LOG.error("Error while closing the table " + table.getName(), e);
101 }
102 }
103 } catch (Exception e) {
104 LOG.error("Error while closing the HTable "+table.getName(), e);
105 }
106 }
107
108 @Override
109 protected Result getRow(final Get get, final long rowKeyBase, final byte[] cf) {
110 PrivilegedExceptionAction<Object> action = new PrivilegedExceptionAction<Object>() {
111
112 @Override
113 public Object run() throws Exception {
114 Result res = null;
115 HTable localTable = null;
116 try {
117 int mod = ((int) rowKeyBase % userNames.length);
118 if (userVsTable.get(userNames[mod]) == null) {
119 localTable = new HTable(conf, tableName);
120 userVsTable.put(userNames[mod], localTable);
121 res = localTable.get(get);
122 } else {
123 localTable = userVsTable.get(userNames[mod]);
124 res = localTable.get(get);
125 }
126 } catch (IOException ie) {
127 LOG.warn("Failed to get the row for key = [" + get.getRow() + "], column family = ["
128 + Bytes.toString(cf) + "]", ie);
129 }
130 return res;
131 }
132 };
133
134 if (userNames != null && userNames.length > 0) {
135 int mod = ((int) rowKeyBase % userNames.length);
136 User user;
137 if(!users.containsKey(userNames[mod])) {
138 UserGroupInformation realUserUgi = UserGroupInformation.createRemoteUser(userNames[mod]);
139 user = User.create(realUserUgi);
140 users.put(userNames[mod], user);
141 } else {
142 user = users.get(userNames[mod]);
143 }
144 try {
145 Result result = (Result) user.runAs(action);
146 return result;
147 } catch (Exception ie) {
148 LOG.warn("Failed to get the row for key = [" + get.getRow() + "], column family = ["
149 + Bytes.toString(cf) + "]", ie);
150 }
151 }
152
153 return null;
154 }
155
156 @Override
157 public void mutate(final HTable table, Mutation m, final long keyBase, final byte[] row,
158 final byte[] cf, final byte[] q, final byte[] v) {
159 final long start = System.currentTimeMillis();
160 try {
161 m = dataGenerator.beforeMutate(keyBase, m);
162 mutateAction.setMutation(m);
163 mutateAction.setCF(cf);
164 mutateAction.setRow(row);
165 mutateAction.setQualifier(q);
166 mutateAction.setValue(v);
167 mutateAction.setStartTime(start);
168 mutateAction.setKeyBase(keyBase);
169 userOwner.runAs(mutateAction);
170 } catch (IOException e) {
171 recordFailure(m, keyBase, start, e);
172 } catch (InterruptedException e) {
173 failedKeySet.add(keyBase);
174 }
175 }
176
177 class MutateAccessAction implements PrivilegedExceptionAction<Object> {
178 private HTable table;
179 private long start;
180 private Mutation m;
181 private long keyBase;
182 private byte[] row;
183 private byte[] cf;
184 private byte[] q;
185 private byte[] v;
186
187 public MutateAccessAction() {
188
189 }
190
191 public void setStartTime(final long start) {
192 this.start = start;
193 }
194
195 public void setMutation(final Mutation m) {
196 this.m = m;
197 }
198
199 public void setRow(final byte[] row) {
200 this.row = row;
201 }
202
203 public void setCF(final byte[] cf) {
204 this.cf = cf;
205 }
206
207 public void setQualifier(final byte[] q) {
208 this.q = q;
209 }
210
211 public void setValue(final byte[] v) {
212 this.v = v;
213 }
214
215 public void setKeyBase(final long keyBase) {
216 this.keyBase = keyBase;
217 }
218
219 @Override
220 public Object run() throws Exception {
221 try {
222 if (table == null) {
223 table = new HTable(conf, tableName);
224 }
225 if (m instanceof Increment) {
226 table.increment((Increment) m);
227 } else if (m instanceof Append) {
228 table.append((Append) m);
229 } else if (m instanceof Put) {
230 table.checkAndPut(row, cf, q, v, (Put) m);
231 } else if (m instanceof Delete) {
232 table.checkAndDelete(row, cf, q, v, (Delete) m);
233 } else {
234 throw new IllegalArgumentException("unsupported mutation "
235 + m.getClass().getSimpleName());
236 }
237 totalOpTimeMs.addAndGet(System.currentTimeMillis() - start);
238 } catch (IOException e) {
239 recordFailure(m, keyBase, start, e);
240 }
241 return null;
242 }
243 }
244
245 private void recordFailure(final Mutation m, final long keyBase,
246 final long start, IOException e) {
247 failedKeySet.add(keyBase);
248 String exceptionInfo;
249 if (e instanceof RetriesExhaustedWithDetailsException) {
250 RetriesExhaustedWithDetailsException aggEx = (RetriesExhaustedWithDetailsException) e;
251 exceptionInfo = aggEx.getExhaustiveDescription();
252 } else {
253 StringWriter stackWriter = new StringWriter();
254 PrintWriter pw = new PrintWriter(stackWriter);
255 e.printStackTrace(pw);
256 pw.flush();
257 exceptionInfo = StringUtils.stringifyException(e);
258 }
259 LOG.error("Failed to mutate: " + keyBase + " after " + (System.currentTimeMillis() - start)
260 + "ms; region information: " + getRegionDebugInfoSafe(table, m.getRow()) + "; errors: "
261 + exceptionInfo);
262 }
263 }
264 }