~ubuntu-branches/ubuntu/trusty/ceph/trusty-updates

« back to all changes in this revision

Viewing changes to src/erasure-code/jerasure/jerasure.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-04-09 11:14:03 UTC
  • mfrom: (1.1.33)
  • Revision ID: package-import@ubuntu.com-20140409111403-jlql95pa8kg1nk9a
Tags: 0.79-0ubuntu1
* New upstream release (LP: #1278466):
  - d/p/modules.patch: Refreshed.
  - d/ceph.install: Install all jerasure modules.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* jerasure.c
2
 
 * James S. Plank
3
 
 
4
 
Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure Coding Techniques
5
 
 
6
 
Revision 1.2A
7
 
May 24, 2011
8
 
 
9
 
James S. Plank
10
 
Department of Electrical Engineering and Computer Science
11
 
University of Tennessee
12
 
Knoxville, TN 37996
13
 
plank@cs.utk.edu
14
 
 
15
 
Copyright (c) 2011, James S. Plank
16
 
All rights reserved.
17
 
 
18
 
Redistribution and use in source and binary forms, with or without
19
 
modification, are permitted provided that the following conditions
20
 
are met:
21
 
 
22
 
 - Redistributions of source code must retain the above copyright
23
 
   notice, this list of conditions and the following disclaimer.
24
 
 
25
 
 - Redistributions in binary form must reproduce the above copyright
26
 
   notice, this list of conditions and the following disclaimer in
27
 
   the documentation and/or other materials provided with the
28
 
   distribution.
29
 
 
30
 
 - Neither the name of the University of Tennessee nor the names of its
31
 
   contributors may be used to endorse or promote products derived
32
 
   from this software without specific prior written permission.
33
 
 
34
 
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
35
 
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
36
 
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
37
 
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
38
 
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
39
 
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
40
 
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
41
 
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
42
 
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
43
 
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
44
 
WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
45
 
POSSIBILITY OF SUCH DAMAGE.
46
 
 
47
 
 */
48
 
 
49
 
#include <stdio.h>
50
 
#include <stdlib.h>
51
 
#include <string.h>
52
 
 
53
 
#include "galois.h"
54
 
#include "jerasure.h"
55
 
 
56
 
#define talloc(type, num) (type *) malloc(sizeof(type)*(num))
57
 
 
58
 
static double jerasure_total_xor_bytes = 0;
59
 
static double jerasure_total_gf_bytes = 0;
60
 
static double jerasure_total_memcpy_bytes = 0;
61
 
 
62
 
void jerasure_print_matrix(int *m, int rows, int cols, int w)
63
 
{
64
 
  int i, j;
65
 
  int fw;
66
 
  char s[30];
67
 
  unsigned int w2;
68
 
 
69
 
  if (w == 32) {
70
 
    fw = 10;
71
 
  } else {
72
 
    w2 = (1 << w);
73
 
    sprintf(s, "%u", w2-1);
74
 
    fw = strlen(s);
75
 
  }
76
 
 
77
 
  for (i = 0; i < rows; i++) {
78
 
    for (j = 0; j < cols; j++) {
79
 
      if (j != 0) printf(" ");
80
 
      printf("%*u", fw, m[i*cols+j]); 
81
 
    }
82
 
    printf("\n");
83
 
  }
84
 
}
85
 
 
86
 
void jerasure_print_bitmatrix(int *m, int rows, int cols, int w)
87
 
{
88
 
  int i, j;
89
 
 
90
 
  for (i = 0; i < rows; i++) {
91
 
    if (i != 0 && i%w == 0) printf("\n");
92
 
    for (j = 0; j < cols; j++) {
93
 
      if (j != 0 && j%w == 0) printf(" ");
94
 
      printf("%d", m[i*cols+j]); 
95
 
    }
96
 
    printf("\n");
97
 
  }
98
 
}
99
 
 
100
 
int jerasure_make_decoding_matrix(int k, int m, int w, int *matrix, int *erased, int *decoding_matrix, int *dm_ids)
101
 
{
102
 
  int i, j, *tmpmat;
103
 
 
104
 
  j = 0;
105
 
  for (i = 0; j < k; i++) {
106
 
    if (erased[i] == 0) {
107
 
      dm_ids[j] = i;
108
 
      j++;
109
 
    }
110
 
  }
111
 
 
112
 
  tmpmat = talloc(int, k*k);
113
 
  if (tmpmat == NULL) { return -1; }
114
 
  for (i = 0; i < k; i++) {
115
 
    if (dm_ids[i] < k) {
116
 
      for (j = 0; j < k; j++) tmpmat[i*k+j] = 0;
117
 
      tmpmat[i*k+dm_ids[i]] = 1;
118
 
    } else {
119
 
      for (j = 0; j < k; j++) {
120
 
        tmpmat[i*k+j] = matrix[(dm_ids[i]-k)*k+j];
121
 
      }
122
 
    }
123
 
  }
124
 
 
125
 
  i = jerasure_invert_matrix(tmpmat, decoding_matrix, k, w);
126
 
  free(tmpmat);
127
 
  return i;
128
 
}
129
 
 
130
 
/* Internal Routine */
131
 
int jerasure_make_decoding_bitmatrix(int k, int m, int w, int *matrix, int *erased, int *decoding_matrix, int *dm_ids)
132
 
{
133
 
  int i, j, *tmpmat;
134
 
  int index, mindex;
135
 
 
136
 
  j = 0;
137
 
  for (i = 0; j < k; i++) {
138
 
    if (erased[i] == 0) {
139
 
      dm_ids[j] = i;
140
 
      j++;
141
 
    }
142
 
  }
143
 
 
144
 
  tmpmat = talloc(int, k*k*w*w);
145
 
  if (tmpmat == NULL) { return -1; }
146
 
  for (i = 0; i < k; i++) {
147
 
    if (dm_ids[i] < k) {
148
 
      index = i*k*w*w;
149
 
      for (j = 0; j < k*w*w; j++) tmpmat[index+j] = 0;
150
 
      index = i*k*w*w+dm_ids[i]*w;
151
 
      for (j = 0; j < w; j++) {
152
 
        tmpmat[index] = 1;
153
 
        index += (k*w+1);
154
 
      }
155
 
    } else {
156
 
      index = i*k*w*w;
157
 
      mindex = (dm_ids[i]-k)*k*w*w;
158
 
      for (j = 0; j < k*w*w; j++) {
159
 
        tmpmat[index+j] = matrix[mindex+j];
160
 
      }
161
 
    }
162
 
  }
163
 
 
164
 
  i = jerasure_invert_bitmatrix(tmpmat, decoding_matrix, k*w);
165
 
  free(tmpmat);
166
 
  return i;
167
 
}
168
 
 
169
 
int jerasure_matrix_decode(int k, int m, int w, int *matrix, int row_k_ones, int *erasures,
170
 
                          char **data_ptrs, char **coding_ptrs, int size)
171
 
{
172
 
  int i, edd, lastdrive;
173
 
  int *tmpids;
174
 
  int *erased, *decoding_matrix, *dm_ids;
175
 
 
176
 
  if (w != 8 && w != 16 && w != 32) return -1;
177
 
 
178
 
  erased = jerasure_erasures_to_erased(k, m, erasures);
179
 
  if (erased == NULL) return -1;
180
 
 
181
 
  /* Find the number of data drives failed */
182
 
 
183
 
  lastdrive = k;
184
 
 
185
 
  edd = 0;
186
 
  for (i = 0; i < k; i++) {
187
 
    if (erased[i]) {
188
 
      edd++;
189
 
      lastdrive = i;
190
 
    }
191
 
  }
192
 
    
193
 
  /* You only need to create the decoding matrix in the following cases:
194
 
 
195
 
      1. edd > 0 and row_k_ones is false.
196
 
      2. edd > 0 and row_k_ones is true and coding device 0 has been erased.
197
 
      3. edd > 1
198
 
 
199
 
      We're going to use lastdrive to denote when to stop decoding data.
200
 
      At this point in the code, it is equal to the last erased data device.
201
 
      However, if we can't use the parity row to decode it (i.e. row_k_ones=0
202
 
         or erased[k] = 1, we're going to set it to k so that the decoding 
203
 
         pass will decode all data.
204
 
   */
205
 
 
206
 
  if (!row_k_ones || erased[k]) lastdrive = k;
207
 
 
208
 
  dm_ids = NULL;
209
 
  decoding_matrix = NULL;
210
 
 
211
 
  if (edd > 1 || (edd > 0 && (!row_k_ones || erased[k]))) {
212
 
    dm_ids = talloc(int, k);
213
 
    if (dm_ids == NULL) {
214
 
      free(erased);
215
 
      return -1;
216
 
    }
217
 
 
218
 
    decoding_matrix = talloc(int, k*k);
219
 
    if (decoding_matrix == NULL) {
220
 
      free(erased);
221
 
      free(dm_ids);
222
 
      return -1;
223
 
    }
224
 
 
225
 
    if (jerasure_make_decoding_matrix(k, m, w, matrix, erased, decoding_matrix, dm_ids) < 0) {
226
 
      free(erased);
227
 
      free(dm_ids);
228
 
      free(decoding_matrix);
229
 
      return -1;
230
 
    }
231
 
  }
232
 
 
233
 
  /* Decode the data drives.  
234
 
     If row_k_ones is true and coding device 0 is intact, then only decode edd-1 drives.
235
 
     This is done by stopping at lastdrive.
236
 
     We test whether edd > 0 so that we can exit the loop early if we're done.
237
 
   */
238
 
 
239
 
  for (i = 0; edd > 0 && i < lastdrive; i++) {
240
 
    if (erased[i]) {
241
 
      jerasure_matrix_dotprod(k, w, decoding_matrix+(i*k), dm_ids, i, data_ptrs, coding_ptrs, size);
242
 
      edd--;
243
 
    }
244
 
  }
245
 
 
246
 
  /* Then if necessary, decode drive lastdrive */
247
 
 
248
 
  if (edd > 0) {
249
 
    tmpids = talloc(int, k);
250
 
    for (i = 0; i < k; i++) {
251
 
      tmpids[i] = (i < lastdrive) ? i : i+1;
252
 
    }
253
 
    jerasure_matrix_dotprod(k, w, matrix, tmpids, lastdrive, data_ptrs, coding_ptrs, size);
254
 
    free(tmpids);
255
 
  }
256
 
  
257
 
  /* Finally, re-encode any erased coding devices */
258
 
 
259
 
  for (i = 0; i < m; i++) {
260
 
    if (erased[k+i]) {
261
 
      jerasure_matrix_dotprod(k, w, matrix+(i*k), NULL, i+k, data_ptrs, coding_ptrs, size);
262
 
    }
263
 
  }
264
 
 
265
 
  free(erased);
266
 
  if (dm_ids != NULL) free(dm_ids);
267
 
  if (decoding_matrix != NULL) free(decoding_matrix);
268
 
 
269
 
  return 0;
270
 
}
271
 
 
272
 
 
273
 
int *jerasure_matrix_to_bitmatrix(int k, int m, int w, int *matrix) 
274
 
{
275
 
  int *bitmatrix;
276
 
  int rowelts, rowindex, colindex, elt, i, j, l, x;
277
 
 
278
 
  bitmatrix = talloc(int, k*m*w*w);
279
 
  if (bitmatrix == NULL) { return NULL; }
280
 
 
281
 
  rowelts = k * w;
282
 
  rowindex = 0;
283
 
 
284
 
  for (i = 0; i < m; i++) {
285
 
    colindex = rowindex;
286
 
    for (j = 0; j < k; j++) {
287
 
      elt = matrix[i*k+j];
288
 
      for (x = 0; x < w; x++) {
289
 
        for (l = 0; l < w; l++) {
290
 
          bitmatrix[colindex+x+l*rowelts] = ((elt & (1 << l)) ? 1 : 0);
291
 
        }
292
 
        elt = galois_single_multiply(elt, 2, w);
293
 
      }
294
 
      colindex += w;
295
 
    }
296
 
    rowindex += rowelts * w;
297
 
  }
298
 
  return bitmatrix;
299
 
}
300
 
 
301
 
void jerasure_matrix_encode(int k, int m, int w, int *matrix,
302
 
                          char **data_ptrs, char **coding_ptrs, int size)
303
 
{
304
 
  int i;
305
 
  
306
 
  if (w != 8 && w != 16 && w != 32) {
307
 
    fprintf(stderr, "ERROR: jerasure_matrix_encode() and w is not 8, 16 or 32\n");
308
 
    exit(1);
309
 
  }
310
 
 
311
 
  for (i = 0; i < m; i++) {
312
 
    jerasure_matrix_dotprod(k, w, matrix+(i*k), NULL, k+i, data_ptrs, coding_ptrs, size);
313
 
  }
314
 
}
315
 
 
316
 
void jerasure_bitmatrix_dotprod(int k, int w, int *bitmatrix_row,
317
 
                             int *src_ids, int dest_id,
318
 
                             char **data_ptrs, char **coding_ptrs, int size, int packetsize)
319
 
{
320
 
  int j, sindex, pstarted, index, x, y;
321
 
  char *dptr, *pptr, *bdptr, *bpptr;
322
 
 
323
 
  if (size%(w*packetsize) != 0) {
324
 
    fprintf(stderr, "jerasure_bitmatrix_dotprod - size%c(w*packetsize)) must = 0\n", '%');
325
 
    exit(1);
326
 
  }
327
 
 
328
 
  bpptr = (dest_id < k) ? data_ptrs[dest_id] : coding_ptrs[dest_id-k];
329
 
 
330
 
  for (sindex = 0; sindex < size; sindex += (packetsize*w)) {
331
 
    index = 0;
332
 
    for (j = 0; j < w; j++) {
333
 
      pstarted = 0;
334
 
      pptr = bpptr + sindex + j*packetsize;
335
 
      for (x = 0; x < k; x++) {
336
 
        if (src_ids == NULL) {
337
 
          bdptr = data_ptrs[x];
338
 
        } else if (src_ids[x] < k) {
339
 
          bdptr = data_ptrs[src_ids[x]];
340
 
        } else {
341
 
          bdptr = coding_ptrs[src_ids[x]-k];
342
 
        }
343
 
        for (y = 0; y < w; y++) {
344
 
          if (bitmatrix_row[index]) {
345
 
            dptr = bdptr + sindex + y*packetsize;
346
 
            if (!pstarted) {
347
 
              memcpy(pptr, dptr, packetsize);
348
 
              jerasure_total_memcpy_bytes += packetsize;
349
 
              pstarted = 1;
350
 
            } else {
351
 
              galois_region_xor(pptr, dptr, pptr, packetsize);
352
 
              jerasure_total_xor_bytes += packetsize;
353
 
            }
354
 
          }
355
 
          index++;
356
 
        }
357
 
      }
358
 
    }
359
 
  }
360
 
}
361
 
 
362
 
void jerasure_do_parity(int k, char **data_ptrs, char *parity_ptr, int size) 
363
 
{
364
 
  int i;
365
 
 
366
 
  memcpy(parity_ptr, data_ptrs[0], size);
367
 
  jerasure_total_memcpy_bytes += size;
368
 
  
369
 
  for (i = 1; i < k; i++) {
370
 
    galois_region_xor(data_ptrs[i], parity_ptr, parity_ptr, size);
371
 
    jerasure_total_xor_bytes += size;
372
 
  }
373
 
}
374
 
 
375
 
int jerasure_invert_matrix(int *mat, int *inv, int rows, int w)
376
 
{
377
 
  int cols, i, j, k, x, rs2;
378
 
  int row_start, tmp, inverse;
379
 
 
380
 
  cols = rows;
381
 
 
382
 
  k = 0;
383
 
  for (i = 0; i < rows; i++) {
384
 
    for (j = 0; j < cols; j++) {
385
 
      inv[k] = (i == j) ? 1 : 0;
386
 
      k++;
387
 
    }
388
 
  }
389
 
 
390
 
  /* First -- convert into upper triangular  */
391
 
  for (i = 0; i < cols; i++) {
392
 
    row_start = cols*i;
393
 
 
394
 
    /* Swap rows if we ave a zero i,i element.  If we can't swap, then the 
395
 
       matrix was not invertible  */
396
 
 
397
 
    if (mat[row_start+i] == 0) { 
398
 
      for (j = i+1; j < rows && mat[cols*j+i] == 0; j++) ;
399
 
      if (j == rows) return -1;
400
 
      rs2 = j*cols;
401
 
      for (k = 0; k < cols; k++) {
402
 
        tmp = mat[row_start+k];
403
 
        mat[row_start+k] = mat[rs2+k];
404
 
        mat[rs2+k] = tmp;
405
 
        tmp = inv[row_start+k];
406
 
        inv[row_start+k] = inv[rs2+k];
407
 
        inv[rs2+k] = tmp;
408
 
      }
409
 
    }
410
 
 
411
 
    /* Multiply the row by 1/element i,i  */
412
 
    tmp = mat[row_start+i];
413
 
    if (tmp != 1) {
414
 
      inverse = galois_single_divide(1, tmp, w);
415
 
      for (j = 0; j < cols; j++) { 
416
 
        mat[row_start+j] = galois_single_multiply(mat[row_start+j], inverse, w);
417
 
        inv[row_start+j] = galois_single_multiply(inv[row_start+j], inverse, w);
418
 
      }
419
 
    }
420
 
 
421
 
    /* Now for each j>i, add A_ji*Ai to Aj  */
422
 
    k = row_start+i;
423
 
    for (j = i+1; j != cols; j++) {
424
 
      k += cols;
425
 
      if (mat[k] != 0) {
426
 
        if (mat[k] == 1) {
427
 
          rs2 = cols*j;
428
 
          for (x = 0; x < cols; x++) {
429
 
            mat[rs2+x] ^= mat[row_start+x];
430
 
            inv[rs2+x] ^= inv[row_start+x];
431
 
          }
432
 
        } else {
433
 
          tmp = mat[k];
434
 
          rs2 = cols*j;
435
 
          for (x = 0; x < cols; x++) {
436
 
            mat[rs2+x] ^= galois_single_multiply(tmp, mat[row_start+x], w);
437
 
            inv[rs2+x] ^= galois_single_multiply(tmp, inv[row_start+x], w);
438
 
          }
439
 
        }
440
 
      }
441
 
    }
442
 
  }
443
 
 
444
 
  /* Now the matrix is upper triangular.  Start at the top and multiply down  */
445
 
 
446
 
  for (i = rows-1; i >= 0; i--) {
447
 
    row_start = i*cols;
448
 
    for (j = 0; j < i; j++) {
449
 
      rs2 = j*cols;
450
 
      if (mat[rs2+i] != 0) {
451
 
        tmp = mat[rs2+i];
452
 
        mat[rs2+i] = 0; 
453
 
        for (k = 0; k < cols; k++) {
454
 
          inv[rs2+k] ^= galois_single_multiply(tmp, inv[row_start+k], w);
455
 
        }
456
 
      }
457
 
    }
458
 
  }
459
 
  return 0;
460
 
}
461
 
 
462
 
int jerasure_invertible_matrix(int *mat, int rows, int w)
463
 
{
464
 
  int cols, i, j, k, x, rs2;
465
 
  int row_start, tmp, inverse;
466
 
 
467
 
  cols = rows;
468
 
 
469
 
  /* First -- convert into upper triangular  */
470
 
  for (i = 0; i < cols; i++) {
471
 
    row_start = cols*i;
472
 
 
473
 
    /* Swap rows if we ave a zero i,i element.  If we can't swap, then the 
474
 
       matrix was not invertible  */
475
 
 
476
 
    if (mat[row_start+i] == 0) { 
477
 
      for (j = i+1; j < rows && mat[cols*j+i] == 0; j++) ;
478
 
      if (j == rows) return 0;
479
 
      rs2 = j*cols;
480
 
      for (k = 0; k < cols; k++) {
481
 
        tmp = mat[row_start+k];
482
 
        mat[row_start+k] = mat[rs2+k];
483
 
        mat[rs2+k] = tmp;
484
 
      }
485
 
    }
486
 
 
487
 
    /* Multiply the row by 1/element i,i  */
488
 
    tmp = mat[row_start+i];
489
 
    if (tmp != 1) {
490
 
      inverse = galois_single_divide(1, tmp, w);
491
 
      for (j = 0; j < cols; j++) { 
492
 
        mat[row_start+j] = galois_single_multiply(mat[row_start+j], inverse, w);
493
 
      }
494
 
    }
495
 
 
496
 
    /* Now for each j>i, add A_ji*Ai to Aj  */
497
 
    k = row_start+i;
498
 
    for (j = i+1; j != cols; j++) {
499
 
      k += cols;
500
 
      if (mat[k] != 0) {
501
 
        if (mat[k] == 1) {
502
 
          rs2 = cols*j;
503
 
          for (x = 0; x < cols; x++) {
504
 
            mat[rs2+x] ^= mat[row_start+x];
505
 
          }
506
 
        } else {
507
 
          tmp = mat[k];
508
 
          rs2 = cols*j;
509
 
          for (x = 0; x < cols; x++) {
510
 
            mat[rs2+x] ^= galois_single_multiply(tmp, mat[row_start+x], w);
511
 
          }
512
 
        }
513
 
      }
514
 
    }
515
 
  }
516
 
  return 1;
517
 
}
518
 
 
519
 
/* Converts a list-style version of the erasures into an array of k+m elements
520
 
   where the element = 1 if the index has been erased, and zero otherwise */
521
 
 
522
 
int *jerasure_erasures_to_erased(int k, int m, int *erasures)
523
 
{
524
 
  int td;
525
 
  int t_non_erased;
526
 
  int *erased;
527
 
  int i;
528
 
 
529
 
  td = k+m;
530
 
  erased = talloc(int, td);
531
 
  if (erased == NULL) return NULL;
532
 
  t_non_erased = td;
533
 
 
534
 
  for (i = 0; i < td; i++) erased[i] = 0;
535
 
 
536
 
  for (i = 0; erasures[i] != -1; i++) {
537
 
    if (erased[erasures[i]] == 0) {
538
 
      erased[erasures[i]] = 1;
539
 
      t_non_erased--;
540
 
      if (t_non_erased < k) {
541
 
        free(erased);
542
 
        return NULL;
543
 
      }
544
 
    }
545
 
  }
546
 
  return erased;
547
 
}
548
 
  
549
 
void jerasure_free_schedule(int **schedule)
550
 
{
551
 
  int i;
552
 
 
553
 
  for (i = 0; schedule[i][0] >= 0; i++) free(schedule[i]);
554
 
  free(schedule[i]);
555
 
  free(schedule);
556
 
}
557
 
 
558
 
void jerasure_free_schedule_cache(int k, int m, int ***cache)
559
 
{
560
 
  int e1, e2;
561
 
 
562
 
  if (m != 2) {
563
 
    fprintf(stderr, "jerasure_free_schedule_cache(): m must equal 2\n");
564
 
    exit(1);
565
 
  }
566
 
 
567
 
  for (e1 = 0; e1 < k+m; e1++) {
568
 
    for (e2 = 0; e2 < e1; e2++) {
569
 
      jerasure_free_schedule(cache[e1*(k+m)+e2]);
570
 
    }
571
 
    jerasure_free_schedule(cache[e1*(k+m)+e1]);
572
 
  }
573
 
  free(cache);
574
 
}
575
 
 
576
 
void jerasure_matrix_dotprod(int k, int w, int *matrix_row,
577
 
                          int *src_ids, int dest_id,
578
 
                          char **data_ptrs, char **coding_ptrs, int size)
579
 
{
580
 
  int init;
581
 
  char *dptr, *sptr;
582
 
  int i;
583
 
 
584
 
  if (w != 1 && w != 8 && w != 16 && w != 32) {
585
 
    fprintf(stderr, "ERROR: jerasure_matrix_dotprod() called and w is not 1, 8, 16 or 32\n");
586
 
    exit(1);
587
 
  }
588
 
 
589
 
  init = 0;
590
 
 
591
 
  dptr = (dest_id < k) ? data_ptrs[dest_id] : coding_ptrs[dest_id-k];
592
 
 
593
 
  /* First copy or xor any data that does not need to be multiplied by a factor */
594
 
 
595
 
  for (i = 0; i < k; i++) {
596
 
    if (matrix_row[i] == 1) {
597
 
      if (src_ids == NULL) {
598
 
        sptr = data_ptrs[i];
599
 
      } else if (src_ids[i] < k) {
600
 
        sptr = data_ptrs[src_ids[i]];
601
 
      } else {
602
 
        sptr = coding_ptrs[src_ids[i]-k];
603
 
      }
604
 
      if (init == 0) {
605
 
        memcpy(dptr, sptr, size);
606
 
        jerasure_total_memcpy_bytes += size;
607
 
        init = 1;
608
 
      } else {
609
 
        galois_region_xor(sptr, dptr, dptr, size);
610
 
        jerasure_total_xor_bytes += size;
611
 
      }
612
 
    }
613
 
  }
614
 
 
615
 
  /* Now do the data that needs to be multiplied by a factor */
616
 
 
617
 
  for (i = 0; i < k; i++) {
618
 
    if (matrix_row[i] != 0 && matrix_row[i] != 1) {
619
 
      if (src_ids == NULL) {
620
 
        sptr = data_ptrs[i];
621
 
      } else if (src_ids[i] < k) {
622
 
        sptr = data_ptrs[src_ids[i]];
623
 
      } else {
624
 
        sptr = coding_ptrs[src_ids[i]-k];
625
 
      }
626
 
      switch (w) {
627
 
        case 8:  galois_w08_region_multiply(sptr, matrix_row[i], size, dptr, init); break;
628
 
        case 16: galois_w16_region_multiply(sptr, matrix_row[i], size, dptr, init); break;
629
 
        case 32: galois_w32_region_multiply(sptr, matrix_row[i], size, dptr, init); break;
630
 
      }
631
 
      jerasure_total_gf_bytes += size;
632
 
      init = 1;
633
 
    }
634
 
  }
635
 
}
636
 
 
637
 
 
638
 
int jerasure_bitmatrix_decode(int k, int m, int w, int *bitmatrix, int row_k_ones, int *erasures,
639
 
                            char **data_ptrs, char **coding_ptrs, int size, int packetsize)
640
 
{
641
 
  int i;
642
 
  int *erased;
643
 
  int *decoding_matrix;
644
 
  int *dm_ids;
645
 
  int edd, *tmpids, lastdrive;
646
 
  
647
 
  erased = jerasure_erasures_to_erased(k, m, erasures);
648
 
  if (erased == NULL) return -1;
649
 
 
650
 
  /* See jerasure_matrix_decode for the logic of this routine.  This one works just like
651
 
     it, but calls the bitmatrix ops instead */
652
 
 
653
 
  lastdrive = k;
654
 
    
655
 
  edd = 0;
656
 
  for (i = 0; i < k; i++) {
657
 
    if (erased[i]) {
658
 
      edd++;
659
 
      lastdrive = i;
660
 
    } 
661
 
  }
662
 
 
663
 
  if (row_k_ones != 1 || erased[k]) lastdrive = k;
664
 
  
665
 
  dm_ids = NULL;
666
 
  decoding_matrix = NULL;
667
 
  
668
 
  if (edd > 1 || (edd > 0 && (row_k_ones != 1 || erased[k]))) {
669
 
 
670
 
    dm_ids = talloc(int, k);
671
 
    if (dm_ids == NULL) {
672
 
      free(erased);
673
 
      return -1;
674
 
    }
675
 
  
676
 
    decoding_matrix = talloc(int, k*k*w*w);
677
 
    if (decoding_matrix == NULL) {
678
 
      free(erased);
679
 
      free(dm_ids);
680
 
      return -1;
681
 
    }
682
 
  
683
 
    if (jerasure_make_decoding_bitmatrix(k, m, w, bitmatrix, erased, decoding_matrix, dm_ids) < 0) {
684
 
      free(erased);
685
 
      free(dm_ids);
686
 
      free(decoding_matrix);
687
 
      return -1;
688
 
    }
689
 
  }
690
 
 
691
 
  for (i = 0; edd > 0 && i < lastdrive; i++) {
692
 
    if (erased[i]) {
693
 
      jerasure_bitmatrix_dotprod(k, w, decoding_matrix+i*k*w*w, dm_ids, i, data_ptrs, coding_ptrs, size, packetsize);
694
 
      edd--;
695
 
    }
696
 
  }
697
 
 
698
 
  if (edd > 0) {
699
 
    tmpids = talloc(int, k);
700
 
    for (i = 0; i < k; i++) {
701
 
      tmpids[i] = (i < lastdrive) ? i : i+1;
702
 
    }
703
 
    jerasure_bitmatrix_dotprod(k, w, bitmatrix, tmpids, lastdrive, data_ptrs, coding_ptrs, size, packetsize);
704
 
    free(tmpids);
705
 
  }
706
 
 
707
 
  for (i = 0; i < m; i++) {
708
 
    if (erased[k+i]) {
709
 
      jerasure_bitmatrix_dotprod(k, w, bitmatrix+i*k*w*w, NULL, k+i, data_ptrs, coding_ptrs, size, packetsize);
710
 
    }
711
 
  }
712
 
 
713
 
  free(erased);
714
 
  if (dm_ids != NULL) free(dm_ids);
715
 
  if (decoding_matrix != NULL) free(decoding_matrix);
716
 
 
717
 
  return 0;
718
 
}
719
 
 
720
 
static char **set_up_ptrs_for_scheduled_decoding(int k, int m, int *erasures, char **data_ptrs, char **coding_ptrs)
721
 
{
722
 
  int ddf, cdf;
723
 
  int *erased;
724
 
  char **ptrs;
725
 
  int i, j, x;
726
 
 
727
 
  ddf = 0;
728
 
  cdf = 0;
729
 
  for (i = 0; erasures[i] != -1; i++) {
730
 
    if (erasures[i] < k) ddf++; else cdf++;
731
 
  }
732
 
  
733
 
  erased = jerasure_erasures_to_erased(k, m, erasures);
734
 
  if (erased == NULL) return NULL;
735
 
 
736
 
  /* Set up ptrs.  It will be as follows:
737
 
 
738
 
       - If data drive i has not failed, then ptrs[i] = data_ptrs[i].
739
 
       - If data drive i has failed, then ptrs[i] = coding_ptrs[j], where j is the 
740
 
            lowest unused non-failed coding drive.
741
 
       - Elements k to k+ddf-1 are data_ptrs[] of the failed data drives.
742
 
       - Elements k+ddf to k+ddf+cdf-1 are coding_ptrs[] of the failed data drives.
743
 
 
744
 
       The array row_ids contains the ids of ptrs.
745
 
       The array ind_to_row_ids contains the row_id of drive i.
746
 
  
747
 
       However, we're going to set row_ids and ind_to_row in a different procedure.
748
 
   */
749
 
         
750
 
  ptrs = talloc(char *, k+m);
751
 
 
752
 
  j = k;
753
 
  x = k;
754
 
  for (i = 0; i < k; i++) {
755
 
    if (erased[i] == 0) {
756
 
      ptrs[i] = data_ptrs[i];
757
 
    } else {
758
 
      while (erased[j]) j++;
759
 
      ptrs[i] = coding_ptrs[j-k];
760
 
      j++;
761
 
      ptrs[x] = data_ptrs[i];
762
 
      x++;
763
 
    }
764
 
  }
765
 
  for (i = k; i < k+m; i++) {
766
 
    if (erased[i]) {
767
 
      ptrs[x] = coding_ptrs[i-k];
768
 
      x++;
769
 
    }
770
 
  }
771
 
  free(erased);
772
 
  return ptrs;
773
 
}
774
 
 
775
 
static int set_up_ids_for_scheduled_decoding(int k, int m, int *erasures, int *row_ids, int *ind_to_row)
776
 
{
777
 
  int ddf, cdf;
778
 
  int *erased;
779
 
  int i, j, x;
780
 
 
781
 
  ddf = 0;
782
 
  cdf = 0;
783
 
  for (i = 0; erasures[i] != -1; i++) {
784
 
    if (erasures[i] < k) ddf++; else cdf++;
785
 
  }
786
 
  
787
 
  erased = jerasure_erasures_to_erased(k, m, erasures);
788
 
  if (erased == NULL) return -1;
789
 
 
790
 
  /* See set_up_ptrs_for_scheduled_decoding for how these are set */
791
 
 
792
 
  j = k;
793
 
  x = k;
794
 
  for (i = 0; i < k; i++) {
795
 
    if (erased[i] == 0) {
796
 
      row_ids[i] = i;
797
 
      ind_to_row[i] = i;
798
 
    } else {
799
 
      while (erased[j]) j++;
800
 
      row_ids[i] = j;
801
 
      ind_to_row[j] = i;
802
 
      j++;
803
 
      row_ids[x] = i;
804
 
      ind_to_row[i] = x;
805
 
      x++;
806
 
    }
807
 
  }
808
 
  for (i = k; i < k+m; i++) {
809
 
    if (erased[i]) {
810
 
      row_ids[x] = i;
811
 
      ind_to_row[i] = x;
812
 
      x++;
813
 
    }
814
 
  }
815
 
  free(erased);
816
 
  return 0;
817
 
}
818
 
 
819
 
static int **jerasure_generate_decoding_schedule(int k, int m, int w, int *bitmatrix, int *erasures, int smart)
820
 
{
821
 
  int i, j, x, drive, y, index, z;
822
 
  int *decoding_matrix, *inverse, *real_decoding_matrix;
823
 
  int *ptr;
824
 
  int *row_ids;
825
 
  int *ind_to_row;
826
 
  int ddf, cdf;
827
 
  int **schedule;
828
 
  int *b1, *b2;
829
 
 
830
 
 /* First, figure out the number of data drives that have failed, and the
831
 
    number of coding drives that have failed: ddf and cdf */
832
 
 
833
 
  ddf = 0;
834
 
  cdf = 0;
835
 
  for (i = 0; erasures[i] != -1; i++) {
836
 
    if (erasures[i] < k) ddf++; else cdf++;
837
 
  }
838
 
  
839
 
  row_ids = talloc(int, k+m);
840
 
  ind_to_row = talloc(int, k+m);
841
 
 
842
 
  if (set_up_ids_for_scheduled_decoding(k, m, erasures, row_ids, ind_to_row) < 0) {
843
 
    free(row_ids);
844
 
    free(ind_to_row);
845
 
    return NULL;
846
 
  }
847
 
 
848
 
  /* Now, we're going to create one decoding matrix which is going to 
849
 
     decode everything with one call.  The hope is that the scheduler
850
 
     will do a good job.    This matrix has w*e rows, where e is the
851
 
     number of erasures (ddf+cdf) */
852
 
 
853
 
  real_decoding_matrix = talloc(int, k*w*(cdf+ddf)*w);
854
 
 
855
 
  /* First, if any data drives have failed, then initialize the first
856
 
     ddf*w rows of the decoding matrix from the standard decoding
857
 
     matrix inversion */
858
 
 
859
 
  if (ddf > 0) {
860
 
    
861
 
    decoding_matrix = talloc(int, k*k*w*w);
862
 
    ptr = decoding_matrix;
863
 
    for (i = 0; i < k; i++) {
864
 
      if (row_ids[i] == i) {
865
 
        bzero(ptr, k*w*w*sizeof(int));
866
 
        for (x = 0; x < w; x++) {
867
 
          ptr[x+i*w+x*k*w] = 1;
868
 
        } 
869
 
      } else {
870
 
        memcpy(ptr, bitmatrix+k*w*w*(row_ids[i]-k), k*w*w*sizeof(int));
871
 
      }
872
 
      ptr += (k*w*w);
873
 
    }
874
 
    inverse = talloc(int, k*k*w*w);
875
 
    jerasure_invert_bitmatrix(decoding_matrix, inverse, k*w);
876
 
 
877
 
/*    printf("\nMatrix to invert\n");
878
 
    jerasure_print_bitmatrix(decoding_matrix, k*w, k*w, w);
879
 
    printf("\n");
880
 
    printf("\nInverse\n");
881
 
    jerasure_print_bitmatrix(inverse, k*w, k*w, w);
882
 
    printf("\n"); */
883
 
 
884
 
    free(decoding_matrix);
885
 
    ptr = real_decoding_matrix;
886
 
    for (i = 0; i < ddf; i++) {
887
 
      memcpy(ptr, inverse+k*w*w*row_ids[k+i], sizeof(int)*k*w*w);
888
 
      ptr += (k*w*w);
889
 
    }
890
 
    free(inverse);
891
 
  } 
892
 
 
893
 
  /* Next, here comes the hard part.  For each coding node that needs
894
 
     to be decoded, you start by putting its rows of the distribution
895
 
     matrix into the decoding matrix.  If there were no failed data
896
 
     nodes, then you're done.  However, if there have been failed
897
 
     data nodes, then you need to modify the columns that correspond
898
 
     to the data nodes.  You do that by first zeroing them.  Then
899
 
     whereever there is a one in the distribution matrix, you XOR
900
 
     in the corresponding row from the failed data node's entry in
901
 
     the decoding matrix.  The whole process kind of makes my head
902
 
     spin, but it works.
903
 
   */
904
 
 
905
 
  for (x = 0; x < cdf; x++) {
906
 
    drive = row_ids[x+ddf+k]-k;
907
 
    ptr = real_decoding_matrix + k*w*w*(ddf+x);
908
 
    memcpy(ptr, bitmatrix+drive*k*w*w, sizeof(int)*k*w*w);
909
 
 
910
 
    for (i = 0; i < k; i++) {
911
 
      if (row_ids[i] != i) {
912
 
        for (j = 0; j < w; j++) {
913
 
          bzero(ptr+j*k*w+i*w, sizeof(int)*w);
914
 
        }
915
 
      }  
916
 
    }
917
 
 
918
 
    /* There's the yucky part */
919
 
 
920
 
    index = drive*k*w*w;
921
 
    for (i = 0; i < k; i++) {
922
 
      if (row_ids[i] != i) {
923
 
        b1 = real_decoding_matrix+(ind_to_row[i]-k)*k*w*w;
924
 
        for (j = 0; j < w; j++) {
925
 
          b2 = ptr + j*k*w;
926
 
          for (y = 0; y < w; y++) {
927
 
            if (bitmatrix[index+j*k*w+i*w+y]) {
928
 
              for (z = 0; z < k*w; z++) {
929
 
                b2[z] = b2[z] ^ b1[z+y*k*w];
930
 
              }
931
 
            }
932
 
          }
933
 
        }
934
 
      }  
935
 
    }
936
 
  }
937
 
 
938
 
/*
939
 
  printf("\n\nReal Decoding Matrix\n\n");
940
 
  jerasure_print_bitmatrix(real_decoding_matrix, (ddf+cdf)*w, k*w, w);
941
 
  printf("\n"); */
942
 
  if (smart) {
943
 
    schedule = jerasure_smart_bitmatrix_to_schedule(k, ddf+cdf, w, real_decoding_matrix);
944
 
  } else {
945
 
    schedule = jerasure_dumb_bitmatrix_to_schedule(k, ddf+cdf, w, real_decoding_matrix);
946
 
  }
947
 
  free(row_ids);
948
 
  free(ind_to_row);
949
 
  free(real_decoding_matrix);
950
 
  return schedule;
951
 
}
952
 
 
953
 
int jerasure_schedule_decode_lazy(int k, int m, int w, int *bitmatrix, int *erasures,
954
 
                            char **data_ptrs, char **coding_ptrs, int size, int packetsize, 
955
 
                            int smart)
956
 
{
957
 
  int i, tdone;
958
 
  char **ptrs;
959
 
  int **schedule;
960
 
 
961
 
  ptrs = set_up_ptrs_for_scheduled_decoding(k, m, erasures, data_ptrs, coding_ptrs);
962
 
  if (ptrs == NULL) return -1;
963
 
 
964
 
  schedule = jerasure_generate_decoding_schedule(k, m, w, bitmatrix, erasures, smart);
965
 
  if (schedule == NULL) {
966
 
    free(ptrs);
967
 
    return -1;
968
 
  }
969
 
 
970
 
  for (tdone = 0; tdone < size; tdone += packetsize*w) {
971
 
  jerasure_do_scheduled_operations(ptrs, schedule, packetsize);
972
 
    for (i = 0; i < k+m; i++) ptrs[i] += (packetsize*w);
973
 
  }
974
 
 
975
 
  jerasure_free_schedule(schedule);
976
 
  free(ptrs);
977
 
 
978
 
  return 0;
979
 
}
980
 
 
981
 
int jerasure_schedule_decode_cache(int k, int m, int w, int ***scache, int *erasures,
982
 
                            char **data_ptrs, char **coding_ptrs, int size, int packetsize)
983
 
{
984
 
  int i, tdone;
985
 
  char **ptrs;
986
 
  int **schedule;
987
 
  int index;
988
 
 
989
 
  if (erasures[1] == -1) {
990
 
    index = erasures[0]*(k+m) + erasures[0];
991
 
  } else if (erasures[2] == -1) {
992
 
    index = erasures[0]*(k+m) + erasures[1];
993
 
  } else {
994
 
    return -1;
995
 
  }
996
 
 
997
 
  schedule = scache[index];
998
 
 
999
 
  ptrs = set_up_ptrs_for_scheduled_decoding(k, m, erasures, data_ptrs, coding_ptrs);
1000
 
  if (ptrs == NULL) return -1;
1001
 
 
1002
 
 
1003
 
  for (tdone = 0; tdone < size; tdone += packetsize*w) {
1004
 
  jerasure_do_scheduled_operations(ptrs, schedule, packetsize);
1005
 
    for (i = 0; i < k+m; i++) ptrs[i] += (packetsize*w);
1006
 
  }
1007
 
 
1008
 
  free(ptrs);
1009
 
 
1010
 
  return 0;
1011
 
}
1012
 
 
1013
 
/* This only works when m = 2 */
1014
 
 
1015
 
int ***jerasure_generate_schedule_cache(int k, int m, int w, int *bitmatrix, int smart)
1016
 
{
1017
 
  int ***scache;
1018
 
  int erasures[3];
1019
 
  int e1, e2;
1020
 
 
1021
 
  /* Ok -- this is yucky, but it's how I'm doing it.  You will make an index out
1022
 
     of erasures, which will be  e1*(k+m)+(e2).  If there is no e2, then e2 = e1.
1023
 
     Isn't that clever and confusing.  Sorry.
1024
 
 
1025
 
     We're not going to worry about ordering -- in other words, the schedule for
1026
 
     e1,e2 will be the same as e2,e1.  They will have the same pointer -- the 
1027
 
     schedule will not be duplicated. */
1028
 
 
1029
 
  if (m != 2) return NULL;
1030
 
 
1031
 
  scache = talloc(int **, (k+m)*(k+m+1));
1032
 
  if (scache == NULL) return NULL;
1033
 
  
1034
 
  for (e1 = 0; e1 < k+m; e1++) {
1035
 
    erasures[0] = e1;
1036
 
    for (e2 = 0; e2 < e1; e2++) {
1037
 
      erasures[1] = e2;
1038
 
      erasures[2] = -1;
1039
 
      scache[e1*(k+m)+e2] = jerasure_generate_decoding_schedule(k, m, w, bitmatrix, erasures, smart);
1040
 
      scache[e2*(k+m)+e1] = scache[e1*(k+m)+e2];
1041
 
    }
1042
 
    erasures[1] = -1;
1043
 
    scache[e1*(k+m)+e1] = jerasure_generate_decoding_schedule(k, m, w, bitmatrix, erasures, smart);
1044
 
  }
1045
 
  return scache;
1046
 
 
1047
 
}
1048
 
 
1049
 
int jerasure_invert_bitmatrix(int *mat, int *inv, int rows)
1050
 
{
1051
 
  int cols, i, j, k;
1052
 
  int tmp;
1053
 
 
1054
 
  cols = rows;
1055
 
 
1056
 
  k = 0;
1057
 
  for (i = 0; i < rows; i++) {
1058
 
    for (j = 0; j < cols; j++) {
1059
 
      inv[k] = (i == j) ? 1 : 0;
1060
 
      k++;
1061
 
    }
1062
 
  }
1063
 
 
1064
 
  /* First -- convert into upper triangular */
1065
 
 
1066
 
  for (i = 0; i < cols; i++) {
1067
 
 
1068
 
    /* Swap rows if we have a zero i,i element.  If we can't swap, then the 
1069
 
       matrix was not invertible */
1070
 
 
1071
 
    if ((mat[i*cols+i]) == 0) { 
1072
 
      for (j = i+1; j < rows && (mat[j*cols+i]) == 0; j++) ;
1073
 
      if (j == rows) return -1;
1074
 
      for (k = 0; k < cols; k++) {
1075
 
        tmp = mat[i*cols+k]; mat[i*cols+k] = mat[j*cols+k]; mat[j*cols+k] = tmp;
1076
 
        tmp = inv[i*cols+k]; inv[i*cols+k] = inv[j*cols+k]; inv[j*cols+k] = tmp;
1077
 
      }
1078
 
    }
1079
 
 
1080
 
    /* Now for each j>i, add A_ji*Ai to Aj */
1081
 
    for (j = i+1; j != rows; j++) {
1082
 
      if (mat[j*cols+i] != 0) {
1083
 
        for (k = 0; k < cols; k++) {
1084
 
          mat[j*cols+k] ^= mat[i*cols+k]; 
1085
 
          inv[j*cols+k] ^= inv[i*cols+k];
1086
 
        }
1087
 
      }
1088
 
    }
1089
 
  }
1090
 
 
1091
 
  /* Now the matrix is upper triangular.  Start at the top and multiply down */
1092
 
 
1093
 
  for (i = rows-1; i >= 0; i--) {
1094
 
    for (j = 0; j < i; j++) {
1095
 
      if (mat[j*cols+i]) {
1096
 
        for (k = 0; k < cols; k++) {
1097
 
          mat[j*cols+k] ^= mat[i*cols+k]; 
1098
 
          inv[j*cols+k] ^= inv[i*cols+k];
1099
 
        }
1100
 
      }
1101
 
    }
1102
 
  } 
1103
 
  return 0;
1104
 
}
1105
 
 
1106
 
int jerasure_invertible_bitmatrix(int *mat, int rows)
1107
 
{
1108
 
  int cols, i, j, k;
1109
 
  int tmp;
1110
 
 
1111
 
  cols = rows;
1112
 
 
1113
 
  /* First -- convert into upper triangular */
1114
 
 
1115
 
  for (i = 0; i < cols; i++) {
1116
 
 
1117
 
    /* Swap rows if we have a zero i,i element.  If we can't swap, then the 
1118
 
       matrix was not invertible */
1119
 
 
1120
 
    if ((mat[i*cols+i]) == 0) { 
1121
 
      for (j = i+1; j < rows && (mat[j*cols+i]) == 0; j++) ;
1122
 
      if (j == rows) return 0;
1123
 
      for (k = 0; k < cols; k++) {
1124
 
        tmp = mat[i*cols+k]; mat[i*cols+k] = mat[j*cols+k]; mat[j*cols+k] = tmp;
1125
 
      }
1126
 
    }
1127
 
 
1128
 
    /* Now for each j>i, add A_ji*Ai to Aj */
1129
 
    for (j = i+1; j != rows; j++) {
1130
 
      if (mat[j*cols+i] != 0) {
1131
 
        for (k = 0; k < cols; k++) {
1132
 
          mat[j*cols+k] ^= mat[i*cols+k]; 
1133
 
        }
1134
 
      }
1135
 
    }
1136
 
  }
1137
 
  return 1;
1138
 
}
1139
 
 
1140
 
  
1141
 
int *jerasure_matrix_multiply(int *m1, int *m2, int r1, int c1, int r2, int c2, int w)
1142
 
{
1143
 
  int *product, i, j, k;
1144
 
 
1145
 
  product = (int *) malloc(sizeof(int)*r1*c2);
1146
 
  for (i = 0; i < r1*c2; i++) product[i] = 0;
1147
 
 
1148
 
  for (i = 0; i < r1; i++) {
1149
 
    for (j = 0; j < c2; j++) {
1150
 
      for (k = 0; k < r2; k++) {
1151
 
        product[i*c2+j] ^= galois_single_multiply(m1[i*c1+k], m2[k*c2+j], w);
1152
 
      }
1153
 
    }
1154
 
  }
1155
 
  return product;
1156
 
}
1157
 
 
1158
 
void jerasure_get_stats(double *fill_in)
1159
 
{
1160
 
  fill_in[0] = jerasure_total_xor_bytes;
1161
 
  fill_in[1] = jerasure_total_gf_bytes;
1162
 
  fill_in[2] = jerasure_total_memcpy_bytes;
1163
 
  jerasure_total_xor_bytes = 0;
1164
 
  jerasure_total_gf_bytes = 0;
1165
 
  jerasure_total_memcpy_bytes = 0;
1166
 
}
1167
 
 
1168
 
void jerasure_do_scheduled_operations(char **ptrs, int **operations, int packetsize)
1169
 
{
1170
 
  char *sptr;
1171
 
  char *dptr;
1172
 
  int op;
1173
 
 
1174
 
  for (op = 0; operations[op][0] >= 0; op++) {
1175
 
    sptr = ptrs[operations[op][0]] + operations[op][1]*packetsize;
1176
 
    dptr = ptrs[operations[op][2]] + operations[op][3]*packetsize;
1177
 
    if (operations[op][4]) {
1178
 
/*      printf("%d,%d %d,%d\n", operations[op][0], 
1179
 
      operations[op][1], 
1180
 
      operations[op][2], 
1181
 
      operations[op][3]); 
1182
 
      printf("xor(0x%x, 0x%x -> 0x%x, %d)\n", sptr, dptr, dptr, packetsize); */
1183
 
      galois_region_xor(sptr, dptr, dptr, packetsize);
1184
 
      jerasure_total_xor_bytes += packetsize;
1185
 
    } else {
1186
 
/*      printf("memcpy(0x%x <- 0x%x)\n", dptr, sptr); */
1187
 
      memcpy(dptr, sptr, packetsize);
1188
 
      jerasure_total_memcpy_bytes += packetsize;
1189
 
    }
1190
 
  }  
1191
 
}
1192
 
 
1193
 
void jerasure_schedule_encode(int k, int m, int w, int **schedule,
1194
 
                                   char **data_ptrs, char **coding_ptrs, int size, int packetsize)
1195
 
{
1196
 
  char **ptr_copy;
1197
 
  int i, tdone;
1198
 
 
1199
 
  ptr_copy = talloc(char *, (k+m));
1200
 
  for (i = 0; i < k; i++) ptr_copy[i] = data_ptrs[i];
1201
 
  for (i = 0; i < m; i++) ptr_copy[i+k] = coding_ptrs[i];
1202
 
  for (tdone = 0; tdone < size; tdone += packetsize*w) {
1203
 
    jerasure_do_scheduled_operations(ptr_copy, schedule, packetsize);
1204
 
    for (i = 0; i < k+m; i++) ptr_copy[i] += (packetsize*w);
1205
 
  }
1206
 
  free(ptr_copy);
1207
 
}
1208
 
    
1209
 
int **jerasure_dumb_bitmatrix_to_schedule(int k, int m, int w, int *bitmatrix)
1210
 
{
1211
 
  int **operations;
1212
 
  int op;
1213
 
  int index, optodo, i, j;
1214
 
 
1215
 
  operations = talloc(int *, k*m*w*w+1);
1216
 
  op = 0;
1217
 
  
1218
 
  index = 0;
1219
 
  for (i = 0; i < m*w; i++) {
1220
 
    optodo = 0;
1221
 
    for (j = 0; j < k*w; j++) {
1222
 
      if (bitmatrix[index]) {
1223
 
        operations[op] = talloc(int, 5);
1224
 
        operations[op][4] = optodo;
1225
 
        operations[op][0] = j/w;
1226
 
        operations[op][1] = j%w;
1227
 
        operations[op][2] = k+i/w;
1228
 
        operations[op][3] = i%w;
1229
 
        optodo = 1;
1230
 
        op++;
1231
 
        
1232
 
      }
1233
 
      index++;
1234
 
    }
1235
 
  }
1236
 
  operations[op] = talloc(int, 5);
1237
 
  operations[op][0] = -1;
1238
 
  return operations;
1239
 
}
1240
 
 
1241
 
int **jerasure_smart_bitmatrix_to_schedule(int k, int m, int w, int *bitmatrix)
1242
 
{
1243
 
  int **operations;
1244
 
  int op;
1245
 
  int i, j;
1246
 
  int *diff, *from, *b1, *flink, *blink;
1247
 
  int *ptr, no, row;
1248
 
  int optodo;
1249
 
  int bestrow = 0, bestdiff, top;
1250
 
 
1251
 
/*   printf("Scheduling:\n\n");
1252
 
  jerasure_print_bitmatrix(bitmatrix, m*w, k*w, w); */
1253
 
 
1254
 
  operations = talloc(int *, k*m*w*w+1);
1255
 
  op = 0;
1256
 
  
1257
 
  diff = talloc(int, m*w);
1258
 
  from = talloc(int, m*w);
1259
 
  flink = talloc(int, m*w);
1260
 
  blink = talloc(int, m*w);
1261
 
 
1262
 
  ptr = bitmatrix;
1263
 
 
1264
 
  bestdiff = k*w+1;
1265
 
  top = 0;
1266
 
  for (i = 0; i < m*w; i++) {
1267
 
    no = 0;
1268
 
    for (j = 0; j < k*w; j++) {
1269
 
      no += *ptr;
1270
 
      ptr++;
1271
 
    }
1272
 
    diff[i] = no;
1273
 
    from[i] = -1;
1274
 
    flink[i] = i+1;
1275
 
    blink[i] = i-1;
1276
 
    if (no < bestdiff) {
1277
 
      bestdiff = no;
1278
 
      bestrow = i;
1279
 
    }
1280
 
  }
1281
 
 
1282
 
  flink[m*w-1] = -1;
1283
 
  
1284
 
  while (top != -1) {
1285
 
    row = bestrow;
1286
 
    /* printf("Doing row %d - %d from %d\n", row, diff[row], from[row]);  */
1287
 
 
1288
 
    if (blink[row] == -1) {
1289
 
      top = flink[row];
1290
 
      if (top != -1) blink[top] = -1;
1291
 
    } else {
1292
 
      flink[blink[row]] = flink[row];
1293
 
      if (flink[row] != -1) {
1294
 
        blink[flink[row]] = blink[row];
1295
 
      }
1296
 
    }
1297
 
 
1298
 
    ptr = bitmatrix + row*k*w;
1299
 
    if (from[row] == -1) {
1300
 
      optodo = 0;
1301
 
      for (j = 0; j < k*w; j++) {
1302
 
        if (ptr[j]) {
1303
 
          operations[op] = talloc(int, 5);
1304
 
          operations[op][4] = optodo;
1305
 
          operations[op][0] = j/w;
1306
 
          operations[op][1] = j%w;
1307
 
          operations[op][2] = k+row/w;
1308
 
          operations[op][3] = row%w;
1309
 
          optodo = 1;
1310
 
          op++;
1311
 
        }
1312
 
      }
1313
 
    } else {
1314
 
      operations[op] = talloc(int, 5);
1315
 
      operations[op][4] = 0;
1316
 
      operations[op][0] = k+from[row]/w;
1317
 
      operations[op][1] = from[row]%w;
1318
 
      operations[op][2] = k+row/w;
1319
 
      operations[op][3] = row%w;
1320
 
      op++;
1321
 
      b1 = bitmatrix + from[row]*k*w;
1322
 
      for (j = 0; j < k*w; j++) {
1323
 
        if (ptr[j] ^ b1[j]) {
1324
 
          operations[op] = talloc(int, 5);
1325
 
          operations[op][4] = 1;
1326
 
          operations[op][0] = j/w;
1327
 
          operations[op][1] = j%w;
1328
 
          operations[op][2] = k+row/w;
1329
 
          operations[op][3] = row%w;
1330
 
          optodo = 1;
1331
 
          op++;
1332
 
        }
1333
 
      }
1334
 
    }
1335
 
    bestdiff = k*w+1;
1336
 
    for (i = top; i != -1; i = flink[i]) {
1337
 
      no = 1;
1338
 
      b1 = bitmatrix + i*k*w;
1339
 
      for (j = 0; j < k*w; j++) no += (ptr[j] ^ b1[j]);
1340
 
      if (no < diff[i]) {
1341
 
        from[i] = row;
1342
 
        diff[i] = no;
1343
 
      }
1344
 
      if (diff[i] < bestdiff) {
1345
 
        bestdiff = diff[i];
1346
 
        bestrow = i;
1347
 
      }
1348
 
    }
1349
 
  }
1350
 
  
1351
 
  operations[op] = talloc(int, 5);
1352
 
  operations[op][0] = -1;
1353
 
  free(from);
1354
 
  free(diff);
1355
 
  free(blink);
1356
 
  free(flink);
1357
 
 
1358
 
  return operations;
1359
 
}
1360
 
 
1361
 
void jerasure_bitmatrix_encode(int k, int m, int w, int *bitmatrix,
1362
 
                            char **data_ptrs, char **coding_ptrs, int size, int packetsize)
1363
 
{
1364
 
  int i;
1365
 
 
1366
 
  if (packetsize%sizeof(long) != 0) {
1367
 
    fprintf(stderr, "jerasure_bitmatrix_encode - packetsize(%d) %c sizeof(long) != 0\n", packetsize, '%');
1368
 
    exit(1);
1369
 
  }
1370
 
  if (size%(packetsize*w) != 0) {
1371
 
    fprintf(stderr, "jerasure_bitmatrix_encode - size(%d) %c (packetsize(%d)*w(%d))) != 0\n", 
1372
 
         size, '%', packetsize, w);
1373
 
    exit(1);
1374
 
  }
1375
 
 
1376
 
  for (i = 0; i < m; i++) {
1377
 
    jerasure_bitmatrix_dotprod(k, w, bitmatrix+i*k*w*w, NULL, k+i, data_ptrs, coding_ptrs, size, packetsize);
1378
 
  }
1379
 
}
1380