/* * Copyright (C) 2015 hops.io. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.hops.metadata; import com.google.common.annotations.VisibleForTesting; import io.hops.DalDriver; import io.hops.DalStorageFactory; import io.hops.StorageConnector; import io.hops.common.IDsMonitor; import io.hops.exception.StorageException; import io.hops.exception.StorageInitializtionException; import io.hops.log.NDCWrapper; import io.hops.metadata.hdfs.dal.GroupDataAccess; import io.hops.metadata.hdfs.dal.UserDataAccess; import io.hops.metadata.hdfs.dal.UserGroupDataAccess; import io.hops.resolvingcache.Cache; import io.hops.metadata.adaptor.BlockInfoDALAdaptor; import io.hops.metadata.adaptor.INodeAttributeDALAdaptor; import io.hops.metadata.adaptor.INodeDALAdaptor; import io.hops.metadata.adaptor.LeaseDALAdaptor; import io.hops.metadata.adaptor.PendingBlockInfoDALAdaptor; import io.hops.metadata.adaptor.ReplicaUnderConstructionDALAdaptor; import io.hops.metadata.common.EntityDataAccess; import io.hops.metadata.common.entity.ArrayVariable; import io.hops.metadata.common.entity.ByteArrayVariable; import io.hops.metadata.common.entity.IntVariable; import io.hops.metadata.common.entity.LongVariable; import io.hops.metadata.common.entity.StringVariable; import io.hops.metadata.common.entity.Variable; import io.hops.metadata.election.dal.HdfsLeDescriptorDataAccess; import io.hops.metadata.election.dal.LeDescriptorDataAccess; import io.hops.metadata.election.entity.LeDescriptor.HdfsLeDescriptor; import io.hops.metadata.hdfs.dal.BlockChecksumDataAccess; import io.hops.metadata.hdfs.dal.BlockInfoDataAccess; import io.hops.metadata.hdfs.dal.CorruptReplicaDataAccess; import io.hops.metadata.hdfs.dal.EncodingStatusDataAccess; import io.hops.metadata.hdfs.dal.ExcessReplicaDataAccess; import io.hops.metadata.hdfs.dal.INodeAttributesDataAccess; import io.hops.metadata.hdfs.dal.INodeDataAccess; import io.hops.metadata.hdfs.dal.InvalidateBlockDataAccess; import io.hops.metadata.hdfs.dal.LeaseDataAccess; import io.hops.metadata.hdfs.dal.LeasePathDataAccess; import io.hops.metadata.hdfs.dal.OngoingSubTreeOpsDataAccess; import io.hops.metadata.hdfs.dal.MetadataLogDataAccess; import io.hops.metadata.hdfs.dal.PendingBlockDataAccess; import io.hops.metadata.hdfs.dal.QuotaUpdateDataAccess; import io.hops.metadata.hdfs.dal.ReplicaDataAccess; import io.hops.metadata.hdfs.dal.ReplicaUnderConstructionDataAccess; import io.hops.metadata.hdfs.dal.UnderReplicatedBlockDataAccess; import io.hops.metadata.hdfs.dal.VariableDataAccess; import io.hops.metadata.hdfs.entity.BlockChecksum; import io.hops.metadata.hdfs.entity.CorruptReplica; import io.hops.metadata.hdfs.entity.EncodingStatus; import io.hops.metadata.hdfs.entity.ExcessReplica; import io.hops.metadata.hdfs.entity.Replica; import io.hops.metadata.hdfs.entity.InvalidatedBlock; import io.hops.metadata.hdfs.entity.LeasePath; import io.hops.metadata.hdfs.entity.MetadataLogEntry; import io.hops.metadata.hdfs.entity.QuotaUpdate; import io.hops.metadata.hdfs.entity.SubTreeOperation; import io.hops.metadata.hdfs.entity.UnderReplicatedBlock; import io.hops.security.Users; import io.hops.security.UsersGroups; import io.hops.transaction.EntityManager; import io.hops.transaction.context.BlockChecksumContext; import io.hops.transaction.context.BlockInfoContext; import io.hops.transaction.context.ContextInitializer; import io.hops.transaction.context.CorruptReplicaContext; import io.hops.transaction.context.EncodingStatusContext; import io.hops.transaction.context.EntityContext; import io.hops.transaction.context.ExcessReplicaContext; import io.hops.transaction.context.INodeAttributesContext; import io.hops.transaction.context.INodeContext; import io.hops.transaction.context.InvalidatedBlockContext; import io.hops.transaction.context.LeSnapshot; import io.hops.transaction.context.LeaseContext; import io.hops.transaction.context.LeasePathContext; import io.hops.transaction.context.MetadataLogContext; import io.hops.transaction.context.PendingBlockContext; import io.hops.transaction.context.QuotaUpdateContext; import io.hops.transaction.context.ReplicaContext; import io.hops.transaction.context.ReplicaUnderConstructionContext; import io.hops.transaction.context.SubTreeOperationsContext; import io.hops.transaction.context.TransactionsStats; import io.hops.transaction.context.UnderReplicatedBlockContext; import io.hops.transaction.context.VariableContext; import io.hops.transaction.lock.LockFactory; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.CommonConfigurationKeys; import org.apache.hadoop.hdfs.DFSConfigKeys; import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfo; import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfoUnderConstruction; import org.apache.hadoop.hdfs.server.blockmanagement.PendingBlockInfo; import org.apache.hadoop.hdfs.server.blockmanagement.ReplicaUnderConstruction; import org.apache.hadoop.hdfs.server.namenode.INode; import org.apache.hadoop.hdfs.server.namenode.INodeAttributes; import org.apache.hadoop.hdfs.server.namenode.INodeDirectory; import org.apache.hadoop.hdfs.server.namenode.INodeDirectoryWithQuota; import org.apache.hadoop.hdfs.server.namenode.INodeFile; import org.apache.hadoop.hdfs.server.namenode.INodeFileUnderConstruction; import org.apache.hadoop.hdfs.server.namenode.INodeSymlink; import org.apache.hadoop.hdfs.server.namenode.Lease; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.HashMap; import java.util.Map; import java.util.Properties; public class HdfsStorageFactory { private static boolean isDALInitialized = false; private static DalStorageFactory dStorageFactory; private static Map<Class, EntityDataAccess> dataAccessAdaptors = new HashMap<Class, EntityDataAccess>(); public static StorageConnector getConnector() { return dStorageFactory.getConnector(); } @VisibleForTesting public static void resetDALInitialized() { isDALInitialized = false; } public static void setConfiguration(Configuration conf) throws IOException { IDsMonitor.getInstance().setConfiguration(conf); Cache.getInstance(conf); LockFactory.getInstance().setConfiguration(conf); NDCWrapper.enableNDC(conf.getBoolean(DFSConfigKeys.DFS_NDC_ENABLED_KEY, DFSConfigKeys.DFS_NDC_ENABLED_DEFAULT)); TransactionsStats.getInstance().setConfiguration( conf.getBoolean(DFSConfigKeys.DFS_TRANSACTION_STATS_ENABLED, DFSConfigKeys.DFS_TRANSACTION_STATS_ENABLED_DEFAULT), conf.get(DFSConfigKeys.DFS_TRANSACTION_STATS_DIR, DFSConfigKeys.DFS_TRANSACTION_STATS_DIR_DEFAULT), conf.getInt (DFSConfigKeys.DFS_TRANSACTION_STATS_WRITER_ROUND, DFSConfigKeys .DFS_TRANSACTION_STATS_WRITER_ROUND_DEFAULT), conf .getBoolean(DFSConfigKeys.DFS_TRANSACTION_STATS_DETAILED_ENABLED, DFSConfigKeys.DFS_TRANSACTION_STATS_DETAILED_ENABLED_DEFAULT)); if (!isDALInitialized) { HdfsVariables.registerDefaultValues(conf); addToClassPath(conf.get(DFSConfigKeys.DFS_STORAGE_DRIVER_JAR_FILE, DFSConfigKeys.DFS_STORAGE_DRIVER_JAR_FILE_DEFAULT)); dStorageFactory = DalDriver.load( conf.get(DFSConfigKeys.DFS_STORAGE_DRIVER_CLASS, DFSConfigKeys.DFS_STORAGE_DRIVER_CLASS_DEFAULT)); dStorageFactory.setConfiguration(getMetadataClusterConfiguration(conf)); initDataAccessWrappers(); EntityManager.addContextInitializer(getContextInitializer()); if(conf.getBoolean(CommonConfigurationKeys.HOPS_GROUPS_ENABLE, CommonConfigurationKeys .HOPS_GROUPS_ENABLE_DEFAULT)) { UsersGroups.init((UserDataAccess) getDataAccess (UserDataAccess.class), (UserGroupDataAccess) getDataAccess (UserGroupDataAccess.class), (GroupDataAccess) getDataAccess (GroupDataAccess.class), conf.getInt(CommonConfigurationKeys .HOPS_GROUPS_UPDATER_ROUND, CommonConfigurationKeys .HOPS_GROUPS_UPDATER_ROUND_DEFAULT), conf.getInt(CommonConfigurationKeys .HOPS_USERS_LRU_THRESHOLD, CommonConfigurationKeys .HOPS_USERS_LRU_THRESHOLD_DEFAULT)); } isDALInitialized = true; } } public static Properties getMetadataClusterConfiguration(Configuration conf) throws IOException { String configFile = conf.get(DFSConfigKeys.DFS_STORAGE_DRIVER_CONFIG_FILE, DFSConfigKeys.DFS_STORAGE_DRIVER_CONFIG_FILE_DEFAULT); Properties clusterConf = new Properties(); InputStream inStream = StorageConnector.class.getClassLoader().getResourceAsStream(configFile); clusterConf.load(inStream); return clusterConf; } //[M]: just for testing purposes private static void addToClassPath(String s) throws StorageInitializtionException { try { File f = new File(s); URL u = f.toURI().toURL(); URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader(); Class urlClass = URLClassLoader.class; Method method = urlClass.getDeclaredMethod("addURL", new Class[]{URL.class}); method.setAccessible(true); method.invoke(urlClassLoader, new Object[]{u}); } catch (MalformedURLException ex) { throw new StorageInitializtionException(ex); } catch (IllegalAccessException ex) { throw new StorageInitializtionException(ex); } catch (IllegalArgumentException ex) { throw new StorageInitializtionException(ex); } catch (InvocationTargetException ex) { throw new StorageInitializtionException(ex); } catch (NoSuchMethodException ex) { throw new StorageInitializtionException(ex); } catch (SecurityException ex) { throw new StorageInitializtionException(ex); } } private static void initDataAccessWrappers() { dataAccessAdaptors.clear(); dataAccessAdaptors.put(BlockInfoDataAccess.class, new BlockInfoDALAdaptor( (BlockInfoDataAccess) getDataAccess(BlockInfoDataAccess.class))); dataAccessAdaptors.put(ReplicaUnderConstructionDataAccess.class, new ReplicaUnderConstructionDALAdaptor( (ReplicaUnderConstructionDataAccess) getDataAccess( ReplicaUnderConstructionDataAccess.class))); dataAccessAdaptors.put(LeaseDataAccess.class, new LeaseDALAdaptor( (LeaseDataAccess) getDataAccess(LeaseDataAccess.class))); dataAccessAdaptors.put(PendingBlockDataAccess.class, new PendingBlockInfoDALAdaptor((PendingBlockDataAccess) getDataAccess( PendingBlockDataAccess.class))); dataAccessAdaptors.put(INodeDataAccess.class, new INodeDALAdaptor( (INodeDataAccess) getDataAccess(INodeDataAccess.class))); dataAccessAdaptors.put(INodeAttributesDataAccess.class, new INodeAttributeDALAdaptor((INodeAttributesDataAccess) getDataAccess( INodeAttributesDataAccess.class))); } private static ContextInitializer getContextInitializer() { return new ContextInitializer() { @Override public Map<Class, EntityContext> createEntityContexts() { Map<Class, EntityContext> entityContexts = new HashMap<Class, EntityContext>(); BlockInfoContext bic = new BlockInfoContext( (BlockInfoDataAccess) getDataAccess(BlockInfoDataAccess.class)); entityContexts.put(BlockInfo.class, bic); entityContexts.put(BlockInfoUnderConstruction.class, bic); entityContexts.put(ReplicaUnderConstruction.class, new ReplicaUnderConstructionContext( (ReplicaUnderConstructionDataAccess) getDataAccess( ReplicaUnderConstructionDataAccess.class))); entityContexts.put(Replica.class, new ReplicaContext( (ReplicaDataAccess) getDataAccess(ReplicaDataAccess.class))); entityContexts.put(ExcessReplica.class, new ExcessReplicaContext( (ExcessReplicaDataAccess) getDataAccess( ExcessReplicaDataAccess.class))); entityContexts.put(InvalidatedBlock.class, new InvalidatedBlockContext( (InvalidateBlockDataAccess) getDataAccess( InvalidateBlockDataAccess.class))); entityContexts.put(Lease.class, new LeaseContext( (LeaseDataAccess) getDataAccess(LeaseDataAccess.class))); entityContexts.put(LeasePath.class, new LeasePathContext( (LeasePathDataAccess) getDataAccess(LeasePathDataAccess.class))); entityContexts.put(PendingBlockInfo.class, new PendingBlockContext( (PendingBlockDataAccess) getDataAccess( PendingBlockDataAccess.class))); INodeContext inodeContext = new INodeContext( (INodeDataAccess) getDataAccess(INodeDataAccess.class)); entityContexts.put(INode.class, inodeContext); entityContexts.put(INodeDirectory.class, inodeContext); entityContexts.put(INodeFile.class, inodeContext); entityContexts.put(INodeDirectoryWithQuota.class, inodeContext); entityContexts.put(INodeSymlink.class, inodeContext); entityContexts.put(INodeFileUnderConstruction.class, inodeContext); entityContexts.put(CorruptReplica.class, new CorruptReplicaContext( (CorruptReplicaDataAccess) getDataAccess( CorruptReplicaDataAccess.class))); entityContexts.put(UnderReplicatedBlock.class, new UnderReplicatedBlockContext( (UnderReplicatedBlockDataAccess) getDataAccess( UnderReplicatedBlockDataAccess.class))); VariableContext variableContext = new VariableContext( (VariableDataAccess) getDataAccess(VariableDataAccess.class)); entityContexts.put(Variable.class, variableContext); entityContexts.put(IntVariable.class, variableContext); entityContexts.put(LongVariable.class, variableContext); entityContexts.put(ByteArrayVariable.class, variableContext); entityContexts.put(StringVariable.class, variableContext); entityContexts.put(ArrayVariable.class, variableContext); entityContexts.put(HdfsLeDescriptor.class, new LeSnapshot.HdfsLESnapshot( (LeDescriptorDataAccess) getDataAccess( HdfsLeDescriptorDataAccess.class))); entityContexts.put(INodeAttributes.class, new INodeAttributesContext( (INodeAttributesDataAccess) getDataAccess( INodeAttributesDataAccess.class))); entityContexts.put(EncodingStatus.class, new EncodingStatusContext( (EncodingStatusDataAccess) getDataAccess( EncodingStatusDataAccess.class))); entityContexts.put(BlockChecksum.class, new BlockChecksumContext( (BlockChecksumDataAccess) getDataAccess( BlockChecksumDataAccess.class))); entityContexts.put(QuotaUpdate.class, new QuotaUpdateContext( (QuotaUpdateDataAccess) getDataAccess( QuotaUpdateDataAccess.class))); entityContexts.put(MetadataLogEntry.class, new MetadataLogContext( (MetadataLogDataAccess) getDataAccess(MetadataLogDataAccess.class) )); entityContexts.put(SubTreeOperation.class, new SubTreeOperationsContext( (OngoingSubTreeOpsDataAccess) getDataAccess(OngoingSubTreeOpsDataAccess.class))); return entityContexts; } @Override public StorageConnector getConnector() { return dStorageFactory.getConnector(); } }; } public static EntityDataAccess getDataAccess(Class type) { if (dataAccessAdaptors.containsKey(type)) { return dataAccessAdaptors.get(type); } return dStorageFactory.getDataAccess(type); } public static boolean formatStorage() throws StorageException { Cache.getInstance().flush(); Users.flushCache(); return dStorageFactory.getConnector().formatStorage(); } public static boolean formatHdfsStorage() throws StorageException { Cache.getInstance().flush(); return dStorageFactory.getConnector().formatHDFSStorage(); } public static boolean formatHdfsStorageNonTransactional() throws StorageException { Cache.getInstance().flush(); return dStorageFactory.getConnector().formatHDFSStorageNonTransactional(); } public static boolean formatAllStorageNonTransactional() throws StorageException { Cache.getInstance().flush(); return dStorageFactory.getConnector().formatAllStorageNonTransactional(); } public static boolean formatStorage(Class<? extends EntityDataAccess>... das) throws StorageException { Cache.getInstance().flush(); return dStorageFactory.getConnector().formatStorage(das); } }