Merge branch 'main' of feistymeow.org:feisty_meow
[feisty_meow.git] / octopi / library / tentacles / recursive_file_copy.cpp
index 657bc80cd24744678d5d81180f61740680ccf64f..b012ef0850d25823b2f8811b02ffff4b02286aa0 100644 (file)
 #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;
@@ -36,9 +38,13 @@ using namespace filesystem;
 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
@@ -46,6 +52,11 @@ namespace octopi {
 #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.
 
@@ -59,11 +70,6 @@ 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)
@@ -79,7 +85,9 @@ outcome recursive_file_copy::copy_hierarchy(int transfer_mode,
   }
 */
 
-  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;
   }
@@ -89,31 +97,72 @@ outcome recursive_file_copy::copy_hierarchy(int transfer_mode,
       (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,
+  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;
@@ -141,7 +190,9 @@ outcome recursive_file_copy::copy_hierarchy(int transfer_mode,
 
   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;
@@ -160,7 +211,7 @@ LOG(a_sprintf("ongoing chunk %d", ++iter));
     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;
@@ -172,14 +223,13 @@ LOG(a_sprintf("ongoing chunk %d", ++iter));
       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())