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, *
013 * software distributed under the License is distributed on an *
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
015 * KIND, either express or implied. See the License for the *
016 * specific language governing permissions and limitations *
017 * under the License. *
018 ****************************************************************/
019 package org.apache.james.system.hbase;
020
021 import java.io.IOException;
022
023 import org.apache.hadoop.conf.Configuration;
024 import org.apache.hadoop.hbase.HBaseConfiguration;
025 import org.apache.hadoop.hbase.HColumnDescriptor;
026 import org.apache.hadoop.hbase.HTableDescriptor;
027 import org.apache.hadoop.hbase.client.HBaseAdmin;
028 import org.apache.hadoop.hbase.client.HTable;
029 import org.apache.hadoop.hbase.client.HTablePool;
030 import org.apache.james.domainlist.hbase.def.HDomainList;
031 import org.apache.james.rrt.api.RecipientRewriteTable;
032 import org.apache.james.rrt.hbase.def.HRecipientRewriteTable;
033 import org.apache.james.user.api.UsersRepository;
034 import org.apache.james.user.hbase.def.HUsersRepository;
035
036 /**
037 * Table Pool singleton to get the DomainList, RecipientRewriteTable and UserRepository HBase tables.
038 *
039 * TODO Two getInstance methods are public, one for the impl, one for the tests. This is not good.
040 */
041 public class TablePool {
042
043 private static Configuration configuration;
044 private static TablePool hbaseSchema;
045 private static HTablePool htablePool;
046
047 /**
048 * Use getInstance to get an instance of the {@link HTablePool}.
049 *
050 * Don't give any configuration, the default one will be used
051 * via {@link HBaseConfiguration#create(Configuration)}.
052 *
053 * If you want to create the instance with a specific {@link HBaseConfiguration},
054 * use {@link #getInstance(Configuration)}
055 *
056 * @return An instance using a default configuration
057 * @throws IOException
058 */
059 public static synchronized TablePool getInstance() throws IOException {
060 return getInstance(HBaseConfiguration.create());
061 }
062
063 /**
064 * Use getInstance to get an instance of the {@link HTablePool}.
065 *
066 * You can give at first call a specific {@link HBaseConfiguration} to suit your needs.
067 *
068 * @param configuration
069 * @return An instance of {@link HTablePool}
070 * @throws IOException
071 */
072 public static synchronized TablePool getInstance(Configuration configuration) throws IOException {
073 if (hbaseSchema == null) {
074 TablePool.configuration = configuration;
075 TablePool.hbaseSchema = new TablePool();
076 TablePool.htablePool = new HTablePool(configuration, 100);
077 ensureTable(HDomainList.TABLE_NAME, HDomainList.COLUMN_FAMILY_NAME);
078 ensureTable(HRecipientRewriteTable.TABLE_NAME, HRecipientRewriteTable.COLUMN_FAMILY_NAME);
079 ensureTable(HUsersRepository.TABLE_NAME, HUsersRepository.COLUMN_FAMILY_NAME);
080 }
081 return hbaseSchema;
082 }
083
084 /**
085 * Get an instance of the {@link HDomainList} table.
086 *
087 * @return An instance of {@link HDomainList}
088 */
089 public HTable getDomainlistTable() {
090 return (HTable) htablePool.getTable(HDomainList.TABLE_NAME);
091 }
092
093 /**
094 * Get an instance of the RecipientRewriteTable table.
095 *
096 * @return An instance of {@link RecipientRewriteTable}
097 */
098 public HTable getRecipientRewriteTable() {
099 return (HTable) htablePool.getTable(HRecipientRewriteTable.TABLE_NAME);
100 }
101
102 /**
103 * Get an instance of the UsersRepository table.
104 *
105 * @return An instance of {@link UsersRepository}
106 */
107 public HTable getUsersRepositoryTable() {
108 return (HTable) htablePool.getTable(HUsersRepository.TABLE_NAME);
109 }
110
111 /**
112 * Put back the table in the pool after usage.
113 *
114 * With later HBase versions, we won't have to put back the table in the pool.
115 * See https://issues.apache.org/jira/browse/HBASE-4054
116 *
117 * @param table
118 */
119 public void putTable(HTable table) {
120 if (table != null) {
121 htablePool.putTable(table);
122 }
123 }
124
125 /**
126 * Create a table if needed.
127 *
128 * @param tableName
129 * @param columnFamilyName
130 * @throws IOException
131 */
132 private static void ensureTable(byte[] tableName, byte[] columnFamilyName) throws IOException {
133 HBaseAdmin hbaseAdmin = new HBaseAdmin(configuration);
134 if (! hbaseAdmin.tableExists(tableName)) {
135 HTableDescriptor desc = new HTableDescriptor(tableName);
136 HColumnDescriptor hColumnDescriptor = new HColumnDescriptor(columnFamilyName);
137 hColumnDescriptor.setMaxVersions(1);
138 desc.addFamily(hColumnDescriptor);
139 hbaseAdmin.createTable(desc);
140 }
141 }
142
143 }