/// <summary>Test the fsimage saving/loading while file appending.</summary> /// <exception cref="System.Exception"/> public virtual void TestSaveLoadImageWithAppending() { Path sub1 = new Path(dir, "sub1"); Path sub1file1 = new Path(sub1, "sub1file1"); Path sub1file2 = new Path(sub1, "sub1file2"); DFSTestUtil.CreateFile(hdfs, sub1file1, Blocksize, Replication, seed); DFSTestUtil.CreateFile(hdfs, sub1file2, Blocksize, Replication, seed); // 1. create snapshot s0 hdfs.AllowSnapshot(dir); hdfs.CreateSnapshot(dir, "s0"); // 2. create snapshot s1 before appending sub1file1 finishes HdfsDataOutputStream @out = AppendFileWithoutClosing(sub1file1, Blocksize); @out.Hsync(EnumSet.Of(HdfsDataOutputStream.SyncFlag.UpdateLength)); // also append sub1file2 DFSTestUtil.AppendFile(hdfs, sub1file2, Blocksize); hdfs.CreateSnapshot(dir, "s1"); @out.Close(); // 3. create snapshot s2 before appending finishes @out = AppendFileWithoutClosing(sub1file1, Blocksize); @out.Hsync(EnumSet.Of(HdfsDataOutputStream.SyncFlag.UpdateLength)); hdfs.CreateSnapshot(dir, "s2"); @out.Close(); // 4. save fsimage before appending finishes @out = AppendFileWithoutClosing(sub1file1, Blocksize); @out.Hsync(EnumSet.Of(HdfsDataOutputStream.SyncFlag.UpdateLength)); // dump fsdir FilePath fsnBefore = DumpTree2File("before"); // save the namesystem to a temp file FilePath imageFile = SaveFSImageToTempFile(); // 5. load fsimage and compare // first restart the cluster, and format the cluster @out.Close(); cluster.Shutdown(); cluster = new MiniDFSCluster.Builder(conf).Format(true).NumDataNodes(Replication) .Build(); cluster.WaitActive(); fsn = cluster.GetNamesystem(); hdfs = cluster.GetFileSystem(); // then load the fsimage LoadFSImageFromTempFile(imageFile); // dump the fsdir tree again FilePath fsnAfter = DumpTree2File("after"); // compare two dumped tree SnapshotTestHelper.CompareDumpedTreeInFile(fsnBefore, fsnAfter, true); }
/// <summary> /// Test snapshot during file appending, before the corresponding /// <see cref="Org.Apache.Hadoop.FS.FSDataOutputStream"/> /// instance closes. /// </summary> /// <exception cref="System.Exception"/> public virtual void TestSnapshotWhileAppending() { Path file = new Path(dir, "file"); DFSTestUtil.CreateFile(hdfs, file, Blocksize, Replication, seed); // 1. append without closing stream --> create snapshot HdfsDataOutputStream @out = AppendFileWithoutClosing(file, Blocksize); @out.Hsync(EnumSet.Of(HdfsDataOutputStream.SyncFlag.UpdateLength)); SnapshotTestHelper.CreateSnapshot(hdfs, dir, "s0"); @out.Close(); // check: an INodeFileUnderConstructionWithSnapshot should be stored into s0's // deleted list, with size BLOCKSIZE*2 INodeFile fileNode = (INodeFile)fsdir.GetINode(file.ToString()); NUnit.Framework.Assert.AreEqual(Blocksize * 2, fileNode.ComputeFileSize()); INodeDirectory dirNode = fsdir.GetINode(dir.ToString()).AsDirectory(); DirectoryWithSnapshotFeature.DirectoryDiff last = dirNode.GetDiffs().GetLast(); // 2. append without closing stream @out = AppendFileWithoutClosing(file, Blocksize); @out.Hsync(EnumSet.Of(HdfsDataOutputStream.SyncFlag.UpdateLength)); // re-check nodeInDeleted_S0 dirNode = fsdir.GetINode(dir.ToString()).AsDirectory(); NUnit.Framework.Assert.AreEqual(Blocksize * 2, fileNode.ComputeFileSize(last.GetSnapshotId ())); // 3. take snapshot --> close stream hdfs.CreateSnapshot(dir, "s1"); @out.Close(); // check: an INodeFileUnderConstructionWithSnapshot with size BLOCKSIZE*3 should // have been stored in s1's deleted list fileNode = (INodeFile)fsdir.GetINode(file.ToString()); dirNode = fsdir.GetINode(dir.ToString()).AsDirectory(); last = dirNode.GetDiffs().GetLast(); NUnit.Framework.Assert.IsTrue(fileNode.IsWithSnapshot()); NUnit.Framework.Assert.AreEqual(Blocksize * 3, fileNode.ComputeFileSize(last.GetSnapshotId ())); // 4. modify file --> append without closing stream --> take snapshot --> // close stream hdfs.SetReplication(file, (short)(Replication - 1)); @out = AppendFileWithoutClosing(file, Blocksize); hdfs.CreateSnapshot(dir, "s2"); @out.Close(); // re-check the size of nodeInDeleted_S1 NUnit.Framework.Assert.AreEqual(Blocksize * 3, fileNode.ComputeFileSize(last.GetSnapshotId ())); }
public virtual void TestGetBlockLocations() { Path root = new Path("/"); Path file = new Path("/file"); DFSTestUtil.CreateFile(hdfs, file, Blocksize, Replication, seed); // take a snapshot on root SnapshotTestHelper.CreateSnapshot(hdfs, root, "s1"); Path fileInSnapshot = SnapshotTestHelper.GetSnapshotPath(root, "s1", file.GetName ()); FileStatus status = hdfs.GetFileStatus(fileInSnapshot); // make sure we record the size for the file NUnit.Framework.Assert.AreEqual(Blocksize, status.GetLen()); // append data to file DFSTestUtil.AppendFile(hdfs, file, Blocksize - 1); status = hdfs.GetFileStatus(fileInSnapshot); // the size of snapshot file should still be BLOCKSIZE NUnit.Framework.Assert.AreEqual(Blocksize, status.GetLen()); // the size of the file should be (2 * BLOCKSIZE - 1) status = hdfs.GetFileStatus(file); NUnit.Framework.Assert.AreEqual(Blocksize * 2 - 1, status.GetLen()); // call DFSClient#callGetBlockLocations for the file in snapshot LocatedBlocks blocks = DFSClientAdapter.CallGetBlockLocations(cluster.GetNameNodeRpc (), fileInSnapshot.ToString(), 0, long.MaxValue); IList <LocatedBlock> blockList = blocks.GetLocatedBlocks(); // should be only one block NUnit.Framework.Assert.AreEqual(Blocksize, blocks.GetFileLength()); NUnit.Framework.Assert.AreEqual(1, blockList.Count); // check the last block LocatedBlock lastBlock = blocks.GetLastLocatedBlock(); NUnit.Framework.Assert.AreEqual(0, lastBlock.GetStartOffset()); NUnit.Framework.Assert.AreEqual(Blocksize, lastBlock.GetBlockSize()); // take another snapshot SnapshotTestHelper.CreateSnapshot(hdfs, root, "s2"); Path fileInSnapshot2 = SnapshotTestHelper.GetSnapshotPath(root, "s2", file.GetName ()); // append data to file without closing HdfsDataOutputStream @out = AppendFileWithoutClosing(file, Blocksize); @out.Hsync(EnumSet.Of(HdfsDataOutputStream.SyncFlag.UpdateLength)); status = hdfs.GetFileStatus(fileInSnapshot2); // the size of snapshot file should be BLOCKSIZE*2-1 NUnit.Framework.Assert.AreEqual(Blocksize * 2 - 1, status.GetLen()); // the size of the file should be (3 * BLOCKSIZE - 1) status = hdfs.GetFileStatus(file); NUnit.Framework.Assert.AreEqual(Blocksize * 3 - 1, status.GetLen()); blocks = DFSClientAdapter.CallGetBlockLocations(cluster.GetNameNodeRpc(), fileInSnapshot2 .ToString(), 0, long.MaxValue); NUnit.Framework.Assert.IsFalse(blocks.IsUnderConstruction()); NUnit.Framework.Assert.IsTrue(blocks.IsLastBlockComplete()); blockList = blocks.GetLocatedBlocks(); // should be 2 blocks NUnit.Framework.Assert.AreEqual(Blocksize * 2 - 1, blocks.GetFileLength()); NUnit.Framework.Assert.AreEqual(2, blockList.Count); // check the last block lastBlock = blocks.GetLastLocatedBlock(); NUnit.Framework.Assert.AreEqual(Blocksize, lastBlock.GetStartOffset()); NUnit.Framework.Assert.AreEqual(Blocksize, lastBlock.GetBlockSize()); blocks = DFSClientAdapter.CallGetBlockLocations(cluster.GetNameNodeRpc(), fileInSnapshot2 .ToString(), Blocksize, 0); blockList = blocks.GetLocatedBlocks(); NUnit.Framework.Assert.AreEqual(1, blockList.Count); // check blocks for file being written blocks = DFSClientAdapter.CallGetBlockLocations(cluster.GetNameNodeRpc(), file.ToString (), 0, long.MaxValue); blockList = blocks.GetLocatedBlocks(); NUnit.Framework.Assert.AreEqual(3, blockList.Count); NUnit.Framework.Assert.IsTrue(blocks.IsUnderConstruction()); NUnit.Framework.Assert.IsFalse(blocks.IsLastBlockComplete()); lastBlock = blocks.GetLastLocatedBlock(); NUnit.Framework.Assert.AreEqual(Blocksize * 2, lastBlock.GetStartOffset()); NUnit.Framework.Assert.AreEqual(Blocksize - 1, lastBlock.GetBlockSize()); @out.Close(); }
/// <exception cref="System.IO.IOException"/> internal virtual void HandleWrite(DFSClient dfsClient, WRITE3Request request, Org.Jboss.Netty.Channel.Channel channel, int xid, Nfs3FileAttributes preOpAttr) { int count = request.GetCount(); byte[] data = ((byte[])request.GetData().Array()); if (data.Length < count) { WRITE3Response response = new WRITE3Response(Nfs3Status.Nfs3errInval); Nfs3Utils.WriteChannel(channel, response.Serialize(new XDR(), xid, new VerifierNone ()), xid); return; } FileHandle handle = request.GetHandle(); if (Log.IsDebugEnabled()) { Log.Debug("handleWrite " + request); } // Check if there is a stream to write FileHandle fileHandle = request.GetHandle(); OpenFileCtx openFileCtx = fileContextCache.Get(fileHandle); if (openFileCtx == null) { Log.Info("No opened stream for fileId: " + fileHandle.GetFileId()); string fileIdPath = Nfs3Utils.GetFileIdPath(fileHandle.GetFileId()); HdfsDataOutputStream fos = null; Nfs3FileAttributes latestAttr = null; try { int bufferSize = config.GetInt(CommonConfigurationKeysPublic.IoFileBufferSizeKey, CommonConfigurationKeysPublic.IoFileBufferSizeDefault); fos = dfsClient.Append(fileIdPath, bufferSize, EnumSet.Of(CreateFlag.Append), null , null); latestAttr = Nfs3Utils.GetFileAttr(dfsClient, fileIdPath, iug); } catch (RemoteException e) { IOException io = e.UnwrapRemoteException(); if (io is AlreadyBeingCreatedException) { Log.Warn("Can't append file: " + fileIdPath + ". Possibly the file is being closed. Drop the request: " + request + ", wait for the client to retry..."); return; } throw; } catch (IOException e) { Log.Error("Can't append to file: " + fileIdPath, e); if (fos != null) { fos.Close(); } WccData fileWcc = new WccData(Nfs3Utils.GetWccAttr(preOpAttr), preOpAttr); WRITE3Response response = new WRITE3Response(Nfs3Status.Nfs3errIo, fileWcc, count , request.GetStableHow(), Nfs3Constant.WriteCommitVerf); Nfs3Utils.WriteChannel(channel, response.Serialize(new XDR(), xid, new VerifierNone ()), xid); return; } // Add open stream string writeDumpDir = config.Get(NfsConfigKeys.DfsNfsFileDumpDirKey, NfsConfigKeys .DfsNfsFileDumpDirDefault); openFileCtx = new OpenFileCtx(fos, latestAttr, writeDumpDir + "/" + fileHandle.GetFileId (), dfsClient, iug, aixCompatMode, config); if (!AddOpenFileStream(fileHandle, openFileCtx)) { Log.Info("Can't add new stream. Close it. Tell client to retry."); try { fos.Close(); } catch (IOException e) { Log.Error("Can't close stream for fileId: " + handle.GetFileId(), e); } // Notify client to retry WccData fileWcc = new WccData(latestAttr.GetWccAttr(), latestAttr); WRITE3Response response = new WRITE3Response(Nfs3Status.Nfs3errJukebox, fileWcc, 0, request.GetStableHow(), Nfs3Constant.WriteCommitVerf); Nfs3Utils.WriteChannel(channel, response.Serialize(new XDR(), xid, new VerifierNone ()), xid); return; } if (Log.IsDebugEnabled()) { Log.Debug("Opened stream for appending file: " + fileHandle.GetFileId()); } } // Add write into the async job queue openFileCtx.ReceivedNewWrite(dfsClient, request, channel, xid, asyncDataService, iug); return; }