/**
* 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.
*/
package org.apache.hadoop.raid;
import java.io.IOException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class XORCode extends ErasureCode {
public static final Log LOG = LogFactory.getLog(XORCode.class);
private int stripeSize;
private int paritySize;
private int[] dataBuff;
@Deprecated
public XORCode(int stripeSize, int paritySize) {
init(stripeSize, paritySize);
}
public XORCode() {
}
@Override
public void init(int stripeSize, int paritySize) {
assert(paritySize == 1);
this.stripeSize = stripeSize;
this.paritySize = paritySize;
this.dataBuff = new int[paritySize + stripeSize];
LOG.info("Initialized " + XORCode.class +
" stripeLength:" + stripeSize +
" parityLength:" + paritySize);
}
@Override
public void encode(int[] message, int[] parity) {
assert(message.length == stripeSize && parity.length == 1);
int val = 0;
parity[0] = message[0];
for (int i = 1; i < message.length; i++) {
parity[0] ^= message[i];
}
}
@Override
public void decode(int[] data, int[] erasedLocation, int[] erasedValue) {
if (erasedLocation.length != 1) {
return;
}
assert(erasedLocation.length == erasedValue.length);
int skipIndex = erasedLocation[0];
int val = 0;
for (int i = 0; i < data.length; i++) {
if (i == skipIndex) {
continue;
}
val ^= data[i];
}
erasedValue[0] = val;
}
@Override
public int stripeSize() {
return this.stripeSize;
}
@Override
public int paritySize() {
return this.paritySize;
}
@Override
public int symbolSize() {
return 8;
}
@Override
public void encodeBulk(byte[][] inputs, byte[][] outputs) {
byte[] output = outputs[0];
int bufSize = output.length;
// Get the first buffer's data.
for (int j = 0; j < bufSize; j++) {
output[j] = inputs[0][j];
}
// XOR with everything else.
for (int i = 1; i < inputs.length; i++) {
for (int j = 0; j < bufSize; j++) {
output[j] ^= inputs[i][j];
}
}
}
@Override
public void decodeBulk(byte[][] readBufs, byte[][] writeBufs,
int[] erasedLocations, int dataStart, int dataLen) throws IOException {
assert(erasedLocations.length == writeBufs.length);
assert(erasedLocations.length <= 1);
byte[] output = writeBufs[0];
int erasedIdx = erasedLocations[0];
// Set the output to zeros.
for (int j = dataStart; j < dataStart + dataLen; j++) {
output[j] = 0;
}
// Process the inputs.
for (int i = 0; i < readBufs.length; i++) {
// Skip the erased location.
if (i == erasedIdx) {
continue;
}
byte[] input = readBufs[i];
for (int j = dataStart; j < dataStart + dataLen; j++) {
output[j] ^= input[j];
}
}
}
@Override
public void decodeBulk(
byte[][] readBufs, byte[][] writeBufs, int[] erasedLocations) throws IOException {
decodeBulk(readBufs, writeBufs, erasedLocations, 0, readBufs[0].length);
}
@Override
public void encodeBulk(byte[][] inputs, byte[][] outputs, boolean useNative)
throws IOException {
if (useNative) {
LOG.info("XORCode is doing an Non-Native Java Implementation");
}
encodeBulk(inputs, outputs);
}
@Override
public void decodeOneBlock(byte[][] readBufs, byte[] decodeVec, int dataLen,
int[] erasedLocation, int decodeLocation, int decodePos, int decodeLen,
boolean useNative) throws IOException {
throw new IOException("XORCode not support decodeOneBlock");
}
}