mirror of
https://github.com/SlavikMIPT/tgcloud.git
synced 2025-03-09 15:40:14 +00:00
dedupfs added
This commit is contained in:
parent
5b4ed0194e
commit
4d66c44764
14 changed files with 2877 additions and 1 deletions
8
dedupfs/lzo/README
Normal file
8
dedupfs/lzo/README
Normal file
|
@ -0,0 +1,8 @@
|
|||
This is a simple binding to the canonical LZO compression library. To compile
|
||||
first make sure you have both liblzo2 and the headers installed (on Ubuntu you
|
||||
can install the packages `liblzo2' and `liblzo2-dev'), then run the command
|
||||
`python setup.py build && python setup.py install'.
|
||||
|
||||
Please note that this is my first Python/C interfacing code so be careful :-)
|
||||
|
||||
- Peter Odding <peter@peterodding.com>
|
149
dedupfs/lzo/lzomodule.c
Normal file
149
dedupfs/lzo/lzomodule.c
Normal file
|
@ -0,0 +1,149 @@
|
|||
#define BLOCK_SIZE (1024 * 128)
|
||||
|
||||
#include <python2.6/Python.h>
|
||||
#include <lzo/lzo1x.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* The following formula gives the worst possible compressed size. */
|
||||
#define lzo1x_worst_compress(x) ((x) + ((x) / 16) + 64 + 3)
|
||||
|
||||
/* The size of and pointer to the shared buffer. */
|
||||
static int block_size, buffer_size = 0;
|
||||
static unsigned char *shared_buffer = NULL;
|
||||
|
||||
/* Don't store the size of compressed blocks in headers and trust the user to
|
||||
* configure the correct block size? */
|
||||
static int omit_headers = 0;
|
||||
|
||||
/* Working memory required by LZO library, allocated on first use. */
|
||||
static char *working_memory = NULL;
|
||||
|
||||
#define ADD_SIZE(p) (omit_headers ? (p) : ((p) + sizeof(int)))
|
||||
#define SUB_SIZE(p) (omit_headers ? (p) : ((p) - sizeof(int)))
|
||||
|
||||
static unsigned char *
|
||||
get_buffer(int length)
|
||||
{
|
||||
if (omit_headers) {
|
||||
if (!shared_buffer)
|
||||
shared_buffer = malloc(buffer_size);
|
||||
} else if (!shared_buffer || buffer_size < length) {
|
||||
free(shared_buffer);
|
||||
shared_buffer = malloc(length);
|
||||
buffer_size = length;
|
||||
}
|
||||
return shared_buffer;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
set_block_size(PyObject *self, PyObject *args)
|
||||
{
|
||||
int new_block_size;
|
||||
|
||||
if (PyArg_ParseTuple(args, "i", &new_block_size)) {
|
||||
if (shared_buffer)
|
||||
free(shared_buffer);
|
||||
block_size = new_block_size;
|
||||
buffer_size = lzo1x_worst_compress(block_size);
|
||||
shared_buffer = malloc(buffer_size);
|
||||
omit_headers = 1;
|
||||
}
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
lzo_compress(PyObject *self, PyObject *args)
|
||||
{
|
||||
const unsigned char *input;
|
||||
unsigned char *output;
|
||||
unsigned int inlen, status;
|
||||
lzo_uint outlen;
|
||||
|
||||
/* Get the uncompressed string and its length. */
|
||||
if (!PyArg_ParseTuple(args, "s#", &input, &inlen))
|
||||
return NULL;
|
||||
|
||||
/* Make sure never to touch unallocated memory. */
|
||||
if (omit_headers && inlen > block_size)
|
||||
return PyErr_Format(PyExc_ValueError, "The given input of %i bytes is larger than the configured block size of %i bytes!", block_size, inlen);
|
||||
|
||||
/* Allocate the working memory on first use? */
|
||||
if (!working_memory && !(working_memory = malloc(LZO1X_999_MEM_COMPRESS)))
|
||||
return PyErr_NoMemory();
|
||||
|
||||
/* Allocate the output buffer. */
|
||||
outlen = lzo1x_worst_compress(inlen);
|
||||
output = get_buffer(ADD_SIZE(outlen));
|
||||
if (!output)
|
||||
return PyErr_NoMemory();
|
||||
|
||||
/* Store the input size in the header of the compressed block? */
|
||||
if (!omit_headers)
|
||||
*((int*)output) = inlen;
|
||||
|
||||
/* Compress the input string. The default LZO compression function is
|
||||
* lzo1x_1_compress(). There's also variants like lzo1x_1_15_compress() which
|
||||
* is faster and lzo1x_999_compress() which achieves higher compression. */
|
||||
status = lzo1x_1_15_compress(input, inlen, ADD_SIZE(output), &outlen, working_memory);
|
||||
if (status != LZO_E_OK)
|
||||
return PyErr_Format(PyExc_Exception, "lzo_compress() failed with error code %i!", status);
|
||||
|
||||
/* Return the compressed string. */
|
||||
return Py_BuildValue("s#", output, ADD_SIZE(outlen));
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
lzo_decompress(PyObject *self, PyObject *args)
|
||||
{
|
||||
const unsigned char *input;
|
||||
unsigned char *output;
|
||||
int inlen, outlen_expected = 0, status;
|
||||
lzo_uint outlen_actual;
|
||||
|
||||
/* Get the compressed string and its length. */
|
||||
if (!PyArg_ParseTuple(args, "s#", &input, &inlen))
|
||||
return NULL;
|
||||
|
||||
/* Get the length of the uncompressed string? */
|
||||
if (!omit_headers)
|
||||
outlen_expected = *((int*)input);
|
||||
|
||||
/* Allocate the output buffer. */
|
||||
output = get_buffer(outlen_expected);
|
||||
if (!output)
|
||||
return PyErr_NoMemory();
|
||||
|
||||
/* Decompress the compressed string. */
|
||||
status = lzo1x_decompress(ADD_SIZE(input), SUB_SIZE(inlen), output, &outlen_actual, NULL);
|
||||
if (status != LZO_E_OK)
|
||||
return PyErr_Format(PyExc_Exception, "lzo_decompress() failed with error code %i!", status);
|
||||
|
||||
/* Verify the length of the uncompressed data? */
|
||||
if (!omit_headers && outlen_expected != outlen_actual)
|
||||
return PyErr_Format(PyExc_Exception, "The expected length (%i) doesn't match the actual uncompressed length (%i)!", outlen_expected, (int)outlen_actual);
|
||||
|
||||
/* Return the decompressed string. */
|
||||
return Py_BuildValue("s#", output, (int)outlen_actual);
|
||||
}
|
||||
|
||||
static PyMethodDef functions[] = {
|
||||
{ "compress", lzo_compress, METH_VARARGS, "Compress a string using the LZO algorithm." },
|
||||
{ "decompress", lzo_decompress, METH_VARARGS, "Decompress a string that was previously compressed using the compress() function of this same module." },
|
||||
{ "set_block_size", set_block_size, METH_VARARGS, "Set the max. length of the strings you will be compressing and/or decompressing so that the LZO module can allocate a single buffer shared by all lzo.compress() and lzo.decompress() calls." },
|
||||
{ NULL, NULL, 0, NULL }
|
||||
};
|
||||
|
||||
PyMODINIT_FUNC
|
||||
initlzo(void)
|
||||
{
|
||||
int status;
|
||||
|
||||
if ((status = lzo_init()) != LZO_E_OK)
|
||||
PyErr_Format(PyExc_Exception, "Failed to initialize the LZO library! (lzo_init() failed with error code %i)", status);
|
||||
else if (!Py_InitModule("lzo", functions))
|
||||
PyErr_Format(PyExc_Exception, "Failed to register module functions!");
|
||||
}
|
||||
|
||||
/* vim: set ts=2 sw=2 et : */
|
4
dedupfs/lzo/setup.py
Normal file
4
dedupfs/lzo/setup.py
Normal file
|
@ -0,0 +1,4 @@
|
|||
from distutils.core import setup, Extension
|
||||
|
||||
setup(name = "LZO", version = "1.0",
|
||||
ext_modules = [Extension("lzo", ["lzomodule.c"], libraries=['lzo2'])])
|
Loading…
Add table
Add a link
Reference in a new issue