use of org.apache.ignite.igfs.IgfsBlockLocation in project ignite by apache.
the class HadoopIgfs20FileSystemAbstractSelfTest method testZeroReplicationFactor.
/**
* @throws Exception If failed.
*/
public void testZeroReplicationFactor() throws Exception {
// This test doesn't make sense for any mode except of PRIMARY.
if (mode == PRIMARY) {
Path igfsHome = new Path(primaryFsUri);
Path file = new Path(igfsHome, "someFile");
try (FSDataOutputStream out = fs.create(file, EnumSet.noneOf(CreateFlag.class), Options.CreateOpts.perms(FsPermission.getDefault()), Options.CreateOpts.repFac((short) 1))) {
out.write(new byte[1024 * 1024]);
}
IgniteFileSystem igfs = grid(0).fileSystem("igfs");
IgfsPath filePath = new IgfsPath("/someFile");
IgfsFile fileInfo = igfs.info(filePath);
Collection<IgfsBlockLocation> locations = igfs.affinity(filePath, 0, fileInfo.length());
assertEquals(1, locations.size());
IgfsBlockLocation location = F.first(locations);
assertEquals(1, location.nodeIds().size());
}
}
use of org.apache.ignite.igfs.IgfsBlockLocation in project ignite by apache.
the class IgniteHadoopWeightedMapReducePlanner method igfsAffinityNodesForSplit.
/**
* Get IGFS affinity nodes for split if possible.
* <p>
* Order in the returned collection *is* significant, meaning that nodes containing more data
* go first. This way, the 1st nodes in the collection considered to be preferable for scheduling.
*
* @param split Input split.
* @return IGFS affinity or {@code null} if IGFS is not available.
* @throws IgniteCheckedException If failed.
*/
@Nullable
private Collection<UUID> igfsAffinityNodesForSplit(HadoopInputSplit split) throws IgniteCheckedException {
if (split instanceof HadoopFileBlock) {
HadoopFileBlock split0 = (HadoopFileBlock) split;
if (IgniteFileSystem.IGFS_SCHEME.equalsIgnoreCase(split0.file().getScheme())) {
HadoopIgfsEndpoint endpoint = new HadoopIgfsEndpoint(split0.file().getAuthority());
IgfsEx igfs = (IgfsEx) ((IgniteEx) ignite).igfsx(endpoint.igfs());
if (igfs != null && !igfs.isProxy(split0.file())) {
IgfsPath path = new IgfsPath(split0.file());
if (igfs.exists(path)) {
Collection<IgfsBlockLocation> blocks;
try {
blocks = igfs.affinity(path, split0.start(), split0.length());
} catch (IgniteException e) {
throw new IgniteCheckedException("Failed to get IGFS file block affinity [path=" + path + ", start=" + split0.start() + ", len=" + split0.length() + ']', e);
}
assert blocks != null;
if (blocks.size() == 1)
return blocks.iterator().next().nodeIds();
else {
// The most "local" nodes go first.
Map<UUID, Long> idToLen = new HashMap<>();
for (IgfsBlockLocation block : blocks) {
for (UUID id : block.nodeIds()) {
Long len = idToLen.get(id);
idToLen.put(id, len == null ? block.length() : block.length() + len);
}
}
// Sort the nodes in non-ascending order by contained data lengths.
Map<NodeIdAndLength, UUID> res = new TreeMap<>();
for (Map.Entry<UUID, Long> idToLenEntry : idToLen.entrySet()) {
UUID id = idToLenEntry.getKey();
res.put(new NodeIdAndLength(id, idToLenEntry.getValue()), id);
}
return new LinkedHashSet<>(res.values());
}
}
}
}
}
return null;
}
use of org.apache.ignite.igfs.IgfsBlockLocation in project ignite by apache.
the class LocalIgfsSecondaryFileSystem method affinity.
/**
* {@inheritDoc}
*/
@Override
public Collection<IgfsBlockLocation> affinity(IgfsPath path, long start, long len, long maxLen) throws IgniteException {
File f = fileForPath(path);
if (!f.exists())
throw new IgfsPathNotFoundException("File not found: " + path);
// Create fake block & fake affinity for blocks
long blockSize = igfs.configuration().getBlockSize();
if (maxLen <= 0)
maxLen = Long.MAX_VALUE;
assert maxLen > 0 : "maxLen : " + maxLen;
long end = start + len;
Collection<IgfsBlockLocation> blocks = new ArrayList<>((int) (len / maxLen));
IgfsDataManager data = igfs.context().data();
Collection<ClusterNode> lastNodes = null;
long lastBlockIdx = -1;
IgfsBlockLocationImpl lastBlock = null;
for (long offset = start; offset < end; ) {
long blockIdx = offset / blockSize;
// Each step is min of maxLen and end of block.
long lenStep = Math.min(maxLen - (lastBlock != null ? lastBlock.length() : 0), (blockIdx + 1) * blockSize - offset);
lenStep = Math.min(lenStep, end - offset);
// Create fake affinity key to map blocks of secondary filesystem to nodes.
LocalFileSystemBlockKey affKey = new LocalFileSystemBlockKey(path, blockIdx);
if (blockIdx != lastBlockIdx) {
Collection<ClusterNode> nodes = data.affinityNodes(affKey);
if (!nodes.equals(lastNodes) && lastNodes != null && lastBlock != null) {
blocks.add(lastBlock);
lastBlock = null;
}
lastNodes = nodes;
lastBlockIdx = blockIdx;
}
if (lastBlock == null)
lastBlock = new IgfsBlockLocationImpl(offset, lenStep, lastNodes);
else
lastBlock.increaseLength(lenStep);
if (lastBlock.length() == maxLen || lastBlock.start() + lastBlock.length() == end) {
blocks.add(lastBlock);
lastBlock = null;
}
offset += lenStep;
}
return blocks;
}
use of org.apache.ignite.igfs.IgfsBlockLocation in project ignite by apache.
the class IgfsDataManager method affinity.
/**
* Resolve affinity nodes for specified part of file.
*
* @param info File info to resolve affinity nodes for.
* @param start Start position in the file.
* @param len File part length to get affinity for.
* @param maxLen Maximum block length.
* @return Affinity blocks locations.
* @throws IgniteCheckedException If failed.
*/
public Collection<IgfsBlockLocation> affinity(IgfsEntryInfo info, long start, long len, long maxLen) throws IgniteCheckedException {
assert info.isFile() : "Failed to get affinity (not a file): " + info;
assert start >= 0 : "Start position should not be negative: " + start;
assert len >= 0 : "Part length should not be negative: " + len;
if (log.isDebugEnabled())
log.debug("Calculating affinity for file [info=" + info + ", start=" + start + ", len=" + len + ']');
// Skip affinity resolving, if no data requested.
if (len == 0)
return Collections.emptyList();
if (maxLen > 0) {
maxLen -= maxLen % info.blockSize();
// If maxLen is smaller than block size, then adjust it to the block size.
if (maxLen < info.blockSize())
maxLen = info.blockSize();
} else
maxLen = 0;
// In case when affinity key is not null the whole file resides on one node.
if (info.affinityKey() != null) {
Collection<IgfsBlockLocation> res = new LinkedList<>();
splitBlocks(start, len, maxLen, dataCache.affinity().mapKeyToPrimaryAndBackups(new IgfsBlockKey(info.id(), info.affinityKey(), info.evictExclude(), 0)), res);
return res;
}
// Need to merge ranges affinity with non-colocated affinity.
Deque<IgfsBlockLocation> res = new LinkedList<>();
if (info.fileMap().ranges().isEmpty()) {
affinity0(info, start, len, maxLen, res);
return res;
}
long pos = start;
long end = start + len;
for (IgfsFileAffinityRange range : info.fileMap().ranges()) {
if (log.isDebugEnabled())
log.debug("Checking range [range=" + range + ", pos=" + pos + ']');
// If current position is less than range start, add non-colocated affinity ranges.
if (range.less(pos)) {
long partEnd = Math.min(end, range.startOffset());
affinity0(info, pos, partEnd - pos, maxLen, res);
pos = partEnd;
}
IgfsBlockLocation last = res.peekLast();
if (range.belongs(pos)) {
long partEnd = Math.min(range.endOffset() + 1, end);
Collection<ClusterNode> affNodes = dataCache.affinity().mapKeyToPrimaryAndBackups(range.affinityKey());
if (log.isDebugEnabled())
log.debug("Calculated affinity for range [start=" + pos + ", end=" + partEnd + ", nodes=" + F.nodeIds(affNodes) + ", range=" + range + ", affNodes=" + F.nodeIds(affNodes) + ']');
if (last != null && equal(last.nodeIds(), F.viewReadOnly(affNodes, F.node2id()))) {
// Merge with the previous block in result.
res.removeLast();
splitBlocks(last.start(), last.length() + partEnd - pos, maxLen, affNodes, res);
} else
// Do not merge with the previous block.
splitBlocks(pos, partEnd - pos, maxLen, affNodes, res);
pos = partEnd;
}
if (log.isDebugEnabled())
log.debug("Finished range check [range=" + range + ", pos=" + pos + ", res=" + res + ']');
if (pos == end)
break;
}
// Final chunk.
if (pos != end)
affinity0(info, pos, end, maxLen, res);
return res;
}
use of org.apache.ignite.igfs.IgfsBlockLocation in project ignite by apache.
the class IgfsDataManager method affinity0.
/**
* Calculates non-colocated affinity for given file info and given region of file.
*
* @param info File info.
* @param start Start offset.
* @param len Length.
* @param maxLen Maximum allowed split length.
* @param res Result collection to add regions to.
*/
private void affinity0(IgfsEntryInfo info, long start, long len, long maxLen, Deque<IgfsBlockLocation> res) {
long firstGrpIdx = start / grpBlockSize;
long limitGrpIdx = (start + len + grpBlockSize - 1) / grpBlockSize;
if (limitGrpIdx - firstGrpIdx > Integer.MAX_VALUE)
throw new IgfsException("Failed to get affinity (range is too wide)" + " [info=" + info + ", start=" + start + ", len=" + len + ']');
if (log.isDebugEnabled())
log.debug("Mapping file region [fileInfo=" + info + ", start=" + start + ", len=" + len + ']');
for (long grpIdx = firstGrpIdx; grpIdx < limitGrpIdx; grpIdx++) {
// Boundaries of the block.
long blockStart;
long blockLen;
// The first block.
if (grpIdx == firstGrpIdx) {
blockStart = start % grpBlockSize;
blockLen = Math.min(grpBlockSize - blockStart, len);
} else // The last block.
if (grpIdx == limitGrpIdx - 1) {
blockStart = 0;
blockLen = (start + len - 1) % grpBlockSize + 1;
} else // Other blocks.
{
blockStart = 0;
blockLen = grpBlockSize;
}
// Affinity for the first block in the group.
IgfsBlockKey key = new IgfsBlockKey(info.id(), info.affinityKey(), info.evictExclude(), grpIdx * grpSize);
Collection<ClusterNode> affNodes = dataCache.affinity().mapKeyToPrimaryAndBackups(key);
if (log.isDebugEnabled())
log.debug("Mapped key to nodes [key=" + key + ", nodes=" + F.nodeIds(affNodes) + ", blockStart=" + blockStart + ", blockLen=" + blockLen + ']');
IgfsBlockLocation last = res.peekLast();
// Merge with previous affinity block location?
if (last != null && equal(last.nodeIds(), F.viewReadOnly(affNodes, F.node2id()))) {
// Remove previous incomplete value.
res.removeLast();
// Update affinity block location with merged one.
splitBlocks(last.start(), last.length() + blockLen, maxLen, affNodes, res);
} else
splitBlocks(grpIdx * grpBlockSize + blockStart, blockLen, maxLen, affNodes, res);
}
if (log.isDebugEnabled())
log.debug("Calculated file affinity [info=" + info + ", start=" + start + ", len=" + len + ", res=" + res + ']');
}
Aggregations