aboutsummaryrefslogtreecommitdiffstats
path: root/libtransport/src/hicn
diff options
context:
space:
mode:
authorOlivier Roques <oroques@cisco.com>2019-11-07 10:05:52 +0000
committerAlberto Compagno <acompagn+fdio@cisco.com>2019-11-14 08:59:00 +0100
commitf2b7325ae6114b6b5b9e4d32c0a7cdc07576f224 (patch)
tree0413a1475a3cba5bba7db872cf0a4a5defaf47d5 /libtransport/src/hicn
parent4f57ca72e8131e5cfb023b26417b924e774d5e73 (diff)
[HICN-392] Assign independent suffixes for manifests/contents
This patch introduces a new class, SuffixStrategy and two sub-classes, SuffixContent and SuffixManifest which allow to independently assign suffixes to contents and manifests respectively. The produce() function in socket_producer.cc has also been changed to use them. Given a strategy and an offset (and optionally the capacity of a manifest), these classes automatically compute the correct next suffixes for both type of data (manifest or content). This removes the burden of having to manage suffixes for instance when producing or when retrieving content, and could be expanded to add more strategy in the future. Currently the only existing strategy is "INCREMENTAL": manifests with capacity N have a suffix multiple of N+1: 0, N+1, 2(N+1) etc. Contents have a suffix incremented by 1 except when it conflicts with a manifest: 1, 2, ..., N, N+2, N+3, ..., 2N+1, 2N+3... Signed-off-by: Olivier Roques <olvrqs@gmail.com> Change-Id: Ia7692d7325240de7bea6e38b668077042e5f8758 Signed-off-by: Alberto Compagno <acompagn+fdio@cisco.com>
Diffstat (limited to 'libtransport/src/hicn')
-rw-r--r--libtransport/src/hicn/transport/core/manifest.h6
-rw-r--r--libtransport/src/hicn/transport/core/manifest_format.h6
-rw-r--r--libtransport/src/hicn/transport/core/manifest_format_fixed.cc6
-rw-r--r--libtransport/src/hicn/transport/core/manifest_format_fixed.h4
-rw-r--r--libtransport/src/hicn/transport/interfaces/socket_producer.cc70
-rw-r--r--libtransport/src/hicn/transport/interfaces/socket_producer.h9
-rw-r--r--libtransport/src/hicn/transport/utils/CMakeLists.txt4
-rw-r--r--libtransport/src/hicn/transport/utils/suffix_strategy.cc73
-rw-r--r--libtransport/src/hicn/transport/utils/suffix_strategy.h134
9 files changed, 270 insertions, 42 deletions
diff --git a/libtransport/src/hicn/transport/core/manifest.h b/libtransport/src/hicn/transport/core/manifest.h
index 9f7dc59..9650de9 100644
--- a/libtransport/src/hicn/transport/core/manifest.h
+++ b/libtransport/src/hicn/transport/core/manifest.h
@@ -85,6 +85,10 @@ class Manifest : public Base {
return Encoder::getManifestHeaderSize();
}
+ static std::size_t getManifestEntrySize() {
+ return Encoder::getManifestEntrySize();
+ }
+
Manifest &setManifestType(ManifestType type) {
manifest_type_ = type;
encoder_.setManifestType(manifest_type_);
@@ -142,4 +146,4 @@ class Manifest : public Base {
} // end namespace core
-} // end namespace transport \ No newline at end of file
+} // end namespace transport
diff --git a/libtransport/src/hicn/transport/core/manifest_format.h b/libtransport/src/hicn/transport/core/manifest_format.h
index 00782f1..451e3db 100644
--- a/libtransport/src/hicn/transport/core/manifest_format.h
+++ b/libtransport/src/hicn/transport/core/manifest_format.h
@@ -135,6 +135,10 @@ class ManifestEncoder {
static std::size_t getManifestHeaderSize() {
return Implementation::getManifestHeaderSizeImpl();
}
+
+ static std::size_t getManifestEntrySize() {
+ return Implementation::getManifestEntrySizeImpl();
+ }
};
template <typename Implementation>
@@ -193,4 +197,4 @@ class ManifestDecoder {
} // namespace core
-} // namespace transport \ No newline at end of file
+} // namespace transport
diff --git a/libtransport/src/hicn/transport/core/manifest_format_fixed.cc b/libtransport/src/hicn/transport/core/manifest_format_fixed.cc
index b97aa70..f5e31d7 100644
--- a/libtransport/src/hicn/transport/core/manifest_format_fixed.cc
+++ b/libtransport/src/hicn/transport/core/manifest_format_fixed.cc
@@ -140,6 +140,10 @@ std::size_t FixedManifestEncoder::getManifestHeaderSizeImpl() {
return sizeof(ManifestHeader);
}
+std::size_t FixedManifestEncoder::getManifestEntrySizeImpl() {
+ return sizeof(ManifestEntry);
+}
+
FixedManifestDecoder::FixedManifestDecoder(Packet &packet)
: packet_(packet),
manifest_header_(reinterpret_cast<ManifestHeader *>(
@@ -219,4 +223,4 @@ uint32_t FixedManifestDecoder::getFinalBlockNumberImpl() const {
} // end namespace core
-} // end namespace transport \ No newline at end of file
+} // end namespace transport
diff --git a/libtransport/src/hicn/transport/core/manifest_format_fixed.h b/libtransport/src/hicn/transport/core/manifest_format_fixed.h
index c9bc3f8..2c6e2bc 100644
--- a/libtransport/src/hicn/transport/core/manifest_format_fixed.h
+++ b/libtransport/src/hicn/transport/core/manifest_format_fixed.h
@@ -116,6 +116,8 @@ class FixedManifestEncoder : public ManifestEncoder<FixedManifestEncoder> {
static std::size_t getManifestHeaderSizeImpl();
+ static std::size_t getManifestEntrySizeImpl();
+
private:
void addSuffixHashBytes(uint32_t suffix, const uint8_t *hash,
std::size_t length);
@@ -166,4 +168,4 @@ class FixedManifestDecoder : public ManifestDecoder<FixedManifestDecoder> {
} // namespace core
-} // namespace transport \ No newline at end of file
+} // namespace transport
diff --git a/libtransport/src/hicn/transport/interfaces/socket_producer.cc b/libtransport/src/hicn/transport/interfaces/socket_producer.cc
index 8f8fc1a..5cf40cd 100644
--- a/libtransport/src/hicn/transport/interfaces/socket_producer.cc
+++ b/libtransport/src/hicn/transport/interfaces/socket_producer.cc
@@ -38,6 +38,8 @@ ProducerSocket::ProducerSocket(asio::io_service &io_service)
registration_status_(REGISTRATION_NOT_ATTEMPTED),
making_manifest_(false),
hash_algorithm_(HashAlgorithm::SHA_256),
+ suffix_manifest_(core::NextSegmentCalculationStrategy::INCREMENTAL, 0),
+ suffix_content_(core::NextSegmentCalculationStrategy::INCREMENTAL, 0),
on_interest_input_(VOID_HANDLER),
on_interest_dropped_input_buffer_(VOID_HANDLER),
on_interest_inserted_input_buffer_(VOID_HANDLER),
@@ -151,33 +153,32 @@ uint32_t ProducerSocket::produce(Name content_name,
return 0;
}
- // Copy the atomic variable to ensure always the same value during the a
- // production
+ // Copy the atomic variables to ensure they keep the same value
+ // during the production
std::size_t data_packet_size = data_packet_size_;
uint32_t content_object_expiry_time = content_object_expiry_time_;
- HashAlgorithm algo = hash_algorithm_;
+ HashAlgorithm hash_algo = hash_algorithm_;
bool making_manifest = making_manifest_;
+ utils::SuffixContent suffix_content = suffix_content_;
+ utils::SuffixManifest suffix_manifest = suffix_manifest_;
std::shared_ptr<utils::Identity> identity;
getSocketOption(GeneralTransportOptions::IDENTITY, identity);
auto buffer_size = buffer->length();
-
const std::size_t hash_size = 32;
-
int bytes_segmented = 0;
std::size_t header_size;
std::size_t manifest_header_size = 0;
std::size_t signature_length = 0;
std::uint32_t final_block_number = 0;
-
uint64_t free_space_for_content = 0;
core::Packet::Format format;
-
- uint32_t current_segment = start_offset;
std::shared_ptr<ContentObjectManifest> manifest;
bool is_last_manifest = false;
std::unique_ptr<utils::CryptoHash> zero_hash;
+ suffix_content.updateSuffix(start_offset);
+ suffix_content.setUsingManifest(making_manifest);
// TODO Manifest may still be used for indexing
if (making_manifest && !identity) {
@@ -210,35 +211,37 @@ uint32_t ProducerSocket::produce(Name content_name,
}
header_size = core::Packet::getHeaderSizeFromFormat(format, signature_length);
-
free_space_for_content = data_packet_size - header_size;
-
uint32_t number_of_segments =
uint32_t(std::ceil(double(buffer_size) / double(free_space_for_content)));
-
if (free_space_for_content * number_of_segments < buffer_size) {
number_of_segments++;
}
// TODO allocate space for all the headers
-
if (making_manifest) {
- auto segment_in_manifest = static_cast<float>(
+ uint32_t segment_in_manifest = static_cast<uint32_t>(
std::floor(double(data_packet_size - manifest_header_size -
ContentObjectManifest::getManifestHeaderSize()) /
- (4.0 + 32.0)) -
+ ContentObjectManifest::getManifestEntrySize()) -
1.0);
- auto number_of_manifests = static_cast<uint32_t>(
+ uint32_t number_of_manifests = static_cast<uint32_t>(
std::ceil(float(number_of_segments) / segment_in_manifest));
final_block_number = number_of_segments + number_of_manifests - 1;
+ suffix_manifest.updateSuffix(start_offset);
+ suffix_manifest.setNbSegments(segment_in_manifest);
+ suffix_content.updateSuffix(start_offset + 1);
+ suffix_content.setNbSegments(segment_in_manifest);
+
manifest.reset(ContentObjectManifest::createManifest(
- content_name.setSuffix(current_segment++),
+ content_name.setSuffix(suffix_manifest.getSuffix()),
core::ManifestVersion::VERSION_1, core::ManifestType::INLINE_MANIFEST,
- hash_algorithm_, is_last_manifest, content_name,
+ hash_algo, is_last_manifest, content_name,
core::NextSegmentCalculationStrategy::INCREMENTAL,
identity->getSignatureLength()));
manifest->setLifetime(content_object_expiry_time);
+ suffix_manifest++;
if (is_last) {
manifest->setFinalBlockNumber(final_block_number);
@@ -249,7 +252,7 @@ uint32_t ProducerSocket::produce(Name content_name,
uint8_t hash[hash_size];
std::memset(hash, 0, hash_size);
zero_hash = std::make_unique<utils::CryptoHash>(
- hash, hash_size, static_cast<utils::CryptoHashType>(algo));
+ hash, hash_size, static_cast<utils::CryptoHashType>(hash_algo));
}
for (unsigned int packaged_segments = 0;
@@ -258,42 +261,41 @@ uint32_t ProducerSocket::produce(Name content_name,
if (manifest->estimateManifestSize(2) >
data_packet_size - manifest_header_size) {
// Add next manifest
- manifest->addSuffixHash(current_segment, *zero_hash);
-
+ manifest->addSuffixHash(suffix_manifest.getSuffix(), *zero_hash);
// Send the current manifest
manifest->encode();
-
identity->getSigner().sign(*manifest);
-
passContentObjectToCallbacks(manifest);
// Create new manifest. The reference to the last manifest has been
// acquired in the passContentObjectToCallbacks function, so we can
// safely release this reference
manifest.reset(ContentObjectManifest::createManifest(
- content_name.setSuffix(current_segment),
+ content_name.setSuffix(suffix_manifest.getSuffix()),
core::ManifestVersion::VERSION_1,
- core::ManifestType::INLINE_MANIFEST, hash_algorithm_,
- is_last_manifest, content_name,
- core::NextSegmentCalculationStrategy::INCREMENTAL,
+ core::ManifestType::INLINE_MANIFEST, hash_algo, is_last_manifest,
+ content_name, core::NextSegmentCalculationStrategy::INCREMENTAL,
identity->getSignatureLength()));
manifest->setLifetime(content_object_expiry_time);
+
if (is_last) {
manifest->setFinalBlockNumber(final_block_number);
} else {
manifest->setFinalBlockNumber(std::numeric_limits<uint32_t>::max());
}
- current_segment++;
+
+ suffix_manifest++;
}
}
auto content_object = std::make_shared<ContentObject>(
- content_name.setSuffix(current_segment), format);
+ content_name.setSuffix(suffix_content.getSuffix()), format);
content_object->setLifetime(content_object_expiry_time);
auto b = buffer->cloneOne();
b->trimStart(free_space_for_content * packaged_segments);
b->trimEnd(b->length());
+
if (TRANSPORT_EXPECT_FALSE(packaged_segments == number_of_segments - 1)) {
b->append(buffer_size - bytes_segmented);
bytes_segmented += (int)(buffer_size - bytes_segmented);
@@ -313,14 +315,14 @@ uint32_t ProducerSocket::produce(Name content_name,
if (making_manifest) {
using namespace std::chrono_literals;
- utils::CryptoHash hash = content_object->computeDigest(hash_algorithm_);
- manifest->addSuffixHash(current_segment, hash);
+ utils::CryptoHash hash = content_object->computeDigest(hash_algo);
+ manifest->addSuffixHash(suffix_content.getSuffix(), hash);
} else if (identity) {
identity->getSigner().sign(*content_object);
}
- current_segment++;
passContentObjectToCallbacks(content_object);
+ suffix_content++;
}
if (making_manifest) {
@@ -329,7 +331,7 @@ uint32_t ProducerSocket::produce(Name content_name,
}
if (!is_last) {
- manifest->addSuffixHash(current_segment, *zero_hash);
+ manifest->addSuffixHash(suffix_content.getSuffix(), *zero_hash);
}
manifest->encode();
@@ -344,7 +346,7 @@ uint32_t ProducerSocket::produce(Name content_name,
});
}
- return current_segment - start_offset;
+ return suffix_content.getSuffix() - start_offset;
}
void ProducerSocket::asyncProduce(ContentObject &content_object) {
@@ -880,4 +882,4 @@ asio::io_service &ProducerSocket::getIoService() { return io_service_; }
} // namespace interface
-} // end namespace transport \ No newline at end of file
+} // end namespace transport
diff --git a/libtransport/src/hicn/transport/interfaces/socket_producer.h b/libtransport/src/hicn/transport/interfaces/socket_producer.h
index 709a258..952587b 100644
--- a/libtransport/src/hicn/transport/interfaces/socket_producer.h
+++ b/libtransport/src/hicn/transport/interfaces/socket_producer.h
@@ -18,6 +18,7 @@
#include <hicn/transport/interfaces/socket.h>
#include <hicn/transport/utils/content_store.h>
#include <hicn/transport/utils/event_thread.h>
+#include <hicn/transport/utils/suffix_strategy.h>
#include <atomic>
#include <cmath>
@@ -190,6 +191,8 @@ class ProducerSocket : public Socket<BasePortal>,
std::atomic<utils::CryptoSuite> crypto_suite_;
utils::SpinLock identity_lock_;
std::shared_ptr<utils::Identity> identity_;
+ utils::SuffixManifest suffix_manifest_;
+ utils::SuffixContent suffix_content_;
// callbacks
ProducerInterestCallback on_interest_input_;
@@ -220,8 +223,8 @@ class ProducerSocket : public Socket<BasePortal>,
/* Condition variable for the wait */
std::condition_variable cv;
bool done = false;
- io_service_.dispatch([&socket_option_key, &socket_option_value,
- &mtx, &cv, &result, &done, &func]() {
+ io_service_.dispatch([&socket_option_key, &socket_option_value, &mtx, &cv,
+ &result, &done, &func]() {
std::unique_lock<std::mutex> lck(mtx);
done = true;
result = func(socket_option_key, socket_option_value);
@@ -247,4 +250,4 @@ class ProducerSocket : public Socket<BasePortal>,
} // namespace interface
-} // namespace transport \ No newline at end of file
+} // namespace transport
diff --git a/libtransport/src/hicn/transport/utils/CMakeLists.txt b/libtransport/src/hicn/transport/utils/CMakeLists.txt
index 4ce1e53..cbbca86 100644
--- a/libtransport/src/hicn/transport/utils/CMakeLists.txt
+++ b/libtransport/src/hicn/transport/utils/CMakeLists.txt
@@ -19,6 +19,7 @@ list(APPEND SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/signer.cc
${CMAKE_CURRENT_SOURCE_DIR}/verifier.cc
${CMAKE_CURRENT_SOURCE_DIR}/identity.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/suffix_strategy.cc
${CMAKE_CURRENT_SOURCE_DIR}/log.cc
${CMAKE_CURRENT_SOURCE_DIR}/membuf.cc
${CMAKE_CURRENT_SOURCE_DIR}/content_store.cc
@@ -46,6 +47,7 @@ list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/crypto_hash.h
${CMAKE_CURRENT_SOURCE_DIR}/crypto_hash_type.h
${CMAKE_CURRENT_SOURCE_DIR}/identity.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/suffix_strategy.h
${CMAKE_CURRENT_SOURCE_DIR}/conversions.h
${CMAKE_CURRENT_SOURCE_DIR}/linux.h
${CMAKE_CURRENT_SOURCE_DIR}/log.h
@@ -78,4 +80,4 @@ if(NOT WIN32)
endif()
set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
-set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) \ No newline at end of file
+set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE)
diff --git a/libtransport/src/hicn/transport/utils/suffix_strategy.cc b/libtransport/src/hicn/transport/utils/suffix_strategy.cc
new file mode 100644
index 0000000..f3bcc45
--- /dev/null
+++ b/libtransport/src/hicn/transport/utils/suffix_strategy.cc
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <hicn/transport/utils/suffix_strategy.h>
+
+using transport::core::NextSegmentCalculationStrategy;
+
+namespace utils {
+std::uint32_t SuffixManifest::getNextSuffix() {
+ uint32_t next_suffix;
+
+ switch (suffix_stragegy_) {
+ case NextSegmentCalculationStrategy::INCREMENTAL:
+ if (!nb_segments_) {
+ throw errors::RuntimeException(
+ "The number of segments in a manifest must be set "
+ "before assigning incremental suffixes.");
+ }
+ /* The current manifest's suffix + the number of segments in a */
+ /* manifest give the suffix of the last segment in the manifest. */
+ /* The next manifest's suffix is therefore that number plus one. */
+ next_suffix = suffix_ + nb_segments_ + 1;
+ break;
+
+ default:
+ throw errors::RuntimeException("Unknown suffix strategy.");
+ }
+
+ return next_suffix;
+}
+
+std::uint32_t SuffixContent::getNextSuffix() {
+ uint32_t next_suffix;
+
+ switch (suffix_stragegy_) {
+ case NextSegmentCalculationStrategy::INCREMENTAL:
+ next_suffix = suffix_ + 1;
+ if (making_manifest_) {
+ if (!nb_segments_) {
+ throw errors::RuntimeException(
+ "The number of segments in a manifest must be set "
+ "before assigning incremental suffixes.");
+ }
+
+ content_counter_++;
+ /* If the counter have reached the manifest's capacity,
+ * it means that the next suffix will be a manifest, so we skip it. */
+ if (content_counter_ % nb_segments_ == 0) {
+ next_suffix++;
+ content_counter_ = 0;
+ }
+ }
+ break;
+
+ default:
+ throw errors::RuntimeException("Unknown suffix strategy.");
+ }
+
+ return next_suffix;
+}
+} // namespace utils
diff --git a/libtransport/src/hicn/transport/utils/suffix_strategy.h b/libtransport/src/hicn/transport/utils/suffix_strategy.h
new file mode 100644
index 0000000..99e5573
--- /dev/null
+++ b/libtransport/src/hicn/transport/utils/suffix_strategy.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <hicn/transport/core/manifest_format.h>
+
+namespace utils {
+class SuffixStrategy {
+ public:
+ SuffixStrategy(
+ transport::core::NextSegmentCalculationStrategy suffix_stragegy,
+ std::uint32_t start_offset)
+ : suffix_stragegy_(suffix_stragegy),
+ suffix_(start_offset),
+ nb_segments_(0) {}
+
+ transport::core::NextSegmentCalculationStrategy getSuffixStrategy() {
+ return suffix_stragegy_;
+ }
+
+ std::uint32_t getSuffix() { return suffix_; }
+
+ virtual std::uint32_t getNextSuffix() = 0;
+
+ void updateSuffix(std::uint32_t new_suffix) { suffix_ = new_suffix; }
+
+ std::size_t getNbSegments() { return nb_segments_; }
+
+ void setNbSegments(std::size_t nb_segments) { nb_segments_ = nb_segments; }
+
+ void reset(std::uint32_t reset_suffix) {
+ suffix_ = reset_suffix;
+ nb_segments_ = 0;
+ }
+
+ ~SuffixStrategy() {}
+
+ protected:
+ transport::core::NextSegmentCalculationStrategy suffix_stragegy_;
+ std::uint32_t suffix_;
+ std::size_t nb_segments_;
+};
+
+class SuffixManifest : public SuffixStrategy {
+ public:
+ SuffixManifest(
+ transport::core::NextSegmentCalculationStrategy suffix_stragegy,
+ std::uint32_t start_offset)
+ : SuffixStrategy(suffix_stragegy, start_offset) {}
+
+ std::uint32_t getNextSuffix();
+
+ SuffixManifest operator++() {
+ uint32_t next_suffix = getNextSuffix();
+ updateSuffix(next_suffix);
+ return SuffixManifest(suffix_stragegy_, next_suffix);
+ }
+
+ SuffixManifest operator++(int) {
+ SuffixManifest temp_suffix(suffix_stragegy_, suffix_);
+ uint32_t next_suffix = getNextSuffix();
+ updateSuffix(next_suffix);
+ return temp_suffix;
+ }
+
+ SuffixManifest operator+(uint32_t shift) {
+ for (uint32_t i = 0; i < shift; i++) {
+ updateSuffix(getNextSuffix());
+ }
+ return SuffixManifest(suffix_stragegy_, getSuffix());
+ }
+};
+
+class SuffixContent : public SuffixStrategy {
+ public:
+ SuffixContent(transport::core::NextSegmentCalculationStrategy suffix_stragegy,
+ std::uint32_t start_offset, bool making_manifest)
+ : SuffixStrategy(suffix_stragegy, start_offset),
+ making_manifest_(making_manifest),
+ content_counter_(0) {}
+
+ SuffixContent(transport::core::NextSegmentCalculationStrategy suffix_stragegy,
+ std::uint32_t start_offset)
+ : SuffixContent(suffix_stragegy, start_offset, false) {}
+
+ std::uint32_t getNextSuffix();
+
+ SuffixContent operator++() {
+ uint32_t next_suffix = getNextSuffix();
+ updateSuffix(next_suffix);
+ return SuffixContent(suffix_stragegy_, next_suffix, making_manifest_);
+ }
+
+ SuffixContent operator++(int) {
+ SuffixContent temp_suffix(suffix_stragegy_, suffix_, making_manifest_);
+ uint32_t next_suffix = getNextSuffix();
+ updateSuffix(next_suffix);
+ return temp_suffix;
+ }
+
+ SuffixContent operator+(uint32_t shift) {
+ for (uint32_t i = 0; i < shift; i++) {
+ updateSuffix(getNextSuffix());
+ }
+ return SuffixContent(suffix_stragegy_, getSuffix(), making_manifest_);
+ }
+
+ void setUsingManifest(bool value) { making_manifest_ = value; }
+
+ void reset(std::uint32_t reset_suffix) {
+ SuffixStrategy::reset(reset_suffix);
+ content_counter_ = 0;
+ }
+
+ protected:
+ bool making_manifest_;
+ /* content_counter_ keeps track of the number of segments */
+ /* between two manifests */
+ uint32_t content_counter_;
+};
+} // namespace utils