/*
* 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.blockmanagement;
import io.hops.exception.StorageException;
import io.hops.exception.TransactionContextException;
import io.hops.metadata.HdfsStorageFactory;
import io.hops.metadata.hdfs.dal.ExcessReplicaDataAccess;
import io.hops.metadata.hdfs.entity.ExcessReplica;
import io.hops.transaction.EntityManager;
import io.hops.transaction.handler.HDFSOperationType;
import io.hops.transaction.handler.LightWeightRequestHandler;
import org.apache.hadoop.hdfs.protocol.Block;
import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfo;
import org.apache.hadoop.hdfs.server.blockmanagement.DatanodeManager;
import org.apache.hadoop.hdfs.util.LightWeightLinkedSet;
import java.io.IOException;
import java.util.Collection;
import java.util.TreeSet;
public class ExcessReplicasMap {
private final DatanodeManager datanodeManager;
public ExcessReplicasMap(DatanodeManager datanodeManager) {
this.datanodeManager = datanodeManager;
}
//[M] only needed in TestOverReplicatedBlocks
public LightWeightLinkedSet<Block> get(String dn) throws IOException {
Collection<ExcessReplica> excessReplicas =
getExcessReplicas(datanodeManager.getDatanode(dn).getSId());
if (excessReplicas == null) {
return null;
}
LightWeightLinkedSet<Block> excessBlocks =
new LightWeightLinkedSet<Block>();
for (ExcessReplica er : excessReplicas) {
//FIXME: [M] might need to get the blockinfo from the db, but for now we don't need it
excessBlocks.add(new Block(er.getBlockId()));
}
return excessBlocks;
}
public boolean put(String dn, BlockInfo excessBlk)
throws StorageException, TransactionContextException {
ExcessReplica er =
getExcessReplica(datanodeManager.getDatanode(dn).getSId(), excessBlk);
if (er == null) {
addExcessReplicaToDB(
new ExcessReplica(datanodeManager.getDatanode(dn).getSId(),
excessBlk.getBlockId(), excessBlk.getInodeId()));
return true;
}
return false;
}
public boolean remove(String dn, BlockInfo block)
throws StorageException, TransactionContextException {
ExcessReplica er =
getExcessReplica(datanodeManager.getDatanode(dn).getSId(), block);
if (er != null) {
removeExcessReplicaFromDB(er);
return true;
} else {
return false;
}
}
public Collection<String> get(BlockInfo blk)
throws StorageException, TransactionContextException {
Collection<ExcessReplica> excessReplicas = getExcessReplicas(blk);
if (excessReplicas == null) {
return null;
}
TreeSet<String> stIds = new TreeSet<String>();
for (ExcessReplica er : excessReplicas) {
stIds.add(datanodeManager.getDatanode(er.getStorageId()).getStorageID());
}
return stIds;
}
public boolean contains(String dn, BlockInfo blk)
throws StorageException, TransactionContextException {
Collection<ExcessReplica> ers = getExcessReplicas(blk);
if (ers == null) {
return false;
}
return ers.contains(
new ExcessReplica(datanodeManager.getDatanode(dn).getSId(),
blk.getBlockId(), blk.getInodeId()));
}
public void clear() throws IOException {
new LightWeightRequestHandler(HDFSOperationType.DEL_ALL_EXCESS_BLKS) {
@Override
public Object performTask() throws StorageException, IOException {
ExcessReplicaDataAccess da =
(ExcessReplicaDataAccess) HdfsStorageFactory
.getDataAccess(ExcessReplicaDataAccess.class);
da.removeAll();
return null;
}
}.handle();
}
private Collection<ExcessReplica> getExcessReplicas(final int dn)
throws IOException {
return (Collection<ExcessReplica>) new LightWeightRequestHandler(
HDFSOperationType.GET_EXCESS_RELPLICAS_BY_STORAGEID) {
@Override
public Object performTask() throws StorageException, IOException {
ExcessReplicaDataAccess da =
(ExcessReplicaDataAccess) HdfsStorageFactory
.getDataAccess(ExcessReplicaDataAccess.class);
return da.findExcessReplicaByStorageId(dn);
}
}.handle();
}
private void addExcessReplicaToDB(ExcessReplica er)
throws StorageException, TransactionContextException {
EntityManager.add(er);
}
private void removeExcessReplicaFromDB(ExcessReplica er)
throws StorageException, TransactionContextException {
EntityManager.remove(er);
}
private Collection<ExcessReplica> getExcessReplicas(BlockInfo blk)
throws StorageException, TransactionContextException {
return EntityManager
.findList(ExcessReplica.Finder.ByBlockIdAndINodeId, blk.getBlockId(),
blk.getInodeId());
}
private ExcessReplica getExcessReplica(int dn, BlockInfo block)
throws StorageException, TransactionContextException {
return EntityManager.find(ExcessReplica.Finder.ByBlockIdStorageIdAndINodeId,
block.getBlockId(), dn, block.getInodeId());
}
}