// uncomment for noisier debugging.
#undef LOG
-#ifdef DEBUG_HEAVY_FILE_OPS
- #include <stdio.h>
- #define LOG(to_print) printf("%s::%s: %s\n", static_class_name(), func, astring(to_print).s())
-#else
- #define LOG(s) {if(!!s){}}
-#endif
+#include <stdio.h>
+#define LOG(to_print) printf("%s::%s: %s\n", static_class_name(), func, astring(to_print).s())
+
+//////////////
+
+// the smallest we let the packing area's available space get before we stop filling it.
+const int MINIMUM_ARRAY_SIZE = 1024;
//////////////
double byte_start, const byte_array &chunk, bool truncate,
int copy_chunk_factor)
{
-#ifdef DEBUG_HEAVY_FILE_OPS
-// FUNCDEF("write_file_chunk");
-#endif
+ FUNCDEF("write_file_chunk");
if (byte_start < 0) return BAD_INPUT;
filename targ_name(target);
- if (!directory::recursive_create(targ_name.dirname().raw()))
+ astring targ_dir = targ_name.dirname().raw();
+#ifdef DEBUG_HEAVY_FILE_OPS
+ LOG(astring("creating target's directory: ") + targ_name.dirname().raw());
+#endif
+ if (!directory::recursive_create(targ_dir)) {
+ LOG(astring("failed to create directory: ") + targ_name.dirname().raw());
return TARGET_DIR_ERROR;
+ }
if (!targ_name.exists()) {
huge_file target_file(target, "w");
// open the file for updating (either read or write).
if (!target_file.good()) return TARGET_ACCESS_ERROR;
double curr_len = target_file.length();
+ target_file.touch();
if (curr_len < byte_start) {
byte_array new_chunk;
return OKAY;
}
-bool heavy_file_operations::advance(const filename_list &to_transfer,
+basis::outcome heavy_file_operations::advance(const filename_list &to_transfer,
file_transfer_header &last_action)
{
-#ifdef DEBUG_HEAVY_FILE_OPS
FUNCDEF("advance");
-#endif
int indy = to_transfer.locate(last_action._filename);
- if (negative(indy)) return false; // error.
- if (indy == to_transfer.elements() - 1) return false; // done.
+ if (negative(indy)) return BAD_INPUT; // error, file not found in list.
+ if (indy >= to_transfer.elements() - 1) return FINISHED; // done.
const file_info *currfile = to_transfer.get(indy + 1);
last_action._filename = currfile->raw();
last_action._time = currfile->_time;
last_action._byte_start = 0;
last_action._length = 0;
- return true;
+ return OKAY;
}
outcome heavy_file_operations::buffer_files(const astring &source_root,
outcome to_return = OKAY;
+ // this records if we're working on a new file.
+ bool fresh_file = false;
+
// start filling the array with bytes from the files.
while (storage.length() < maximum_bytes) {
double remaining_in_array = maximum_bytes - storage.length()
- last_action.packed_size();
- if (remaining_in_array < 128) {
+ if (remaining_in_array < MINIMUM_ARRAY_SIZE) {
// ensure that we at least have a reasonable amount of space left
// for storing into the array.
break;
last_action._time = currfile->_time;
last_action._byte_start = 0;
last_action._length = 0;
+ fresh_file = true;
}
const file_info *found = to_transfer.find(last_action._filename);
if (!found) {
// they have referenced a file that we don't have. that's bad news.
+ LOG(astring("unknown last file requested in transfer: ") + last_action._filename);
return BAD_INPUT;
}
huge_file current(full_file, "rb");
if (!current.good()) {
// we need to skip this file.
-LOG(astring("skipping bad file: ") + full_file);
- if (!advance(to_transfer, last_action)) break;
+ LOG(astring("skipping bad file: ") + full_file);
+ fresh_file = true;
+ to_return = advance(to_transfer, last_action);
+ if (to_return != OKAY) break;
continue;
}
+//LOG(astring("working on file: ") + current.name());
- if ((last_action._byte_start + last_action._length >= current.length())
- && current.length()) {
-//LOG(astring("finished handling file: ") + full_file);
+ // we don't try to check done if we just started this file.
+ if (!fresh_file && (last_action._byte_start + last_action._length >= current.length())) {
// this file is done now. go to the next one.
- if (!advance(to_transfer, last_action)) break;
+#ifdef DEBUG_HEAVY_FILE_OPS
+ LOG(astring("finished stuffing file: ") + full_file);
+#endif
+ fresh_file = true;
+ to_return = advance(to_transfer, last_action);
+ if (to_return != OKAY) break;
continue;
}
+ // now that we tested if the file was fresh in our 'finished' check above, we
+ // consider the file not to be fresh until told otherwise.
+ fresh_file = false;
// calculate the largest piece remaining of that file that will fit in the
// allotted space.
if (bytes_read != new_len) {
if (!bytes_read) {
// some kind of problem reading the file.
- if (!advance(to_transfer, last_action)) break;
+ fresh_file = true;
+ to_return = advance(to_transfer, last_action);
+ if (to_return != OKAY) break;
continue;
}
//why would this happen? just complain, i guess.
if (!current.length()) {
// ensure we don't get stuck redoing zero length files, which we allowed
// to go past their end above (since otherwise we'd never see them).
- if (!advance(to_transfer, last_action)) break;
+ fresh_file = true;
+ to_return = advance(to_transfer, last_action);
+ if (to_return != OKAY) break;
continue;
}