1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
|
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/reporting/compression/compression_module.h"
#include <optional>
#include <string>
#include <utility>
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/memory/ref_counted.h"
#include "base/task/thread_pool.h"
#include "components/reporting/proto/synced/record.pb.h"
#include "components/reporting/resources/resource_manager.h"
#include "third_party/snappy/src/snappy.h"
namespace reporting {
// static
scoped_refptr<CompressionModule> CompressionModule::Create(
uint64_t compression_threshold,
CompressionInformation::CompressionAlgorithm compression_type) {
return base::WrapRefCounted(
new CompressionModule(compression_threshold, compression_type));
}
void CompressionModule::CompressRecord(
std::string record,
scoped_refptr<ResourceManager> memory_resource,
base::OnceCallback<void(std::string, std::optional<CompressionInformation>)>
cb) const {
// Compress if record is larger than the compression threshold and compression
// enabled
switch (compression_type_) {
case CompressionInformation::COMPRESSION_NONE: {
// Don't compress, simply return serialized record
CompressionInformation compression_information;
compression_information.set_compression_algorithm(
CompressionInformation::COMPRESSION_NONE);
std::move(cb).Run(std::move(record), std::move(compression_information));
break;
}
case CompressionInformation::COMPRESSION_SNAPPY: {
if (record.length() < compression_threshold_) {
// Record size is smaller than threshold, don't compress.
CompressionInformation compression_information;
compression_information.set_compression_algorithm(
CompressionInformation::COMPRESSION_NONE);
std::move(cb).Run(std::move(record),
std::move(compression_information));
return;
}
// Before doing compression, we must make sure there is enough memory - we
// are going to temporarily double the record.
ScopedReservation scoped_reservation(record.size(), memory_resource);
if (!scoped_reservation.reserved()) {
CompressionInformation compression_information;
compression_information.set_compression_algorithm(
CompressionInformation::COMPRESSION_NONE);
std::move(cb).Run(std::move(record),
std::move(compression_information));
return;
}
// Perform compression.
CompressionModule::CompressRecordSnappy(std::move(record), std::move(cb));
break;
}
}
}
CompressionModule::CompressionModule(
uint64_t compression_threshold,
CompressionInformation::CompressionAlgorithm compression_type)
: compression_type_(compression_type),
compression_threshold_(compression_threshold) {}
CompressionModule::~CompressionModule() = default;
void CompressionModule::CompressRecordSnappy(
std::string record,
base::OnceCallback<void(std::string, std::optional<CompressionInformation>)>
cb) const {
// Compression is enabled and crosses the threshold.
std::string output;
snappy::Compress(record.data(), record.size(), &output);
if (output.size() >= record.size()) {
// Compression increases size, discard it.
CompressionInformation compression_information;
compression_information.set_compression_algorithm(
CompressionInformation::COMPRESSION_NONE);
std::move(cb).Run(std::move(record), std::move(compression_information));
return;
}
// Compression us shorter, accept it.
// Return compressed string.
CompressionInformation compression_information;
compression_information.set_compression_algorithm(
CompressionInformation::COMPRESSION_SNAPPY);
std::move(cb).Run(std::move(output), std::move(compression_information));
}
} // namespace reporting
|