recursive_file_copy.cpp

Go to the documentation of this file.
00001 /*****************************************************************************\
00002 *                                                                             *
00003 *  Name   : recursive_file_copy                                               *
00004 *  Author : Chris Koeritz                                                     *
00005 *                                                                             *
00006 *******************************************************************************
00007 * Copyright (c) 2005-$now By Author.  This program is free software; you can  *
00008 * redistribute it and/or modify it under the terms of the GNU General Public  *
00009 * License as published by the Free Software Foundation; either version 2 of   *
00010 * the License or (at your option) any later version.  This is online at:      *
00011 *     http://www.fsf.org/copyleft/gpl.html                                    *
00012 * Please send any updates to: fred@gruntose.com                               *
00013 \*****************************************************************************/
00014 
00015 #include "file_transfer_infoton.h"
00016 #include "file_transfer_tentacle.h"
00017 #include "recursive_file_copy.h"
00018 
00019 #include <application/application_shell.h>
00020 #include <basis/guards.h>
00021 #include <filesystem/directory.h>
00022 #include <filesystem/directory_tree.h>
00023 #include <filesystem/filename.h>
00024 #include <filesystem/filename_list.h>
00025 #include <filesystem/heavy_file_ops.h>
00026 #include <filesystem/huge_file.h>
00027 #include <loggers/program_wide_logger.h>
00028 #include <octopus/entity_defs.h>
00029 #include <octopus/octopus.h>
00030 #include <structures/static_memory_gremlin.h>
00031 #include <textual/string_manipulation.h>
00032 
00033 using namespace application;
00034 using namespace basis;
00035 using namespace filesystem;
00036 using namespace loggers;
00037 using namespace structures;
00038 using namespace textual;
00039 
00040 namespace octopi {
00041 
00042 #define FAKE_HOSTNAME "internal_fake_host"
00043 
00044 #undef LOG
00045 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s)
00046 #undef BASE_LOG
00047 #define BASE_LOG(s) EMERGENCY_LOG(program_wide_logger::get(), s)
00048 
00049 const int MAX_CHUNK_RFC_COPY_HIER = 1 * MEGABYTE;
00050   // maximum size for each transfer chunk.
00051 
00052 recursive_file_copy::~recursive_file_copy() {}
00053 
00054 const char *recursive_file_copy::outcome_name(const outcome &to_name)
00055 { return common::outcome_name(to_name); }
00056 
00057 #define RETURN_ERROR_RFC(msg, err) { \
00058   LOG(msg); \
00059   return err; \
00060 }
00061 
00062 outcome recursive_file_copy::copy_hierarchy(int transfer_mode,
00063   const astring &source_dir, const astring &target_dir,
00064   const string_array &includes, const astring &source_start)
00065 {
00066   FUNCDEF("copy_hierarchy");
00067 
00068 /*
00069   string_array includes;
00070   if (_global_argc >= 5) {
00071     for (int i = 4; i < _global_argc; i++) {
00072       includes += _global_argv[i];
00073     }
00074   }
00075 */
00076 
00077   astring source_root = "snootums";
00078   if (source_start.t()) {
00079     source_root += filename::default_separator() + source_start;
00080   }
00081 
00082   octopus ring_leader(FAKE_HOSTNAME, 10 * MEGABYTE);
00083   file_transfer_tentacle *tran = new file_transfer_tentacle
00084       (MAX_CHUNK_RFC_COPY_HIER, (file_transfer_tentacle::transfer_modes)transfer_mode);
00085   ring_leader.add_tentacle(tran);
00086 
00087   outcome add_ret = tran->add_correspondence("snootums", source_dir,
00088       10 * MINUTE_ms);
00089   if (add_ret != tentacle::OKAY)
00090     RETURN_ERROR_RFC("failed to add the correspondence", NOT_FOUND);
00091 
00092   file_transfer_infoton *initiate = new file_transfer_infoton;
00093   initiate->_request = true;
00094   initiate->_command = file_transfer_infoton::TREE_COMPARISON;
00095   initiate->_src_root = source_root;
00096   initiate->_dest_root = target_dir;
00097   directory_tree target_area(target_dir);
00098 //hmmm: simple asset counting debugging in calculate would be nice too.
00099   target_area.calculate( !(transfer_mode & file_transfer_tentacle::COMPARE_CONTENT_SAMPLE) );
00100   initiate->package_tree_info(target_area, includes);
00101 
00102   octopus_entity ent = ring_leader.issue_identity();
00103   octopus_request_id req_id(ent, 1);
00104   outcome start_ret = ring_leader.evaluate(initiate, req_id);
00105   if (start_ret != tentacle::OKAY)
00106     RETURN_ERROR_RFC("failed to start the comparison", NONE_READY);
00107 
00108   file_transfer_infoton *reply_from_init
00109       = (file_transfer_infoton *)ring_leader.acquire_specific_result(req_id);
00110   if (!reply_from_init)
00111     RETURN_ERROR_RFC("no response to tree compare start", NONE_READY);
00112 
00113   filename_list diffs;
00114   byte_array pack_copy = reply_from_init->_packed_data;
00115   if (!diffs.unpack(pack_copy)) {
00116     RETURN_ERROR_RFC("could not unpack filename list!", GARBAGE);
00117   }
00118 //  LOG(astring("got list of diffs:\n") + diffs.text_form());
00119 
00120   octopus client_spider(FAKE_HOSTNAME, 10 * MEGABYTE);
00121   file_transfer_tentacle *tran2 = new file_transfer_tentacle
00122       (MAX_CHUNK_RFC_COPY_HIER, (file_transfer_tentacle::transfer_modes)transfer_mode);
00123   tran2->register_file_transfer(ent, source_root, target_dir, includes);
00124   client_spider.add_tentacle(tran2);
00125 
00126   octopus_request_id resp_id(ent, 2);
00127   outcome ini_resp_ret = client_spider.evaluate(reply_from_init, resp_id);
00128   if (ini_resp_ret != tentacle::OKAY)
00129     RETURN_ERROR_RFC("failed to process the start response!", FAILURE);
00130 
00131   infoton *junk = client_spider.acquire_specific_result(resp_id);
00132   if (junk)
00133     RETURN_ERROR_RFC("got a response we shouldn't have!", FAILURE);
00134 
00135   astring current_file;  // what file is in progress right now?
00136 
00137   int iter = 0;
00138   while (true) {
00139 //LOG(a_sprintf("ongoing chunk %d", ++iter));
00140 
00141     // keep going until we find a broken reply.
00142     file_transfer_infoton *ongoing = new file_transfer_infoton;
00143     ongoing->_request = true;
00144     ongoing->_command = file_transfer_infoton::PLACE_FILE_CHUNKS;
00145     ongoing->_src_root = source_root;
00146     ongoing->_dest_root = target_dir;
00147 
00148     octopus_request_id chunk_id(ent, iter + 10);
00149     outcome place_ret = ring_leader.evaluate(ongoing, chunk_id);
00150     if (place_ret != tentacle::OKAY)
00151       RETURN_ERROR_RFC("failed to run ongoing transfer", FAILURE);
00152   
00153     file_transfer_infoton *reply = (file_transfer_infoton *)ring_leader
00154          .acquire_specific_result(chunk_id);
00155     if (!reply)
00156       RETURN_ERROR_RFC("failed to get ongoing transfer reply", NONE_READY);
00157 
00158     if (!reply->_packed_data.length()) {
00159       BASE_LOG(astring("finished transfer from \"") + source_dir
00160           + "\" to \"" + target_dir + "\"");
00161       break;
00162     }
00163 
00164     byte_array copy = reply->_packed_data;
00165     while (copy.length()) {
00166       file_time empty;
00167       file_transfer_header head(empty);
00168       if (!head.unpack(copy)) 
00169         RETURN_ERROR_RFC("failed to unpack header", GARBAGE);
00170 //LOG(a_sprintf("size in array: %d", copy.length()));
00171       if (copy.length() < head._length)
00172         RETURN_ERROR_RFC("not enough length in array", GARBAGE);
00173 //hmmm: are we doing nothing here besides validating that we GOT something in the header?
00174       copy.zap(0, head._length - 1);
00175 //LOG(a_sprintf("size in array now: %d", copy.length()));
00176 
00177 //hmmm: if logging, then...
00178       BASE_LOG(head.readable_text_form());
00179     }
00180     if (copy.length())
00181       RETURN_ERROR_RFC("still had data in array", GARBAGE);
00182 
00183     octopus_request_id resp_id(ent, iter + 11);
00184     outcome resp_ret = client_spider.evaluate(reply, resp_id);
00185     if (resp_ret != tentacle::OKAY)
00186       RETURN_ERROR_RFC("failed to process the transfer reply!", FAILURE);
00187   }
00188 
00189   return OKAY;
00190 }
00191 
00192 } //namespace.
00193 
00194 
Generated on Sat Jan 28 04:22:51 2012 for hoople2 project by  doxygen 1.6.3