Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ protected BlockExtendedInputStream getOrOpenStream(int locationIndex) throws IOE

BlockLocationInfo blkInfo = new BlockLocationInfo.Builder()
.setBlockID(blockInfo.getBlockID())
.setLength(internalBlockLength(locationIndex + 1))
.setLength(internalBlockLength(locationIndex + 1, this.repConfig, this.blockInfo.getLength()))
.setPipeline(blockInfo.getPipeline())
.setToken(blockInfo.getToken())
.setPartNumber(blockInfo.getPartNumber())
Expand Down Expand Up @@ -238,11 +238,21 @@ protected Function<BlockID, BlockLocationInfo> ecPipelineRefreshFunction(
* Returns the length of the Nth block in the block group, taking account of a
* potentially partial last stripe. Note that the internal block index is
* numbered starting from 1.
* @param index - Index number of the internal block, starting from 1
* @param index index number of the internal block, starting from 1.
* @param repConfig EC replication config.
* @param length length of the whole block group.
*/
protected long internalBlockLength(int index) {
long lastStripe = blockInfo.getLength() % stripeSize;
long blockSize = (blockInfo.getLength() - lastStripe) / repConfig.getData();
public static long internalBlockLength(int index, ECReplicationConfig repConfig, long length) {
if (index <= 0) {
throw new IllegalArgumentException("Index must start from 1.");
}
if (length < 0) {
throw new IllegalArgumentException("Block length cannot be negative.");
}
long ecChunkSize = (long) repConfig.getEcChunkSize();
long stripeSize = ecChunkSize * repConfig.getData();
long lastStripe = length % stripeSize;
long blockSize = (length - lastStripe) / repConfig.getData();
long lastCell = lastStripe / ecChunkSize + 1;
long lastCellLength = lastStripe % ecChunkSize;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.apache.hadoop.ozone.om.helpers.OzoneFSUtils;
import org.apache.hadoop.util.Time;
import org.apache.hadoop.hdds.client.DefaultReplicationConfig;
import org.apache.hadoop.hdds.client.RatisReplicationConfig;
import org.apache.hadoop.hdds.client.ECReplicationConfig;
import org.apache.hadoop.hdds.client.ReplicationConfig;
import org.apache.hadoop.hdds.client.ReplicationConfigValidator;
Expand Down Expand Up @@ -94,6 +95,7 @@
import org.apache.hadoop.ozone.client.io.OzoneDataStreamOutput;
import org.apache.hadoop.ozone.client.io.OzoneInputStream;
import org.apache.hadoop.ozone.client.io.OzoneOutputStream;
import org.apache.hadoop.ozone.client.io.ECBlockInputStream;
import org.apache.hadoop.ozone.client.protocol.ClientProtocol;
import org.apache.hadoop.ozone.om.OMConfigKeys;
import org.apache.hadoop.ozone.om.exceptions.OMException;
Expand Down Expand Up @@ -1540,6 +1542,17 @@ public OzoneInputStream getKey(
return getInputStreamWithRetryFunction(keyInfo);
}

/**
* Returns a map that contains {@link org.apache.hadoop.ozone.om.helpers.OmKeyLocationInfo} objects of the given key
* as keys of the map.
* Values of the returned map are internal blocks of {@link org.apache.hadoop.ozone.om.helpers.OmKeyLocationInfo}.
* The blocks are represented by another map of {@link org.apache.hadoop.hdds.protocol.DatanodeDetails} as keys and
* {@link org.apache.hadoop.ozone.client.io.OzoneInputStream} as values.
* replicaitonConfig in dnKeyInfo is used to instantiate an input stream for each block.
* In case of EC, ECBlockInputStream is instantiated and causes an error later when the stream is processed.
* To prevent such an error, RATIS ONE replication is used instead and the length of each block is calculated by a
* helper method.
*/
@Override
public Map<OmKeyLocationInfo, Map<DatanodeDetails, OzoneInputStream> >
getKeysEveryReplicas(String volumeName,
Expand All @@ -1554,6 +1567,7 @@ public OzoneInputStream getKey(
OmKeyInfo keyInfo = getKeyInfo(volumeName, bucketName, keyName, true);
List<OmKeyLocationInfo> keyLocationInfos
= keyInfo.getLatestVersionLocations().getBlocksLatestVersionOnly();
ReplicationConfig replicationConfig = keyInfo.getReplicationConfig();

for (OmKeyLocationInfo locationInfo : keyLocationInfos) {
Map<DatanodeDetails, OzoneInputStream> blocks = new HashMap<>();
Expand All @@ -1568,9 +1582,13 @@ public OzoneInputStream getKey(
Pipeline pipeline
= new Pipeline.Builder(pipelineBefore).setNodes(nodes)
.setId(PipelineID.randomId()).build();
long length = replicationConfig instanceof ECReplicationConfig
? ECBlockInputStream.internalBlockLength(pipelineBefore.getReplicaIndex(dn),
(ECReplicationConfig) replicationConfig, locationInfo.getLength())
: locationInfo.getLength();
OmKeyLocationInfo dnKeyLocation = new OmKeyLocationInfo.Builder()
.setBlockID(locationInfo.getBlockID())
.setLength(locationInfo.getLength())
.setLength(length)
.setOffset(locationInfo.getOffset())
.setToken(locationInfo.getToken())
.setPartNumber(locationInfo.getPartNumber())
Expand All @@ -1594,7 +1612,9 @@ public OzoneInputStream getKey(
.setDataSize(keyInfo.getDataSize())
.setCreationTime(keyInfo.getCreationTime())
.setModificationTime(keyInfo.getModificationTime())
.setReplicationConfig(keyInfo.getReplicationConfig())
.setReplicationConfig(replicationConfig instanceof ECReplicationConfig
? RatisReplicationConfig.getInstance(HddsProtos.ReplicationFactor.ONE)
: keyInfo.getReplicationConfig())
.setFileEncryptionInfo(keyInfo.getFileEncryptionInfo())
.setAcls(keyInfo.getAcls())
.setObjectID(keyInfo.getObjectID())
Expand Down
4 changes: 4 additions & 0 deletions hadoop-ozone/dist/src/main/compose/common/replicas-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,7 @@ execute_robot_test ${SCM} -v "PREFIX:${prefix}" debug/ozone-debug-dead-datanode.
docker start "${container}"

wait_for_datanode "${container}" HEALTHY 60

start_docker_env 9
execute_robot_test ${SCM} -v "PREFIX:${prefix}" debug/ozone-debug-tests-ec3-2.robot
execute_robot_test ${SCM} -v "PREFIX:${prefix}" debug/ozone-debug-tests-ec6-3.robot
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.

*** Settings ***
Documentation Test ozone Debug CLI for EC(3,2) replicated keys
Library OperatingSystem
Library Process
Resource ../lib/os.robot
Resource ozone-debug.robot
Test Timeout 5 minute
Suite Setup Create Volume Bucket

*** Variables ***
${PREFIX} ${EMPTY}
${VOLUME} cli-debug-volume${PREFIX}
${BUCKET} cli-debug-bucket
${TESTFILE} testfile
${EC_DATA} 3
${EC_PARITY} 2

*** Keywords ***
Create Volume Bucket
Execute ozone sh volume create o3://om/${VOLUME}
Execute ozone sh bucket create o3://om/${VOLUME}/${BUCKET}

Create EC key
[arguments] ${bs} ${count}

Execute dd if=/dev/urandom of=${TEMP_DIR}/testfile bs=${bs} count=${count}
Execute ozone sh key put o3://om/${VOLUME}/${BUCKET}/testfile ${TEMP_DIR}/testfile -r rs-${EC_DATA}-${EC_PARITY}-1024k -t EC

*** Test Cases ***
0 data block
Create EC key 1000 0
${directory} = Execute read-replicas CLI tool
${count_files} = Count Files In Directory ${directory}
Should Be Equal As Integers ${count_files} 1

1 data block
Create EC key 1048576 1
${directory} = Execute read-replicas CLI tool
${count_files} = Count Files In Directory ${directory}
Should Be Equal As Integers ${count_files} 6
${sum_size} = Evaluate 1048576 * 3
Verify Healthy EC Replica ${directory} 1 ${sum_size}

2 data blocks
Create EC key 1048576 2
${directory} = Execute read-replicas CLI tool
${sum_size} = Evaluate 1048576 * 4
${count_files} = Count Files In Directory ${directory}
Should Be Equal As Integers ${count_files} 6
Verify Healthy EC Replica ${directory} 1 ${sum_size}

3 data blocks
Create EC key 1048576 3
${directory} = Execute read-replicas CLI tool
${sum_size} = Evaluate 1048576 * 5
${count_files} = Count Files In Directory ${directory}
Should Be Equal As Integers ${count_files} 6
Verify Healthy EC Replica ${directory} 1 ${sum_size}

3 data blocks and partial stripe
Create EC key 1000000 4
${directory} = Execute read-replicas CLI tool
${count_files} = Count Files In Directory ${directory}
${sum_size} = Evaluate 1048576 * 5
${sum_size_last_stripe} = Evaluate ((1000000 * 4) % 1048576) * 3
Should Be Equal As Integers ${count_files} 11
Verify Healthy EC Replica ${directory} 1 ${sum_size}
Verify Healthy EC Replica ${directory} 2 ${sum_size_last_stripe}

4 data blocks and partial stripe
Create EC key 1000000 5
${directory} = Execute read-replicas CLI tool
${count_files} = Count Files In Directory ${directory}
${sum_size} = Evaluate 1048576 * 5
${sum_size_last_stripe} = Evaluate 1048576 * 3 + ((1000000 * 5) % 1048576)
Should Be Equal As Integers ${count_files} 11
Verify Healthy EC Replica ${directory} 1 ${sum_size}
Verify Healthy EC Replica ${directory} 2 ${sum_size_last_stripe}

6 data blocks
Create EC key 1048576 6
${directory} = Execute read-replicas CLI tool
${count_files} = Count Files In Directory ${directory}
${sum_size} = Evaluate 1048576 * 5
Should Be Equal As Integers ${count_files} 11
FOR ${block} IN RANGE 1 3
Verify Healthy EC Replica ${directory} ${block} ${sum_size}
END
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.

*** Settings ***
Documentation Test ozone Debug CLI for EC(6,3) replicated key
Library OperatingSystem
Library Process
Resource ../lib/os.robot
Resource ozone-debug.robot
Test Timeout 5 minute

*** Variables ***
${PREFIX} ${EMPTY}
${VOLUME} cli-debug-volume${PREFIX}
${BUCKET} cli-debug-bucket
${TESTFILE} testfile
${EC_DATA} 6
${EC_PARITY} 3

*** Keywords ***
Create EC key
[arguments] ${bs} ${count}

Execute dd if=/dev/urandom of=${TEMP_DIR}/testfile bs=${bs} count=${count}
Execute ozone sh key put o3://om/${VOLUME}/${BUCKET}/testfile ${TEMP_DIR}/testfile -r rs-${EC_DATA}-${EC_PARITY}-1024k -t EC

*** Test Cases ***
0 data block
Create EC key 1048576 0
${directory} = Execute read-replicas CLI tool
${count_files} = Count Files In Directory ${directory}
Should Be Equal As Integers ${count_files} 1

1 data block
Create EC key 1048576 1
${directory} = Execute read-replicas CLI tool
${count_files} = Count Files In Directory ${directory}
Should Be Equal As Integers ${count_files} 10
${sum_size} = Evaluate 1048576 * 4
Verify Healthy EC Replica ${directory} 1 ${sum_size}

2 data blocks
Create EC key 1048576 2
${directory} = Execute read-replicas CLI tool
${sum_size} = Evaluate 1048576 * 5
${count_files} = Count Files In Directory ${directory}
Should Be Equal As Integers ${count_files} 10
Verify Healthy EC Replica ${directory} 1 ${sum_size}

3 data blocks
Create EC key 1048576 3
${directory} = Execute read-replicas CLI tool
${sum_size} = Evaluate 1048576 * 6
${count_files} = Count Files In Directory ${directory}
Should Be Equal As Integers ${count_files} 10
Verify Healthy EC Replica ${directory} 1 ${sum_size}

4 data blocks
Create EC key 1048576 4
${directory} = Execute read-replicas CLI tool
${count_files} = Count Files In Directory ${directory}
${sum_size} = Evaluate 1048576 * 7
Should Be Equal As Integers ${count_files} 10
Verify Healthy EC Replica ${directory} 1 ${sum_size}

5 data blocks
Create EC key 1048576 5
${directory} = Execute read-replicas CLI tool
${count_files} = Count Files In Directory ${directory}
${sum_size} = Evaluate 1048576 * 8
Should Be Equal As Integers ${count_files} 10
Verify Healthy EC Replica ${directory} 1 ${sum_size}

6 data blocks
Create EC key 1048576 6
${directory} = Execute read-replicas CLI tool
${count_files} = Count Files In Directory ${directory}
${sum_size} = Evaluate 1048576 * 9
Should Be Equal As Integers ${count_files} 10
Verify Healthy EC Replica ${directory} 1 ${sum_size}

6 data blocks and partial stripe
Create EC key 1000000 7
${directory} = Execute read-replicas CLI tool
${count_files} = Count Files In Directory ${directory}
${sum_size} = Evaluate 1048576 * 9
${sum_size_last_stripe} = Evaluate ((1000000 * 7) % 1048576) * 4
Should Be Equal As Integers ${count_files} 19
Verify Healthy EC Replica ${directory} 1 ${sum_size}
Verify Healthy EC Replica ${directory} 2 ${sum_size_last_stripe}

7 data blocks and partial stripe
Create EC key 1000000 8
${directory} = Execute read-replicas CLI tool
${count_files} = Count Files In Directory ${directory}
${sum_size} = Evaluate 1048576 * 9
${sum_size_last_stripe} = Evaluate 1048576 * 4 + ((1000000 * 8) % 1048576)
Should Be Equal As Integers ${count_files} 19
Verify Healthy EC Replica ${directory} 1 ${sum_size}
Verify Healthy EC Replica ${directory} 2 ${sum_size_last_stripe}
6 changes: 6 additions & 0 deletions hadoop-ozone/dist/src/main/smoketest/debug/ozone-debug.robot
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ Verify Healthy Replica
${md5sum} = Execute cat ${block_filenames} | md5sum | awk '{print $1}'
Should Be Equal ${md5sum} ${expected_md5sum}

Verify Healthy EC Replica
[arguments] ${directory} ${block} ${expected_block_size}

${block_size} = Execute ls -l ${directory} | grep "testfile_block${block}_ozone-datanode-.*\.ozone_default" | awk '{sum += $5} END {print sum}'
Should Be Equal As Integers ${block_size} ${expected_block_size}

Verify Corrupt Replica
[arguments] ${json} ${replica} ${valid_md5sum}

Expand Down