Merge branch 'master' of feistymeow.org:feisty_meow
[feisty_meow.git] / octopi / library / tentacles / file_transfer_tentacle.h
1 #ifndef FILE_TRANSFER_TENTACLE_CLASS
2 #define FILE_TRANSFER_TENTACLE_CLASS
3
4 /*****************************************************************************\
5 *                                                                             *
6 *  Name   : file_transfer_tentacle                                            *
7 *  Author : Chris Koeritz                                                     *
8 *                                                                             *
9 *******************************************************************************
10 * Copyright (c) 2005-$now By Author.  This program is free software; you can  *
11 * redistribute it and/or modify it under the terms of the GNU General Public  *
12 * License as published by the Free Software Foundation; either version 2 of   *
13 * the License or (at your option) any later version.  This is online at:      *
14 *     http://www.fsf.org/copyleft/gpl.html                                    *
15 * Please send any updates to: fred@gruntose.com                               *
16 \*****************************************************************************/
17
18 #include "file_transfer_infoton.h"
19
20 #include <basis/mutex.h>
21 #include <filesystem/directory_tree.h>
22 #include <filesystem/filename_list.h>
23 #include <octopus/tentacle_helper.h>
24 #include <timely/time_stamp.h>
25
26 namespace octopi {
27
28 class file_transfer_cleaner;
29 class file_transfer_status;
30
31 //! Manages the transferrence of directory trees from one place to another.
32 /*!
33   Note: this is a fairly heavy-weight header due to the inclusion of the
34   file transfer infoton header.  It is better to forward declare the
35   objects in both file transfer headers when using the types in other
36   headers.
37 */
38
39 class file_transfer_tentacle
40 : public tentacle_helper<file_transfer_infoton>
41 {
42 public:
43   enum transfer_modes {
44     ONLY_REPORT_DIFFS = 0x1,  //!< no actual file transfer, just reports.
45     COMPARE_SIZE_AND_TIME = 0x2,  //!< uses size and time to see differences.
46     COMPARE_CONTENT_SAMPLE = 0x4,  //!< samples parts of file for comparison.
47     COMPARE_ALL = 0x6  //!< compares all of the file size, file time, and contents.
48   };
49
50
51   file_transfer_tentacle(int maximum_transfer, transfer_modes mode_of_transfer);
52     //!< constructs a tentacle for either transfers or comparisons.
53     /*!< the "maximum_transfer" is the largest chunk of data we will try to
54     sling across the network at a time.  the "mode_of_transfer" selects how
55     to perform the operation.  if "ONLY_REPORT_DIFFS" is set, then there
56     will only be a report of differences and no files will be copied.  if
57     COMPARE_SIZE_AND_TIME is set, then the comparison will use the file's
58     size and its access time for determining if it has changed.  if the
59     COMPARE_CONTENT_SAMPLE flag is set, then the file will be sampled at some
60     key locations and that will decide differences.  the comparison modes
61     can be mixed together.  if there are no comparison modes, then the files
62     will always be copied. */
63
64   virtual ~file_transfer_tentacle();
65
66   DEFINE_CLASS_NAME("file_transfer_tentacle");
67
68   basis::astring text_form() const;
69     //!< returns a string representing the current state of transfers.
70
71   filesystem::directory_tree *lock_directory(const basis::astring &source_mapping);
72     //!< provides a view of the tentacle's current state.
73   void unlock_directory();
74     //!< unlock MUST be called when one is done looking at the tree.
75
76   // these methods are for the "server" side--the side that has files to offer.
77
78   basis::outcome add_correspondence(const basis::astring &source_mapping,
79           const basis::astring &source_root, int refresh_interval);
80     //!< adds a file transfer correspondence.
81     /*!< this is a "source_mapping" which is a short string that is made
82     available to the other side for transfer requests.  when they specify the
83     "source_mapping", it will be translated on this side to the "source_root",
84     which must be a valid filesystem path.  the "refresh_interval" dictates
85     how frequently, in milliseconds, the source will be scanned to update the
86     internal directory tree.  this is done the first time the "source_mapping"
87     is set up also.  if a previous identical "source_mapping" existed, then it
88     is removed and replaced with the information from the new invocation. */
89
90   basis::outcome remove_correspondence(const basis::astring &source_mapping);
91     //!< takes out the "source_mapping" which was previously added.
92     /*!< this keeps any transfers from occurring on that name, and will cause
93     aborted transfers if any were still ongoing. */
94
95   basis::outcome refresh_now(const basis::astring &source_mapping);
96     //!< refreshes the "source_mapping" right now, regardless of the interval.
97     /*!< the mapping must already have been created with add_correspondence().
98     */
99
100   bool add_path(const basis::astring &source_mapping, const basis::astring &new_path);
101     //!< inserts the "new_path" into a registered correspondence.
102     /*!< the "source_mapping" must already be registered. */
103
104   bool remove_path(const basis::astring &source_mapping, const basis::astring &old_path);
105     //!< deletes the "old_path" out of an existing correspondence.
106
107   // these methods are for the client side--the side that wants to get files.
108
109   basis::outcome register_file_transfer(const octopus_entity &ent,
110           const basis::astring &src_root, const basis::astring &dest_root,
111           const structures::string_array &include);
112     //!< records a transfer that is going to commence.
113     /*!< the side that wishes to download files must invoke this before
114     starting the transfer.  if the "include" list is not empty, then only
115     those files will be transferred.  they have to match the suffix of the
116     files that would have been transferred and wildcards are not currently
117     supported. */
118
119   basis::outcome cancel_file_transfer(const octopus_entity &ent,
120           const basis::astring &src_root, const basis::astring &dest_root);
121     //!< tosses a previously registered file transfer.
122     /*!< this will be done automatically after a time-out period, but it is
123     better to clean it up as soon as one is finished with the transfer. */
124
125   bool status(const octopus_entity &ent, const basis::astring &src,
126         const basis::astring &dest, double &total_size, int &total_files,
127         double &current_size, int &current_files, bool &done,
128         timely::time_stamp &last_active);
129     //!< locates the transfer specified and returns information about it.
130     /*!< the transfer is designated by the "ent", "src" and "dest" parameters
131     and returns the current progress.  files refers to how many files are
132     being transferred and size refers to their combined weight in bytes.  the
133     "done" flag is set if the transfer seems finished.  note that this will
134     not set any values until the first reply comes back from the server. */
135
136   bool get_differences(const octopus_entity &ent, const basis::astring &src,
137         const basis::astring &dest, filesystem::filename_list &diffs);
138     //!< accesses the list of difference for an ongoing transfer.
139     /*!< the progress is stored in "diffs". */
140
141   // required tentacle methods...
142
143   virtual basis::outcome reconstitute(const structures::string_array &classifier,
144           basis::byte_array &packed_form, infoton * &reformed);
145     //!< recreates a "reformed" infoton from its packed form.
146     /*!< this requires the "classifier" and packed infoton data in
147     "packed_form".  this will only succeed if the classifier's first name
148     is understood here. */
149
150   virtual basis::outcome consume(infoton &to_chow, const octopus_request_id &item_id,
151           basis::byte_array &transformed);
152     //!< processes the "to_chow" infoton as a file transfer request.
153
154   virtual void expunge(const octopus_entity &to_remove);
155     //!< throws out any transfers occurring for the entity "to_remove".
156
157   // internal use only.
158
159   void periodic_actions();  //!< drops timed out transfers.
160
161 private:
162   int _maximum_transfer;  //!< largest chunk to send at a time.
163   file_transfer_status *_transfers;  //!< our record of ongoing transfers.
164   file_transfer_status *_correspondences;  //!< the synonyms for mapping.
165   basis::mutex *_lock;  //!< protects our lists.
166   file_transfer_cleaner *_cleaner;  //!< cleans up dead transfers.
167   int _mode;  //!< how will the comparison be done?
168
169   // these process the request and response infotons that are passed to us.
170   basis::outcome handle_build_target_tree_request(file_transfer_infoton &req,
171           const octopus_request_id &item_id);
172   basis::outcome handle_build_target_tree_response(file_transfer_infoton &resp,
173           const octopus_request_id &item_id);
174   basis::outcome handle_tree_compare_request(file_transfer_infoton &req,
175           const octopus_request_id &item_id);
176   basis::outcome handle_tree_compare_response(file_transfer_infoton &resp,
177           const octopus_request_id &item_id);
178   basis::outcome handle_storage_request(file_transfer_infoton &req,
179           const octopus_request_id &item_id);
180   basis::outcome handle_storage_response(file_transfer_infoton &resp,
181           const octopus_request_id &item_id);
182   basis::outcome conclude_storage_request(file_transfer_infoton &req,
183           const octopus_request_id &item_id);
184   basis::outcome conclude_storage_response(file_transfer_infoton &resp,
185           const octopus_request_id &item_id);
186 };
187
188 } //namespace.
189
190 #endif
191