// Returns zero iff all the input files for a result are present // (both WU and app version) // Called from CLIENT_STATE::update_results (with verify=false) // to transition result from DOWNLOADING to DOWNLOADED. // Called from ACTIVE_TASK::start() (with verify=true) // when project has verify_files_on_app_start set. // // If fipp is nonzero, return a pointer to offending FILE_INFO on error // int CLIENT_STATE::input_files_available( RESULT* rp, bool verify_contents, FILE_INFO** fipp ) { WORKUNIT* wup = rp->wup; FILE_INFO* fip; unsigned int i; APP_VERSION* avp; FILE_REF fr; PROJECT* project = rp->project; int retval; avp = rp->avp; for (i=0; i<avp->app_files.size(); i++) { fr = avp->app_files[i]; fip = fr.file_info; if (fip->status != FILE_PRESENT) { if (fipp) *fipp = fip; return ERR_FILE_MISSING; } // don't verify app files if using anonymous platform // if (verify_contents && !project->anonymous_platform) { retval = fip->verify_file(true, true, false); if (retval) { if (fipp) *fipp = fip; return retval; } } } for (i=0; i<wup->input_files.size(); i++) { fip = wup->input_files[i].file_info; if (fip->status != FILE_PRESENT) { if (wup->input_files[i].optional) continue; if (fipp) *fipp = fip; return ERR_FILE_MISSING; } if (verify_contents) { retval = fip->verify_file(true, true, false); if (retval) { if (fipp) *fipp = fip; return retval; } } } return 0; }
// scan FILE_INFOs and create PERS_FILE_XFERs as needed. // NOTE: this doesn't start the file transfers // scan PERS_FILE_XFERs and delete finished ones. // bool CLIENT_STATE::create_and_delete_pers_file_xfers() { unsigned int i; FILE_INFO* fip; PERS_FILE_XFER *pfx; bool action = false; int retval; static double last_time; if (!clock_change && now - last_time < PERS_FILE_XFER_START_PERIOD) return false; last_time = now; // Look for FILE_INFOs for which we should start a transfer, // and make PERS_FILE_XFERs for them // for (i=0; i<file_infos.size(); i++) { fip = file_infos[i]; pfx = fip->pers_file_xfer; if (pfx) continue; if (fip->downloadable() && fip->status == FILE_NOT_PRESENT) { pfx = new PERS_FILE_XFER; pfx->init(fip, false); fip->pers_file_xfer = pfx; pers_file_xfers->insert(fip->pers_file_xfer); action = true; } else if (fip->uploadable() && fip->status == FILE_PRESENT && !fip->uploaded) { pfx = new PERS_FILE_XFER; pfx->init(fip, true); fip->pers_file_xfer = pfx; pers_file_xfers->insert(fip->pers_file_xfer); action = true; } } // Scan existing PERS_FILE_XFERs, looking for those that are done, // and deleting them // vector<PERS_FILE_XFER*>::iterator iter; iter = pers_file_xfers->pers_file_xfers.begin(); while (iter != pers_file_xfers->pers_file_xfers.end()) { pfx = *iter; // If the transfer finished, remove the PERS_FILE_XFER object // from the set and delete it // if (pfx->pers_xfer_done) { fip = pfx->fip; if (pfx->is_upload) { // file has been uploaded - delete if not sticky // if (!fip->sticky) { fip->delete_file(); } fip->uploaded = true; active_tasks.upload_notify_app(fip); } else if (fip->status >= 0) { // file transfer did not fail (non-negative status) // If this was a compressed download, rename .gzt to .gz // if (fip->download_gzipped) { char path[MAXPATHLEN], from_path[MAXPATHLEN], to_path[MAXPATHLEN]; get_pathname(fip, path, sizeof(path)); snprintf(from_path, sizeof(from_path), "%s.gzt", path); snprintf(to_path, sizeof(to_path), "%s.gz", path); boinc_rename(from_path, to_path); } // verify the file with RSA or MD5, and change permissions // retval = fip->verify_file(true, true, true); if (retval == ERR_IN_PROGRESS) { // do nothing } else if (retval) { msg_printf(fip->project, MSG_INTERNAL_ERROR, "Checksum or signature error for %s", fip->name ); fip->status = retval; } else { // Set the appropriate permissions depending on whether // it's an executable or normal file // retval = fip->set_permissions(); fip->status = FILE_PRESENT; } // if it's a user file, tell running apps to reread prefs // if (fip->is_user_file) { active_tasks.request_reread_prefs(fip->project); } // if it's a project file, make a link in project dir // if (fip->is_project_file) { PROJECT* p = fip->project; p->write_symlink_for_project_file(fip); p->update_project_files_downloaded_time(); } } iter = pers_file_xfers->pers_file_xfers.erase(iter); delete pfx; action = true; // `delete pfx' should have set pfx->fip->pfx to NULL assert (fip == NULL || fip->pers_file_xfer == NULL); } else { ++iter; } } return action; }