All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.bigdata.ha.althalog.HALogManager Maven / Gradle / Ivy

/**

Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016.  All rights reserved.

Contact:
     SYSTAP, LLC DBA Blazegraph
     2501 Calvert ST NW #106
     Washington, DC 20008
     [email protected]

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package com.bigdata.ha.althalog;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.log4j.Logger;

import com.bigdata.ha.msg.IHAWriteMessage;
import com.bigdata.io.DirectBufferPool;
import com.bigdata.io.IBufferAccess;
import com.bigdata.journal.IRootBlockView;
import com.bigdata.journal.StoreTypeEnum;

/**
 * Provides the top level control
 * 
 * @author Martyn Cutcher
 *
 */
public class HALogManager {
	/**
	 * Logger for HA events.
	 */
	private static final Logger haLog = Logger.getLogger("com.bigdata.haLog");

	private final File m_halogdir;
	
	private final Lock m_currentLock = new ReentrantLock();
	
	// protected by m_curretnLock
	private HALogFile m_current = null;
	
	/**
	 * Ensures private communication from created log files
	 */
	interface IHALogManagerCallback {
		File getHALogDir();
		void release(HALogFile logfile);
	}
	
	/*
	 * This callback is passed to HALogFiles when they are created.
	 * 
	 * A 
	 */
	private IHALogManagerCallback m_callback = new IHALogManagerCallback() {

		@Override
		public void release(final HALogFile logfile) {
			HALogManager.this.closeLog(logfile);
		}

		@Override
		public File getHALogDir() {
			return HALogManager.this.getHALogDir();
		}
		
	};
	
	public HALogManager(final File halogdir) {
		m_halogdir = halogdir;
		
		if (!m_halogdir.exists())
			throw new IllegalArgumentException();
		
		if (haLog.isInfoEnabled())
			haLog.info("HALogManager initialized");
	}
	
	public HALogFile createLog(final IRootBlockView rbv) throws IOException {
		
		if (haLog.isInfoEnabled())
			haLog.info("Creating log for commit " + rbv.getCommitCounter());

		m_currentLock.lock();
		try {
			if (m_current != null)
				throw new IllegalStateException();
			
			final HALogFile ret = new HALogFile(rbv, m_callback);
			
			m_current = ret;
			
			return ret;
		} finally {
			m_currentLock.unlock();
		}
	}
	
	/*
	 * Called by the logWriter via the callback when the
	 * closing rootblock is written
	 */
	private void closeLog(final HALogFile current) {

		m_currentLock.lock();
		try {
			if (m_current != current)
				throw new IllegalStateException();
			
			m_current = null;
		} finally {
			m_currentLock.unlock();
		}
	}
	
	/**
	 * 
	 * @return the the open HALogFile
	 */
	public HALogFile getOpenLogFile() {
		m_currentLock.lock();
		try {
			return m_current;
		} finally {
			m_currentLock.unlock();
		}
	}
	
	/**
	 * Utility to retrieve a File reference to the current open file
	 * 
	 * @return
	 */
	public File getCurrentFile() {
		final HALogFile file = getOpenLogFile();
		
		return file == null ? null : file.getFile();
	}

	/**
	 * 
	 * @return the directory used to store the log files
	 */
	public File getHALogDir() {
		return m_halogdir;
	}
	

	
	public IHALogReader getReader(final long commitCounter) throws IOException {
		m_currentLock.lock();
		try {
			if (m_current != null && m_current.getCommitCounter() == commitCounter)
				return m_current.getReader();
		} finally {
			m_currentLock.unlock();
		}
		
		final File file = HALogFile.getHALogFileName(m_halogdir, commitCounter);
		final HALogFile halog = new HALogFile(file);
		
		return halog.getReader();
	}
	
	/**
	 * Returns the HALogFile for the commitCounter if it exists.
	 * It will return either the current or an historical file
	 * 
	 * @param commitCounter
	 * @return the HALogFile for this commit counter
	 * @throws FileNotFoundException
	 */
	public HALogFile getHALogFile(final long commitCounter) throws FileNotFoundException {
		/*
		 * Check the file exists first
		 */
		final File file = HALogFile.getHALogFileName(m_halogdir, commitCounter);
		if (!file.exists())
			throw new FileNotFoundException();
		
		m_currentLock.lock();
		try {
			if (m_current != null && m_current.getCommitCounter() == commitCounter)
				return m_current;
		} finally {
			m_currentLock.unlock();
		}
		
		/*
		 * If the file existed before we checked for current open file, then it must now
		 * be a read only log
		 */		
		return new HALogFile(file);
	}


	/**
	 * Closes and removes the current writer
	 * @throws IOException 
	 */
	public void disable() throws IOException {
		m_currentLock.lock();
		try {
			if (m_current != null)
				m_current.disable();
			
			m_current = null;
		} finally {
			m_currentLock.unlock();
		}
	}

	/*
	 * This logic is handled by the HAJournalServer, which is also aware
	 * of the backup integration through zookeeper.
	 */
//	/**
//	 * Disables any current log file, then removes all log files
//	 * from the directory
//	 * 
//	 * @throws IOException
//	 */
//	public void removeAllLogFiles() {
//		m_currentLock.lock();
//		try {
//			// No longer disables the current log file
//			
//			removeAllLogFiles(m_halogdir, getCurrentFile());
//		} finally {
//			m_currentLock.unlock();
//		}
//	}
//
//	/**
//	 * Recursively removes all log files from the provided directory
//	 * @param dir
//	 */
//	private void removeAllLogFiles(final File dir, final File preserve) {
//		final File[] files = logFiles(dir);
//		for (File f : files) {
//			try {
//				if (f.isDirectory()) {
//					removeAllLogFiles(f, preserve);
//					
//					// FIXME: should we remove the directory?
//					// Probably not
//					// f.delete();
//				} else if (f != preserve) {
//					f.delete();
//				}
//			} catch (final SecurityException se) {
//				haLog.warn("Unabel to delete file " + f.getAbsolutePath(), se);
//			}
//		}
//	}
	
	/**
	 * Utility program will dump log files (or directories containing log files)
	 * provided as arguments.
	 * 
	 * @param args
	 *            Zero or more files or directories.
	 * 
	 * @throws IOException
	 * @throws InterruptedException
	 */
	public static void main(final String[] args) throws IOException,
			InterruptedException {

		final IBufferAccess buf = DirectBufferPool.INSTANCE.acquire();

		try {

			for (String arg : args) {

				final File file = new File(arg);

				if (!file.exists()) {

					System.err.println("No such file: " + file);

					continue;

				}

				if (file.isDirectory()) {

					doDirectory(file, buf);

				} else {

					doFile(file, buf);

				}

			}

		} finally {

			buf.release();

		}

	}
	
	private static File[] logFiles(final File dir) {
		return dir.listFiles(new FilenameFilter() {

			@Override
			public boolean accept(File dir, String name) {

				if (new File(dir, name).isDirectory()) {

					// Allow recursion through directories.
					return true;

				}

				return name.endsWith(IHALogReader.HA_LOG_EXT);

			}
		});
	}

	private static void doDirectory(final File dir, final IBufferAccess buf)
			throws IOException {

		final File[] files = logFiles(dir);

		for (File file : files) {

			if (file.isDirectory()) {

				doDirectory(file, buf);

			} else {

				doFile(file, buf);

			}

		}

	}

	private static void doFile(final File file, final IBufferAccess buf)
			throws IOException {

		final HALogFile f = new HALogFile(file);
		final IHALogReader r = f.getReader();

		try {

			final IRootBlockView openingRootBlock = r.getOpeningRootBlock();

			final IRootBlockView closingRootBlock = r.getClosingRootBlock();

			final boolean isWORM = openingRootBlock.getStoreType() == StoreTypeEnum.WORM;

			if (openingRootBlock.getCommitCounter() == closingRootBlock
					.getCommitCounter()) {

				System.err.println("EMPTY LOG: " + file);

			}

			System.out.println("----------begin----------");
			System.out.println("file=" + file);
			System.out.println("openingRootBlock=" + openingRootBlock);
			System.out.println("closingRootBlock=" + closingRootBlock);
			

			while (r.hasMoreBuffers()) {

				// don't pass buffer in if WORM, just validate the messages
				final IHAWriteMessage msg = r.processNextBuffer(isWORM ? null
						: buf.buffer());

				System.out.println(msg.toString());

			}
			System.out.println("-----------end-----------");

		} finally {

			r.close();

		}

	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy