Show More
@@ -3000,6 +3000,8 b' class compressormanager(object):' | |||
|
3000 | 3000 | self._bundlenames = {} |
|
3001 | 3001 | # Internal bundle identifier to engine name. |
|
3002 | 3002 | self._bundletypes = {} |
|
3003 | # Revlog header to engine name. | |
|
3004 | self._revlogheaders = {} | |
|
3003 | 3005 | # Wire proto identifier to engine name. |
|
3004 | 3006 | self._wiretypes = {} |
|
3005 | 3007 | |
@@ -3053,6 +3055,14 b' class compressormanager(object):' | |||
|
3053 | 3055 | |
|
3054 | 3056 | self._wiretypes[wiretype] = name |
|
3055 | 3057 | |
|
3058 | revlogheader = engine.revlogheader() | |
|
3059 | if revlogheader and revlogheader in self._revlogheaders: | |
|
3060 | raise error.Abort(_('revlog header %s already registered by %s') % | |
|
3061 | (revlogheader, self._revlogheaders[revlogheader])) | |
|
3062 | ||
|
3063 | if revlogheader: | |
|
3064 | self._revlogheaders[revlogheader] = name | |
|
3065 | ||
|
3056 | 3066 | self._engines[name] = engine |
|
3057 | 3067 | |
|
3058 | 3068 | @property |
@@ -3121,6 +3131,13 b' class compressormanager(object):' | |||
|
3121 | 3131 | engine.name()) |
|
3122 | 3132 | return engine |
|
3123 | 3133 | |
|
3134 | def forrevlogheader(self, header): | |
|
3135 | """Obtain a compression engine registered to a revlog header. | |
|
3136 | ||
|
3137 | Will raise KeyError if the revlog header value isn't registered. | |
|
3138 | """ | |
|
3139 | return self._engines[self._revlogheaders[header]] | |
|
3140 | ||
|
3124 | 3141 | compengines = compressormanager() |
|
3125 | 3142 | |
|
3126 | 3143 | class compressionengine(object): |
@@ -3186,6 +3203,16 b' class compressionengine(object):' | |||
|
3186 | 3203 | """ |
|
3187 | 3204 | return None |
|
3188 | 3205 | |
|
3206 | def revlogheader(self): | |
|
3207 | """Header added to revlog chunks that identifies this engine. | |
|
3208 | ||
|
3209 | If this engine can be used to compress revlogs, this method should | |
|
3210 | return the bytes used to identify chunks compressed with this engine. | |
|
3211 | Else, the method should return ``None`` to indicate it does not | |
|
3212 | participate in revlog compression. | |
|
3213 | """ | |
|
3214 | return None | |
|
3215 | ||
|
3189 | 3216 | def compressstream(self, it, opts=None): |
|
3190 | 3217 | """Compress an iterator of chunks. |
|
3191 | 3218 | |
@@ -3215,6 +3242,13 b' class compressionengine(object):' | |||
|
3215 | 3242 | the data could not be compressed (too small, not compressible, etc). |
|
3216 | 3243 | The returned data should have a header uniquely identifying this |
|
3217 | 3244 | compression format so decompression can be routed to this engine. |
|
3245 | This header should be identified by the ``revlogheader()`` return | |
|
3246 | value. | |
|
3247 | ||
|
3248 | The object has a ``decompress(data)`` method that decompresses | |
|
3249 | data. The method will only be called if ``data`` begins with | |
|
3250 | ``revlogheader()``. The method should return the raw, uncompressed | |
|
3251 | data or raise a ``RevlogError``. | |
|
3218 | 3252 | |
|
3219 | 3253 | The object is reusable but is not thread safe. |
|
3220 | 3254 | """ |
@@ -3230,6 +3264,9 b' class _zlibengine(compressionengine):' | |||
|
3230 | 3264 | def wireprotosupport(self): |
|
3231 | 3265 | return compewireprotosupport('zlib', 20, 20) |
|
3232 | 3266 | |
|
3267 | def revlogheader(self): | |
|
3268 | return 'x' | |
|
3269 | ||
|
3233 | 3270 | def compressstream(self, it, opts=None): |
|
3234 | 3271 | opts = opts or {} |
|
3235 | 3272 | |
@@ -3286,6 +3323,13 b' class _zlibengine(compressionengine):' | |||
|
3286 | 3323 | return ''.join(parts) |
|
3287 | 3324 | return None |
|
3288 | 3325 | |
|
3326 | def decompress(self, data): | |
|
3327 | try: | |
|
3328 | return zlib.decompress(data) | |
|
3329 | except zlib.error as e: | |
|
3330 | raise error.RevlogError(_('revlog decompress error: %s') % | |
|
3331 | str(e)) | |
|
3332 | ||
|
3289 | 3333 | def revlogcompressor(self, opts=None): |
|
3290 | 3334 | return self.zlibrevlogcompressor() |
|
3291 | 3335 | |
@@ -3357,6 +3401,9 b' class _noopengine(compressionengine):' | |||
|
3357 | 3401 | def wireprotosupport(self): |
|
3358 | 3402 | return compewireprotosupport('none', 0, 10) |
|
3359 | 3403 | |
|
3404 | # We don't implement revlogheader because it is handled specially | |
|
3405 | # in the revlog class. | |
|
3406 | ||
|
3360 | 3407 | def compressstream(self, it, opts=None): |
|
3361 | 3408 | return it |
|
3362 | 3409 | |
@@ -3397,6 +3444,9 b' class _zstdengine(compressionengine):' | |||
|
3397 | 3444 | def wireprotosupport(self): |
|
3398 | 3445 | return compewireprotosupport('zstd', 50, 50) |
|
3399 | 3446 | |
|
3447 | def revlogheader(self): | |
|
3448 | return '\x28' | |
|
3449 | ||
|
3400 | 3450 | def compressstream(self, it, opts=None): |
|
3401 | 3451 | opts = opts or {} |
|
3402 | 3452 | # zstd level 3 is almost always significantly faster than zlib |
@@ -3425,7 +3475,9 b' class _zstdengine(compressionengine):' | |||
|
3425 | 3475 | # pre-allocate a buffer to hold the result. |
|
3426 | 3476 | self._cctx = zstd.ZstdCompressor(level=level, |
|
3427 | 3477 | write_content_size=True) |
|
3478 | self._dctx = zstd.ZstdDecompressor() | |
|
3428 | 3479 | self._compinsize = zstd.COMPRESSION_RECOMMENDED_INPUT_SIZE |
|
3480 | self._decompinsize = zstd.DECOMPRESSION_RECOMMENDED_INPUT_SIZE | |
|
3429 | 3481 | |
|
3430 | 3482 | def compress(self, data): |
|
3431 | 3483 | insize = len(data) |
@@ -3456,6 +3508,28 b' class _zstdengine(compressionengine):' | |||
|
3456 | 3508 | return ''.join(chunks) |
|
3457 | 3509 | return None |
|
3458 | 3510 | |
|
3511 | def decompress(self, data): | |
|
3512 | insize = len(data) | |
|
3513 | ||
|
3514 | try: | |
|
3515 | # This was measured to be faster than other streaming | |
|
3516 | # decompressors. | |
|
3517 | dobj = self._dctx.decompressobj() | |
|
3518 | chunks = [] | |
|
3519 | pos = 0 | |
|
3520 | while pos < insize: | |
|
3521 | pos2 = pos + self._decompinsize | |
|
3522 | chunk = dobj.decompress(data[pos:pos2]) | |
|
3523 | if chunk: | |
|
3524 | chunks.append(chunk) | |
|
3525 | pos = pos2 | |
|
3526 | # Frame should be exhausted, so no finish() API. | |
|
3527 | ||
|
3528 | return ''.join(chunks) | |
|
3529 | except Exception as e: | |
|
3530 | raise error.RevlogError(_('revlog decompress error: %s') % | |
|
3531 | str(e)) | |
|
3532 | ||
|
3459 | 3533 | def revlogcompressor(self, opts=None): |
|
3460 | 3534 | opts = opts or {} |
|
3461 | 3535 | return self.zstdrevlogcompressor(self._module, |
General Comments 0
You need to be logged in to leave comments.
Login now