1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 package org.apache.hadoop.hdfs;
19 
20 import java.io.IOException;
21 
22 import org.apache.commons.logging.impl.Log4JLogger;
23 import org.apache.hadoop.conf.Configuration;
24 import org.apache.hadoop.fs.FSDataOutputStream;
25 import org.apache.hadoop.fs.FileSystem;
26 import org.apache.hadoop.fs.Path;
27 import org.apache.hadoop.hdfs.server.namenode.FSNamesystem;
28 import org.apache.hadoop.hdfs.server.namenode.LeaseManager;
29 import org.apache.hadoop.hdfs.server.namenode.NameNode;
30 import org.apache.log4j.Level;
31 
32 public class TestRenameWhileOpen extends junit.framework.TestCase {
33   {
34     ((Log4JLogger)NameNode.stateChangeLog).getLogger().setLevel(Level.ALL);
35     ((Log4JLogger)LeaseManager.LOG).getLogger().setLevel(Level.ALL);
36     ((Log4JLogger)FSNamesystem.LOG).getLogger().setLevel(Level.ALL);
37   }
38 
39   /**
40    * open /user/dir1/file1 /user/dir2/file2
41    * mkdir /user/dir3
42    * move /user/dir1 /user/dir3
43    */
testWhileOpenRenameParent()44   public void testWhileOpenRenameParent() throws IOException {
45     Configuration conf = new Configuration();
46     final int MAX_IDLE_TIME = 2000; // 2s
47     conf.setInt("ipc.client.connection.maxidletime", MAX_IDLE_TIME);
48     conf.setInt("heartbeat.recheck.interval", 1000);
49     conf.setInt("dfs.heartbeat.interval", 1);
50     conf.setInt("dfs.safemode.threshold.pct", 1);
51 
52     // create cluster
53     System.out.println("Test 1*****************************");
54     MiniDFSCluster cluster = new MiniDFSCluster(conf, 1, true, null);
55     FileSystem fs = null;
56     try {
57       cluster.waitActive();
58       fs = cluster.getFileSystem();
59       final int nnport = cluster.getNameNodePort();
60 
61       // create file1.
62       Path dir1 = new Path("/user/a+b/dir1");
63       Path file1 = new Path(dir1, "file1");
64       FSDataOutputStream stm1 = TestFileCreation.createFile(fs, file1, 1);
65       System.out.println("testFileCreationDeleteParent: "
66           + "Created file " + file1);
67       TestFileCreation.writeFile(stm1);
68       stm1.sync();
69 
70       // create file2.
71       Path dir2 = new Path("/user/dir2");
72       Path file2 = new Path(dir2, "file2");
73       FSDataOutputStream stm2 = TestFileCreation.createFile(fs, file2, 1);
74       System.out.println("testFileCreationDeleteParent: "
75           + "Created file " + file2);
76       TestFileCreation.writeFile(stm2);
77       stm2.sync();
78 
79       // move dir1 while file1 is open
80       Path dir3 = new Path("/user/dir3");
81       fs.mkdirs(dir3);
82       fs.rename(dir1, dir3);
83 
84       // create file3
85       Path file3 = new Path(dir3, "file3");
86       FSDataOutputStream stm3 = TestFileCreation.createFile(fs, file3, 1);
87       TestFileCreation.writeFile(stm3);
88       // rename file3 to some bad name
89       try {
90         fs.rename(file3, new Path(dir3, "$ "));
91       } catch(Exception e) {
92         e.printStackTrace();
93       }
94 
95       // restart cluster with the same namenode port as before.
96       // This ensures that leases are persisted in fsimage.
97       cluster.shutdown();
98       try {Thread.sleep(2*MAX_IDLE_TIME);} catch (InterruptedException e) {}
99       cluster = new MiniDFSCluster(nnport, conf, 1, false, true,
100                                    null, null, null);
101       cluster.waitActive();
102 
103       // restart cluster yet again. This triggers the code to read in
104       // persistent leases from fsimage.
105       cluster.shutdown();
106       try {Thread.sleep(5000);} catch (InterruptedException e) {}
107       cluster = new MiniDFSCluster(nnport, conf, 1, false, true,
108                                    null, null, null);
109       cluster.waitActive();
110       fs = cluster.getFileSystem();
111 
112       Path newfile = new Path("/user/dir3/dir1", "file1");
113       assertTrue(!fs.exists(file1));
114       assertTrue(fs.exists(file2));
115       assertTrue(fs.exists(newfile));
116       TestFileCreation.checkFullFile(fs, newfile);
117     } finally {
118       fs.close();
119       cluster.shutdown();
120     }
121   }
122 
123   /**
124    * open /user/dir1/file1 /user/dir2/file2
125    * move /user/dir1 /user/dir3
126    */
testWhileOpenRenameParentToNonexistentDir()127   public void testWhileOpenRenameParentToNonexistentDir() throws IOException {
128     Configuration conf = new Configuration();
129     final int MAX_IDLE_TIME = 2000; // 2s
130     conf.setInt("ipc.client.connection.maxidletime", MAX_IDLE_TIME);
131     conf.setInt("heartbeat.recheck.interval", 1000);
132     conf.setInt("dfs.heartbeat.interval", 1);
133     conf.setInt("dfs.safemode.threshold.pct", 1);
134     System.out.println("Test 2************************************");
135 
136     // create cluster
137     MiniDFSCluster cluster = new MiniDFSCluster(conf, 1, true, null);
138     FileSystem fs = null;
139     try {
140       cluster.waitActive();
141       fs = cluster.getFileSystem();
142       final int nnport = cluster.getNameNodePort();
143 
144       // create file1.
145       Path dir1 = new Path("/user/dir1");
146       Path file1 = new Path(dir1, "file1");
147       FSDataOutputStream stm1 = TestFileCreation.createFile(fs, file1, 1);
148       System.out.println("testFileCreationDeleteParent: "
149           + "Created file " + file1);
150       TestFileCreation.writeFile(stm1);
151       stm1.sync();
152 
153       // create file2.
154       Path dir2 = new Path("/user/dir2");
155       Path file2 = new Path(dir2, "file2");
156       FSDataOutputStream stm2 = TestFileCreation.createFile(fs, file2, 1);
157       System.out.println("testFileCreationDeleteParent: "
158           + "Created file " + file2);
159       TestFileCreation.writeFile(stm2);
160       stm2.sync();
161 
162       // move dir1 while file1 is open
163       Path dir3 = new Path("/user/dir3");
164       fs.rename(dir1, dir3);
165 
166       // restart cluster with the same namenode port as before.
167       // This ensures that leases are persisted in fsimage.
168       cluster.shutdown();
169       try {Thread.sleep(2*MAX_IDLE_TIME);} catch (InterruptedException e) {}
170       cluster = new MiniDFSCluster(nnport, conf, 1, false, true,
171                                    null, null, null);
172       cluster.waitActive();
173 
174       // restart cluster yet again. This triggers the code to read in
175       // persistent leases from fsimage.
176       cluster.shutdown();
177       try {Thread.sleep(5000);} catch (InterruptedException e) {}
178       cluster = new MiniDFSCluster(nnport, conf, 1, false, true,
179                                    null, null, null);
180       cluster.waitActive();
181       fs = cluster.getFileSystem();
182 
183       Path newfile = new Path("/user/dir3", "file1");
184       assertTrue(!fs.exists(file1));
185       assertTrue(fs.exists(file2));
186       assertTrue(fs.exists(newfile));
187       TestFileCreation.checkFullFile(fs, newfile);
188     } finally {
189       fs.close();
190       cluster.shutdown();
191     }
192   }
193 
194   /**
195    * open /user/dir1/file1
196    * mkdir /user/dir2
197    * move /user/dir1/file1 /user/dir2/
198    */
testWhileOpenRenameToExistentDirectory()199   public void testWhileOpenRenameToExistentDirectory() throws IOException {
200     Configuration conf = new Configuration();
201     final int MAX_IDLE_TIME = 2000; // 2s
202     conf.setInt("ipc.client.connection.maxidletime", MAX_IDLE_TIME);
203     conf.setInt("heartbeat.recheck.interval", 1000);
204     conf.setInt("dfs.heartbeat.interval", 1);
205     conf.setInt("dfs.safemode.threshold.pct", 1);
206     System.out.println("Test 3************************************");
207 
208     // create cluster
209     MiniDFSCluster cluster = new MiniDFSCluster(conf, 1, true, null);
210     FileSystem fs = null;
211     try {
212       cluster.waitActive();
213       fs = cluster.getFileSystem();
214       final int nnport = cluster.getNameNodePort();
215 
216       // create file1.
217       Path dir1 = new Path("/user/dir1");
218       Path file1 = new Path(dir1, "file1");
219       FSDataOutputStream stm1 = TestFileCreation.createFile(fs, file1, 1);
220       System.out.println("testFileCreationDeleteParent: " +
221                          "Created file " + file1);
222       TestFileCreation.writeFile(stm1);
223       stm1.sync();
224 
225       Path dir2 = new Path("/user/dir2");
226       fs.mkdirs(dir2);
227 
228       fs.rename(file1, dir2);
229 
230       // restart cluster with the same namenode port as before.
231       // This ensures that leases are persisted in fsimage.
232       cluster.shutdown();
233       try {Thread.sleep(2*MAX_IDLE_TIME);} catch (InterruptedException e) {}
234       cluster = new MiniDFSCluster(nnport, conf, 1, false, true,
235                                    null, null, null);
236       cluster.waitActive();
237 
238       // restart cluster yet again. This triggers the code to read in
239       // persistent leases from fsimage.
240       cluster.shutdown();
241       try {Thread.sleep(5000);} catch (InterruptedException e) {}
242       cluster = new MiniDFSCluster(nnport, conf, 1, false, true,
243                                    null, null, null);
244       cluster.waitActive();
245       fs = cluster.getFileSystem();
246 
247       Path newfile = new Path("/user/dir2", "file1");
248       assertTrue(!fs.exists(file1));
249       assertTrue(fs.exists(newfile));
250       TestFileCreation.checkFullFile(fs, newfile);
251     } finally {
252       fs.close();
253       cluster.shutdown();
254     }
255   }
256 
257   /**
258    * open /user/dir1/file1
259    * move /user/dir1/file1 /user/dir2/
260    */
testWhileOpenRenameToNonExistentDirectory()261   public void testWhileOpenRenameToNonExistentDirectory() throws IOException {
262     Configuration conf = new Configuration();
263     final int MAX_IDLE_TIME = 2000; // 2s
264     conf.setInt("ipc.client.connection.maxidletime", MAX_IDLE_TIME);
265     conf.setInt("heartbeat.recheck.interval", 1000);
266     conf.setInt("dfs.heartbeat.interval", 1);
267     conf.setInt("dfs.safemode.threshold.pct", 1);
268     System.out.println("Test 4************************************");
269 
270     // create cluster
271     MiniDFSCluster cluster = new MiniDFSCluster(conf, 1, true, null);
272     FileSystem fs = null;
273     try {
274       cluster.waitActive();
275       fs = cluster.getFileSystem();
276       final int nnport = cluster.getNameNodePort();
277 
278       // create file1.
279       Path dir1 = new Path("/user/dir1");
280       Path file1 = new Path(dir1, "file1");
281       FSDataOutputStream stm1 = TestFileCreation.createFile(fs, file1, 1);
282       System.out.println("testFileCreationDeleteParent: "
283           + "Created file " + file1);
284       TestFileCreation.writeFile(stm1);
285       stm1.sync();
286 
287       Path dir2 = new Path("/user/dir2");
288 
289       fs.rename(file1, dir2);
290 
291       // restart cluster with the same namenode port as before.
292       // This ensures that leases are persisted in fsimage.
293       cluster.shutdown();
294       try {Thread.sleep(2*MAX_IDLE_TIME);} catch (InterruptedException e) {}
295       cluster = new MiniDFSCluster(nnport, conf, 1, false, true,
296                                    null, null, null);
297       cluster.waitActive();
298 
299       // restart cluster yet again. This triggers the code to read in
300       // persistent leases from fsimage.
301       cluster.shutdown();
302       try {Thread.sleep(5000);} catch (InterruptedException e) {}
303       cluster = new MiniDFSCluster(nnport, conf, 1, false, true,
304                                    null, null, null);
305       cluster.waitActive();
306       fs = cluster.getFileSystem();
307 
308       Path newfile = new Path("/user", "dir2");
309       assertTrue(!fs.exists(file1));
310       assertTrue(fs.exists(newfile));
311       TestFileCreation.checkFullFile(fs, newfile);
312     } finally {
313       fs.close();
314       cluster.shutdown();
315     }
316   }
317 }
318