]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | /* | |
4 | * Ceph - scalable distributed file system | |
5 | * | |
6 | * Copyright (C) 2015 Haomai Wang <haomaiwang@gmail.com> | |
7 | * | |
8 | * This is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License version 2.1, as published by the Free Software | |
11 | * Foundation. See file COPYING. | |
12 | * | |
13 | */ | |
14 | ||
15 | #ifndef CEPH_SNAPPYCOMPRESSOR_H | |
16 | #define CEPH_SNAPPYCOMPRESSOR_H | |
17 | ||
18 | #include <snappy.h> | |
19 | #include <snappy-sinksource.h> | |
20 | #include "include/buffer.h" | |
21 | #include "compressor/Compressor.h" | |
22 | ||
23 | class CEPH_BUFFER_API BufferlistSource : public snappy::Source { | |
24 | bufferlist::iterator pb; | |
25 | size_t remaining; | |
26 | ||
27 | public: | |
28 | explicit BufferlistSource(bufferlist::iterator _pb, size_t _input_len) | |
29 | : pb(_pb), | |
30 | remaining(_input_len) { | |
31 | remaining = std::min(remaining, (size_t)pb.get_remaining()); | |
32 | } | |
33 | size_t Available() const override { | |
34 | return remaining; | |
35 | } | |
36 | const char *Peek(size_t *len) override { | |
37 | const char *data = NULL; | |
38 | *len = 0; | |
39 | size_t avail = Available(); | |
40 | if (avail) { | |
41 | auto ptmp = pb; | |
42 | *len = ptmp.get_ptr_and_advance(avail, &data); | |
43 | } | |
44 | return data; | |
45 | } | |
46 | void Skip(size_t n) override { | |
47 | assert(n <= remaining); | |
48 | pb.advance(n); | |
49 | remaining -= n; | |
50 | } | |
51 | ||
52 | bufferlist::iterator get_pos() const { | |
53 | return pb; | |
54 | } | |
55 | }; | |
56 | ||
57 | class SnappyCompressor : public Compressor { | |
58 | public: | |
59 | SnappyCompressor() : Compressor(COMP_ALG_SNAPPY, "snappy") {} | |
60 | ||
61 | int compress(const bufferlist &src, bufferlist &dst) override { | |
62 | BufferlistSource source(const_cast<bufferlist&>(src).begin(), src.length()); | |
63 | bufferptr ptr = buffer::create_page_aligned( | |
64 | snappy::MaxCompressedLength(src.length())); | |
65 | snappy::UncheckedByteArraySink sink(ptr.c_str()); | |
66 | snappy::Compress(&source, &sink); | |
67 | dst.append(ptr, 0, sink.CurrentDestination() - ptr.c_str()); | |
68 | return 0; | |
69 | } | |
70 | ||
71 | int decompress(const bufferlist &src, bufferlist &dst) override { | |
72 | bufferlist::iterator i = const_cast<bufferlist&>(src).begin(); | |
73 | return decompress(i, src.length(), dst); | |
74 | } | |
75 | ||
76 | int decompress(bufferlist::iterator &p, | |
77 | size_t compressed_len, | |
78 | bufferlist &dst) override { | |
79 | snappy::uint32 res_len = 0; | |
80 | BufferlistSource source_1(p, compressed_len); | |
81 | if (!snappy::GetUncompressedLength(&source_1, &res_len)) { | |
82 | return -1; | |
83 | } | |
84 | BufferlistSource source_2(p, compressed_len); | |
85 | bufferptr ptr(res_len); | |
86 | if (snappy::RawUncompress(&source_2, ptr.c_str())) { | |
87 | p = source_2.get_pos(); | |
88 | dst.append(ptr); | |
89 | return 0; | |
90 | } | |
91 | return -2; | |
92 | } | |
93 | }; | |
94 | ||
95 | #endif |