001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.wal; 019 020import java.io.Closeable; 021import java.io.IOException; 022import java.util.concurrent.atomic.AtomicReference; 023import org.apache.hadoop.conf.Configuration; 024import org.apache.hadoop.hbase.Abortable; 025import org.apache.hadoop.hbase.regionserver.wal.MetricsWAL; 026import org.apache.hadoop.hbase.wal.WALFactory.Providers; 027import org.apache.yetus.audience.InterfaceAudience; 028 029/** 030 * A lazy initialized WAL provider for holding the WALProvider for some special tables, such as 031 * hbase:meta, hbase:replication, etc. 032 */ 033@InterfaceAudience.Private 034class LazyInitializedWALProvider implements Closeable { 035 036 private final WALFactory factory; 037 038 private final String providerId; 039 040 private final String providerConfigName; 041 042 private final Abortable abortable; 043 044 private final AtomicReference<WALProvider> holder = new AtomicReference<>(); 045 046 LazyInitializedWALProvider(WALFactory factory, String providerId, String providerConfigName, 047 Abortable abortable) { 048 this.factory = factory; 049 this.providerId = providerId; 050 this.providerConfigName = providerConfigName; 051 this.abortable = abortable; 052 } 053 054 WALProvider getProvider() throws IOException { 055 Configuration conf = factory.getConf(); 056 for (;;) { 057 WALProvider provider = this.holder.get(); 058 if (provider != null) { 059 return provider; 060 } 061 Class<? extends WALProvider> clz = null; 062 if (conf.get(providerConfigName) == null) { 063 try { 064 clz = conf.getClass(WALFactory.WAL_PROVIDER, Providers.defaultProvider.clazz, 065 WALProvider.class); 066 } catch (Throwable t) { 067 // the WAL provider should be an enum. Proceed 068 } 069 } 070 if (clz == null) { 071 clz = factory.getProviderClass(providerConfigName, 072 conf.get(WALFactory.WAL_PROVIDER, WALFactory.DEFAULT_WAL_PROVIDER)); 073 } 074 provider = WALFactory.createProvider(clz); 075 provider.init(factory, conf, providerId, this.abortable); 076 provider.addWALActionsListener(new MetricsWAL()); 077 if (this.holder.compareAndSet(null, provider)) { 078 return provider; 079 } else { 080 // someone is ahead of us, close and try again. 081 provider.close(); 082 } 083 } 084 } 085 086 /** 087 * Get the provider if it already initialized, otherwise just return {@code null} instead of 088 * creating it. 089 */ 090 WALProvider getProviderNoCreate() { 091 return holder.get(); 092 } 093 094 @Override 095 public void close() throws IOException { 096 WALProvider provider = this.holder.get(); 097 if (provider != null) { 098 provider.close(); 099 } 100 } 101 102 void shutdown() throws IOException { 103 WALProvider provider = this.holder.get(); 104 if (provider != null) { 105 provider.shutdown(); 106 } 107 } 108}