• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

bench/H12-Nov-2020-11078

haskell/H12-Nov-2020-305226

misc/build_helpers/H12-Nov-2020-209182

zfec/H12-Nov-2020-2,5881,803

zfec.egg-info/H03-May-2022-381295

.travis.ymlH A D12-Nov-2020451 2019

COPYING.GPLH A D12-Nov-202023.7 KiB452374

COPYING.TGPPL.rstH A D12-Nov-202016.9 KiB292251

MANIFEST.inH A D12-Nov-2020411 2115

PKG-INFOH A D12-Nov-202019 KiB381295

README.rstH A D12-Nov-202014.4 KiB332246

Setup.lhsH A D12-Nov-202076 42

TODOH A D12-Nov-2020579 1612

changelogH A D12-Nov-20202 KiB5435

copyrightH A D12-Nov-202014.5 KiB247226

fec.cabalH A D12-Nov-20201.3 KiB3130

setup.cfgH A D12-Nov-20201.9 KiB6963

setup.pyH A D12-Nov-20201.9 KiB7257

stack.yamlH A D12-Nov-20201,007 3323

stridetune-bench.ba.shH A D12-Nov-2020479 1714

stridetune-bench.pyH A D12-Nov-20201.1 KiB4432

stridetune-dat.bashH A D12-Nov-2020228 118

stridetune-graph.pyH A D12-Nov-2020212 116

tox.iniH A D12-Nov-2020160 118

versioneer.pyH A D12-Nov-202067 KiB1,8231,415

README.rst

1
2
3zfec -- efficient, portable erasure coding tool
4===============================================
5
6Generate redundant blocks of information such that if some of the blocks are
7lost then the original data can be recovered from the remaining blocks. This
8package includes command-line tools, C API, Python API, and Haskell API.
9
10|pypi| |travis| |appveyor|
11
12Intro and Licence
13-----------------
14
15This package implements an "erasure code", or "forward error correction
16code".
17
18You may use this package under the GNU General Public License, version 2 or,
19at your option, any later version.  You may use this package under the
20Transitive Grace Period Public Licence, version 1.0 or, at your option, any
21later version.  (You may choose to use this package under the terms of either
22licence, at your option.)  See the file COPYING.GPL for the terms of the GNU
23General Public License, version 2.  See the file COPYING.TGPPL.rst for the
24terms of the Transitive Grace Period Public Licence, version 1.0.
25
26The most widely known example of an erasure code is the RAID-5 algorithm
27which makes it so that in the event of the loss of any one hard drive, the
28stored data can be completely recovered.  The algorithm in the zfec package
29has a similar effect, but instead of recovering from the loss of only a
30single element, it can be parameterized to choose in advance the number of
31elements whose loss it can tolerate.
32
33This package is largely based on the old "fec" library by Luigi Rizzo et al.,
34which is a mature and optimized implementation of erasure coding.  The zfec
35package makes several changes from the original "fec" package, including
36addition of the Python API, refactoring of the C API to support zero-copy
37operation, a few clean-ups and optimizations of the core code itself, and the
38addition of a command-line tool named "zfec".
39
40
41Installation
42------------
43
44``pip install zfec``
45
46To run the self-tests, execute ``tox`` from an unpacked source tree or git checkout.
47
48To run the tests of the Haskell API: ``runhaskell haskell/test/FECTest.hs``
49
50Note that in order to run the Haskell API tests you must have installed the
51library first due to the fact that the interpreter cannot process FEC.hs as
52it takes a reference to an FFI function.
53
54
55Community
56---------
57
58The source is currently available via git on the web with the command:
59
60``git clone https://github.com/tahoe-lafs/zfec``
61
62Please post about zfec to the Tahoe-LAFS mailing list and contribute patches:
63
64<https://tahoe-lafs.org/cgi-bin/mailman/listinfo/tahoe-dev>
65
66If you find a bug in zfec, please open an issue on github:
67
68<https://github.com/tahoe-lafs/zfec/issues>
69
70Overview
71--------
72
73This package performs two operations, encoding and decoding.  Encoding takes
74some input data and expands its size by producing extra "check blocks", also
75called "secondary blocks".  Decoding takes some data -- any combination of
76blocks of the original data (called "primary blocks") and "secondary blocks",
77and produces the original data.
78
79The encoding is parameterized by two integers, k and m.  m is the total
80number of blocks produced, and k is how many of those blocks are necessary to
81reconstruct the original data.  m is required to be at least 1 and at most
82256, and k is required to be at least 1 and at most m.
83
84(Note that when k == m then there is no point in doing erasure coding -- it
85degenerates to the equivalent of the Unix "split" utility which simply splits
86the input into successive segments.  Similarly, when k == 1 it degenerates to
87the equivalent of the unix "cp" utility -- each block is a complete copy of
88the input data.)
89
90Note that each "primary block" is a segment of the original data, so its size
91is 1/k'th of the size of original data, and each "secondary block" is of the
92same size, so the total space used by all the blocks is m/k times the size of
93the original data (plus some padding to fill out the last primary block to be
94the same size as all the others).  In addition to the data contained in the
95blocks themselves there are also a few pieces of metadata which are necessary
96for later reconstruction.  Those pieces are: 1.  the value of K, 2.  the
97value of M, 3.  the sharenum of each block, 4.  the number of bytes of
98padding that were used.  The "zfec" command-line tool compresses these pieces
99of data and prepends them to the beginning of each share, so each the
100sharefile produced by the "zfec" command-line tool is between one and four
101bytes larger than the share data alone.
102
103The decoding step requires as input k of the blocks which were produced by
104the encoding step.  The decoding step produces as output the data that was
105earlier input to the encoding step.
106
107
108Command-Line Tool
109-----------------
110
111The bin/ directory contains two Unix-style, command-line tools "zfec" and
112"zunfec".  Execute ``zfec --help`` or ``zunfec --help`` for usage
113instructions.
114
115
116Performance
117-----------
118
119To run the benchmarks, execute the included bench/bench_zfec.py script with
120optional --k= and --m= arguments.
121
122On my Athlon 64 2.4 GHz workstation (running Linux), the "zfec" command-line
123tool encoded a 160 MB file with m=100, k=94 (about 6% redundancy) in 3.9
124seconds, where the "par2" tool encoded the file with about 6% redundancy in
12527 seconds.  zfec encoded the same file with m=12, k=6 (100% redundancy) in
1264.1 seconds, where par2 encoded it with about 100% redundancy in 7 minutes
127and 56 seconds.
128
129The underlying C library in benchmark mode encoded from a file at about 4.9
130million bytes per second and decoded at about 5.8 million bytes per second.
131
132On Peter's fancy Intel Mac laptop (2.16 GHz Core Duo), it encoded from a file
133at about 6.2 million bytes per second.
134
135On my even fancier Intel Mac laptop (2.33 GHz Core Duo), it encoded from a
136file at about 6.8 million bytes per second.
137
138On my old PowerPC G4 867 MHz Mac laptop, it encoded from a file at about 1.3
139million bytes per second.
140
141Here is a paper analyzing the performance of various erasure codes and their
142implementations, including zfec:
143
144http://www.usenix.org/events/fast09/tech/full_papers/plank/plank.pdf
145
146Zfec shows good performance on different machines and with different values
147of K and M. It also has a nice small memory footprint.
148
149
150API
151---
152
153Each block is associated with "blocknum".  The blocknum of each primary block
154is its index (starting from zero), so the 0'th block is the first primary
155block, which is the first few bytes of the file, the 1'st block is the next
156primary block, which is the next few bytes of the file, and so on.  The last
157primary block has blocknum k-1.  The blocknum of each secondary block is an
158arbitrary integer between k and 255 inclusive.  (When using the Python API,
159if you don't specify which secondary blocks you want when invoking encode(),
160then it will by default provide the blocks with ids from k to m-1 inclusive.)
161
162- C API
163
164  fec_encode() takes as input an array of k pointers, where each pointer
165  points to a memory buffer containing the input data (i.e., the i'th buffer
166  contains the i'th primary block).  There is also a second parameter which
167  is an array of the blocknums of the secondary blocks which are to be
168  produced.  (Each element in that array is required to be the blocknum of a
169  secondary block, i.e. it is required to be >= k and < m.)
170
171  The output from fec_encode() is the requested set of secondary blocks which
172  are written into output buffers provided by the caller.
173
174  Note that this fec_encode() is a "low-level" API in that it requires the
175  input data to be provided in a set of memory buffers of exactly the right
176  sizes.  If you are starting instead with a single buffer containing all of
177  the data then please see easyfec.py's "class Encoder" as an example of how
178  to split a single large buffer into the appropriate set of input buffers
179  for fec_encode().  If you are starting with a file on disk, then please see
180  filefec.py's encode_file_stringy_easyfec() for an example of how to read
181  the data from a file and pass it to "class Encoder".  The Python interface
182  provides these higher-level operations, as does the Haskell interface.  If
183  you implement functions to do these higher-level tasks in other languages,
184  please send a patch to tahoe-dev@tahoe-lafs.org so that your API can be
185  included in future releases of zfec.
186
187  fec_decode() takes as input an array of k pointers, where each pointer
188  points to a buffer containing a block.  There is also a separate input
189  parameter which is an array of blocknums, indicating the blocknum of each
190  of the blocks which is being passed in.
191
192  The output from fec_decode() is the set of primary blocks which were
193  missing from the input and had to be reconstructed.  These reconstructed
194  blocks are written into output buffers provided by the caller.
195
196
197- Python API
198
199  encode() and decode() take as input a sequence of k buffers, where a
200  "sequence" is any object that implements the Python sequence protocol (such
201  as a list or tuple) and a "buffer" is any object that implements the Python
202  buffer protocol (such as a string or array).  The contents that are
203  required to be present in these buffers are the same as for the C API.
204
205  encode() also takes a list of desired blocknums.  Unlike the C API, the
206  Python API accepts blocknums of primary blocks as well as secondary blocks
207  in its list of desired blocknums.  encode() returns a list of buffer
208  objects which contain the blocks requested.  For each requested block which
209  is a primary block, the resulting list contains a reference to the
210  apppropriate primary block from the input list.  For each requested block
211  which is a secondary block, the list contains a newly created string object
212  containing that block.
213
214  decode() also takes a list of integers indicating the blocknums of the
215  blocks being passed int.  decode() returns a list of buffer objects which
216  contain all of the primary blocks of the original data (in order).  For
217  each primary block which was present in the input list, then the result
218  list simply contains a reference to the object that was passed in the input
219  list.  For each primary block which was not present in the input, the
220  result list contains a newly created string object containing that primary
221  block.
222
223  Beware of a "gotcha" that can result from the combination of mutable data
224  and the fact that the Python API returns references to inputs when
225  possible.
226
227  Returning references to its inputs is efficient since it avoids making an
228  unnecessary copy of the data, but if the object which was passed as input
229  is mutable and if that object is mutated after the call to zfec returns,
230  then the result from zfec -- which is just a reference to that same object
231  -- will also be mutated.  This subtlety is the price you pay for avoiding
232  data copying.  If you don't want to have to worry about this then you can
233  simply use immutable objects (e.g. Python strings) to hold the data that
234  you pass to zfec.
235
236- Haskell API
237
238  The Haskell code is fully Haddocked, to generate the documentation, run
239  ``runhaskell Setup.lhs haddock``.
240
241
242Utilities
243---------
244
245The filefec.py module has a utility function for efficiently reading a file
246and encoding it piece by piece.  This module is used by the "zfec" and
247"zunfec" command-line tools from the bin/ directory.
248
249
250Dependencies
251------------
252
253A C compiler is required.  To use the Python API or the command-line tools a
254Python interpreter is also required.  We have tested it with Python v2.7,
255v3.5 and v3.6.  For the Haskell interface, GHC >= 6.8.1 is required.
256
257
258Acknowledgements
259----------------
260
261Thanks to the author of the original fec lib, Luigi Rizzo, and the folks that
262contributed to it: Phil Karn, Robert Morelos-Zaragoza, Hari Thirumoorthy, and
263Dan Rubenstein.  Thanks to the Mnet hackers who wrote an earlier Python
264wrapper, especially Myers Carpenter and Hauke Johannknecht.  Thanks to Brian
265Warner and Amber O'Whielacronx for help with the API, documentation,
266debugging, compression, and unit tests.  Thanks to Adam Langley for improving
267the C API and contributing the Haskell API.  Thanks to the creators of GCC
268(starting with Richard M. Stallman) and Valgrind (starting with Julian
269Seward) for a pair of excellent tools.  Thanks to my coworkers at Allmydata
270-- http://allmydata.com -- Fabrice Grinda, Peter Secor, Rob Kinninmont, Brian
271Warner, Zandr Milewski, Justin Boreta, Mark Meras for sponsoring this work
272and releasing it under a Free Software licence. Thanks to Jack Lloyd, Samuel
273Neves, and David-Sarah Hopwood.
274
275
276Related Works
277-------------
278
279Note: a Unix-style tool like "zfec" does only one thing -- in this case
280erasure coding -- and leaves other tasks to other tools.  Other Unix-style
281tools that go well with zfec include `GNU tar`_ for archiving multiple files
282and directories into one file, `lzip`_ for compression, and `GNU Privacy
283Guard`_ for encryption or `b2sum`_ for integrity.  It is important to do
284things in order: first archive, then compress, then either encrypt or
285integrity-check, then erasure code.  Note that if GNU Privacy Guard is used
286for privacy, then it will also ensure integrity, so the use of b2sum is
287unnecessary in that case. Note also that you also need to do integrity
288checking (such as with b2sum) on the blocks that result from the erasure
289coding in *addition* to doing it on the file contents! (There are two
290different subtle failure modes -- see "more than one file can match an
291immutable file cap" on the `Hack Tahoe-LAFS!`_ Hall of Fame.)
292
293The `Tahoe-LAFS`_ project uses zfec as part of a complete distributed
294filesystem with integrated encryption, integrity, remote distribution of the
295blocks, directory structure, backup of changed files or directories, access
296control, immutable files and directories, proof-of-retrievability, and repair
297of damaged files and directories.
298
299`fecpp`_ is an alternative to zfec. It implements a bitwise-compatible
300algorithm to zfec and is BSD-licensed.
301
302.. _GNU tar: http://directory.fsf.org/project/tar/
303.. _lzip: http://www.nongnu.org/lzip/lzip.html
304.. _GNU Privacy Guard: http://gnupg.org/
305.. _b2sum: https://blake2.net/
306.. _Tahoe-LAFS: https://tahoe-lafs.org
307.. _Hack Tahoe-LAFS!: https://tahoe-lafs.org/hacktahoelafs/
308.. _fecpp: http://www.randombit.net/code/fecpp/
309
310
311Enjoy!
312
313Zooko Wilcox-O'Hearn
314
3152013-05-15
316
317Boulder, Colorado
318
319----
320
321.. |pypi| image:: http://img.shields.io/pypi/v/zfec.svg
322   :alt: PyPI release status
323   :target: https://pypi.python.org/pypi/zfec
324
325.. |travis| image:: https://travis-ci.org/tahoe-lafs/zfec.png?branch=master
326    :alt: build status
327    :target: https://travis-ci.org/tahoe-lafs/zfec
328
329.. |appveyor| image:: https://ci.appveyor.com/api/projects/status/uamocktx0h84ahqa/branch/master
330   :alt: Appveyor (windows) build status
331   :target: https://ci.appveyor.com/project/tahoe-lafs/zfec
332