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