Exemple #1
0
int DeleteOp::executeOp() {
    DavixError* tmp_err=NULL;

    DAVIX_SLOG(DAVIX_LOG_DEBUG, DAVIX_LOG_CORE, "{} executing op on ", _scope, _destination_url);

    if(_opts.params.getProtocol() == RequestProtocol::AwsS3) {
        _destination_url += "/?delete";
        PostRequest req(_c, _destination_url, &tmp_err);

        if(tmp_err) {
            Tool::errorPrint(&tmp_err);
            return -1;
        }

        req.setParameters(_opts.params);

        std::ostringstream ss;
        ss << _buf.size();

        // calculate md5 of body and set header fields, these are required for S3 multi-objects delete
        std::string md5;
        S3::calculateMD5(_buf, md5);

        req.addHeaderField("Content-MD5", md5);
        req.addHeaderField("Content-Length", ss.str());

        req.setRequestBody(_buf);

        req.executeRequest(&tmp_err);

        if(tmp_err) {
            Tool::errorPrint(&tmp_err);
            return -1;
        }

        // check response code
        int code = req.getRequestCode();

        if(!httpcodeIsValid(code)) {
            httpcodeToDavixError(req.getRequestCode(), davix_scope_http_request(), "during S3 multi-objects delete operation", &tmp_err);
            if(tmp_err) {
                Tool::errorPrint(&tmp_err);
                return -1;
            }
        }

        std::vector<char> body = req.getAnswerContentVec();

        TRY_DAVIX{
            parse_deletion_result(code, Uri(_destination_url), _scope, body);
        } CATCH_DAVIX(&tmp_err);

        if(tmp_err) {
            Tool::errorPrint(&tmp_err);
            return -1;
        }
    }
Exemple #2
0
// do a multi-range on selected ranges
MultirangeResult HttpIOVecOps::performMultirange(IOChainContext & iocontext,
                                                 const IntervalTree<ElemChunk> &tree,
                                                 const SortedRanges & ranges) {

    DavixError * tmp_err=NULL;
    dav_ssize_t tmp_ret=-1, ret = 0;
    ptrdiff_t p_diff=0;
    dav_size_t counter = 0;
    MultirangeResult::OperationResult opresult = MultirangeResult::SUCCESS;

    // calculate total bytes to be read (approximate, since ranges could overlap)
    dav_ssize_t bytes_to_read = 0;
    for(dav_size_t i = 0; i < ranges.size(); i++) {
        bytes_to_read += (ranges[i].second - ranges[i].first + 1);
    }

    std::function<int (dav_off_t &, dav_off_t &)> offsetProvider = std::bind(&davIOVecProvider, ranges, std::ref(counter), std::placeholders::_1, std::placeholders::_2);

    // header line need to be inferior to 8K on Apache2 / ngnix
    // in Addition, some S3 implementation limit the total header size to 4k....
    // 3900 bytes maximum for the range seems to be a ood compromise
    std::vector< std::pair<dav_size_t, std::string> > vecRanges = generateRangeHeaders(3900, offsetProvider);

    DAVIX_SLOG(DAVIX_LOG_DEBUG, DAVIX_LOG_CHAIN, " -> getPartialVec operation for {} vectors", ranges.size());

    for(std::vector< std::pair<dav_size_t, std::string> >::iterator it = vecRanges.begin(); it < vecRanges.end(); ++it){
        DAVIX_SLOG(DAVIX_LOG_DEBUG, DAVIX_LOG_CHAIN, " -> getPartialVec request for {} chunks", it->first);

        if(it->first == 1){ // one chunk only : no need of multi part
            ret += singleRangeRequest(iocontext, tree, ranges[p_diff].first, ranges[p_diff].second - ranges[p_diff].first + 1);
            p_diff += 1;
        }else{
            GetRequest req (iocontext._context, iocontext._uri, &tmp_err);
            if(tmp_err == NULL){
                RequestParams request_params(iocontext._reqparams);
                req.setParameters(request_params);
                req.addHeaderField(req_header_byte_range, it->second);

                if( req.beginRequest(&tmp_err) == 0){
                    const int retcode = req.getRequestCode();

                    // looks like the server supports multi-range requests.. yay
                    if(retcode == 206) {
                        ret = parseMultipartRequest(req, tree, &tmp_err);

                        // could not parse multipart response - server's broken?
                        // known to happen with ceph - return code is 206, but only
                        // returns the first range
                        if(ret == -1) {
                            opresult = MultirangeResult::NOMULTIRANGE;
                            req.endRequest(&tmp_err);
                            break;
                        }
                    }
                    // no multi-range.. bad server, bad
                    else if(retcode == 200) {
                        DAVIX_SLOG(DAVIX_LOG_DEBUG, DAVIX_LOG_CHAIN, "Multi-range request resulted in getting the whole file.");
                        // we have two options: read the entire file or abort current
                        // request and start a multi-range simulation

                        // if this is a huge file, reading the entire contents is
                        // definitely not an option
                        if(req.getAnswerSize() > 1000000 && req.getAnswerSize() > 2*bytes_to_read) {
                            DAVIX_SLOG(DAVIX_LOG_DEBUG, DAVIX_LOG_CHAIN, "File is too large; will not waste bandwidth, bailing out");
                            opresult = MultirangeResult::NOMULTIRANGE;
                            req.endRequest(&tmp_err);
                        }
                        else {
                            DAVIX_SLOG(DAVIX_LOG_DEBUG, DAVIX_LOG_CHAIN, "Simulating multi-part response from the contents of the entire file");
                            opresult = MultirangeResult::SUCCESS_BUT_NO_MULTIRANGE;
                            ret = simulateMultiPartRequest(req, tree, &tmp_err);
                        }
                        break;
                    }
                    else if(retcode == 416) {
                      ret = 0;
                      DavixError::clearError(&tmp_err);
                    }
                    else {
                        httpcodeToDavixError(req.getRequestCode(),davix_scope_http_request(),", ", &tmp_err);
                        ret = -1;
                        break;
                    }

                    p_diff += it->first;
                    ret += tmp_ret;
                } else {
                   ret = -1;
                   break;
                }
            }
        }
    }

    DAVIX_SLOG(DAVIX_LOG_DEBUG, DAVIX_LOG_CHAIN, " <- getPartialVec operation for {} vectors", ranges.size());
    checkDavixError(&tmp_err);
    return MultirangeResult(opresult, ret);
}