Mercurial > hg
comparison contrib/python-zstandard/c-ext/compressionwriter.c @ 31796:e0dc40530c5a
zstd: vendor python-zstandard 0.8.0
Commit 81e1f5bbf1fc54808649562d3ed829730765c540 from
https://github.com/indygreg/python-zstandard is imported without
modifications (other than removing unwanted files).
Updates relevant to Mercurial include:
* Support for multi-threaded compression (we can use this for
bundle and wire protocol compression).
* APIs for batch compression and decompression operations using
multiple threads and optimal memory allocation mechanism. (Can
be useful for revlog perf improvements.)
* A ``BufferWithSegments`` type that models a single memory buffer
containing N discrete items of known lengths. This type can be
used for very efficient 0-copy data operations.
# no-check-commit
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Sat, 01 Apr 2017 15:24:03 -0700 |
parents | c32454d69b85 |
children | b1fb341d8a61 |
comparison
equal
deleted
inserted
replaced
31795:2b130e26c3a4 | 31796:e0dc40530c5a |
---|---|
16 | 16 |
17 static void ZstdCompressionWriter_dealloc(ZstdCompressionWriter* self) { | 17 static void ZstdCompressionWriter_dealloc(ZstdCompressionWriter* self) { |
18 Py_XDECREF(self->compressor); | 18 Py_XDECREF(self->compressor); |
19 Py_XDECREF(self->writer); | 19 Py_XDECREF(self->writer); |
20 | 20 |
21 if (self->cstream) { | |
22 ZSTD_freeCStream(self->cstream); | |
23 self->cstream = NULL; | |
24 } | |
25 | |
26 PyObject_Del(self); | 21 PyObject_Del(self); |
27 } | 22 } |
28 | 23 |
29 static PyObject* ZstdCompressionWriter_enter(ZstdCompressionWriter* self) { | 24 static PyObject* ZstdCompressionWriter_enter(ZstdCompressionWriter* self) { |
30 if (self->entered) { | 25 if (self->entered) { |
31 PyErr_SetString(ZstdError, "cannot __enter__ multiple times"); | 26 PyErr_SetString(ZstdError, "cannot __enter__ multiple times"); |
32 return NULL; | 27 return NULL; |
33 } | 28 } |
34 | 29 |
35 self->cstream = CStream_from_ZstdCompressor(self->compressor, self->sourceSize); | 30 if (self->compressor->mtcctx) { |
36 if (!self->cstream) { | 31 if (init_mtcstream(self->compressor, self->sourceSize)) { |
37 return NULL; | 32 return NULL; |
33 } | |
34 } | |
35 else { | |
36 if (0 != init_cstream(self->compressor, self->sourceSize)) { | |
37 return NULL; | |
38 } | |
38 } | 39 } |
39 | 40 |
40 self->entered = 1; | 41 self->entered = 1; |
41 | 42 |
42 Py_INCREF(self); | 43 Py_INCREF(self); |
56 return NULL; | 57 return NULL; |
57 } | 58 } |
58 | 59 |
59 self->entered = 0; | 60 self->entered = 0; |
60 | 61 |
61 if (self->cstream && exc_type == Py_None && exc_value == Py_None && | 62 if ((self->compressor->cstream || self->compressor->mtcctx) && exc_type == Py_None |
62 exc_tb == Py_None) { | 63 && exc_value == Py_None && exc_tb == Py_None) { |
63 | 64 |
64 output.dst = PyMem_Malloc(self->outSize); | 65 output.dst = PyMem_Malloc(self->outSize); |
65 if (!output.dst) { | 66 if (!output.dst) { |
66 return PyErr_NoMemory(); | 67 return PyErr_NoMemory(); |
67 } | 68 } |
68 output.size = self->outSize; | 69 output.size = self->outSize; |
69 output.pos = 0; | 70 output.pos = 0; |
70 | 71 |
71 while (1) { | 72 while (1) { |
72 zresult = ZSTD_endStream(self->cstream, &output); | 73 if (self->compressor->mtcctx) { |
74 zresult = ZSTDMT_endStream(self->compressor->mtcctx, &output); | |
75 } | |
76 else { | |
77 zresult = ZSTD_endStream(self->compressor->cstream, &output); | |
78 } | |
73 if (ZSTD_isError(zresult)) { | 79 if (ZSTD_isError(zresult)) { |
74 PyErr_Format(ZstdError, "error ending compression stream: %s", | 80 PyErr_Format(ZstdError, "error ending compression stream: %s", |
75 ZSTD_getErrorName(zresult)); | 81 ZSTD_getErrorName(zresult)); |
76 PyMem_Free(output.dst); | 82 PyMem_Free(output.dst); |
77 return NULL; | 83 return NULL; |
93 | 99 |
94 output.pos = 0; | 100 output.pos = 0; |
95 } | 101 } |
96 | 102 |
97 PyMem_Free(output.dst); | 103 PyMem_Free(output.dst); |
98 ZSTD_freeCStream(self->cstream); | |
99 self->cstream = NULL; | |
100 } | 104 } |
101 | 105 |
102 Py_RETURN_FALSE; | 106 Py_RETURN_FALSE; |
103 } | 107 } |
104 | 108 |
105 static PyObject* ZstdCompressionWriter_memory_size(ZstdCompressionWriter* self) { | 109 static PyObject* ZstdCompressionWriter_memory_size(ZstdCompressionWriter* self) { |
106 if (!self->cstream) { | 110 if (!self->compressor->cstream) { |
107 PyErr_SetString(ZstdError, "cannot determine size of an inactive compressor; " | 111 PyErr_SetString(ZstdError, "cannot determine size of an inactive compressor; " |
108 "call when a context manager is active"); | 112 "call when a context manager is active"); |
109 return NULL; | 113 return NULL; |
110 } | 114 } |
111 | 115 |
112 return PyLong_FromSize_t(ZSTD_sizeof_CStream(self->cstream)); | 116 return PyLong_FromSize_t(ZSTD_sizeof_CStream(self->compressor->cstream)); |
113 } | 117 } |
114 | 118 |
115 static PyObject* ZstdCompressionWriter_write(ZstdCompressionWriter* self, PyObject* args) { | 119 static PyObject* ZstdCompressionWriter_write(ZstdCompressionWriter* self, PyObject* args) { |
116 const char* source; | 120 const char* source; |
117 Py_ssize_t sourceSize; | 121 Py_ssize_t sourceSize; |
145 input.size = sourceSize; | 149 input.size = sourceSize; |
146 input.pos = 0; | 150 input.pos = 0; |
147 | 151 |
148 while ((ssize_t)input.pos < sourceSize) { | 152 while ((ssize_t)input.pos < sourceSize) { |
149 Py_BEGIN_ALLOW_THREADS | 153 Py_BEGIN_ALLOW_THREADS |
150 zresult = ZSTD_compressStream(self->cstream, &output, &input); | 154 if (self->compressor->mtcctx) { |
155 zresult = ZSTDMT_compressStream(self->compressor->mtcctx, | |
156 &output, &input); | |
157 } | |
158 else { | |
159 zresult = ZSTD_compressStream(self->compressor->cstream, &output, &input); | |
160 } | |
151 Py_END_ALLOW_THREADS | 161 Py_END_ALLOW_THREADS |
152 | 162 |
153 if (ZSTD_isError(zresult)) { | 163 if (ZSTD_isError(zresult)) { |
154 PyMem_Free(output.dst); | 164 PyMem_Free(output.dst); |
155 PyErr_Format(ZstdError, "zstd compress error: %s", ZSTD_getErrorName(zresult)); | 165 PyErr_Format(ZstdError, "zstd compress error: %s", ZSTD_getErrorName(zresult)); |
193 output.size = self->outSize; | 203 output.size = self->outSize; |
194 output.pos = 0; | 204 output.pos = 0; |
195 | 205 |
196 while (1) { | 206 while (1) { |
197 Py_BEGIN_ALLOW_THREADS | 207 Py_BEGIN_ALLOW_THREADS |
198 zresult = ZSTD_flushStream(self->cstream, &output); | 208 if (self->compressor->mtcctx) { |
209 zresult = ZSTDMT_flushStream(self->compressor->mtcctx, &output); | |
210 } | |
211 else { | |
212 zresult = ZSTD_flushStream(self->compressor->cstream, &output); | |
213 } | |
199 Py_END_ALLOW_THREADS | 214 Py_END_ALLOW_THREADS |
200 | 215 |
201 if (ZSTD_isError(zresult)) { | 216 if (ZSTD_isError(zresult)) { |
202 PyMem_Free(output.dst); | 217 PyMem_Free(output.dst); |
203 PyErr_Format(ZstdError, "zstd compress error: %s", ZSTD_getErrorName(zresult)); | 218 PyErr_Format(ZstdError, "zstd compress error: %s", ZSTD_getErrorName(zresult)); |