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 static org.junit.Assert.*;
21
22 import java.io.FileNotFoundException;
23 import java.io.IOException;
24 import java.util.Arrays;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.apache.hadoop.fs.FileStatus;
29 import org.apache.hadoop.fs.FileSystem;
30 import org.apache.hadoop.fs.Path;
31 import org.apache.hadoop.hbase.HBaseTestingUtility;
32 import org.apache.hadoop.hbase.HColumnDescriptor;
33 import org.apache.hadoop.hbase.HConstants;
34 import org.apache.hadoop.hbase.HTableDescriptor;
35 import org.apache.hadoop.hbase.TableDescriptors;
36 import org.apache.hadoop.hbase.TableExistsException;
37 import org.junit.Test;
38
39
40
41
42
43 public class TestFSTableDescriptors {
44 private static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
45 private static final Log LOG = LogFactory.getLog(TestFSTableDescriptors.class);
46
47 @Test (expected=IllegalArgumentException.class)
48 public void testRegexAgainstOldStyleTableInfo() {
49 Path p = new Path("/tmp", FSTableDescriptors.TABLEINFO_NAME);
50 int i = FSTableDescriptors.getTableInfoSequenceid(p);
51 assertEquals(0, i);
52
53 p = new Path("/tmp", "abc");
54 FSTableDescriptors.getTableInfoSequenceid(p);
55 }
56
57 @Test
58 public void testCreateAndUpdate() throws IOException {
59 Path testdir = UTIL.getDataTestDir();
60 HTableDescriptor htd = new HTableDescriptor("testCreate");
61 FileSystem fs = FileSystem.get(UTIL.getConfiguration());
62 assertTrue(FSTableDescriptors.createTableDescriptor(fs, testdir, htd));
63 assertFalse(FSTableDescriptors.createTableDescriptor(fs, testdir, htd));
64 FileStatus [] statuses = fs.listStatus(testdir);
65 assertTrue(statuses.length == 1);
66 for (int i = 0; i < 10; i++) {
67 FSTableDescriptors.updateHTableDescriptor(fs, testdir, htd);
68 }
69 statuses = fs.listStatus(testdir);
70 assertTrue(statuses.length == 1);
71 Path tmpTableDir = new Path(FSUtils.getTablePath(testdir, htd.getName()), ".tmp");
72 statuses = fs.listStatus(tmpTableDir);
73 assertTrue(statuses.length == 0);
74 }
75
76 @Test
77 public void testSequenceidAdvancesOnTableInfo() throws IOException {
78 Path testdir = UTIL.getDataTestDir("testSequenceidAdvancesOnTableInfo");
79 HTableDescriptor htd = new HTableDescriptor("testSequenceidAdvancesOnTableInfo");
80 FileSystem fs = FileSystem.get(UTIL.getConfiguration());
81 Path p0 = FSTableDescriptors.updateHTableDescriptor(fs, testdir, htd);
82 int i0 = FSTableDescriptors.getTableInfoSequenceid(p0);
83 Path p1 = FSTableDescriptors.updateHTableDescriptor(fs, testdir, htd);
84
85 assertTrue(!fs.exists(p0));
86 int i1 = FSTableDescriptors.getTableInfoSequenceid(p1);
87 assertTrue(i1 == i0 + 1);
88 Path p2 = FSTableDescriptors.updateHTableDescriptor(fs, testdir, htd);
89
90 assertTrue(!fs.exists(p1));
91 int i2 = FSTableDescriptors.getTableInfoSequenceid(p2);
92 assertTrue(i2 == i1 + 1);
93 }
94
95 @Test
96 public void testFormatTableInfoSequenceId() {
97 Path p0 = assertWriteAndReadSequenceid(0);
98
99 StringBuilder sb = new StringBuilder();
100 for (int i = 0; i < FSTableDescriptors.WIDTH_OF_SEQUENCE_ID; i++) {
101 sb.append("0");
102 }
103 assertEquals(FSTableDescriptors.TABLEINFO_NAME + "." + sb.toString(),
104 p0.getName());
105
106 Path p2 = assertWriteAndReadSequenceid(2);
107 Path p10000 = assertWriteAndReadSequenceid(10000);
108
109 Path p = new Path(p0.getParent(), FSTableDescriptors.TABLEINFO_NAME);
110 FileStatus fs = new FileStatus(0, false, 0, 0, 0, p);
111 FileStatus fs0 = new FileStatus(0, false, 0, 0, 0, p0);
112 FileStatus fs2 = new FileStatus(0, false, 0, 0, 0, p2);
113 FileStatus fs10000 = new FileStatus(0, false, 0, 0, 0, p10000);
114 FSTableDescriptors.FileStatusFileNameComparator comparator =
115 new FSTableDescriptors.FileStatusFileNameComparator();
116 assertTrue(comparator.compare(fs, fs0) > 0);
117 assertTrue(comparator.compare(fs0, fs2) > 0);
118 assertTrue(comparator.compare(fs2, fs10000) > 0);
119 }
120
121 private Path assertWriteAndReadSequenceid(final int i) {
122 Path p = FSTableDescriptors.getTableInfoFileName(new Path("/tmp"), i);
123 int ii = FSTableDescriptors.getTableInfoSequenceid(p);
124 assertEquals(i, ii);
125 return p;
126 }
127
128 @Test
129 public void testRemoves() throws IOException {
130 final String name = "testRemoves";
131 FileSystem fs = FileSystem.get(UTIL.getConfiguration());
132
133 Path rootdir = new Path(UTIL.getDataTestDir(), name);
134 TableDescriptors htds = new FSTableDescriptors(fs, rootdir);
135 HTableDescriptor htd = new HTableDescriptor(name);
136 htds.add(htd);
137 assertNotNull(htds.remove(htd.getNameAsString()));
138 assertNull(htds.remove(htd.getNameAsString()));
139 }
140
141 @Test public void testReadingHTDFromFS() throws IOException {
142 final String name = "testReadingHTDFromFS";
143 FileSystem fs = FileSystem.get(UTIL.getConfiguration());
144 HTableDescriptor htd = new HTableDescriptor(name);
145 Path rootdir = UTIL.getDataTestDir(name);
146 createHTDInFS(fs, rootdir, htd);
147 HTableDescriptor htd2 =
148 FSTableDescriptors.getTableDescriptor(fs, rootdir, htd.getNameAsString());
149 assertTrue(htd.equals(htd2));
150 }
151
152 private void createHTDInFS(final FileSystem fs, Path rootdir,
153 final HTableDescriptor htd)
154 throws IOException {
155 FSTableDescriptors.createTableDescriptor(fs, rootdir, htd);
156 }
157
158 @Test public void testHTableDescriptors()
159 throws IOException, InterruptedException {
160 final String name = "testHTableDescriptors";
161 FileSystem fs = FileSystem.get(UTIL.getConfiguration());
162
163 Path rootdir = new Path(UTIL.getDataTestDir(), name);
164 final int count = 10;
165
166 for (int i = 0; i < count; i++) {
167 HTableDescriptor htd = new HTableDescriptor(name + i);
168 createHTDInFS(fs, rootdir, htd);
169 }
170 FSTableDescriptors htds = new FSTableDescriptors(fs, rootdir) {
171 @Override
172 public HTableDescriptor get(byte[] tablename)
173 throws TableExistsException, FileNotFoundException, IOException {
174 LOG.info(Bytes.toString(tablename) + ", cachehits=" + this.cachehits);
175 return super.get(tablename);
176 }
177 };
178 for (int i = 0; i < count; i++) {
179 assertTrue(htds.get(Bytes.toBytes(name + i)) != null);
180 }
181 for (int i = 0; i < count; i++) {
182 assertTrue(htds.get(Bytes.toBytes(name + i)) != null);
183 }
184
185 for (int i = 0; i < count; i++) {
186 HTableDescriptor htd = new HTableDescriptor(name + i);
187 htd.addFamily(new HColumnDescriptor("" + i));
188 FSTableDescriptors.updateHTableDescriptor(fs, rootdir, htd);
189 }
190
191 Thread.sleep(100);
192 for (int i = 0; i < count; i++) {
193 assertTrue(htds.get(Bytes.toBytes(name + i)) != null);
194 }
195 for (int i = 0; i < count; i++) {
196 assertTrue(htds.get(Bytes.toBytes(name + i)) != null);
197 }
198 assertEquals(count * 4, htds.invocations);
199 assertTrue("expected=" + (count * 2) + ", actual=" + htds.cachehits,
200 htds.cachehits >= (count * 2));
201 assertTrue(htds.get(HConstants.ROOT_TABLE_NAME) != null);
202 assertEquals(htds.invocations, count * 4 + 1);
203 assertTrue("expected=" + ((count * 2) + 1) + ", actual=" + htds.cachehits,
204 htds.cachehits >= ((count * 2) + 1));
205 }
206
207 @Test (expected=org.apache.hadoop.hbase.TableExistsException.class)
208 public void testNoSuchTable() throws IOException {
209 final String name = "testNoSuchTable";
210 FileSystem fs = FileSystem.get(UTIL.getConfiguration());
211
212 Path rootdir = new Path(UTIL.getDataTestDir(), name);
213 TableDescriptors htds = new FSTableDescriptors(fs, rootdir);
214 htds.get("NoSuchTable");
215 }
216
217 @Test
218 public void testUpdates() throws IOException {
219 final String name = "testUpdates";
220 FileSystem fs = FileSystem.get(UTIL.getConfiguration());
221
222 Path rootdir = new Path(UTIL.getDataTestDir(), name);
223 TableDescriptors htds = new FSTableDescriptors(fs, rootdir);
224 HTableDescriptor htd = new HTableDescriptor(name);
225 htds.add(htd);
226 htds.add(htd);
227 htds.add(htd);
228 }
229
230 @Test
231 public void testTableInfoFileStatusComparator() {
232 FileStatus bare =
233 new FileStatus(0, false, 0, 0, -1, new Path("/tmp", FSTableDescriptors.TABLEINFO_NAME));
234 FileStatus future =
235 new FileStatus(0, false, 0, 0, -1,
236 new Path("/tmp/tablinfo." + System.currentTimeMillis()));
237 FileStatus farFuture =
238 new FileStatus(0, false, 0, 0, -1,
239 new Path("/tmp/tablinfo." + System.currentTimeMillis() + 1000));
240 FileStatus [] alist = {bare, future, farFuture};
241 FileStatus [] blist = {bare, farFuture, future};
242 FileStatus [] clist = {farFuture, bare, future};
243 FSTableDescriptors.FileStatusFileNameComparator c =
244 new FSTableDescriptors.FileStatusFileNameComparator();
245 Arrays.sort(alist, c);
246 Arrays.sort(blist, c);
247 Arrays.sort(clist, c);
248
249 for (int i = 0; i < alist.length; i++) {
250 assertTrue(alist[i].equals(blist[i]));
251 assertTrue(blist[i].equals(clist[i]));
252 assertTrue(clist[i].equals(i == 0? farFuture: i == 1? future: bare));
253 }
254 }
255 }