Refactoring hpfs, hpfs sync and hpfs serve code. (#231)

* Refactoring hpfs code to a class so it can support multiple mounts.
* Refactoring hpfs serve into a class to support mulitiple mount serving.
* Refactoring hpfs sync into class to support multiple instances.
* Code improvements in hpfs_sync.
* Taking a sync target list for hpfs syncing target set.
This commit is contained in:
Savinda Senevirathne
2021-02-02 13:17:21 +05:30
committed by GitHub
parent 08680ee8d4
commit d08d2630f6
21 changed files with 948 additions and 736 deletions

View File

@@ -6,13 +6,12 @@
#include "../ledger.hpp"
#include "../hplog.hpp"
#include "../util/util.hpp"
#include "../hpfs/hpfs.hpp"
#include "../util/h32.hpp"
#include "hpfs_sync.hpp"
#include "../sc.hpp"
#include "../unl.hpp"
namespace hpfs_sync
namespace hpfs
{
// Idle loop sleep time (milliseconds).
constexpr uint16_t IDLE_WAIT = 40;
@@ -28,25 +27,26 @@ namespace hpfs_sync
constexpr int FILE_PERMS = 0644;
// No. of milliseconds to wait before resubmitting a request.
uint16_t REQUEST_RESUBMIT_TIMEOUT;
sync_context ctx;
bool init_success = false;
int init()
/**
* This should be called to activate the hpfs sync.
*/
int hpfs_sync::init(std::string_view name, hpfs::hpfs_mount *fs_mount)
{
if (fs_mount == NULL)
return -1;
this->name = name;
this->fs_mount = fs_mount;
REQUEST_RESUBMIT_TIMEOUT = hpfs::get_request_resubmit_timeout();
ctx.target_state_hash = util::h32_empty;
ctx.target_patch_hash = util::h32_empty;
ctx.current_parent_target_hash = util::h32_empty;
// Patch file sync has the highest priority.
ctx.current_syncing_parent = hpfs::HPFS_PARENT_COMPONENTS::PATCH;
ctx.hpfs_sync_thread = std::thread(hpfs_syncer_loop);
ctx.hpfs_sync_thread = std::thread(&hpfs_sync::hpfs_syncer_loop, this);
init_success = true;
return 0;
}
void deinit()
/**
* Perform relavent cleaning.
*/
void hpfs_sync::deinit()
{
if (init_success)
{
@@ -57,41 +57,35 @@ namespace hpfs_sync
}
/**
* Sets a new target states for the syncing process.
* @param target_state_hash The target hpfs state which we should sync towards.
* @param target_patch_hash The target hpfs patch state which we should sync towards.
* Sets a list of sync targets. Sync finishes when all the targets are synced.
* Syncing happens sequentially.
* @param target_list List of sync targets to sync towards.
*/
void set_target(const util::h32 target_state_hash, const util::h32 target_patch_hash)
void hpfs_sync::set_target(const std::queue<sync_target> &target_list)
{
std::unique_lock lock(ctx.target_state_mutex);
// Do not do anything if we are already syncing towards the specified target states.
if (ctx.is_shutting_down || (ctx.is_syncing && ctx.target_state_hash == target_state_hash && ctx.target_patch_hash == target_patch_hash))
if (target_list.empty())
return;
ctx.target_state_hash = target_state_hash;
ctx.target_patch_hash = target_patch_hash;
if (hpfs::ctx.get_hash(hpfs::HPFS_PARENT_COMPONENTS::PATCH) != target_patch_hash)
{
ctx.current_syncing_parent = hpfs::HPFS_PARENT_COMPONENTS::PATCH;
ctx.current_parent_target_hash = ctx.target_patch_hash;
}
else
{
ctx.current_syncing_parent = hpfs::HPFS_PARENT_COMPONENTS::STATE;
ctx.current_parent_target_hash = ctx.target_state_hash;
}
// Do not do anything if we are already syncing towards the specified target states.
if (ctx.is_shutting_down || (ctx.is_syncing && ctx.original_target_list == target_list))
return;
ctx.original_target_list = target_list;
ctx.target_list = std::move(target_list);
std::unique_lock lock(ctx.current_target_mutex);
ctx.current_target = ctx.target_list.front(); // Make the first element of the list the first target to sync.
ctx.is_syncing = true;
}
/**
* Runs the hpfs sync worker loop.
*/
void hpfs_syncer_loop()
void hpfs_sync::hpfs_syncer_loop()
{
util::mask_signal();
LOG_INFO << "hpfs sync: Worker started.";
LOG_INFO << "hpfs " << name << " sync: Worker started.";
while (!ctx.is_shutting_down)
{
@@ -102,115 +96,81 @@ namespace hpfs_sync
if (!ctx.is_syncing)
continue;
if (hpfs::acquire_rw_session() != -1)
if (fs_mount->acquire_rw_session() != -1)
{
while (!ctx.is_shutting_down)
{
{
std::shared_lock lock(ctx.target_state_mutex);
if (ctx.current_syncing_parent == hpfs::HPFS_PARENT_COMPONENTS::PATCH)
LOG_INFO << "hpfs sync: Starting sync for target patch hash: " << ctx.target_patch_hash;
else
LOG_INFO << "hpfs sync: Starting sync for target state hash: " << ctx.target_state_hash;
std::shared_lock lock(ctx.current_target_mutex);
LOG_INFO << "hpfs " << name << " sync: Starting sync for target " << ctx.current_target.name << " hash: " << ctx.current_target.hash;
}
util::h32 new_state = util::h32_empty;
const int result = request_loop(ctx.current_parent_target_hash, new_state);
const int result = request_loop(ctx.current_target.hash, new_state);
ctx.pending_requests.clear();
ctx.candidate_hpfs_responses.clear();
ctx.submitted_requests.clear();
if (result == -1 || ctx.is_shutting_down)
if (result == -1 || result == 1 || ctx.is_shutting_down)
break;
{
std::shared_lock lock(ctx.target_state_mutex);
std::shared_lock lock(ctx.current_target_mutex);
if (new_state == ctx.current_parent_target_hash)
if (new_state == ctx.current_target.hash)
{
if (ctx.current_syncing_parent == hpfs::HPFS_PARENT_COMPONENTS::PATCH)
{
ctx.target_patch_hash = util::h32_empty;
LOG_INFO << "hpfs sync: Target patch state achieved: " << new_state;
LOG_INFO << "hpfs " << name << " sync: Target " << ctx.current_target.name << " hash achieved: " << new_state;
on_current_sync_state_acheived();
// Appling new patch file changes to hpcore runtime.
if (conf::apply_patch_config(hpfs::RW_SESSION_NAME) == -1)
{
LOG_ERROR << "Appling patch file changes after sync failed";
}
else
{
unl::update_unl_changes_from_patch();
// Update global hash tracker with the new patch file hash.
util::h32 updated_patch_hash;
hpfs::get_hash(updated_patch_hash, hpfs::RW_SESSION_NAME, hpfs::PATCH_FILE_PATH);
hpfs::ctx.set_hash(hpfs::HPFS_PARENT_COMPONENTS::PATCH, updated_patch_hash);
}
if (ctx.target_state_hash == hpfs::ctx.get_hash(hpfs::HPFS_PARENT_COMPONENTS::STATE))
break;
ctx.current_parent_target_hash = ctx.target_state_hash;
ctx.current_syncing_parent = hpfs::HPFS_PARENT_COMPONENTS::STATE;
continue;
}
else if (ctx.current_syncing_parent == hpfs::HPFS_PARENT_COMPONENTS::STATE)
{
ctx.target_state_hash = util::h32_empty;
LOG_INFO << "hpfs sync: Target state achieved: " << new_state;
// Start syncing to next target.
const int result = start_syncing_next_target();
if (result == 0)
break;
}
else if (result == 1)
continue;
}
else
{
LOG_INFO << "hpfs sync: Continuing sync for new target: " << ctx.current_parent_target_hash;
LOG_INFO << "hpfs " << name << " sync: Continuing sync for new target: " << ctx.current_target.hash;
continue;
}
}
}
LOG_INFO << "hpfs sync: All parents synced.";
hpfs::release_rw_session();
LOG_INFO << "hpfs " << name << " sync: All parents synced.";
fs_mount->release_rw_session();
}
else
{
LOG_ERROR << "hpfs sync: Failed to start hpfs rw session";
LOG_ERROR << "hpfs " << name << " sync: Failed to start hpfs rw session";
}
std::unique_lock lock(ctx.target_state_mutex);
ctx.current_parent_target_hash = util::h32_empty;
// Clear target list and original target list since the sync is complete.
ctx.target_list = {};
ctx.original_target_list = {};
ctx.is_syncing = false;
}
LOG_INFO << "hpfs sync: Worker stopped.";
LOG_INFO << "hpfs " << name << " sync: Worker stopped.";
}
int request_loop(const util::h32 current_target, util::h32 &updated_state)
/**
* Reqest loop.
* @return -1 on error. 0 when current sync state acheived or sync is stopped due to target change.
* Returns 1 on successfully finishing all the sync targets.
*/
int hpfs_sync::request_loop(const util::h32 current_target, util::h32 &updated_state)
{
std::string target_parent_vpath;
BACKLOG_ITEM_TYPE target_parent_backlog_item_type;
if (ctx.current_syncing_parent == hpfs::HPFS_PARENT_COMPONENTS::STATE)
{
target_parent_vpath = hpfs::STATE_DIR_PATH;
target_parent_backlog_item_type = BACKLOG_ITEM_TYPE::DIR;
}
else if (ctx.current_syncing_parent == hpfs::HPFS_PARENT_COMPONENTS::PATCH)
{
target_parent_vpath = hpfs::PATCH_FILE_PATH;
target_parent_backlog_item_type = BACKLOG_ITEM_TYPE::FILE;
}
std::string lcl = ledger::ctx.get_lcl();
// Send the initial root hpfs request of the current target.
submit_request(backlog_item{ctx.current_target.item_type, ctx.current_target.vpath, -1, current_target}, lcl);
// Indicates whether any responses were processed in the previous loop iteration.
bool prev_responses_processed = false;
// No. of repetitive resubmissions so far. (This is reset whenever we receive a hpfs response)
uint16_t resubmissions_count = 0;
// Send the initial root hpfs request.
submit_request(backlog_item{target_parent_backlog_item_type, target_parent_vpath, -1, current_target}, lcl);
while (!should_stop_request_loop(current_target))
{
// Wait a small delay if there were no responses processed during previous iteration.
@@ -220,13 +180,8 @@ namespace hpfs_sync
// Get current lcl.
std::string lcl = ledger::ctx.get_lcl();
{
std::scoped_lock lock(p2p::ctx.collected_msgs.hpfs_responses_mutex);
// Move collected hpfs responses over to local candidate responses list.
if (!p2p::ctx.collected_msgs.hpfs_responses.empty())
ctx.candidate_hpfs_responses.splice(ctx.candidate_hpfs_responses.end(), p2p::ctx.collected_msgs.hpfs_responses);
}
// Move the received hpfs responses to the local response list.
swap_collected_responses();
prev_responses_processed = !ctx.candidate_hpfs_responses.empty();
@@ -239,7 +194,7 @@ namespace hpfs_sync
if (should_stop_request_loop(current_target))
return 0;
LOG_DEBUG << "hpfs sync: Processing hpfs response from [" << response.first.substr(2, 10) << "]";
LOG_DEBUG << "hpfs " << name << " sync: Processing hpfs response from [" << response.first.substr(2, 10) << "]";
const msg::fbuf::p2pmsg::Content *content = msg::fbuf::p2pmsg::GetContent(response.second.data());
const msg::fbuf::p2pmsg::Hpfs_Response_Message *resp_msg = content->message_as_Hpfs_Response_Message();
@@ -252,7 +207,7 @@ namespace hpfs_sync
const auto pending_resp_itr = ctx.submitted_requests.find(key);
if (pending_resp_itr == ctx.submitted_requests.end())
{
LOG_DEBUG << "hpfs sync: Skipping hpfs response due to hash mismatch.";
LOG_DEBUG << "hpfs " << name << " sync: Skipping hpfs response due to hash mismatch.";
continue;
}
@@ -270,7 +225,7 @@ namespace hpfs_sync
// Validate received fs data against the hash.
if (!validate_fs_entry_hash(vpath, hash, peer_fs_entry_map))
{
LOG_INFO << "hpfs sync: Skipping hpfs response due to fs entry hash mismatch.";
LOG_INFO << "hpfs " << name << " sync: Skipping hpfs response due to fs entry hash mismatch.";
continue;
}
@@ -287,7 +242,7 @@ namespace hpfs_sync
// Validate received hashmap against the hash.
if (!validate_file_hashmap_hash(vpath, hash, peer_hashes, peer_hash_count))
{
LOG_INFO << "hpfs sync: Skipping hpfs response due to file hashmap hash mismatch.";
LOG_INFO << "hpfs " << name << " sync: Skipping hpfs response due to file hashmap hash mismatch.";
continue;
}
@@ -304,7 +259,7 @@ namespace hpfs_sync
// Validate received block data against the hash.
if (!validate_file_block_hash(hash, block_id, buf))
{
LOG_INFO << "hpfs sync: Skipping hpfs response due to file block hash mismatch.";
LOG_INFO << "hpfs " << name << " sync: Skipping hpfs response due to file block hash mismatch.";
continue;
}
@@ -316,16 +271,16 @@ namespace hpfs_sync
// After handling each response, check whether we have reached target hpfs state.
// get_hash returns 0 incase target parent is not existing in our side.
if (hpfs::get_hash(updated_state, hpfs::RW_SESSION_NAME, target_parent_vpath) == -1)
if (fs_mount->get_hash(updated_state, hpfs::RW_SESSION_NAME, ctx.current_target.vpath) == -1)
{
LOG_ERROR << "hpfs sync: exiting due to hash check error.";
LOG_ERROR << "hpfs " << name << " sync: exiting due to hash check error.";
return -1;
}
// Update the central hpfs state tracker.
hpfs::ctx.set_hash(ctx.current_syncing_parent, updated_state);
fs_mount->set_parent_hash(ctx.current_target.vpath, updated_state);
LOG_DEBUG << "hpfs sync: current:" << updated_state << " | target:" << current_target;
LOG_DEBUG << "hpfs " << name << " sync: current:" << updated_state << " | target:" << current_target;
if (updated_state == current_target)
return 0;
}
@@ -347,13 +302,18 @@ namespace hpfs_sync
{
if (++resubmissions_count > ABANDON_THRESHOLD)
{
LOG_INFO << "hpfs sync: Resubmission threshold exceeded. Abandoning sync.";
return -1;
LOG_INFO << "hpfs " << name << " sync: Resubmission threshold exceeded. Abandoning sync.";
std::shared_lock lock(ctx.current_target_mutex);
const int result = start_syncing_next_target();
if (result == 0)
return 1; // To stop syncing since we have sync all the targets.
return 0;
}
// Reset the counter and re-submit request.
request.waiting_time = 0;
LOG_DEBUG << "hpfs sync: Resubmitting request...";
LOG_DEBUG << "hpfs " << name << " sync: Resubmitting request...";
submit_request(request, lcl);
}
}
@@ -373,7 +333,6 @@ namespace hpfs_sync
}
}
}
return 0;
}
@@ -384,7 +343,7 @@ namespace hpfs_sync
* @param fs_entry_map Received fs entry map.
* @returns true if hash is valid, otherwise false.
*/
bool validate_fs_entry_hash(std::string_view vpath, std::string_view hash, const std::unordered_map<std::string, p2p::hpfs_fs_hash_entry> &fs_entry_map)
bool hpfs_sync::validate_fs_entry_hash(std::string_view vpath, std::string_view hash, const std::unordered_map<std::string, p2p::hpfs_fs_hash_entry> &fs_entry_map)
{
util::h32 content_hash;
@@ -410,7 +369,7 @@ namespace hpfs_sync
* @param hash_count Size of the hash list.
* @returns true if hash is valid, otherwise false.
*/
bool validate_file_hashmap_hash(std::string_view vpath, std::string_view hash, const util::h32 *hashes, const size_t hash_count)
bool hpfs_sync::validate_file_hashmap_hash(std::string_view vpath, std::string_view hash, const util::h32 *hashes, const size_t hash_count)
{
util::h32 content_hash = util::h32_empty;
@@ -435,7 +394,7 @@ namespace hpfs_sync
* @param buf Block buffer.
* @returns true if hash is valid, otherwise false.
*/
bool validate_file_block_hash(std::string_view hash, const uint32_t block_id, std::string_view buf)
bool hpfs_sync::validate_file_block_hash(std::string_view hash, const uint32_t block_id, std::string_view buf)
{
// Calculate block offset of this block.
const off_t block_offset = block_id * hpfs::BLOCK_SIZE;
@@ -446,14 +405,14 @@ namespace hpfs_sync
/**
* Indicates whether to break out of hpfs request processing loop.
*/
bool should_stop_request_loop(const util::h32 current_target)
bool hpfs_sync::should_stop_request_loop(const util::h32 &current_target)
{
if (ctx.is_shutting_down)
return true;
// Stop request loop if the target has changed.
std::shared_lock lock(ctx.target_state_mutex);
return current_target != ctx.current_parent_target_hash;
std::shared_lock lock(ctx.current_target_mutex);
return current_target != ctx.current_target.hash;
}
/**
@@ -464,24 +423,25 @@ namespace hpfs_sync
* @param expected_hash The expected hash of the requested data. The peer will ignore the request if their hash is different.
* @param target_pubkey The peer pubkey the request was submitted to.
*/
void request_state_from_peer(const std::string &path, const bool is_file, const int32_t block_id,
const util::h32 expected_hash, std::string_view lcl, std::string &target_pubkey)
void hpfs_sync::request_state_from_peer(const std::string &path, const bool is_file, const int32_t block_id,
const util::h32 expected_hash, std::string_view lcl, std::string &target_pubkey)
{
p2p::hpfs_request hr;
hr.parent_path = path;
hr.is_file = is_file;
hr.block_id = block_id;
hr.expected_hash = expected_hash;
hr.mount_id = fs_mount->mount_id;
flatbuffers::FlatBufferBuilder fbuf(1024);
msg::fbuf::p2pmsg::create_msg_from_state_request(fbuf, hr, lcl);
msg::fbuf::p2pmsg::create_msg_from_hpfs_request(fbuf, hr, lcl);
p2p::send_message_to_random_peer(fbuf, target_pubkey); //todo: send to a node that hold the majority hpfs state to improve reliability of retrieving hpfs state.
}
/**
* Submits a pending hpfs request to the peer.
*/
void submit_request(const backlog_item &request, std::string_view lcl)
void hpfs_sync::submit_request(const backlog_item &request, std::string_view lcl)
{
const std::string key = std::string(request.path)
.append(reinterpret_cast<const char *>(&request.expected_hash), sizeof(util::h32));
@@ -492,7 +452,7 @@ namespace hpfs_sync
request_state_from_peer(request.path, is_file, request.block_id, request.expected_hash, lcl, target_pubkey);
if (!target_pubkey.empty())
LOG_DEBUG << "hpfs sync: Requesting from [" << target_pubkey.substr(2, 10) << "]. type:" << request.type
LOG_DEBUG << "hpfs " << name << " sync: Requesting from [" << target_pubkey.substr(2, 10) << "]. type:" << request.type
<< " path:" << request.path << " block_id:" << request.block_id
<< " hash:" << request.expected_hash;
}
@@ -503,19 +463,19 @@ namespace hpfs_sync
* @param fs_entry_map Received fs entry map.
* @returns 0 on success, otherwise -1.
*/
int handle_fs_entry_response(std::string_view vpath, std::unordered_map<std::string, p2p::hpfs_fs_hash_entry> &fs_entry_map)
int hpfs_sync::handle_fs_entry_response(std::string_view vpath, std::unordered_map<std::string, p2p::hpfs_fs_hash_entry> &fs_entry_map)
{
// Get the parent path of the fs entries we have received.
LOG_DEBUG << "hpfs sync: Processing fs entries response for " << vpath;
LOG_DEBUG << "hpfs " << name << " sync: Processing fs entries response for " << vpath;
// Create physical directory on our side if not exist.
std::string parent_physical_path = conf::ctx.hpfs_rw_dir + vpath.data();
std::string parent_physical_path = fs_mount->rw_dir + vpath.data();
if (util::create_dir_tree_recursive(parent_physical_path) == -1)
return -1;
// Get the children hash entries and compare with what we got from peer.
std::vector<hpfs::child_hash_node> existing_fs_entries;
if (hpfs::get_dir_children_hashes(existing_fs_entries, hpfs::RW_SESSION_NAME, vpath) == -1)
if (fs_mount->get_dir_children_hashes(existing_fs_entries, hpfs::RW_SESSION_NAME, vpath) == -1)
return -1;
// Request more info on fs entries that exist on both sides but are different.
@@ -544,13 +504,13 @@ namespace hpfs_sync
else
{
// If there was an entry that does not exist on other side, delete it.
std::string child_physical_path = conf::ctx.hpfs_rw_dir + child_vpath.data();
std::string child_physical_path = fs_mount->rw_dir + child_vpath.data();
if ((ex_entry.is_file && unlink(child_physical_path.c_str()) == -1) ||
!ex_entry.is_file && util::remove_directory_recursively(child_physical_path.c_str()) == -1)
return -1;
LOG_DEBUG << "hpfs sync: Deleted " << (ex_entry.is_file ? "file" : "dir") << " path " << child_vpath;
LOG_DEBUG << "hpfs " << name << " sync: Deleted " << (ex_entry.is_file ? "file" : "dir") << " path " << child_vpath;
}
}
@@ -580,14 +540,14 @@ namespace hpfs_sync
* @param file_length Size of the file.
* @returns 0 on success, otherwise -1.
*/
int handle_file_hashmap_response(std::string_view vpath, const util::h32 *hashes, const size_t hash_count, const uint64_t file_length)
int hpfs_sync::handle_file_hashmap_response(std::string_view vpath, const util::h32 *hashes, const size_t hash_count, const uint64_t file_length)
{
// Get the file path of the block hashes we have received.
LOG_DEBUG << "hpfs sync: Processing file block hashes response for " << vpath;
LOG_DEBUG << "hpfs " << name << " sync: Processing file block hashes response for " << vpath;
// File block hashes on our side (file might not exist on our side).
std::vector<util::h32> existing_hashes;
if (hpfs::get_file_block_hashes(existing_hashes, hpfs::RW_SESSION_NAME, vpath) == -1 && errno != ENOENT)
if (fs_mount->get_file_block_hashes(existing_hashes, hpfs::RW_SESSION_NAME, vpath) == -1 && errno != ENOENT)
return -1;
const size_t existing_hash_count = existing_hashes.size();
@@ -604,7 +564,7 @@ namespace hpfs_sync
if (existing_hashes.size() >= hash_count)
{
// If peer file might be smaller, truncate our file to match with peer file.
std::string file_physical_path = conf::ctx.hpfs_rw_dir + vpath.data();
std::string file_physical_path = fs_mount->rw_dir + vpath.data();
if (truncate(file_physical_path.c_str(), file_length) == -1)
return -1;
}
@@ -619,13 +579,13 @@ namespace hpfs_sync
* @param buf Block buffer.
* @returns 0 on success, otherwise -1.
*/
int handle_file_block_response(std::string_view vpath, const uint32_t block_id, std::string_view buf)
int hpfs_sync::handle_file_block_response(std::string_view vpath, const uint32_t block_id, std::string_view buf)
{
LOG_DEBUG << "hpfs sync: Writing block_id " << block_id
LOG_DEBUG << "hpfs " << name << " sync: Writing block_id " << block_id
<< " (len:" << buf.length()
<< ") of " << vpath;
std::string file_physical_path = conf::ctx.hpfs_rw_dir + vpath.data();
std::string file_physical_path = fs_mount->rw_dir + vpath.data();
const int fd = open(file_physical_path.c_str(), O_WRONLY | O_CREAT | O_CLOEXEC, FILE_PERMS);
if (fd == -1)
{
@@ -645,4 +605,61 @@ namespace hpfs_sync
return 0;
}
} // namespace hpfs_sync
/**
* This method can be used to invoke mount specific custom logic (after extending this super class) to be executed after
* a sync target is acheived.
*/
void hpfs_sync::on_current_sync_state_acheived()
{
if (ctx.current_target.vpath == hpfs::PATCH_FILE_PATH)
{
// Appling new patch file changes to hpcore runtime.
if (conf::apply_patch_config(hpfs::RW_SESSION_NAME) == -1)
{
LOG_ERROR << "Appling patch file changes after sync failed";
}
else
{
unl::update_unl_changes_from_patch();
// Update global hash tracker with the new patch file hash.
util::h32 updated_patch_hash;
fs_mount->get_hash(updated_patch_hash, hpfs::RW_SESSION_NAME, hpfs::PATCH_FILE_PATH);
fs_mount->set_parent_hash(ctx.current_target.vpath, updated_patch_hash);
}
}
}
/**
* Starts syncing next target if available after current target finishes.
* @return returns 0 when the full sync is complete and 1 when more sync targets are available.
*/
int hpfs_sync::start_syncing_next_target()
{
ctx.target_list.pop(); // Remove the synced parent from the target list.
if (ctx.target_list.empty())
{
ctx.current_target = {};
return 0;
}
else
{
ctx.current_target = ctx.target_list.front();
return 1;
}
}
/**
* Move the collected responses from hpfs responses to a local response list.
*/
void hpfs_sync::swap_collected_responses()
{
// This logic will be added to a child class in next PBI.
std::scoped_lock lock(p2p::ctx.collected_msgs.contract_hpfs_responses_mutex);
// Move collected hpfs responses over to local candidate responses list.
if (!p2p::ctx.collected_msgs.contract_hpfs_responses.empty())
ctx.candidate_hpfs_responses.splice(ctx.candidate_hpfs_responses.end(), p2p::ctx.collected_msgs.contract_hpfs_responses);
}
} // namespace hpfs