// This file is part of BOINC. // http://boinc.berkeley.edu // Copyright (C) 2008 University of California // // BOINC is free software; you can redistribute it and/or modify it // under the terms of the GNU Lesser General Public License // as published by the Free Software Foundation, // either version 3 of the License, or (at your option) any later version. // // BOINC is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with BOINC. If not, see . #include "cpp.h" #ifdef _WIN32 #include "boinc_win.h" #ifdef _MSC_VER #define strdup _strdup #endif #else #include "config.h" #include #endif #include "error_numbers.h" #include "file_names.h" #include "filesys.h" #include "parse.h" #include "util.h" #include "str_replace.h" #include "str_util.h" #include "client_msgs.h" #include "client_state.h" #include "project.h" #include "sandbox.h" // Scan project dir for file names of the form trickle_up_X_Y // where X is a result name and Y is a timestamp. // Convert them to XML (for sched request message) // int CLIENT_STATE::read_trickle_files(PROJECT* project, FILE* f) { char *p, *q, result_name[256], fname[256]; char* file_contents, path[MAXPATHLEN], newpath[MAXPATHLEN]; string fn; time_t t; int retval; DirScanner ds(project->project_dir()); // trickle-up filenames are of the form trickle_up_RESULTNAME_TIME[.sent] // const size_t prefix_len = strlen("trickle_up_"); while (ds.scan(fn)) { safe_strcpy(fname, fn.c_str()); if (strstr(fname, "trickle_up_") != fname) continue; q = fname + prefix_len; p = strrchr(fname, '_'); if (p <= q) continue; *p = 0; safe_strcpy(result_name, q); *p = '_'; t = atoi(p+1); snprintf(path, sizeof(path), "%s/%s", project->project_dir(), fname); retval = read_file_malloc(path, file_contents); if (retval) { if (log_flags.trickle_debug) { msg_printf(project, MSG_INFO, "[trickle] can't read trickle file %s", path ); } continue; } if (log_flags.trickle_debug) { msg_printf(project, MSG_INFO, "[trickle] read trickle file %s", path ); } fprintf(f, " \n" " %s\n" " \n" "%s\n" " \n", result_name, (int)t, file_contents ); send_replicated_trickles(project, file_contents, result_name, t); free(file_contents); // append .sent to filename, so we'll know which ones to delete later // if (!ends_with(fname, ".sent")) { snprintf(newpath, sizeof(newpath), "%s/%s.sent", project->project_dir(), fname); boinc_rename(path, newpath); } } return 0; } // Remove files when ack has been received. // Remove only those ending with ".sent" // (others arrived from application while RPC was happening) // int CLIENT_STATE::remove_trickle_files(PROJECT* project) { char path[MAXPATHLEN], fname[256]; string fn; DirScanner ds(project->project_dir()); while (ds.scan(fn)) { safe_strcpy(fname, fn.c_str()); if (!starts_with(fname, "trickle_up")) continue; if (!ends_with(fname, ".sent")) continue; snprintf(path, sizeof(path), "%s/%s", project->project_dir(), fname); delete_project_owned_file(path, true); } return 0; } // parse a trickle-down message in a scheduler reply. // Locate the corresponding active task, // write a file in the slot directory, // and notify the task // int CLIENT_STATE::handle_trickle_down(PROJECT* project, FILE* in) { char buf[256]; char result_name[256], path[MAXPATHLEN]; string body; int send_time=0; safe_strcpy(result_name, ""); while (fgets(buf, 256, in)) { if (match_tag(buf, "")) { RESULT* rp = lookup_result(project, result_name); if (!rp) return ERR_NULL; ACTIVE_TASK* atp = lookup_active_task_by_result(rp); if (!atp) return ERR_NULL; snprintf(path, sizeof(path), "%s/trickle_down_%d", atp->slot_dir, send_time); FILE* f = fopen(path, "w"); if (!f) return ERR_FOPEN; fputs(body.c_str(), f); fclose(f); atp->have_trickle_down = true; return 0; } else if (parse_str(buf, "", result_name, 256)) { continue; } else if (parse_int(buf, "