Skip to content

Commit 46ccc90

Browse files
committed
Add a different coding loop that runs through memory
in order (good), but loads each shard multiple times (bad).
1 parent 925067a commit 46ccc90

File tree

3 files changed

+81
-1
lines changed

3 files changed

+81
-1
lines changed

src/main/java/com/backblaze/erasure/CodingLoop.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ public interface CodingLoop {
1111
CodingLoop[] ALL_CODING_LOOPS =
1212
new CodingLoop[] {
1313
new IndexShardInputExpCodingLoop(),
14-
new IndexShardInputTableCodingLoop()
14+
new IndexShardInputTableCodingLoop(),
15+
new ShardInputIndexTableCodingLoop()
1516
};
1617

1718
/**
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/**
2+
* One specific ordering/nesting of the coding loops.
3+
*
4+
* Copyright 2015, Backblaze, Inc. All rights reserved.
5+
*/
6+
7+
package com.backblaze.erasure;
8+
9+
public class ShardInputIndexTableCodingLoop implements CodingLoop {
10+
11+
@Override
12+
public String getName() {
13+
return "shard/input/index (mult table)";
14+
}
15+
16+
@Override
17+
public void codeSomeShards(
18+
byte[][] matrixRows,
19+
byte[][] inputs, int inputCount,
20+
byte[][] outputs, int outputCount,
21+
int offset, int byteCount) {
22+
23+
byte [] [] table = Galois.MULTIPLICATION_TABLE;
24+
for (int iShard = 0; iShard < outputCount; iShard++) {
25+
byte [] outputShard = outputs[iShard];
26+
{
27+
final int iInput = 0;
28+
final byte [] inputShard = inputs[iInput];
29+
final byte [] multTableRow = table[matrixRows[iShard][iInput] & 0xFF];
30+
for (int iByte = offset; iByte < offset + byteCount; iByte++) {
31+
outputShard[iByte] = multTableRow[inputShard[iByte] & 0xFF];
32+
}
33+
}
34+
for (int iInput = 1; iInput < inputCount; iInput++) {
35+
final byte [] inputShard = inputs[iInput];
36+
final byte [] multTableRow = table[matrixRows[iShard][iInput] & 0xFF];
37+
for (int iByte = offset; iByte < offset + byteCount; iByte++) {
38+
outputShard[iByte] ^= multTableRow[inputShard[iByte] & 0xFF];
39+
}
40+
}
41+
}
42+
}
43+
44+
@Override
45+
public boolean checkSomeShards(
46+
byte[][] matrixRows,
47+
byte[][] inputs, int inputCount,
48+
byte[][] toCheck, int checkCount,
49+
int offset, int byteCount) {
50+
51+
// TODO: structure like the coding loop (use a temporary buffer?)
52+
//
53+
// Checking loop doesn't match the coding loop. Need to figure
54+
// out how to do it. The problem is that the coding loop uses
55+
// the output shards as temporary working space, so the original
56+
// value isn't there to check after computing the new value.
57+
58+
byte [] [] table = Galois.MULTIPLICATION_TABLE;
59+
for (int iByte = offset; iByte < offset + byteCount; iByte++) {
60+
for (int iRow = 0; iRow < checkCount; iRow++) {
61+
byte [] matrixRow = matrixRows[iRow];
62+
int value = 0;
63+
for (int c = 0; c < inputCount; c++) {
64+
value ^= table[matrixRow[c] & 0xFF][inputs[c][iByte] & 0xFF];
65+
}
66+
if (toCheck[iRow][iByte] != (byte) value) {
67+
return false;
68+
}
69+
}
70+
}
71+
return true;
72+
}
73+
74+
}

src/test/java/com/backblaze/erasure/ReedSolomonTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,11 @@ public void testCodingLoopsProduceSameAnswers() {
206206
}
207207

208208
codec.encodeParity(allShards, 0, shardSize);
209+
allShards[parityShardCount - 1][0] += 1;
210+
assertFalse(codec.isParityCorrect(allShards, 0, shardSize));
211+
allShards[parityShardCount - 1][0] -= 1;
212+
assertTrue(codec.isParityCorrect(allShards, 0, shardSize));
213+
209214

210215
return parityShards;
211216
}

0 commit comments

Comments
 (0)