/// <summary> /// Create a AsyncDiskServices with a set of volumes (specified by their /// root directories). /// </summary> /// <remarks> /// Create a AsyncDiskServices with a set of volumes (specified by their /// root directories). /// The AsyncDiskServices uses one ThreadPool per volume to do the async disk /// operations. /// </remarks> /// <param name="localFileSystem">The localFileSystem used for deletions.</param> /// <param name="nonCanonicalVols"> /// The roots of the file system volumes, which may /// be absolte paths, or paths relative to the ${user.dir} system property /// ("cwd"). /// </param> /// <exception cref="System.IO.IOException"/> public MRAsyncDiskService(FileSystem localFileSystem, params string[] nonCanonicalVols ) { this.localFileSystem = localFileSystem; this.volumes = new string[nonCanonicalVols.Length]; for (int v = 0; v < nonCanonicalVols.Length; v++) { this.volumes[v] = NormalizePath(nonCanonicalVols[v]); Log.Debug("Normalized volume: " + nonCanonicalVols[v] + " -> " + this.volumes[v]); } asyncDiskService = new AsyncDiskService(this.volumes); // Create one ThreadPool per volume for (int v_1 = 0; v_1 < volumes.Length; v_1++) { // Create the root for file deletion Path absoluteSubdir = new Path(volumes[v_1], Tobedeleted); if (!localFileSystem.Mkdirs(absoluteSubdir)) { // We should tolerate missing volumes. Log.Warn("Cannot create " + Tobedeleted + " in " + volumes[v_1] + ". Ignored."); } } // Create tasks to delete the paths inside the volumes for (int v_2 = 0; v_2 < volumes.Length; v_2++) { Path absoluteSubdir = new Path(volumes[v_2], Tobedeleted); FileStatus[] files = null; try { // List all files inside the volumes TOBEDELETED sub directory files = localFileSystem.ListStatus(absoluteSubdir); } catch (Exception) { } // Ignore exceptions in listStatus // We tolerate missing sub directories. if (files != null) { for (int f = 0; f < files.Length; f++) { // Get the relative file name to the root of the volume string absoluteFilename = files[f].GetPath().ToUri().GetPath(); string relative = Tobedeleted + Path.SeparatorChar + files[f].GetPath().GetName(); MRAsyncDiskService.DeleteTask task = new MRAsyncDiskService.DeleteTask(this, volumes [v_2], absoluteFilename, relative); Execute(volumes[v_2], task); } } } }
/// <summary> /// Move the path name on one volume to a temporary location and then /// delete them. /// </summary> /// <remarks> /// Move the path name on one volume to a temporary location and then /// delete them. /// This functions returns when the moves are done, but not necessarily all /// deletions are done. This is usually good enough because applications /// won't see the path name under the old name anyway after the move. /// </remarks> /// <param name="volume">The disk volume</param> /// <param name="pathName">The path name relative to volume root.</param> /// <exception cref="System.IO.IOException">If the move failed</exception> /// <returns>false if the file is not found</returns> public virtual bool MoveAndDeleteRelativePath(string volume, string pathName) { volume = NormalizePath(volume); // Move the file right now, so that it can be deleted later string newPathName = format.Format(new DateTime()) + "_" + uniqueId.GetAndIncrement (); newPathName = Tobedeleted + Path.SeparatorChar + newPathName; Path source = new Path(volume, pathName); Path target = new Path(volume, newPathName); try { if (!localFileSystem.Rename(source, target)) { // If the source does not exists, return false. // This is necessary because rename can return false if the source // does not exists. if (!localFileSystem.Exists(source)) { return(false); } // Try to recreate the parent directory just in case it gets deleted. if (!localFileSystem.Mkdirs(new Path(volume, Tobedeleted))) { throw new IOException("Cannot create " + Tobedeleted + " under " + volume); } // Try rename again. If it fails, return false. if (!localFileSystem.Rename(source, target)) { throw new IOException("Cannot rename " + source + " to " + target); } } } catch (FileNotFoundException) { // Return false in case that the file is not found. return(false); } MRAsyncDiskService.DeleteTask task = new MRAsyncDiskService.DeleteTask(this, volume , pathName, newPathName); Execute(volume, task); return(true); }