recursive_file_copy.cpp

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

Generated on Fri Nov 28 04:29:32 2008 for HOOPLE Libraries by  doxygen 1.5.1