@SuppressWarnings("resource") public void setLogDirectory(File theDirectory, int processType) { Assert.assertNotNull(theDirectory); if (theDirectory.getName().trim().equalsIgnoreCase("stdout:") || theDirectory.getName().trim().equalsIgnoreCase("stderr:")) { if (currentLoggingDirectory != null && currentLoggingDirectory.getName().trim().equalsIgnoreCase(theDirectory.getName())) { // Nothing to do; great! return; } delegateFileAppender.setDelegate(new NullAppender()); consoleAppender.setLayout(new PatternLayout(CONSOLE_LOGGING_ONLY_PATTERN)); // Logger.addAppender() doesn't double-add, so this is safe Logger.getRootLogger().addAppender(consoleAppender); if (buffering) { BufferingAppender realBufferingAppender = (BufferingAppender) delegateBufferingAppender.setDelegate(new NullAppender()); realBufferingAppender.stopAndSendContentsTo(consoleAppender); realBufferingAppender.close(); buffering = false; } boolean stdout = theDirectory.getName().trim().equalsIgnoreCase("stdout:"); getConsoleLogger() .info( "All logging information now output to standard " + (stdout ? "output" : "error") + "."); return; } synchronized (TCLoggingLog4J.class) { if (currentLoggingDirectory != null) { try { if (theDirectory.getCanonicalPath().equals(currentLoggingDirectory.getCanonicalPath())) { return; } } catch (IOException ioe) { // oh, well -- what can we do? we'll continue on. } } } try { FileUtils.forceMkdir(theDirectory); } catch (IOException ioe) { reportLoggingError( "We can't create the directory '" + theDirectory.getAbsolutePath() + "' that you specified for your logs.", ioe); return; } if (!theDirectory.canWrite()) { // formatting reportLoggingError( "The log directory, '" + theDirectory.getAbsolutePath() + "', can't be written to.", null); return; } FileLock thisDirectoryLock = null; if (!lockingDisabled) { File lockFile = new File(theDirectory, LOCK_FILE_NAME); try { lockFile.createNewFile(); Assert.eval(lockFile.exists()); FileChannel channel = new RandomAccessFile(lockFile, "rw").getChannel(); thisDirectoryLock = channel.tryLock(); if (thisDirectoryLock == null) { reportLoggingError( "The log directory, '" + theDirectory.getAbsolutePath() + "', is already in use by another " + "Terracotta process. Logging will proceed to the console only.", null); return; } } catch (OverlappingFileLockException ofle) { // This VM already holds the lock; no problem } catch (IOException ioe) { reportLoggingError( "We can't lock the file '" + lockFile.getAbsolutePath() + "', to make sure that only one " + "Terracotta process is using this directory for logging. This may be a permission " + "issue, or some unexpected error. Logging will proceed to the console only.", ioe); return; } } RollingFileAppender newFileAppender; String logFileName; switch (processType) { case PROCESS_TYPE_L1: logFileName = TERRACOTTA_L1_LOG_FILE_NAME; break; case PROCESS_TYPE_L2: logFileName = TERRACOTTA_L2_LOG_FILE_NAME; break; case PROCESS_TYPE_GENERIC: logFileName = TERRACOTTA_GENERIC_LOG_FILE_NAME; break; default: throw Assert.failure("Unknown process type: " + processType); } String logFilePath = new File(theDirectory, logFileName).getAbsolutePath(); synchronized (TCLoggingLog4J.class) { try { TCProperties props = TCPropertiesImpl.getProperties().getPropertiesFor(TCPropertiesConsts.LOGGING_CATEGORY); newFileAppender = new TCRollingFileAppender(new PatternLayout(FILE_AND_JMX_PATTERN), logFilePath, true); newFileAppender.setName("file appender"); int maxLogFileSize = props.getInt(MAX_LOG_FILE_SIZE_PROPERTY, DEFAULT_MAX_LOG_FILE_SIZE); newFileAppender.setMaxFileSize(maxLogFileSize + "MB"); newFileAppender.setMaxBackupIndex(props.getInt(MAX_BACKUPS_PROPERTY, DEFAULT_MAX_BACKUPS)); // This makes us start with a new file each time. newFileAppender.rollOver(); // Note: order of operations is very important here. We start the new appender before we // close and remove the // old one so that you don't drop any log records. Appender oldFileAppender = delegateFileAppender.setDelegate(newFileAppender); if (oldFileAppender != null) { oldFileAppender.close(); } if (buffering) { BufferingAppender realBufferingAppender = (BufferingAppender) delegateBufferingAppender.setDelegate(new NullAppender()); realBufferingAppender.stopAndSendContentsTo(delegateFileAppender); realBufferingAppender.close(); buffering = false; } currentLoggingDirectory = theDirectory; if (currentLoggingDirectoryFileLock != null) currentLoggingDirectoryFileLock.release(); currentLoggingDirectoryFileLock = thisDirectoryLock; } catch (IOException ioe) { reportLoggingError( "We were unable to switch the logging system to log to '" + logFilePath + "'.", ioe); } } getConsoleLogger().info("Log file: '" + logFilePath + "'."); writeSystemProperties(); }