1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.hadoop.hbase.hbql.impl;
22
23 import org.apache.hadoop.conf.Configuration;
24 import org.apache.hadoop.hbase.HBaseConfiguration;
25 import org.apache.hadoop.hbase.HColumnDescriptor;
26 import org.apache.hadoop.hbase.HTableDescriptor;
27 import org.apache.hadoop.hbase.MasterNotRunningException;
28 import org.apache.hadoop.hbase.client.HBaseAdmin;
29 import org.apache.hadoop.hbase.client.HTablePool;
30 import org.apache.hadoop.hbase.client.tableindexed.IndexSpecification;
31 import org.apache.hadoop.hbase.client.tableindexed.IndexedTable;
32 import org.apache.hadoop.hbase.client.tableindexed.IndexedTableAdmin;
33 import org.apache.hadoop.hbase.client.tableindexed.IndexedTableDescriptor;
34 import org.apache.hadoop.hbase.hbql.client.AsyncExecutor;
35 import org.apache.hadoop.hbase.hbql.client.AsyncExecutorManager;
36 import org.apache.hadoop.hbase.hbql.client.ExecutionResults;
37 import org.apache.hadoop.hbase.hbql.client.HBatch;
38 import org.apache.hadoop.hbase.hbql.client.HBqlException;
39 import org.apache.hadoop.hbase.hbql.client.HConnection;
40 import org.apache.hadoop.hbase.hbql.client.HMapping;
41 import org.apache.hadoop.hbase.hbql.client.HPreparedStatement;
42 import org.apache.hadoop.hbase.hbql.client.HRecord;
43 import org.apache.hadoop.hbase.hbql.client.HResultSet;
44 import org.apache.hadoop.hbase.hbql.client.HStatement;
45 import org.apache.hadoop.hbase.hbql.client.QueryExecutorPool;
46 import org.apache.hadoop.hbase.hbql.client.QueryExecutorPoolManager;
47 import org.apache.hadoop.hbase.hbql.mapping.AnnotationResultAccessor;
48 import org.apache.hadoop.hbase.hbql.mapping.FamilyMapping;
49 import org.apache.hadoop.hbase.hbql.mapping.TableMapping;
50 import org.apache.hadoop.hbase.hbql.statement.args.KeyInfo;
51 import org.apache.hadoop.hbase.hbql.statement.args.WithArgs;
52 import org.apache.hadoop.hbase.hbql.util.AtomicReferences;
53 import org.apache.hadoop.hbase.hbql.util.Maps;
54 import org.apache.hadoop.hbase.hbql.util.PoolableElement;
55 import org.apache.hadoop.hbase.hbql.util.Sets;
56 import org.apache.hadoop.hbase.util.Bytes;
57
58 import java.io.IOException;
59 import java.util.List;
60 import java.util.Map;
61 import java.util.Set;
62 import java.util.concurrent.atomic.AtomicBoolean;
63 import java.util.concurrent.atomic.AtomicReference;
64
65 public class HConnectionImpl extends PoolableElement<HConnectionImpl> implements HConnection {
66
67 public static final String MAXTABLEREFS = "maxtablerefs";
68 public static final String MASTER = "hbase.master";
69
70 private final AtomicBoolean atomicClosed = new AtomicBoolean(false);
71 private final HBaseConfiguration hbaseConfiguration;
72 private final HTablePool tablePool;
73 private final int maxTablePoolReferencesPerTable;
74 private final MappingManager mappingManager;
75
76 private final AtomicReference<Map<Class, AnnotationResultAccessor>> atomicAnnoMapping = AtomicReferences.newAtomicReference();
77 private final AtomicReference<HBaseAdmin> atomicHbaseAdmin = AtomicReferences.newAtomicReference();
78 private final AtomicReference<IndexedTableAdmin> atomicIndexTableAdmin = AtomicReferences.newAtomicReference();
79
80 private String queryExecutorPoolName = null;
81 private String asyncExecutorName = null;
82
83 public HConnectionImpl(final HBaseConfiguration hbaseConfiguration,
84 final HConnectionPoolImpl connectionPool,
85 final int maxTablePoolReferencesPerTable) throws HBqlException {
86 super(connectionPool);
87 this.hbaseConfiguration = (hbaseConfiguration == null) ? new HBaseConfiguration() : hbaseConfiguration;
88 this.maxTablePoolReferencesPerTable = maxTablePoolReferencesPerTable;
89 this.tablePool = new HTablePool(this.getHBaseConfiguration(), this.getMaxTablePoolReferencesPerTable());
90 this.mappingManager = new MappingManager(this);
91
92 this.getMappingManager().validatePersistentMetadata();
93 }
94
95 public static HBaseConfiguration getHBaseConfiguration(final String master) {
96 final Configuration configuration = new Configuration();
97 configuration.set(HConnectionImpl.MASTER, master);
98 return new HBaseConfiguration(configuration);
99 }
100
101 private AtomicReference<Map<Class, AnnotationResultAccessor>> getAtomicAnnoMapping() {
102 return this.atomicAnnoMapping;
103 }
104
105 public void resetElement() {
106
107 try {
108 this.getAtomicClosed().set(false);
109 this.getMappingManager().clear();
110 }
111 catch (HBqlException e) {
112 e.printStackTrace();
113 }
114
115 if (this.getAtomicAnnoMapping().get() != null)
116 this.getAtomicAnnoMapping().get().clear();
117
118 this.setQueryExecutorPoolName(null);
119 }
120
121 public boolean isPooled() {
122 return this.getElementPool() != null;
123 }
124
125 public HBaseConfiguration getHBaseConfiguration() {
126 return this.hbaseConfiguration;
127 }
128
129 private HTablePool getTablePool() {
130 return this.tablePool;
131 }
132
133 private MappingManager getMappingManager() throws HBqlException {
134 this.checkIfClosed();
135 return this.mappingManager;
136 }
137
138 public int getMaxTablePoolReferencesPerTable() {
139 return this.maxTablePoolReferencesPerTable;
140 }
141
142 private Map<Class, AnnotationResultAccessor> getAnnotationMappingMap() {
143 if (this.getAtomicAnnoMapping().get() == null) {
144 synchronized (this) {
145 if (this.getAtomicAnnoMapping().get() == null) {
146 final Map<Class, AnnotationResultAccessor> newmap = Maps.newConcurrentHashMap();
147 this.getAtomicAnnoMapping().set(newmap);
148 }
149 }
150 }
151 return this.getAtomicAnnoMapping().get();
152 }
153
154 public AnnotationResultAccessor getAnnotationMapping(final Object obj) throws HBqlException {
155 return this.getAnnotationMapping(obj.getClass());
156 }
157
158 public synchronized AnnotationResultAccessor getAnnotationMapping(final Class<?> clazz) throws HBqlException {
159
160 AnnotationResultAccessor accessor = getAnnotationMappingMap().get(clazz);
161
162 if (accessor != null) {
163 return accessor;
164 }
165 else {
166 accessor = AnnotationResultAccessor.newAnnotationMapping(this, clazz);
167 getAnnotationMappingMap().put(clazz, accessor);
168 return accessor;
169 }
170 }
171
172 private AtomicReference<HBaseAdmin> getAtomicHbaseAdmin() {
173 return this.atomicHbaseAdmin;
174 }
175
176 public HBaseAdmin getHBaseAdmin() throws HBqlException {
177 this.checkIfClosed();
178 if (this.getAtomicHbaseAdmin().get() == null) {
179 synchronized (this) {
180 if (this.getAtomicHbaseAdmin().get() == null) {
181 try {
182 this.getAtomicHbaseAdmin().set(new HBaseAdmin(this.getHBaseConfiguration()));
183 }
184 catch (MasterNotRunningException e) {
185 throw new HBqlException(e);
186 }
187 }
188 }
189 }
190 return this.getAtomicHbaseAdmin().get();
191 }
192
193 private AtomicReference<IndexedTableAdmin> getAtomicIndexTableAdmin() {
194 return this.atomicIndexTableAdmin;
195 }
196
197 public IndexedTableAdmin getIndexTableAdmin() throws HBqlException {
198 this.checkIfClosed();
199 if (this.getAtomicIndexTableAdmin().get() == null) {
200 synchronized (this) {
201 if (this.getAtomicIndexTableAdmin().get() == null) {
202 try {
203 this.getAtomicIndexTableAdmin().set(new IndexedTableAdmin(this.getHBaseConfiguration()));
204 }
205 catch (MasterNotRunningException e) {
206 throw new HBqlException(e);
207 }
208 }
209 }
210 }
211 return this.getAtomicIndexTableAdmin().get();
212 }
213
214 public Set<String> getFamilyNames(final String tableName) throws HBqlException {
215 this.checkIfClosed();
216 final HTableDescriptor table = this.getHTableDescriptor(tableName);
217 final Set<String> familySet = Sets.newHashSet();
218 for (final HColumnDescriptor descriptor : table.getColumnFamilies())
219 familySet.add(Bytes.toString(descriptor.getName()));
220 return familySet;
221 }
222
223 public boolean familyExistsForTable(final String familyName, final String tableName) throws HBqlException {
224 final Set<String> names = this.getFamilyNames(tableName);
225 return names.contains(familyName);
226 }
227
228 public boolean familyExistsForMapping(final String familyName, final String mappingName) throws HBqlException {
229 final TableMapping mapping = this.getMapping(mappingName);
230 return mapping.containsFamily(familyName);
231 }
232
233 public IndexedTableDescriptor newIndexedTableDescriptor(final String tableName) throws HBqlException {
234 this.checkIfClosed();
235 try {
236 final HTableDescriptor tableDesc = this.getHTableDescriptor(tableName);
237 return new IndexedTableDescriptor(tableDesc);
238 }
239 catch (IOException e) {
240 throw new HBqlException(e);
241 }
242 }
243
244 public boolean indexExistsForMapping(final String indexName, final String mappingName) throws HBqlException {
245 final TableMapping mapping = this.getMapping(mappingName);
246 return this.indexExistsForTable(indexName, mapping.getTableName());
247 }
248
249 public IndexSpecification getIndexForTable(final String indexName, final String tableName) throws HBqlException {
250 final IndexedTableDescriptor indexDesc = this.newIndexedTableDescriptor(tableName);
251 return indexDesc.getIndex(indexName);
252 }
253
254 public boolean indexExistsForTable(final String indexName, final String tableName) throws HBqlException {
255 this.checkIfClosed();
256 final IndexSpecification index = this.getIndexForTable(indexName, tableName);
257 return index != null;
258 }
259
260 public void dropIndexForMapping(final String indexName, final String mappingName) throws HBqlException {
261 final TableMapping mapping = this.getMapping(mappingName);
262 this.dropIndexForTable(mapping.getTableName(), indexName);
263 }
264
265 public void dropIndexForTable(final String tableName, final String indexName) throws HBqlException {
266 this.validateIndexExistsForTable(indexName, tableName);
267 try {
268 final IndexedTableAdmin ita = this.getIndexTableAdmin();
269 ita.removeIndex(tableName.getBytes(), indexName);
270 }
271 catch (IOException e) {
272 throw new HBqlException(e);
273 }
274 }
275
276 public HStatement createStatement() throws HBqlException {
277 this.checkIfClosed();
278 return new HStatementImpl(this);
279 }
280
281 public HPreparedStatement prepareStatement(final String sql) throws HBqlException {
282 this.checkIfClosed();
283 return new HPreparedStatementImpl(this, sql);
284 }
285
286 public void releaseElement() {
287 this.getElementPool().release(this);
288 }
289
290 private AtomicBoolean getAtomicClosed() {
291 return this.atomicClosed;
292 }
293
294 public boolean isClosed() {
295 return this.getAtomicClosed().get();
296 }
297
298 public synchronized void close() {
299 if (!this.isClosed()) {
300 this.getAtomicClosed().set(true);
301
302 if (this.isPooled())
303 this.releaseElement();
304 }
305 }
306
307 private void checkIfClosed() throws HBqlException {
308 if (this.isClosed())
309 throw new HBqlException("Connection is closed");
310 }
311
312 public ExecutionResults execute(final String sql) throws HBqlException {
313 final HStatement stmt = this.createStatement();
314 return stmt.execute(sql);
315 }
316
317 public HResultSet<HRecord> executeQuery(final String sql) throws HBqlException {
318 final HStatement stmt = this.createStatement();
319 return stmt.executeQuery(sql);
320 }
321
322 public <T> HResultSet<T> executeQuery(final String sql, final Class clazz) throws HBqlException {
323 final HStatement stmt = this.createStatement();
324 return stmt.executeQuery(sql, clazz);
325 }
326
327 public List<HRecord> executeQueryAndFetch(final String sql) throws HBqlException {
328 final HStatement stmt = this.createStatement();
329 return stmt.executeQueryAndFetch(sql);
330 }
331
332 public <T> List<T> executeQueryAndFetch(final String sql, final Class clazz) throws HBqlException {
333 final HStatement stmt = this.createStatement();
334 return stmt.executeQueryAndFetch(sql, clazz);
335 }
336
337 public ExecutionResults executeUpdate(final String sql) throws HBqlException {
338 final HStatement stmt = this.createStatement();
339 return stmt.executeUpdate(sql);
340 }
341
342
343 public boolean mappingExists(final String mappingName) throws HBqlException {
344 return this.getMappingManager().mappingExists(mappingName);
345 }
346
347 public TableMapping getMapping(final String mappingName) throws HBqlException {
348 return this.getMappingManager().getMapping(mappingName);
349 }
350
351 public boolean dropMapping(final String mappingName) throws HBqlException {
352 return this.getMappingManager().dropMapping(mappingName);
353 }
354
355 public Set<HMapping> getAllMappings() throws HBqlException {
356 return this.getMappingManager().getAllMappings();
357 }
358
359 public TableMapping createMapping(final boolean tempMapping,
360 final boolean systemMapping,
361 final String mappingName,
362 final String tableName,
363 final KeyInfo keyInfo,
364 final List<FamilyMapping> familyList) throws HBqlException {
365 return this.getMappingManager().createMapping(tempMapping,
366 systemMapping,
367 mappingName,
368 tableName,
369 keyInfo,
370 familyList);
371 }
372
373
374 public void createTable(final HTableDescriptor tableDesc) throws HBqlException {
375 this.checkIfClosed();
376 final String tableName = tableDesc.getNameAsString();
377 if (this.tableExists(tableName))
378 throw new HBqlException("Table already exists: " + tableName);
379
380 try {
381 this.getHBaseAdmin().createTable(tableDesc);
382 }
383 catch (IOException e) {
384 throw new HBqlException(e);
385 }
386 }
387
388 public HTableWrapper newHTableWrapper(final WithArgs withArgs, final String tableName) throws HBqlException {
389
390 this.checkIfClosed();
391
392 try {
393 if (withArgs != null && withArgs.hasAnIndex())
394 return new HTableWrapper(new IndexedTable(this.getHBaseConfiguration(), tableName.getBytes()), null);
395 else
396 return new HTableWrapper(this.getTablePool().getTable(tableName), this.getTablePool());
397 }
398 catch (IOException e) {
399 throw new HBqlException(e);
400 }
401 catch (RuntimeException e) {
402 throw new HBqlException("Invalid table name: " + tableName);
403 }
404 }
405
406 public boolean tableExists(final String tableName) throws HBqlException {
407 try {
408 return this.getHBaseAdmin().tableExists(tableName);
409 }
410 catch (MasterNotRunningException e) {
411 throw new HBqlException(e);
412 }
413 }
414
415 public HTableDescriptor getHTableDescriptor(final String tableName) throws HBqlException {
416 this.validateTableName(tableName);
417 try {
418 return this.getHBaseAdmin().getTableDescriptor(tableName.getBytes());
419 }
420 catch (IOException e) {
421 throw new HBqlException(e);
422 }
423 }
424
425 public boolean tableAvailable(final String tableName) throws HBqlException {
426 this.validateTableName(tableName);
427 try {
428 return this.getHBaseAdmin().isTableAvailable(tableName);
429 }
430 catch (IOException e) {
431 throw new HBqlException(e);
432 }
433 }
434
435 public boolean tableEnabled(final String tableName) throws HBqlException {
436 this.validateTableName(tableName);
437 try {
438 return this.getHBaseAdmin().isTableEnabled(tableName);
439 }
440 catch (IOException e) {
441 throw new HBqlException(e);
442 }
443 }
444
445 public void dropTable(final String tableName) throws HBqlException {
446 validateTableDisabled(tableName, "drop");
447 try {
448 final byte[] tableNameBytes = tableName.getBytes();
449 this.getHBaseAdmin().deleteTable(tableNameBytes);
450 }
451 catch (IOException e) {
452 throw new HBqlException(e);
453 }
454 }
455
456 public void disableTable(final String tableName) throws HBqlException {
457 try {
458 if (!this.tableEnabled(tableName))
459 throw new HBqlException("Cannot disable disabled table: " + tableName);
460 this.getHBaseAdmin().disableTable(tableName);
461 }
462 catch (IOException e) {
463 throw new HBqlException(e);
464 }
465 }
466
467 public void enableTable(final String tableName) throws HBqlException {
468 validateTableDisabled(tableName, "enable");
469 try {
470 this.getHBaseAdmin().enableTable(tableName);
471 }
472 catch (IOException e) {
473 throw new HBqlException(e);
474 }
475 }
476
477 public Set<String> getTableNames() throws HBqlException {
478 try {
479 final HBaseAdmin admin = this.getHBaseAdmin();
480 final Set<String> tableSet = Sets.newHashSet();
481 for (final HTableDescriptor table : admin.listTables())
482 tableSet.add(table.getNameAsString());
483 return tableSet;
484 }
485 catch (IOException e) {
486 throw new HBqlException(e);
487 }
488 }
489
490
491 public CompletionQueueExecutor getQueryExecutorForConnection() throws HBqlException {
492
493 if (!Utils.isValidString(this.getQueryExecutorPoolName()))
494 throw new HBqlException("Connection not assigned a QueryExecutorPool name");
495
496 this.validateQueryExecutorPoolNameExists(this.getQueryExecutorPoolName());
497
498 final QueryExecutorPool pool = QueryExecutorPoolManager.getQueryExecutorPool(this.getQueryExecutorPoolName());
499 final CompletionQueueExecutor executorQueue = ((QueryExecutorPoolImpl)pool).take();
500
501
502 executorQueue.resetElement();
503 return executorQueue;
504 }
505
506
507 public AsyncExecutorImpl getAsyncExecutorForConnection() throws HBqlException {
508
509 if (!Utils.isValidString(this.getAsyncExecutorName()))
510 throw new HBqlException("Connection not assigned an AsyncExecutor name");
511
512 this.validateAsyncExecutorNameExists(this.getAsyncExecutorName());
513
514 final AsyncExecutor executor = AsyncExecutorManager.getAsyncExecutor(this.getAsyncExecutorName());
515
516 return ((AsyncExecutorImpl)executor);
517 }
518
519
520 public boolean usesQueryExecutor() {
521 return Utils.isValidString(this.getQueryExecutorPoolName());
522 }
523
524 public String getQueryExecutorPoolName() {
525 return this.queryExecutorPoolName;
526 }
527
528 public void setQueryExecutorPoolName(final String poolName) {
529 this.queryExecutorPoolName = poolName;
530 }
531
532 public String getAsyncExecutorName() {
533 return this.asyncExecutorName;
534 }
535
536 public void setAsyncExecutorName(final String poolName) {
537 this.asyncExecutorName = poolName;
538 }
539
540 public <T> HBatch<T> newHBatch() {
541 return new HBatch<T>(this);
542 }
543
544 public void validateTableName(final String tableName) throws HBqlException {
545 if (!this.tableExists(tableName))
546 throw new HBqlException("Table not found: " + tableName);
547 }
548
549 public void validateTableDisabled(final String tableName, final String action) throws HBqlException {
550 if (this.tableEnabled(tableName))
551 throw new HBqlException("Cannot " + action + " enabled table: " + tableName);
552 }
553
554 public void validateFamilyExistsForTable(final String familyName, final String tableName) throws HBqlException {
555 if (!this.familyExistsForTable(familyName, tableName))
556 throw new HBqlException("Family " + familyName + " not defined for table " + tableName);
557 }
558
559 public void validateIndexExistsForTable(final String indexName, final String tableName) throws HBqlException {
560 if (!this.indexExistsForTable(indexName, tableName))
561 throw new HBqlException("Index " + indexName + " not defined for table " + tableName);
562 }
563
564 public void validateQueryExecutorPoolNameExists(final String poolName) throws HBqlException {
565 if (!QueryExecutorPoolManager.queryExecutorPoolExists(poolName))
566 throw new HBqlException("QueryExecutorPool " + poolName + " does not exist.");
567 }
568
569 public void validateAsyncExecutorNameExists(final String name) throws HBqlException {
570 if (!AsyncExecutorManager.asyncExecutorExists(name))
571 throw new HBqlException("AsyncExecutor " + name + " does not exist.");
572 }
573 }