2012-02-16 16:52:07 +00:00
|
|
|
// This file is part of BOINC.
|
|
|
|
// http://boinc.berkeley.edu
|
|
|
|
// Copyright (C) 2012 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 <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
// scheduler component for data archival.
|
|
|
|
// Called on each scheduler request.
|
|
|
|
|
|
|
|
#include <map>
|
|
|
|
#include <string>
|
|
|
|
|
2012-02-28 06:57:28 +00:00
|
|
|
#include "sched_config.h"
|
2012-02-16 23:59:26 +00:00
|
|
|
#include "sched_msgs.h"
|
2012-02-28 06:57:28 +00:00
|
|
|
#include "sched_types.h"
|
2012-02-16 16:52:07 +00:00
|
|
|
|
|
|
|
using std::map;
|
|
|
|
using std::string;
|
2012-02-16 23:59:26 +00:00
|
|
|
using std::pair;
|
2012-02-16 16:52:07 +00:00
|
|
|
|
2012-02-16 23:59:26 +00:00
|
|
|
static int mark_for_update(int vda_file_id) {
|
|
|
|
DB_VDA_FILE f;
|
|
|
|
f.id = vda_file_id;
|
|
|
|
return f.update_field("need_update=1");
|
|
|
|
}
|
|
|
|
|
2012-02-24 22:55:11 +00:00
|
|
|
// handle a scheduler request:
|
|
|
|
// - handle completed uploads
|
|
|
|
// - handle set of files present on client
|
|
|
|
// (update or create VDA_CHUNK_HOST record)
|
|
|
|
// - handle files expected but not present
|
|
|
|
// - issue delete commands if needed to enforce share
|
|
|
|
// - issue upload or download commands to client
|
|
|
|
//
|
2012-02-16 23:59:26 +00:00
|
|
|
// relevant fields of SCHEDULER_REQUEST
|
|
|
|
// file_infos: list of sticky files
|
|
|
|
// file_xfer_results: list of completed file xfers
|
|
|
|
//
|
2012-02-16 16:52:07 +00:00
|
|
|
void handle_vda() {
|
2012-02-16 23:59:26 +00:00
|
|
|
int retval;
|
|
|
|
unsigned int i;
|
2012-02-16 16:52:07 +00:00
|
|
|
map<string, DB_VDA_CHUNK_HOST> chunks;
|
|
|
|
// chunks that are supposed to be on this host
|
|
|
|
|
2012-02-16 23:59:26 +00:00
|
|
|
// get a list of the vda_chunk_host records for this host
|
|
|
|
//
|
2012-02-16 16:52:07 +00:00
|
|
|
DB_VDA_CHUNK_HOST ch;
|
|
|
|
char buf[256];
|
|
|
|
sprintf(buf, "host_id=%d", g_reply->host.id);
|
|
|
|
while (1) {
|
|
|
|
retval = ch.enumerate(buf);
|
|
|
|
if (retval == ERR_DB_NOT_FOUND) break;
|
|
|
|
if (retval) {
|
|
|
|
// give up if we didn't get a complete enumeration
|
|
|
|
//
|
|
|
|
log_messages.printf(MSG_NORMAL,
|
|
|
|
"[vda]: ch.enumerate() failed %d\n", retval
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
2012-02-28 06:57:28 +00:00
|
|
|
if (config.debug_vda) {
|
|
|
|
log_messages.printf(MSG_NORMAL,
|
|
|
|
"[vda] DB: has chunk %s\n", ch.name
|
|
|
|
);
|
|
|
|
}
|
2012-02-16 23:59:26 +00:00
|
|
|
chunks.insert(pair<string, DB_VDA_CHUNK_HOST>(string(ch.name), ch));
|
|
|
|
}
|
|
|
|
|
|
|
|
// process completed uploads:
|
|
|
|
// - verify md5 of upload
|
|
|
|
// - move it from upload dir to vda_file dir
|
|
|
|
// - mark vda_file for update
|
|
|
|
// - clear transfer_in_progress flag in vda_chunk_host
|
|
|
|
//
|
|
|
|
for (i=0; i<g_request->file_xfer_results.size(); i++) {
|
|
|
|
RESULT& r = g_request->file_xfer_results[i];
|
|
|
|
if (!starts_with(r.name, "upload_")) continue;
|
2012-02-28 06:57:28 +00:00
|
|
|
//char* file_name = r.name + strlen("upload_");
|
|
|
|
if (!strstr(r.name, "vdafile")) continue;
|
|
|
|
if (config.debug_vda) {
|
|
|
|
log_messages.printf(MSG_NORMAL,
|
|
|
|
"[vda] DB: completed upload %s\n", r.name
|
|
|
|
);
|
|
|
|
}
|
2012-02-16 23:59:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// process list of present files;
|
|
|
|
// - create a vda_chunk_host record if needed
|
|
|
|
// - set present_on_host flag in vda_chunk_host
|
|
|
|
// - mark our in-memory vda_chunk_host record as "found"
|
|
|
|
// - mark vda_file for update
|
|
|
|
//
|
|
|
|
for (i=0; i<g_request->file_infos.size(); i++) {
|
|
|
|
FILE_INFO& fi = g_request->file_infos[i];
|
2012-02-28 06:57:28 +00:00
|
|
|
if (config.debug_vda) {
|
|
|
|
log_messages.printf(MSG_NORMAL,
|
|
|
|
"[vda] request: client has file %s\n", fi.name
|
|
|
|
);
|
|
|
|
}
|
2012-02-16 23:59:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// for each vda_chunk_host not in file list:
|
|
|
|
// - delete from DB
|
|
|
|
// - mark vda_file for update
|
|
|
|
//
|
|
|
|
map<string, DB_VDA_CHUNK_HOST>::iterator it;
|
|
|
|
it = chunks.begin();
|
|
|
|
while (it != chunks.end()) {
|
|
|
|
DB_VDA_CHUNK_HOST& ch = (*it).second;
|
|
|
|
if (!ch.found) {
|
2012-02-28 06:57:28 +00:00
|
|
|
if (config.debug_vda) {
|
|
|
|
log_messages.printf(MSG_NORMAL,
|
|
|
|
"[vda] in DB but not on client: %s\n", ch.name
|
|
|
|
);
|
|
|
|
}
|
2012-02-16 23:59:26 +00:00
|
|
|
ch.delete_from_db();
|
|
|
|
chunks.erase(it);
|
|
|
|
mark_for_update(ch.vda_file_id);
|
|
|
|
} else {
|
|
|
|
it++;
|
|
|
|
}
|
2012-02-16 16:52:07 +00:00
|
|
|
}
|
|
|
|
|
2012-02-16 23:59:26 +00:00
|
|
|
// if process is using more than its share of disk space,
|
|
|
|
// remove some chunks and mark vda_files for update
|
|
|
|
//
|
|
|
|
if (g_request->host.d_project_share) {
|
|
|
|
double x = g_request->host.d_boinc_used_project;
|
2012-02-28 06:57:28 +00:00
|
|
|
if (config.debug_vda) {
|
|
|
|
log_messages.printf(MSG_NORMAL,
|
|
|
|
"[vda] share: %f used: %f\n",
|
|
|
|
g_request->host.d_project_share, x
|
|
|
|
);
|
|
|
|
}
|
2012-02-16 23:59:26 +00:00
|
|
|
it = chunks.begin();
|
|
|
|
while (x > g_request->host.d_project_share && it != chunks.end()) {
|
|
|
|
DB_VDA_CHUNK_HOST& ch = (*it).second;
|
|
|
|
FILE_INFO fi;
|
|
|
|
strcpy(fi.name, ch.name);
|
2012-02-28 06:57:28 +00:00
|
|
|
if (config.debug_vda) {
|
|
|
|
log_messages.printf(MSG_NORMAL,
|
|
|
|
"[vda] deleting: %s\n", ch.name
|
|
|
|
);
|
|
|
|
}
|
|
|
|
//x -= ch.size;
|
2012-02-16 23:59:26 +00:00
|
|
|
g_reply->file_deletes.push_back(fi);
|
|
|
|
it++;
|
|
|
|
}
|
|
|
|
}
|
2012-02-24 22:55:11 +00:00
|
|
|
|
|
|
|
// issue upload and download commands
|
|
|
|
//
|
|
|
|
it = chunks.begin();
|
|
|
|
while (it != chunks.end()) {
|
|
|
|
DB_VDA_CHUNK_HOST& ch = (*it).second;
|
|
|
|
if (!ch.transfer_in_progress) continue;
|
|
|
|
if (!ch.transfer_wait) continue;
|
|
|
|
if (ch.present_on_host) {
|
2012-02-28 06:57:28 +00:00
|
|
|
if (config.debug_vda) {
|
|
|
|
log_messages.printf(MSG_NORMAL,
|
|
|
|
"[vda] sending upload command: %s\n", ch.name
|
|
|
|
);
|
|
|
|
}
|
2012-02-24 22:55:11 +00:00
|
|
|
// upload
|
|
|
|
} else {
|
2012-02-28 06:57:28 +00:00
|
|
|
if (config.debug_vda) {
|
|
|
|
log_messages.printf(MSG_NORMAL,
|
|
|
|
"[vda] sending download command: %s\n", ch.name
|
|
|
|
);
|
|
|
|
}
|
2012-02-24 22:55:11 +00:00
|
|
|
// download
|
|
|
|
}
|
|
|
|
}
|
2012-02-16 16:52:07 +00:00
|
|
|
}
|