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