summaryrefslogtreecommitdiffstats
path: root/xlators/cluster/ec/src/ec-method.c
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/cluster/ec/src/ec-method.c')
-rw-r--r--xlators/cluster/ec/src/ec-method.c182
1 files changed, 182 insertions, 0 deletions
diff --git a/xlators/cluster/ec/src/ec-method.c b/xlators/cluster/ec/src/ec-method.c
new file mode 100644
index 00000000000..deedf2a21f2
--- /dev/null
+++ b/xlators/cluster/ec/src/ec-method.c
@@ -0,0 +1,182 @@
+/*
+ Copyright (c) 2012 DataLab, s.l. <http://www.datalab.es>
+
+ This file is part of the cluster/ec translator for GlusterFS.
+
+ The cluster/ec translator for GlusterFS is free software: you can
+ redistribute it and/or modify it under the terms of the GNU General
+ Public License as published by the Free Software Foundation, either
+ version 3 of the License, or (at your option) any later version.
+
+ The cluster/ec translator for GlusterFS is distributed in the hope
+ that it will be useful, but WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the cluster/ec translator for GlusterFS. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#include <string.h>
+#include <inttypes.h>
+
+#include "ec-method.h"
+
+#define EC_METHOD_WORD_SIZE 16
+
+static uint32_t GfPow[EC_METHOD_SIZE << 1];
+static uint32_t GfLog[EC_METHOD_SIZE << 1];
+
+void ec_method_initialize(void)
+{
+ uint32_t i;
+
+ GfPow[0] = 1;
+ GfLog[0] = EC_METHOD_SIZE;
+ for (i = 1; i < EC_METHOD_SIZE; i++)
+ {
+ GfPow[i] = GfPow[i - 1] << 1;
+ if (GfPow[i] >= EC_METHOD_SIZE)
+ {
+ GfPow[i] ^= EC_GF_MOD;
+ }
+ GfPow[i + EC_METHOD_SIZE - 1] = GfPow[i];
+ GfLog[GfPow[i] + EC_METHOD_SIZE - 1] = GfLog[GfPow[i]] = i;
+ }
+}
+
+static uint32_t ec_method_mul(uint32_t a, uint32_t b)
+{
+ if (a && b)
+ {
+ return GfPow[GfLog[a] + GfLog[b]];
+ }
+ return 0;
+}
+
+static uint32_t ec_method_div(uint32_t a, uint32_t b)
+{
+ if (b)
+ {
+ if (a)
+ {
+ return GfPow[EC_METHOD_SIZE - 1 + GfLog[a] - GfLog[b]];
+ }
+ return 0;
+ }
+ return EC_METHOD_SIZE;
+}
+
+size_t ec_method_encode(size_t size, uint32_t columns, uint32_t row,
+ uint8_t * in, uint8_t * out)
+{
+ uint32_t i, j;
+
+ size /= EC_METHOD_CHUNK_SIZE * columns;
+ row++;
+ for (j = 0; j < size; j++)
+ {
+ ec_gf_load(in);
+ in += EC_METHOD_CHUNK_SIZE;
+ for (i = 1; i < columns; i++)
+ {
+ ec_gf_mul_table[row]();
+ ec_gf_xor(in);
+ in += EC_METHOD_CHUNK_SIZE;
+ }
+ ec_gf_store(out);
+ out += EC_METHOD_CHUNK_SIZE;
+ }
+
+ return size * EC_METHOD_CHUNK_SIZE;
+}
+
+size_t ec_method_decode(size_t size, uint32_t columns, uint32_t * rows,
+ uint8_t ** in, uint8_t * out)
+{
+ uint32_t i, j, k;
+ uint32_t f, off, mask;
+ uint8_t inv[EC_METHOD_MAX_FRAGMENTS][EC_METHOD_MAX_FRAGMENTS + 1];
+ uint8_t mtx[EC_METHOD_MAX_FRAGMENTS][EC_METHOD_MAX_FRAGMENTS];
+ uint8_t * p[EC_METHOD_MAX_FRAGMENTS];
+
+ size /= EC_METHOD_CHUNK_SIZE;
+
+ memset(inv, 0, sizeof(inv));
+ memset(mtx, 0, sizeof(mtx));
+ mask = 0;
+ for (i = 0; i < columns; i++)
+ {
+ inv[i][i] = 1;
+ inv[i][columns] = 1;
+ }
+ k = 0;
+ for (i = 0; i < columns; i++)
+ {
+ while ((mask & 1) != 0)
+ {
+ k++;
+ mask >>= 1;
+ }
+ mtx[k][columns - 1] = 1;
+ for (j = columns - 1; j > 0; j--)
+ {
+ mtx[k][j - 1] = ec_method_mul(mtx[k][j], rows[i] + 1);
+ }
+ p[k] = in[i];
+ k++;
+ mask >>= 1;
+ }
+
+ for (i = 0; i < columns; i++)
+ {
+ f = mtx[i][i];
+ for (j = 0; j < columns; j++)
+ {
+ mtx[i][j] = ec_method_div(mtx[i][j], f);
+ inv[i][j] = ec_method_div(inv[i][j], f);
+ }
+ for (j = 0; j < columns; j++)
+ {
+ if (i != j)
+ {
+ f = mtx[j][i];
+ for (k = 0; k < columns; k++)
+ {
+ mtx[j][k] ^= ec_method_mul(mtx[i][k], f);
+ inv[j][k] ^= ec_method_mul(inv[i][k], f);
+ }
+ }
+ }
+ }
+ off = 0;
+ for (f = 0; f < size; f++)
+ {
+ for (i = 0; i < columns; i++)
+ {
+ ec_gf_load(p[0] + off);
+ j = 0;
+ while (j < columns)
+ {
+ k = j + 1;
+ while (inv[i][k] == 0)
+ {
+ k++;
+ }
+ ec_gf_mul_table[ec_method_div(inv[i][j], inv[i][k])]();
+ if (k < columns)
+ {
+ ec_gf_xor(p[k] + off);
+ }
+ j = k;
+ }
+ ec_gf_store(out);
+ out += EC_METHOD_CHUNK_SIZE;
+ in[i] += EC_METHOD_CHUNK_SIZE;
+ }
+ off += EC_METHOD_CHUNK_SIZE;
+ }
+
+ return size * EC_METHOD_CHUNK_SIZE * columns;
+}