Exemple #1
0
// this host is declared dead; deal with the loss of data
//
int handle_host(DB_HOST& h) {
    DB_VDA_CHUNK_HOST ch;
    char buf[256];
    int retval;

    log_messages.printf(MSG_NORMAL, "processing dead host %d\n", h.id);

    sprintf(buf, "where host_id=%d", h.id);
    while (1) {
        retval = ch.enumerate(buf);
        if (retval == ERR_DB_NOT_FOUND) break;
        if (retval) return retval;
        log_messages.printf(MSG_NORMAL, "   updating file%d\n", ch.vda_file_id);
        DB_VDA_FILE vf;
        retval = vf.lookup_id(ch.vda_file_id);
        if (retval) {
            log_messages.printf(MSG_CRITICAL,
                "   file lookup failed%d\n", ch.vda_file_id
            );
            return retval;
        }
        retval = vf.update_field("need_update=1");
        if (retval) {
            log_messages.printf(MSG_CRITICAL,
                "   file update failed%d\n", ch.vda_file_id
            );
            return retval;
        }
    }
    return 0;
}
Exemple #2
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;
}
Exemple #3
0
int handle_remove(const char* name) {
    DB_VDA_FILE vf;
    char buf[1024];
    sprintf(buf, "where file_name='%s'", name);
    int retval = vf.lookup(buf);
    if (retval) return retval;

    // delete DB records
    //
    DB_VDA_CHUNK_HOST ch;
    sprintf(buf, "vda_file_id=%d", vf.id);
    ch.delete_from_db_multi(buf);
    vf.delete_from_db();

    // remove symlink from download hier
    //
    dir_hier_path(name, config.download_dir, config.uldl_dir_fanout, buf);
    unlink(buf);

    // remove encoded data and directories
    //
    retval = chdir(vf.dir);
    if (retval) perror("chdir");
    retval = system("/bin/rm -r [0-9]* Coding data.vda");
    if (retval) perror("system");
    return 0;
}
Exemple #4
0
// Process a present file; possibilities:
// - a download finished
// - this host hasn't communicated in a while, and we deleted the
//   VDA_CHUNK_HOST record
// So:
// - 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
//
static void process_present_file(FILE_INFO& fi, CHUNK_LIST& chunks) {
    char fname[256], chunk_name[256], buf[256];
    int hostid, retval;
    retval = parse_physical_filename(fi.name, hostid, chunk_name, fname);
    if (retval) {
        log_messages.printf(MSG_CRITICAL,
            "Can't parse VDA filename %s\n", fi.name
        );
        return;
    }

    DB_VDA_FILE vf;
    sprintf(buf, "where file_name='%s'", fname);
    retval = vf.lookup(buf);
    if (retval) {
        log_messages.printf(MSG_CRITICAL, "No VDA file %s\n", fname);
        return;
    }

    if (fi.nbytes != vf.chunk_size) {
        log_messages.printf(MSG_CRITICAL,
            "wrong chunk size: %.0f != %.0f\n",
            fi.nbytes, vf.chunk_size
        );
        return;
    }

    CHUNK_LIST::iterator cli = chunks.find(string(fi.name));
    if (cli == chunks.end()) {
        // don't have a record of this chunk on this host; make one
        //
        DB_VDA_CHUNK_HOST ch;
        ch.create_time = dtime();
        ch.vda_file_id = vf.id;
        ch.host_id = g_reply->host.id;
        strcpy(ch.physical_file_name, fi.name);
        ch.present_on_host = true;
        ch.transfer_in_progress = false;
        ch.transfer_wait = false;
        ch.transfer_request_time = 0;
        ch.transfer_send_time = 0;
        retval = ch.insert();
        if (retval) {
            log_messages.printf(MSG_CRITICAL, "ch.insert() failed\n");
            return;
        }
    } else {
        // update the existing record
        //
        DB_VDA_CHUNK_HOST* chp = &(cli->second);
        chp->transfer_in_progress = false;
        chp->transfer_wait = false;
        chp->present_on_host = true;
        chp->update();
    }
    mark_for_update(vf.id);
}
Exemple #5
0
// get the state of an already-initialized file:
// expand the encoding tree,
// enumerate the VDA_HOST_CHUNKs from the DB
// and put them in the appropriate lists
//
int VDA_FILE_AUX::get_state() {
    char buf[256];

    sprintf(buf, "%s/chunk_sizes.txt", dir);
    FILE* f = fopen(buf, "r");
    if (!f) return -1;
    for (int i=0; i<policy.coding_levels; i++) {
        int n = fscanf(f, "%lf\n", &(policy.chunk_sizes[i]));
        if (n != 1) {
            fclose(f);
            return -1;
        }
    }
    fclose(f);
    meta_chunk = new META_CHUNK(this, NULL, 0);
    int retval = meta_chunk->get_state(dir, policy, 0);
    if (retval) return retval;
    DB_VDA_CHUNK_HOST vch;
    sprintf(buf, "where vda_file_id=%d", id);
    while (1) {
        retval = vch.enumerate(buf);
        if (retval == ERR_DB_NOT_FOUND) break;
        if (retval) return retval;
        vector<int> chunk_numbers;
        retval = get_chunk_numbers(vch, chunk_numbers);
        if (retval) {
            log_messages.printf(MSG_CRITICAL,
                "get_chunk_numbers(): %d\n", retval
            );
            return retval;
        }
        if ((int)(chunk_numbers.size()) != policy.coding_levels) {
            log_messages.printf(MSG_CRITICAL,
                "wrong get_chunk_numbers: got %d, expected %d\n",
                (int)(chunk_numbers.size()), policy.coding_levels
            );
            return -1;
        }
        META_CHUNK* mc = meta_chunk;
        for (int i=0; i<policy.coding_levels; i++) {
            if (i == policy.coding_levels-1) {
                CHUNK* c = (CHUNK*)(mc->children[chunk_numbers[i]]);
                VDA_CHUNK_HOST* vchp = new VDA_CHUNK_HOST();
                *vchp = vch;
                c->hosts.insert(vchp);
            } else {
                mc = (META_CHUNK*)(mc->children[chunk_numbers[i]]);
            }
        }

    }
    return 0;
}
Exemple #6
0
// 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;
    ch.host_id = host_id;
    strcpy(ch.name, name);
    ch.size = parent->dfile->policy.chunk_size();
    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;
}
Exemple #7
0
// 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
//
void handle_vda() {
    int retval;
    unsigned int i;
    CHUNK_LIST chunks;
        // chunks that are supposed to be on this host

    // if client is outdated, mark as dead
    //
    if (outdated_client(g_reply->host)) {
        g_reply->host.cpu_efficiency = 1;
        return;
    }

    // otherwise mark it as alive
    //
    g_reply->host.cpu_efficiency = 0;

    // enumerate the vda_chunk_host records for this host from DB
    //
    DB_VDA_CHUNK_HOST ch;
    char buf[256];
    sprintf(buf, "where host_id=%d", g_reply->host.id);
    while (1) {
        retval = ch.enumerate(buf);
        if (retval == ERR_DB_NOT_FOUND) break;
        if (retval) {
            // if we didn't get a complete enumeration,
            // give up rather than continuing with partial info
            //
            log_messages.printf(MSG_NORMAL,
                "[vda]: ch.enumerate() failed %d\n", retval
            );
            return;
        }
        if (config.debug_vda) {
            log_messages.printf(MSG_NORMAL,
                "[vda] DB: has chunk %s, file %d\n",
                ch.physical_file_name, ch.vda_file_id
            );
        }
        chunks.insert(
            pair<string, DB_VDA_CHUNK_HOST>(string(ch.physical_file_name), ch)
        );
    }

    // process completed uploads
    // (completed downloads are handled below)
    //
    for (i=0; i<g_request->file_xfer_results.size(); i++) {
        RESULT& r = g_request->file_xfer_results[i];
        if (strstr(r.name, "upload_vda_")) {
            char* phys_file_name = r.name + strlen("upload_");
            if (config.debug_vda) {
                log_messages.printf(MSG_NORMAL,
                    "[vda] completed upload of %s\n", phys_file_name
                );
            }
            retval = process_completed_upload(phys_file_name, chunks);
            if (retval) {
                log_messages.printf(MSG_CRITICAL,
                    "[vda] process_completed_upload(): %d\n", retval
                );
                return;
            }
        }
    }

    // process files present on client
    //
    for (i=0; i<g_request->file_infos.size(); i++) {
        FILE_INFO& fi = g_request->file_infos[i];
        if (!starts_with(fi.name, "vda_")) {
            continue;
        }
        if (config.debug_vda) {
            log_messages.printf(MSG_NORMAL,
                "[vda] request: client has file %s, status %d\n",
                fi.name, fi.status
            );
        }
        if (fi.status != FILE_PRESENT) {
            continue;
        }
        process_chunk_present_on_client(fi, chunks);
    }

    process_chunks_missing_on_client(chunks);

    enforce_quota(chunks);

    issue_transfer_commands(chunks);
}
Exemple #8
0
// Process a file that's present on client.
// A VDA_CHUNK_HOST record may not be in the DB,
// e.g. because this host hasn't communicated in a while
// and we deleted the VDA_CHUNK_HOST record
// So:
// - 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
//
static void process_chunk_present_on_client(FILE_INFO& fi, CHUNK_LIST& chunks) {
    char fname[256], chunk_name[256], buf[1024];
    int hostid, retval;
    retval = parse_physical_filename(fi.name, hostid, chunk_name, fname);
    if (retval) {
        log_messages.printf(MSG_CRITICAL,
            "Can't parse VDA filename %s\n", fi.name
        );
        return;
    }

    DB_VDA_FILE vf;
    sprintf(buf, "where file_name='%s'", fname);
    retval = vf.lookup(buf);
    if (retval) {
        log_messages.printf(MSG_CRITICAL,
            "No VDA file for %s, deleting\n", fi.name
        );
        delete_file_xml(fi.name, buf);
        g_reply->file_transfer_requests.push_back(string(buf));
        return;
    }

    if (fi.nbytes != vf.chunk_size) {
        log_messages.printf(MSG_CRITICAL,
            "wrong chunk size for %s: %.0f != %.0f, deleting\n",
            fi.name, fi.nbytes, vf.chunk_size
        );
        delete_file_xml(fi.name, buf);
        g_reply->file_transfer_requests.push_back(string(buf));
        return;
    }

    CHUNK_LIST::iterator cli = chunks.find(string(fi.name));
    if (cli == chunks.end()) {
        // we don't have a record of this chunk on this host; make one
        //
        DB_VDA_CHUNK_HOST ch;
        ch.create_time = dtime();
        ch.vda_file_id = vf.id;
        ch.host_id = g_reply->host.id;
        strcpy(ch.physical_file_name, fi.name);
        ch.present_on_host = true;
        ch.transfer_in_progress = false;
        ch.transfer_wait = false;
        ch.transfer_request_time = 0;
        ch.transfer_send_time = 0;
        retval = ch.insert();
        if (retval) {
            log_messages.printf(MSG_CRITICAL, "ch.insert() failed\n");
            return;
        }
        mark_for_update(vf.id);
    } else {
        // we already have a DB record.
        // If needed, update it and mark file for update
        //
        DB_VDA_CHUNK_HOST* chp = &(cli->second);
        chp->found = true;

        // if file wasn't previously on host, update the main file
        //
        if (!chp->present_on_host) {
            mark_for_update(vf.id);

            chp->transfer_in_progress = false;
            chp->transfer_wait = false;
            chp->present_on_host = true;
            sprintf(buf,
                "host_id=%d and physical_file_name='%s'",
                chp->host_id, chp->physical_file_name
            );
            chp->update_fields_noid(
                "transfer_in_progress=0, transfer_wait=0, present_on_host=1",
                buf
            );
        }
    }
}
Exemple #9
0
// 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;

    return 467;

    // 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;
}
Exemple #10
0
// 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
//
void handle_vda() {
    int retval;
    unsigned int i;
    CHUNK_LIST chunks;
        // chunks that are supposed to be on this host

    // enumerate the vda_chunk_host records for this host from DB
    //
    DB_VDA_CHUNK_HOST ch;
    char buf[256];
    sprintf(buf, "where host_id=%d", g_reply->host.id);
    while (1) {
        retval = ch.enumerate(buf);
        if (retval == ERR_DB_NOT_FOUND) break;
        if (retval) {
            // if we didn't get a complete enumeration,
            // give up rather than continuing with partial info
            //
            log_messages.printf(MSG_NORMAL,
                "[vda]: ch.enumerate() failed %d\n", retval
            );
            return;
        }
        if (config.debug_vda) {
            log_messages.printf(MSG_NORMAL,
                "[vda] DB: has chunk %s\n", ch.name
            );
        }
        chunks.insert(pair<string, DB_VDA_CHUNK_HOST>(string(ch.name), ch));
    }

    // process completed uploads
    //
    for (i=0; i<g_request->file_xfer_results.size(); i++) {
        RESULT& r = g_request->file_xfer_results[i];
        if (!starts_with(r.name, "vda_upload_")) continue;
        char* chunk_name = r.name + strlen("vda_upload_");
        if (config.debug_vda) {
            log_messages.printf(MSG_NORMAL,
                "[vda] DB: completed upload %s\n", chunk_name
            );
        }
        retval = process_completed_upload(chunk_name, chunks);
        if (retval) {
            log_messages.printf(MSG_CRITICAL,
                "[vda] process_completed_upload(): %d\n", retval
            );
            return;
        }
    }

    // process files present on host
    //
    for (i=0; i<g_request->file_infos.size(); i++) {
        FILE_INFO& fi = g_request->file_infos[i];
        if (!starts_with(fi.name, "vda_")) {
            continue;
        }
        if (config.debug_vda) {
            log_messages.printf(MSG_NORMAL,
                "[vda] request: client has file %s\n", fi.name
            );
        }
        process_present_file(fi, chunks);
    }

    process_missing_chunks(chunks);

    enforce_quota(chunks);

    issue_transfer_commands(chunks);
}