diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterFileSystem.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterFileSystem.java index 9b95ae7..d4d8b7f 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterFileSystem.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterFileSystem.java @@ -102,6 +102,13 @@ public class MasterFileSystem { } }; + final static PathFilter SYS_FILTER = new PathFilter() { + @Override + public boolean accept(Path p) { + return DefaultWALProvider.isSystemFile(p); + } + }; + final static PathFilter NON_META_FILTER = new PathFilter() { @Override public boolean accept(Path p) { @@ -316,6 +323,26 @@ public class MasterFileSystem { splitLog(serverNames, META_FILTER); } + /** + * Specialized method to handle the splitting for system WAL + * @param serverName + * @throws IOException + */ + public void splitSystemLog(final ServerName serverName) throws IOException { + Set serverNames = new HashSet(); + serverNames.add(serverName); + splitSystemLog(serverNames); + } + + /** + * Specialized method to handle the splitting for System WAL + * @param serverNames + * @throws IOException + */ + public void splitSystemLog(final Set serverNames) throws IOException { + splitLog(serverNames, SYS_FILTER); + } + @edu.umd.cs.findbugs.annotations.SuppressWarnings(value="UL_UNRELEASED_LOCK", justification= "We only release this lock when we set it. Updates to code that uses it should verify use " + "of the guard boolean.") diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java index 5312338..f6beed2 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java @@ -361,6 +361,8 @@ public class HRegionServer extends HasThread implements final LogRoller walRoller; // Lazily initialized if this RegionServer hosts a meta table. final AtomicReference metawalRoller = new AtomicReference(); + // Lazily initialized if this RegionServer hosts a system table. + final AtomicReference sysWalRoller = new AtomicReference(); // flag set after we're done setting up server threads final AtomicBoolean online = new AtomicBoolean(false); @@ -1663,6 +1665,28 @@ public class HRegionServer extends HasThread implements return roller; } + /* + * This is similar to ensureMetaWALRoller(). It handles WAL roller for system tables + */ + protected LogRoller ensureSystemWALRoller() { + // Using a tmp log roller to ensure metaLogRoller is alive once it is not null + LogRoller roller = sysWalRoller.get(); + if (null == roller) { + LogRoller tmpLogRoller = new LogRoller(this, this); + String n = Thread.currentThread().getName(); + Threads.setDaemonThreadRunning(tmpLogRoller.getThread(), + n + "-SystemLogRoller", uncaughtExceptionHandler); + if (sysWalRoller.compareAndSet(null, tmpLogRoller)) { + roller = tmpLogRoller; + } else { + // Another thread won starting the roller + Threads.shutdown(tmpLogRoller.getThread()); + roller = sysWalRoller.get(); + } + } + return roller; + } + public MetricsRegionServer getRegionServerMetrics() { return this.metricsRegionServer; } @@ -1837,11 +1861,15 @@ public class HRegionServer extends HasThread implements public WAL getWAL(HRegionInfo regionInfo) throws IOException { WAL wal; LogRoller roller = walRoller; - //_ROOT_ and hbase:meta regions have separate WAL. + // hbase:meta regions have separate WAL. if (regionInfo != null && regionInfo.isMetaTable() && regionInfo.getReplicaId() == HRegionInfo.DEFAULT_REPLICA_ID) { roller = ensureMetaWALRoller(); wal = walFactory.getMetaWAL(regionInfo.getEncodedNameAsBytes()); + } else if (regionInfo != null && regionInfo.isSystemTable() && + regionInfo.getReplicaId() == HRegionInfo.DEFAULT_REPLICA_ID) { + roller = ensureSystemWALRoller(); + wal = walFactory.getSystemWAL(regionInfo.getEncodedNameAsBytes()); } else if (regionInfo == null) { wal = walFactory.getWAL(UNSPECIFIED_REGION); } else { diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/util/MetaUtils.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/util/MetaUtils.java index 1ff4967..bfbd3b8 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/util/MetaUtils.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/util/MetaUtils.java @@ -95,7 +95,9 @@ public class MetaUtils { this.walFactory = new WALFactory(walConf, null, logName); } final byte[] region = info.getEncodedNameAsBytes(); - return info.isMetaRegion() ? walFactory.getMetaWAL(region) : walFactory.getWAL(region); + if (info.isMetaRegion()) return walFactory.getMetaWAL(region); + if (info.isSystemTable()) return walFactory.getSystemWAL(region); + return walFactory.getWAL(region); } /** diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/wal/DefaultWALProvider.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/wal/DefaultWALProvider.java index b41bbfb..c2bc853 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/wal/DefaultWALProvider.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/wal/DefaultWALProvider.java @@ -116,6 +116,8 @@ public class DefaultWALProvider implements WALProvider { /** The hbase:meta region's WAL filename extension */ @VisibleForTesting public static final String META_WAL_PROVIDER_ID = ".meta"; + @VisibleForTesting + public static final String SYS_WAL_PROVIDER_ID = ".sys"; static final String DEFAULT_PROVIDER_ID = "default"; // Implementation details that currently leak in tests or elsewhere follow @@ -344,6 +346,17 @@ public class DefaultWALProvider implements WALProvider { return false; } + public static boolean isSystemFile(Path p) { + return isSystemFile(p.getName()); + } + + public static boolean isSystemFile(String p) { + if (p != null && p.endsWith(SYS_WAL_PROVIDER_ID)) { + return true; + } + return false; + } + /** * public because of FSHLog. Should be package-private */ diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/wal/WALFactory.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/wal/WALFactory.java index c19f8c9..d764e31 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/wal/WALFactory.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/wal/WALFactory.java @@ -89,12 +89,18 @@ public class WALFactory { static final String META_WAL_PROVIDER = "hbase.wal.meta_provider"; static final String DEFAULT_META_WAL_PROVIDER = Providers.defaultProvider.name(); + static final String SYS_WAL_PROVIDER = "hbase.wal.sys_provider"; + static final String DEFAULT_SYS_WAL_PROVIDER = Providers.defaultProvider.name(); + final String factoryId; final WALProvider provider; // The meta updates are written to a different wal. If this // regionserver holds meta regions, then this ref will be non-null. // lazily intialized; most RegionServers don't deal with META final AtomicReference metaProvider = new AtomicReference(); + // The updates to system tables are written to a different wal. + // lazily intialized + final AtomicReference sysProvider = new AtomicReference(); /** * Configuration-specified WAL Reader used when a custom reader is requested @@ -194,6 +200,10 @@ public class WALFactory { if (null != metaProvider) { metaProvider.close(); } + final WALProvider sysProvider = this.sysProvider.get(); + if (null != sysProvider) { + sysProvider.close(); + } // close is called on a WALFactory with null provider in the case of contention handling // within the getInstance method. if (null != provider) { @@ -216,6 +226,14 @@ public class WALFactory { exception = ioe; } } + final WALProvider sysProvider = this.sysProvider.get(); + if (null != sysProvider) { + try { + sysProvider.shutdown(); + } catch(IOException ioe) { + exception = ioe; + } + } provider.shutdown(); if (null != exception) { throw exception; @@ -249,6 +267,26 @@ public class WALFactory { return metaProvider.getWAL(identifier); } + /** + * @param identifier may not be null, contents will not be altered + */ + public WAL getSystemWAL(final byte[] identifier) throws IOException { + WALProvider sysProvider = this.sysProvider.get(); + if (null == sysProvider) { + final WALProvider temp = getProvider(SYS_WAL_PROVIDER, DEFAULT_SYS_WAL_PROVIDER, + Collections.singletonList(new MetricsWAL()), + DefaultWALProvider.SYS_WAL_PROVIDER_ID); + if (this.sysProvider.compareAndSet(null, temp)) { + sysProvider = temp; + } else { + // reference must now be to a provider created in another thread. + temp.close(); + sysProvider = this.sysProvider.get(); + } + } + return sysProvider.getWAL(identifier); + } + public Reader createReader(final FileSystem fs, final Path path) throws IOException { return createReader(fs, path, (CancelableProgressable)null); }