- storage stuff

svn path=/trunk/boinc/; revision=25341
This commit is contained in:
David Anderson 2012-02-24 22:55:11 +00:00
parent d0413886fa
commit ce52c9cf3e
17 changed files with 431 additions and 281 deletions

View File

@ -2165,3 +2165,22 @@ David 24 Feb 2012
vda.cpp
vda_lib2.cpp
vda_lib.h
David 24 Feb 2012
- storage stuff
db/
boinc_db.h
schema_vda.sql
sched/
delete_file.cpp
put_file.cpp
get_file.cpp
tools/
backend_lib.cpp,h
vda/
vda.cpp
vda_policy.cpp,h (new)
vda_lib.cpp,h
Makefile.am
ssim.cpp

View File

@ -1160,6 +1160,10 @@ struct VDA_CHUNK_HOST {
bool found;
void clear();
inline bool download_in_progress() {
return (transfer_in_progress && !present_on_host);
}
};
struct DB_VDA_FILE : public DB_BASE, public VDA_FILE {

View File

@ -24,8 +24,8 @@ create table vda_chunk_host (
) engine = InnoDB;
alter table vda_chunk_host
add index vch_file (vda_file_id),
add index vch_host (host_id);
add index vch_file (vda_file_id),
add index vch_host (host_id);
alter table host
add index host_cpu_eff (cpu_efficiency);

View File

@ -109,7 +109,7 @@ int main(int argc, char** argv) {
exit(1);
}
retval = delete_host_file(host_id, file_name);
retval = create_delete_file_msg(host_id, file_name);
boinc_db.close();
return retval;
}

View File

@ -131,7 +131,7 @@ int main(int argc, char** argv) {
}
}
retval = get_file(
retval = create_get_file_msg(
host_id, file_name, urls, max_nbytes,
dtime() + max_latency,
generate_upload_certificate, key

View File

@ -129,7 +129,7 @@ int main(int argc, char** argv) {
}
}
retval = put_file(
retval = create_put_file_msg(
host_id, file_name, urls, md5, nbytes, dtime()+max_latency
);

View File

@ -334,23 +334,16 @@ int create_work(
// STUFF RELATED TO FILE UPLOAD/DOWNLOAD
int get_file(
int host_id, const char* file_name, vector<const char*> urls,
int get_file_xml(
const char* file_name, vector<const char*> urls,
double max_nbytes,
double report_deadline,
bool generate_upload_certificate,
R_RSA_PRIVATE_KEY& key
) {;
R_RSA_PRIVATE_KEY& key,
char* out
) {
char buf[8192];
DB_MSG_TO_HOST mth;
int retval;
mth.clear();
mth.create_time = time(0);
mth.hostid = host_id;
strcpy(mth.variety, "file_xfer");
mth.handled = false;
sprintf(mth.xml,
sprintf(out,
"<app>\n"
" <name>file_xfer</name>\n"
"</app>\n"
@ -366,7 +359,7 @@ int get_file(
);
for (unsigned int i=0; i<urls.size(); i++) {
sprintf(buf, " <url>%s</url>\n", urls[i]);
strcat(mth.xml, buf);
strcat(out, buf);
}
sprintf(buf,
"</file_info>\n"
@ -388,11 +381,33 @@ int get_file(
file_name,
report_deadline
);
strcat(mth.xml, buf);
strcat(out, buf);
if (generate_upload_certificate) {
add_signatures(mth.xml, key);
add_signatures(out, key);
}
return 0;
}
int create_get_file_msg(
int host_id, const char* file_name, vector<const char*> urls,
double max_nbytes,
double report_deadline,
bool generate_upload_certificate,
R_RSA_PRIVATE_KEY& key
) {
DB_MSG_TO_HOST mth;
int retval;
mth.clear();
mth.create_time = time(0);
mth.hostid = host_id;
strcpy(mth.variety, "file_xfer");
mth.handled = false;
get_file_xml(
file_name, urls, max_nbytes, report_deadline,
generate_upload_certificate, key,
mth.xml
);
retval = mth.insert();
if (retval) {
fprintf(stderr, "msg_to_host.insert(): %s\n", boincerror(retval));
@ -401,20 +416,14 @@ int get_file(
return 0;
}
int put_file(
int host_id, const char* file_name,
int put_file_xml(
const char* file_name,
vector<const char*> urls, const char* md5, double nbytes,
double report_deadline
double report_deadline,
char* out
) {
char buf[8192];
DB_MSG_TO_HOST mth;
int retval;
mth.clear();
mth.create_time = time(0);
mth.hostid = host_id;
strcpy(mth.variety, "file_xfer");
mth.handled = false;
sprintf(mth.xml,
sprintf(out,
"<app>\n"
" <name>file_xfer</name>\n"
"</app>\n"
@ -428,7 +437,7 @@ int put_file(
);
for (unsigned int i=0; i<urls.size(); i++) {
sprintf(buf, " <url>%s</url>\n", urls[i]);
strcat(mth.xml, buf);
strcat(out, buf);
}
sprintf(buf,
" <md5_cksum>%s</md5_cksum>\n"
@ -455,7 +464,23 @@ int put_file(
file_name,
report_deadline
);
strcat(mth.xml, buf);
strcat(out, buf);
return 0;
}
int create_put_file_msg(
int host_id, const char* file_name,
vector<const char*> urls, const char* md5, double nbytes,
double report_deadline
) {
DB_MSG_TO_HOST mth;
int retval;
mth.clear();
mth.create_time = time(0);
mth.hostid = host_id;
strcpy(mth.variety, "file_xfer");
mth.handled = false;
put_file_xml(file_name, urls, md5, nbytes, report_deadline, mth.xml);
retval = mth.insert();
if (retval) {
fprintf(stderr, "msg_to_host.insert(): %s\n", boincerror(retval));
@ -464,14 +489,19 @@ int put_file(
return 0;
}
int delete_host_file(int host_id, const char* file_name) {
int delete_file_xml(const char* file_name, char* out) {
sprintf(out, "<delete_file_info>%s</delete_file_info>\n", file_name);
return 0;
}
int create_delete_file_msg(int host_id, const char* file_name) {
DB_MSG_TO_HOST mth;
int retval;
mth.clear();
mth.create_time = time(0);
mth.hostid = host_id;
mth.handled = false;
sprintf(mth.xml, "<delete_file_info>%s</delete_file_info>\n", file_name);
delete_file_xml(file_name, mth.xml);
sprintf(mth.variety, "delete_file");
retval = mth.insert();
if (retval) {

View File

@ -73,16 +73,38 @@ extern int create_work(
extern int stage_file(const char*, bool);
// the following 3 functions are for programs other than the schedule
// to do file operations.
// They work by creating MSG_TO_HOST records in the DB
// the following functions return XML that can be put in
// scheduler replies to do file operations
//
extern int put_file(
extern int put_file_xml(
const char* file_name, vector<const char*> urls,
const char* md5, double nbytes, double report_deadline,
char* buf
);
extern int get_file_xml(
const char* file_name, vector<const char*> urls,
double max_nbytes,
double report_deadline,
bool generate_upload_certificate,
R_RSA_PRIVATE_KEY& key,
char* buf
);
extern int delete_file_xml(
const char* file_name,
char* buf
);
// the following 3 functions are for programs other than the scheduler
// to do file operations.
// They work by creating MSG_TO_HOST records in the DB,
// containing the needed XML
//
extern int create_put_file_msg(
int host_id, const char* file_name, vector<const char*> urls,
const char* md5, double nbytes, double report_deadline
);
extern int get_file(
extern int create_get_file_msg(
int host_id, const char* file_name, vector<const char*> urls,
double max_nbytes,
double report_deadline,
@ -90,7 +112,10 @@ extern int get_file(
R_RSA_PRIVATE_KEY& key
);
extern int delete_host_file(int host_id, const char* file_name);
extern int create_delete_file_msg(
int host_id,
const char* file_name
);
// cancel jobs from min_id to max_id inclusive
//

View File

@ -5,11 +5,11 @@ bin_PROGRAMS = vda vdad ssim
AM_CXXFLAGS += $(MYSQL_CFLAGS)
AM_LDFLAGS += -static
vda_SOURCES = vda.cpp vda_lib.cpp vda_lib2.cpp
vda_SOURCES = vda.cpp vda_policy.cpp
vda_LDADD = $(SERVERLIBS)
vdad_SOURCES = vdad.cpp vda_lib.cpp vda_lib2.cpp
vdad_SOURCES = vdad.cpp vda_lib.cpp vda_policy.cpp
vdad_LDADD = $(SERVERLIBS)
ssim_SOURCES = ssim.cpp vda_lib.cpp
ssim_SOURCES = ssim.cpp vda_lib.cpp vda_policy.cpp
ssim_LDADD = $(SERVERLIBS)

View File

@ -34,6 +34,14 @@ static int mark_for_update(int vda_file_id) {
return f.update_field("need_update=1");
}
// 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
//
// relevant fields of SCHEDULER_REQUEST
// file_infos: list of sticky files
// file_xfer_results: list of completed file xfers
@ -117,4 +125,18 @@ void handle_vda() {
it++;
}
}
// 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) {
// upload
} else {
// download
}
}
}

View File

@ -169,9 +169,6 @@ struct CHUNK_ON_HOST : VDA_CHUNK_HOST, EVENT {
virtual void handle();
void start_upload();
void start_download();
inline bool download_in_progress() {
return (transfer_in_progress && !present_on_host);
}
void remove();
};
@ -397,16 +394,7 @@ int CHUNK::assign() {
return 0;
}
bool CHUNK::download_in_progress() {
set<VDA_CHUNK_HOST*>::iterator i;
for (i=hosts.begin(); i!=hosts.end(); i++) {
CHUNK_ON_HOST* c = (CHUNK_ON_HOST*)*i;
if (c->download_in_progress()) return true;
}
return false;
}
void CHUNK::start_upload() {
int CHUNK::start_upload() {
// if no upload of this chunk is in progress, start one.
// NOTE: all instances are inherently present_on_host,
// since this is only called if chunk is not present on server
@ -414,10 +402,11 @@ void CHUNK::start_upload() {
set<VDA_CHUNK_HOST*>::iterator i;
for (i=hosts.begin(); i!=hosts.end(); i++) {
CHUNK_ON_HOST* c = (CHUNK_ON_HOST*)*i;
if (c->transfer_in_progress) return;
if (c->transfer_in_progress) return 0;
}
CHUNK_ON_HOST* c = (CHUNK_ON_HOST*)*(hosts.begin());
c->start_upload();
return 0;
}
void CHUNK::host_failed(VDA_CHUNK_HOST* p) {

View File

@ -19,52 +19,16 @@
#include <string.h>
#include <vector>
#include <set>
#include <algorithm>
#include <math.h>
#include <limits.h>
using std::vector;
using std::set;
#include "vda_lib.h"
int POLICY::parse(const char* filename) {
int n;
char buf[256];
strcpy(description, "");
FILE* f = fopen(filename, "r");
if (!f) {
fprintf(stderr, "No policy file %s\n", filename);
return -1;
}
n = fscanf(f, "%d", &replication);
if (n != 1) {
fprintf(stderr, "parse error in %s\n", filename);
return -1;
}
n = fscanf(f, "%d", &coding_levels);
if (n != 1) {
fprintf(stderr, "parse error in %s\n", filename);
return -1;
}
for (int i=0; i<coding_levels; i++) {
CODING& c = codings[i];
n = fscanf(f, "%d %d %d", &c.n, &c.k, &c.n_upload);
if (n != 3) {
fprintf(stderr, "parse error in %s\n", filename);
return -1;
}
c.m = c.n + c.k;
sprintf(buf, "(%d %d %d) ", c.n, c.k, c.n_upload);
strcat(description, buf);
}
sprintf(buf, "X%d", replication);
strcat(description, buf);
return 0;
}
char* time_str(double t) {
static char buf[256];
int n = (int)t;
@ -416,6 +380,15 @@ int META_CHUNK::recovery_action(double now) {
return 0;
}
bool CHUNK::download_in_progress() {
set<VDA_CHUNK_HOST*>::iterator i;
for (i=hosts.begin(); i!=hosts.end(); i++) {
VDA_CHUNK_HOST* ch = *i;
if (ch->download_in_progress()) return true;
}
return false;
}
int CHUNK::recovery_action(double now) {
int retval;
VDA_FILE_AUX* fp = parent->dfile;
@ -442,7 +415,8 @@ int CHUNK::recovery_action(double now) {
#endif
if (data_needed) {
if (!present_on_server) {
start_upload();
retval = start_upload();
if (retval) return retval;
}
} else {
if (present_on_server) {

View File

@ -25,34 +25,13 @@
#include "boinc_db.h"
#include "vda_policy.h"
// a host with rpc_time < now-HOST_TIMEOUT is considered dead.
// Make sure you set next_rpc_delay accordingly (e.g., to 86400)
//
#define VDA_HOST_TIMEOUT (86400*4)
// parameters of 1 level of coding
//
struct CODING {
int n;
int k;
int m; // n + k
int n_upload;
};
// description of overall coding
// (possibly w/ multiple coding levels and replication)
//
struct POLICY {
int replication;
int coding_levels;
CODING codings[10];
double chunk_sizes[10];
char description[256]; // derived from the above
int parse(const char*);
};
// keeps track of a time-varying property of a file
// (server disk usage, up/download rate, fault tolerance level)
//
@ -163,7 +142,7 @@ struct CHUNK : DATA_UNIT {
CHUNK(META_CHUNK* mc, double s, int index);
void start_upload();
int start_upload();
void host_failed(VDA_CHUNK_HOST* p);
bool download_in_progress();
void upload_complete();

View File

@ -1,159 +0,0 @@
// 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/>.
// code used in vda and vdad, but not in the simulator
#include "error_numbers.h"
#include "sched_msgs.h"
#include "util.h"
#include "vda_lib.h"
CHUNK::CHUNK(META_CHUNK* mc, double s, int index) {
parent = mc;
present_on_server = true;
size = s;
if (strlen(parent->name)) {
sprintf(name, "%s.%d", parent->name, index);
} else {
sprintf(name, "%d", index);
}
}
// assign this chunk to a host
//
int CHUNK::assign() {
int host_id = parent->dfile->choose_host();
if (!host_id) {
return ERR_NOT_FOUND;
}
DB_VDA_CHUNK_HOST ch;
ch.create_time = dtime();
ch.vda_file_id = parent->dfile->id;
strcpy(ch.name, name);
ch.host_id = host_id;
ch.present_on_host = 0;
ch.transfer_in_progress = true;
ch.transfer_wait = true;
ch.transfer_request_time = ch.create_time;
ch.transfer_send_time = 0;
int retval = ch.insert();
if (retval) {
log_messages.printf(MSG_CRITICAL, "ch.insert() failed\n");
return retval;
}
return 0;
}
bool CHUNK::download_in_progress() {
return false;
}
void CHUNK::start_upload() {
}
inline bool alive(DB_HOST& h) {
return (h.rpc_time > dtime()-VDA_HOST_TIMEOUT);
}
char* host_alive_clause() {
static char buf[256];
sprintf(buf, "rpc_time > %f", dtime() - VDA_HOST_TIMEOUT);
return buf;
}
// Pick a host to send a chunk of this file to.
// The host must:
// 1) be alive (recent RPC time)
// 2) not have any chunks of this file
//
// We maintain a cache of such hosts
// The policy is:
//
// - scan the cache, removing hosts that are no longer alive;
// return if find a live host
// - pick a random starting point in host ID space,
// and enumerate 100 live hosts; wrap around if needed.
// Return one and put the rest in cache
//
int VDA_FILE_AUX::choose_host() {
int retval;
DB_HOST host;
// replenish cache if needed
//
if (!available_hosts.size()) {
int nhosts_scanned = 0;
int rand_id;
for (int i=0; i<2; i++) {
char buf[256];
if (i == 0) {
retval = host.max_id(rand_id, "");
if (retval) {
log_messages.printf(MSG_CRITICAL, "host.max_id() failed\n");
return 0;
}
rand_id = (int)(((double)id)*drand());
sprintf(buf,
"where %s and id>=%d order by id limit 100",
host_alive_clause(), rand_id
);
} else {
sprintf(buf,
"where %s and id<%d order by id limit %d",
host_alive_clause(), rand_id, 100-nhosts_scanned
);
}
while (1) {
retval = host.enumerate(buf);
if (retval == ERR_DB_NOT_FOUND) break;
if (retval) {
log_messages.printf(MSG_CRITICAL, "host enum failed\n");
return 0;
}
nhosts_scanned++;
DB_VDA_CHUNK_HOST ch;
char buf2[256];
int count;
sprintf(buf2, "where vda_file_id=%d and host_id=%d", id, host.id);
retval = ch.count(count, buf2);
if (retval) {
log_messages.printf(MSG_CRITICAL, "ch.count failed\n");
return 0;
}
if (count == 0) {
available_hosts.push_back(host.id);
}
if (nhosts_scanned == 100) break;
}
if (nhosts_scanned == 100) break;
}
}
while (available_hosts.size()) {
int hostid = available_hosts.back();
available_hosts.pop_back();
retval = host.lookup_id(hostid);
if (retval || !alive(host)) {
continue;
}
return hostid;
}
log_messages.printf(MSG_CRITICAL, "No hosts available\n");
return 0;
}

59
vda/vda_policy.cpp Normal file
View File

@ -0,0 +1,59 @@
// 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/>.
#include <stdio.h>
#include <string.h>
#include "vda_policy.h"
int POLICY::parse(const char* filename) {
int n;
char buf[256];
strcpy(description, "");
FILE* f = fopen(filename, "r");
if (!f) {
fprintf(stderr, "No policy file %s\n", filename);
return -1;
}
n = fscanf(f, "%d", &replication);
if (n != 1) {
fprintf(stderr, "parse error in %s\n", filename);
return -1;
}
n = fscanf(f, "%d", &coding_levels);
if (n != 1) {
fprintf(stderr, "parse error in %s\n", filename);
return -1;
}
for (int i=0; i<coding_levels; i++) {
CODING& c = codings[i];
n = fscanf(f, "%d %d %d", &c.n, &c.k, &c.n_upload);
if (n != 3) {
fprintf(stderr, "parse error in %s\n", filename);
return -1;
}
c.m = c.n + c.k;
sprintf(buf, "(%d %d %d) ", c.n, c.k, c.n_upload);
strcat(description, buf);
}
sprintf(buf, "X%d", replication);
strcat(description, buf);
return 0;
}

45
vda/vda_policy.h Normal file
View File

@ -0,0 +1,45 @@
// 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/>.
#ifndef _VDA_POLICY_
#define _VDA_POLICY_
// parameters of 1 level of coding
//
struct CODING {
int n;
int k;
int m; // n + k
int n_upload;
};
// description of overall coding
// (possibly w/ multiple coding levels and replication)
//
struct POLICY {
int replication;
int coding_levels;
CODING codings[10];
double chunk_sizes[10];
char description[256]; // derived from the above
int parse(const char*);
};
#endif

View File

@ -26,8 +26,10 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <vector>
#include <set>
using std::vector;
using std::set;
#include "boinc_db.h"
#include "sched_config.h"
@ -117,6 +119,167 @@ int encode(const char* dir, CODING& c, double& size) {
return 0;
}
CHUNK::CHUNK(META_CHUNK* mc, double s, int index) {
parent = mc;
present_on_server = true;
size = s;
if (strlen(parent->name)) {
sprintf(name, "%s.%d", parent->name, index);
} else {
sprintf(name, "%d", index);
}
}
// assign this chunk to a host
//
int CHUNK::assign() {
int host_id = parent->dfile->choose_host();
if (!host_id) {
return ERR_NOT_FOUND;
}
DB_VDA_CHUNK_HOST ch;
ch.create_time = dtime();
ch.vda_file_id = parent->dfile->id;
strcpy(ch.name, name);
ch.host_id = host_id;
ch.present_on_host = 0;
ch.transfer_in_progress = true;
ch.transfer_wait = true;
ch.transfer_request_time = ch.create_time;
ch.transfer_send_time = 0;
int retval = ch.insert();
if (retval) {
log_messages.printf(MSG_CRITICAL, "ch.insert() failed\n");
return retval;
}
return 0;
}
int CHUNK::start_upload() {
// if no upload of this chunk is in progress, start one.
// NOTE: all instances are inherently present_on_host,
// since this is only called if chunk is not present on server
//
VDA_CHUNK_HOST* chp;
set<VDA_CHUNK_HOST*>::iterator i;
for (i=hosts.begin(); i!=hosts.end(); i++) {
chp = *i;
if (chp->transfer_in_progress) return 0;
}
chp = *(hosts.begin());
DB_VDA_CHUNK_HOST dch;
char set_clause[256], where_clause[256];
sprintf(set_clause,
"transfer_in_progress=1, transfer_wait=1, transfer_request_time=%f",
dtime()
);
sprintf(where_clause,
"where vda_file_id=%d and host_id=%d and name='%s'",
chp->vda_file_id,
chp->host_id,
name
);
int retval = dch.update_fields_noid(set_clause, where_clause);
return retval;
}
inline bool alive(DB_HOST& h) {
return (h.rpc_time > dtime()-VDA_HOST_TIMEOUT);
}
char* host_alive_clause() {
static char buf[256];
sprintf(buf, "rpc_time > %f", dtime() - VDA_HOST_TIMEOUT);
return buf;
}
// Pick a host to send a chunk of this file to.
// The host must:
// 1) be alive (recent RPC time)
// 2) not have any chunks of this file
//
// We maintain a cache of such hosts
// The policy is:
//
// - scan the cache, removing hosts that are no longer alive;
// return if find a live host
// - pick a random starting point in host ID space,
// and enumerate 100 live hosts; wrap around if needed.
// Return one and put the rest in cache
//
int VDA_FILE_AUX::choose_host() {
int retval;
DB_HOST host;
// replenish cache if needed
//
if (!available_hosts.size()) {
int nhosts_scanned = 0;
int rand_id;
for (int i=0; i<2; i++) {
char buf[256];
if (i == 0) {
retval = host.max_id(rand_id, "");
if (retval) {
log_messages.printf(MSG_CRITICAL, "host.max_id() failed\n");
return 0;
}
rand_id = (int)(((double)id)*drand());
sprintf(buf,
"where %s and id>=%d order by id limit 100",
host_alive_clause(), rand_id
);
} else {
sprintf(buf,
"where %s and id<%d order by id limit %d",
host_alive_clause(), rand_id, 100-nhosts_scanned
);
}
while (1) {
retval = host.enumerate(buf);
if (retval == ERR_DB_NOT_FOUND) break;
if (retval) {
log_messages.printf(MSG_CRITICAL, "host enum failed\n");
return 0;
}
nhosts_scanned++;
DB_VDA_CHUNK_HOST ch;
char buf2[256];
int count;
sprintf(buf2, "where vda_file_id=%d and host_id=%d", id, host.id);
#if 0
retval = ch.count(count, buf2);
if (retval) {
log_messages.printf(MSG_CRITICAL, "ch.count failed\n");
return 0;
}
#else
count = 0;
#endif
if (count == 0) {
available_hosts.push_back(host.id);
}
if (nhosts_scanned == 100) break;
}
if (nhosts_scanned == 100) break;
}
}
while (available_hosts.size()) {
int hostid = available_hosts.back();
available_hosts.pop_back();
retval = host.lookup_id(hostid);
if (retval || !alive(host)) {
continue;
}
return hostid;
}
log_messages.printf(MSG_CRITICAL, "No hosts available\n");
return 0;
}
META_CHUNK::META_CHUNK(VDA_FILE_AUX* d, META_CHUNK* p, int index) {
dfile = d;
parent = p;