#include <filesystem/huge_file.h>
#include <loggers/program_wide_logger.h>
#include <octopus/entity_defs.h>
+#include <octopus/entity_data_bin.h>
#include <octopus/octopus.h>
#include <structures/static_memory_gremlin.h>
#include <textual/string_manipulation.h>
+#include <timely/time_control.h>
using namespace application;
using namespace basis;
using namespace loggers;
using namespace structures;
using namespace textual;
+using namespace timely;
namespace octopi {
+#define DEBUG_RECURSIVE_FILE_COPY
+ // uncomment for noisier debugging.
+
#define FAKE_HOSTNAME "internal_fake_host"
#undef LOG
#undef BASE_LOG
#define BASE_LOG(s) EMERGENCY_LOG(program_wide_logger::get(), s)
+#define RETURN_ERROR_RFC(msg, err) { \
+ LOG(msg); \
+ return err; \
+}
+
const int MAX_CHUNK_RFC_COPY_HIER = 1 * MEGABYTE;
// maximum size for each transfer chunk.
+const int EXPECTED_MAXIMUM_TRANSFER_TIME = 10 * HOUR_ms;
+ // how long do we allow the scanned file lists to stay relevant.
+ // we allow it a long time, since this is a copy and not an active
+ // synchronization.
+
recursive_file_copy::~recursive_file_copy() {}
const char *recursive_file_copy::outcome_name(const outcome &to_name)
{ return common::outcome_name(to_name); }
-#define RETURN_ERROR_RFC(msg, err) { \
- LOG(msg); \
- return err; \
-}
-
outcome recursive_file_copy::copy_hierarchy(int transfer_mode,
const astring &source_dir, const astring &target_dir,
const string_array &includes, const astring &source_start)
}
*/
- astring source_root = "snootums";
+ const astring transfer_name = "snootums";
+
+ astring source_root = transfer_name;
if (source_start.t()) {
source_root += filename::default_separator() + source_start;
}
(MAX_CHUNK_RFC_COPY_HIER, (file_transfer_tentacle::transfer_modes)transfer_mode);
ring_leader.add_tentacle(tran);
- outcome add_ret = tran->add_correspondence("snootums", source_dir,
- 10 * MINUTE_ms);
+ outcome add_ret = tran->add_correspondence(transfer_name, source_dir,
+ EXPECTED_MAXIMUM_TRANSFER_TIME);
if (add_ret != tentacle::OKAY)
RETURN_ERROR_RFC("failed to add the correspondence", NOT_FOUND);
+//hmmm: this kind of object creation should be packaged in helper functions.
file_transfer_infoton *initiate = new file_transfer_infoton;
initiate->_request = true;
- initiate->_command = file_transfer_infoton::TREE_COMPARISON;
+ initiate->_command = file_transfer_infoton::BUILD_TARGET_TREE;
initiate->_src_root = source_root;
initiate->_dest_root = target_dir;
- directory_tree target_area(target_dir);
-//hmmm: simple asset counting debugging in calculate would be nice too.
- target_area.calculate( !(transfer_mode & file_transfer_tentacle::COMPARE_CONTENT_SAMPLE) );
- initiate->package_tree_info(target_area, includes);
+
+ // make a directory snapshot with just directories, no files.
+ directory_tree target_area_just_dirs(source_dir, "*", true);
+ initiate->package_tree_info(target_area_just_dirs, includes);
octopus_entity ent = ring_leader.issue_identity();
octopus_request_id req_id(ent, 1);
outcome start_ret = ring_leader.evaluate(initiate, req_id);
if (start_ret != tentacle::OKAY)
- RETURN_ERROR_RFC("failed to start the comparison", NONE_READY);
+ RETURN_ERROR_RFC("failed to build target tree", NONE_READY);
file_transfer_infoton *reply_from_init
= (file_transfer_infoton *)ring_leader.acquire_specific_result(req_id);
- if (!reply_from_init)
- RETURN_ERROR_RFC("no response to tree compare start", NONE_READY);
+ if (!reply_from_init) {
+LOG("spewing list of what IS there...");
+LOG(ring_leader.responses().text_form());
+ RETURN_ERROR_RFC("no response to request to build target tree", NONE_READY);
+ }
+
+ if (reply_from_init->_success != OKAY) {
+ RETURN_ERROR_RFC("failed to get good result from building target tree", reply_from_init->_success);
+ }
+
+//now repeating a lot of above to get tree compare going.
+
+//hmmm: this kind of object creation should be packaged in helper functions.
+ file_transfer_infoton *comparison_req = new file_transfer_infoton;
+ comparison_req->_request = true;
+ comparison_req->_command = file_transfer_infoton::TREE_COMPARISON;
+ comparison_req->_src_root = source_root;
+ comparison_req->_dest_root = target_dir;
+ // make a directory snapshot with just directories, no files.
+ directory_tree target_area(target_dir);
+
+//hmmm: simple asset counting debugging in calculate would be nice too.
+ target_area.calculate( !(transfer_mode & file_transfer_tentacle::COMPARE_CONTENT_SAMPLE) );
+
+ comparison_req->package_tree_info(target_area, includes);
+
+ ent = ring_leader.issue_identity();
+ req_id = octopus_request_id(ent, 1);
+ start_ret = ring_leader.evaluate(comparison_req, req_id);
+ if (start_ret != tentacle::OKAY)
+ RETURN_ERROR_RFC("failed to build target tree", NONE_READY);
+
+ reply_from_init = (file_transfer_infoton *)ring_leader.acquire_specific_result(req_id);
+ if (!reply_from_init) {
+LOG("spewing list of what IS there...");
+LOG(ring_leader.responses().text_form());
+ RETURN_ERROR_RFC("no response to request to build target tree", NONE_READY);
+ }
+
+
+//resuming
+
filename_list diffs;
byte_array pack_copy = reply_from_init->_packed_data;
int iter = 0;
while (true) {
-//LOG(a_sprintf("ongoing chunk %d", ++iter));
+#ifdef DEBUG_RECURSIVE_FILE_COPY
+ LOG(a_sprintf("ongoing chunk %d", ++iter));
+#endif
// keep going until we find a broken reply.
file_transfer_infoton *ongoing = new file_transfer_infoton;
if (!reply)
RETURN_ERROR_RFC("failed to get ongoing transfer reply", NONE_READY);
- if (!reply->_packed_data.length()) {
+ if (reply->_command == file_transfer_infoton::CONCLUDE_TRANSFER_MARKER) {
BASE_LOG(astring("finished transfer from \"") + source_dir
+ "\" to \"" + target_dir + "\"");
break;
file_transfer_header head(empty);
if (!head.unpack(copy))
RETURN_ERROR_RFC("failed to unpack header", GARBAGE);
-//LOG(a_sprintf("size in array: %d", copy.length()));
if (copy.length() < head._length)
RETURN_ERROR_RFC("not enough length in array", GARBAGE);
-//hmmm: are we doing nothing here besides validating that we GOT something in the header?
- copy.zap(0, head._length - 1);
-//LOG(a_sprintf("size in array now: %d", copy.length()));
+ if (head._length > 0)
+ copy.zap(0, head._length - 1);
-//hmmm: if logging, then...
+//hmmm: this needs better formatting, and should not repeat the same file name even
+// if it's in multiple chunks.
BASE_LOG(head.readable_text_form());
}
if (copy.length())