/// <summary> /// Asserts that the storage lock file in the given directory has been /// released. /// </summary> /// <remarks> /// Asserts that the storage lock file in the given directory has been /// released. This method works by trying to acquire the lock file itself. If /// locking fails here, then the main code must have failed to release it. /// </remarks> /// <param name="dir">the storage directory to check</param> /// <exception cref="System.IO.IOException">if there is an unexpected I/O error</exception> public static void AssertFileLockReleased(string dir) { StorageLocation sl = StorageLocation.Parse(dir); FilePath lockFile = new FilePath(sl.GetFile(), Storage.StorageFileLock); try { using (RandomAccessFile raf = new RandomAccessFile(lockFile, "rws")) { using (FileChannel channel = raf.GetChannel()) { FileLock Lock = channel.TryLock(); NUnit.Framework.Assert.IsNotNull(string.Format("Lock file at %s appears to be held by a different process." , lockFile.GetAbsolutePath()), Lock); if (Lock != null) { try { Lock.Release(); } catch (IOException e) { FsDatasetImpl.Log.Warn(string.Format("I/O error releasing file lock %s.", lockFile .GetAbsolutePath()), e); throw; } } } } } catch (OverlappingFileLockException) { NUnit.Framework.Assert.Fail(string.Format("Must release lock file at %s.", lockFile .GetAbsolutePath())); } }
/// <summary> /// Open the set of output files, based on the configured /// instance variables. /// </summary> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: private void openFiles() throws java.io.IOException private void OpenFiles() { LogManager manager = LogManager.LogManager; manager.CheckPermission(); if (Count < 1) { throw new IllegalArgumentException("file count = " + Count); } if (Limit < 0) { Limit = 0; } // We register our own ErrorManager during initialization // so we can record exceptions. InitializationErrorManager em = new InitializationErrorManager(); ErrorManager = em; // Create a lock file. This grants us exclusive access // to our set of output files, as long as we are alive. int unique = -1; for (;;) { unique++; if (unique > MAX_LOCKS) { throw new IOException("Couldn't get lock for " + Pattern); } // Generate a lock file name from the "unique" int. LockFileName = Generate(Pattern, 0, unique).ToString() + ".lck"; // Now try to lock that filename. // Because some systems (e.g., Solaris) can only do file locks // between processes (and not within a process), we first check // if we ourself already have the file locked. lock (Locks) { if (Locks.Contains(LockFileName)) { // We already own this lock, for a different FileHandler // object. Try again. continue; } //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final java.nio.file.Path lockFilePath = java.nio.file.Paths.get(lockFileName); Path lockFilePath = Paths.Get(LockFileName); FileChannel channel = null; int retries = -1; bool fileCreated = false; while (channel == null && retries++ < 1) { try { channel = FileChannel.Open(lockFilePath, CREATE_NEW, WRITE); fileCreated = true; } catch (FileAlreadyExistsException) { // This may be a zombie file left over by a previous // execution. Reuse it - but only if we can actually // write to its directory. // Note that this is a situation that may happen, // but not too frequently. if (Files.IsRegularFile(lockFilePath, LinkOption.NOFOLLOW_LINKS) && IsParentWritable(lockFilePath)) { try { channel = FileChannel.Open(lockFilePath, WRITE, APPEND); } catch (NoSuchFileException) { // Race condition - retry once, and if that // fails again just try the next name in // the sequence. continue; } catch (IOException) { // the file may not be writable for us. // try the next name in the sequence break; } } else { // at this point channel should still be null. // break and try the next name in the sequence. break; } } } if (channel == null) // try the next name; { continue; } LockFileChannel = channel; bool available; try { available = LockFileChannel.TryLock() != null; // We got the lock OK. // At this point we could call File.deleteOnExit(). // However, this could have undesirable side effects // as indicated by JDK-4872014. So we will instead // rely on the fact that close() will remove the lock // file and that whoever is creating FileHandlers should // be responsible for closing them. } catch (IOException) { // We got an IOException while trying to get the lock. // This normally indicates that locking is not supported // on the target directory. We have to proceed without // getting a lock. Drop through, but only if we did // create the file... available = fileCreated; } catch (OverlappingFileLockException) { // someone already locked this file in this VM, through // some other channel - that is - using something else // than new FileHandler(...); // continue searching for an available lock. available = false; } if (available) { // We got the lock. Remember it. Locks.Add(LockFileName); break; } // We failed to get the lock. Try next file. LockFileChannel.Close(); } } Files = new File[Count]; for (int i = 0; i < Count; i++) { Files[i] = Generate(Pattern, i, unique); } // Create the initial log file. if (Append) { Open(Files[0], true); } else { Rotate(); } // Did we detect any exceptions during initialization? Exception ex = em.LastException; if (ex != null) { if (ex is IOException) { throw (IOException)ex; } else if (ex is SecurityException) { throw (SecurityException)ex; } else { throw new IOException("Exception: " + ex); } } // Install the normal default ErrorManager. ErrorManager = new ErrorManager(); }