2 * Copyright (c) 2014, James S. Plank and Kevin Greenan
5 * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure
8 * Revision 2.0: Galois Field backend now links to GF-Complete
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
14 * - Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
17 * - Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in
19 * the documentation and/or other materials provided with the
22 * - Neither the name of the University of Tennessee nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
31 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
32 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
33 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
34 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
36 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
40 /* Jerasure's authors:
42 Revision 2.x - 2014: James S. Plank and Kevin M. Greenan.
43 Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman.
44 Revision 1.0 - 2007: James S. Plank.
48 This program takes as input an inputfile, k, m, a coding
49 technique, w, and packetsize. It is the companion program
50 of encoder.c, which creates k+m files. This program assumes
51 that up to m erasures have occurred in the k+m files. It
52 reads in the k+m files or marks the file as erased. It then
53 recreates the original file and creates a new file with the
54 suffix "decoded" with the decoded contents of the file.
56 This program does not error check command line arguments because
57 it is assumed that encoder.c has been called previously with the
58 same arguments, and encoder.c does error check.
75 #include "liberation.h"
80 enum Coding_Technique {Reed_Sol_Van, Reed_Sol_R6_Op, Cauchy_Orig, Cauchy_Good, Liberation, Blaum_Roth, Liber8tion, RDP, EVENODD, No_Coding};
82 char *Methods[N] = {"reed_sol_van", "reed_sol_r6_op", "cauchy_orig", "cauchy_good", "liberation", "blaum_roth", "liber8tion", "rdp", "evenodd", "no_coding"};
84 /* Global variables for signal handler */
85 enum Coding_Technique method;
88 /* Function prototype */
89 void ctrl_bs_handler(int dummy);
91 int main (int argc, char **argv) {
92 FILE *fp; // File pointer
94 /* Jerasure arguments */
103 int k, m, w, packetsize, buffersize;
107 int i, j; // loop control variable, s
108 int blocksize = 0; // size of individual files
109 int origsize; // size of file before padding
110 int total; // used to write data, not padding to file
111 struct stat status; // used to find size of individual files
112 int numerased; // number of erased files
114 /* Used to recreate file names */
116 char *cs1, *cs2, *extension;
121 /* Used to time decoding */
122 struct timing t1, t2, t3, t4;
127 signal(SIGQUIT, ctrl_bs_handler);
136 /* Error checking parameters */
138 fprintf(stderr, "usage: inputfile\n");
141 curdir = (char *)malloc(sizeof(char)*1000);
142 assert(curdir == getcwd(curdir, 1000));
144 /* Begin recreation of file names */
145 cs1 = (char*)malloc(sizeof(char)*strlen(argv[1]));
146 cs2 = strrchr(argv[1], '/');
152 strcpy(cs1, argv[1]);
154 cs2 = strchr(cs1, '.');
156 extension = strdup(cs2);
159 extension = strdup("");
161 fname = (char *)malloc(sizeof(char*)*(100+strlen(argv[1])+20));
163 /* Read in parameters from metadata file */
164 sprintf(fname, "%s/Coding/%s_meta.txt", curdir, cs1);
166 fp = fopen(fname, "rb");
168 fprintf(stderr, "Error: no metadata file %s\n", fname);
171 temp = (char *)malloc(sizeof(char)*(strlen(argv[1])+20));
172 if (fscanf(fp, "%s", temp) != 1) {
173 fprintf(stderr, "Metadata file - bad format\n");
177 if (fscanf(fp, "%d", &origsize) != 1) {
178 fprintf(stderr, "Original size is not valid\n");
181 if (fscanf(fp, "%d %d %d %d %d", &k, &m, &w, &packetsize, &buffersize) != 5) {
182 fprintf(stderr, "Parameters are not correct\n");
185 c_tech = (char *)malloc(sizeof(char)*(strlen(argv[1])+20));
186 if (fscanf(fp, "%s", c_tech) != 1) {
187 fprintf(stderr, "Metadata file - bad format\n");
190 if (fscanf(fp, "%d", &tech) != 1) {
191 fprintf(stderr, "Metadata file - bad format\n");
195 if (fscanf(fp, "%d", &readins) != 1) {
196 fprintf(stderr, "Metadata file - bad format\n");
201 /* Allocate memory */
202 erased = (int *)malloc(sizeof(int)*(k+m));
203 for (i = 0; i < k+m; i++)
205 erasures = (int *)malloc(sizeof(int)*(k+m));
207 data = (char **)malloc(sizeof(char *)*k);
208 coding = (char **)malloc(sizeof(char *)*m);
209 if (buffersize != origsize) {
210 for (i = 0; i < k; i++) {
211 data[i] = (char *)malloc(sizeof(char)*(buffersize/k));
213 for (i = 0; i < m; i++) {
214 coding[i] = (char *)malloc(sizeof(char)*(buffersize/k));
216 blocksize = buffersize/k;
219 sprintf(temp, "%d", k);
223 /* Create coding matrix or bitmatrix */
228 matrix = reed_sol_vandermonde_coding_matrix(k, m, w);
231 matrix = reed_sol_r6_coding_matrix(k, w);
234 matrix = cauchy_original_coding_matrix(k, m, w);
235 bitmatrix = jerasure_matrix_to_bitmatrix(k, m, w, matrix);
238 matrix = cauchy_good_general_coding_matrix(k, m, w);
239 bitmatrix = jerasure_matrix_to_bitmatrix(k, m, w, matrix);
242 bitmatrix = liberation_coding_bitmatrix(k, w);
245 bitmatrix = blaum_roth_coding_bitmatrix(k, w);
248 bitmatrix = liber8tion_coding_bitmatrix(k);
251 totalsec += timing_delta(&t3, &t4);
253 /* Begin decoding process */
256 while (n <= readins) {
258 /* Open files, check for erasures, read in data/coding */
259 for (i = 1; i <= k; i++) {
260 sprintf(fname, "%s/Coding/%s_k%0*d%s", curdir, cs1, md, i, extension);
261 fp = fopen(fname, "rb");
264 erasures[numerased] = i-1;
266 //printf("%s failed\n", fname);
269 if (buffersize == origsize) {
270 stat(fname, &status);
271 blocksize = status.st_size;
272 data[i-1] = (char *)malloc(sizeof(char)*blocksize);
273 assert(blocksize == fread(data[i-1], sizeof(char), blocksize, fp));
276 fseek(fp, blocksize*(n-1), SEEK_SET);
277 assert(buffersize/k == fread(data[i-1], sizeof(char), buffersize/k, fp));
282 for (i = 1; i <= m; i++) {
283 sprintf(fname, "%s/Coding/%s_m%0*d%s", curdir, cs1, md, i, extension);
284 fp = fopen(fname, "rb");
287 erasures[numerased] = k+i-1;
289 //printf("%s failed\n", fname);
292 if (buffersize == origsize) {
293 stat(fname, &status);
294 blocksize = status.st_size;
295 coding[i-1] = (char *)malloc(sizeof(char)*blocksize);
296 assert(blocksize == fread(coding[i-1], sizeof(char), blocksize, fp));
299 fseek(fp, blocksize*(n-1), SEEK_SET);
300 assert(blocksize == fread(coding[i-1], sizeof(char), blocksize, fp));
305 /* Finish allocating data/coding if needed */
307 for (i = 0; i < numerased; i++) {
308 if (erasures[i] < k) {
309 data[erasures[i]] = (char *)malloc(sizeof(char)*blocksize);
312 coding[erasures[i]-k] = (char *)malloc(sizeof(char)*blocksize);
317 erasures[numerased] = -1;
320 /* Choose proper decoding method */
321 if (tech == Reed_Sol_Van || tech == Reed_Sol_R6_Op) {
322 i = jerasure_matrix_decode(k, m, w, matrix, 1, erasures, data, coding, blocksize);
324 else if (tech == Cauchy_Orig || tech == Cauchy_Good || tech == Liberation || tech == Blaum_Roth || tech == Liber8tion) {
325 i = jerasure_schedule_decode_lazy(k, m, w, bitmatrix, erasures, data, coding, blocksize, packetsize, 1);
328 fprintf(stderr, "Not a valid coding technique.\n");
333 /* Exit if decoding was unsuccessful */
335 fprintf(stderr, "Unsuccessful!\n");
339 /* Create decoded file */
340 sprintf(fname, "%s/Coding/%s_decoded%s", curdir, cs1, extension);
342 fp = fopen(fname, "wb");
345 fp = fopen(fname, "ab");
347 for (i = 0; i < k; i++) {
348 if (total+blocksize <= origsize) {
349 fwrite(data[i], sizeof(char), blocksize, fp);
353 for (j = 0; j < blocksize; j++) {
354 if (total < origsize) {
355 fprintf(fp, "%c", data[i][j]);
367 totalsec += timing_delta(&t3, &t4);
370 /* Free allocated memory */
379 /* Stop timing and print time */
381 tsec = timing_delta(&t1, &t2);
382 printf("Decoding (MB/sec): %0.10f\n", (((double) origsize)/1024.0/1024.0)/totalsec);
383 printf("De_Total (MB/sec): %0.10f\n\n", (((double) origsize)/1024.0/1024.0)/tsec);
388 void ctrl_bs_handler(int dummy) {
391 fprintf(stderr, "\n%s\n", ctime(&mytime));
392 fprintf(stderr, "You just typed ctrl-\\ in decoder.c\n");
393 fprintf(stderr, "Total number of read ins = %d\n", readins);
394 fprintf(stderr, "Current read in: %d\n", n);
395 fprintf(stderr, "Method: %s\n\n", Methods[method]);
396 signal(SIGQUIT, ctrl_bs_handler);