blob: 97600780ffb588635174f80963d6304bf7ea90d4 [file] [log] [blame]
/*
* Copyright 2016 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "upload.h"
#include <string>
#include <thread>
#include <vector>
namespace speedtest {
Upload::Upload(const Options &options)
: options_(options),
start_time_(0),
end_time_(0),
bytes_transferred_(0) {
}
Upload::Result Upload::operator()(std::atomic_bool *cancel) {
start_time_ = SystemTimeMicros();
bytes_transferred_ = 0;
if (!cancel) {
end_time_ = SystemTimeMicros();
return GetResult(Status(StatusCode::FAILED_PRECONDITION, "cancel is null"));
}
std::vector<std::thread> threads;
for (int i = 0; i < options_.num_transfers; ++i) {
threads.emplace_back([=]{
http::Request::Ptr upload = options_.request_factory(i);
while (!*cancel) {
long uploaded = 0;
upload->set_param("i", to_string(i));
upload->set_param("time", to_string(SystemTimeMicros()));
upload->set_progress_fn([&](curl_off_t,
curl_off_t,
curl_off_t,
curl_off_t ulnow) -> bool {
if (ulnow > uploaded) {
bytes_transferred_ += ulnow - uploaded;
uploaded = ulnow;
}
return *cancel;
});
// disable the Expect header as the server isn't expecting it (perhaps
// it should?). If the server isn't then libcurl waits for 1 second
// before sending the data anyway. So sending this header eliminated
// the 1 second delay.
upload->set_header("Expect", "");
upload->Post(options_.payload->c_str(), options_.payload->size());
upload->Reset();
}
});
}
for (std::thread &thread : threads) {
if (thread.joinable()) {
thread.join();
}
}
end_time_ = SystemTimeMicros();
return GetResult(Status::OK);
}
Upload::Result Upload::GetResult(Status status) const {
Upload::Result result;
result.start_time = start_time_;
result.end_time = end_time_;
result.status = status;
result.bytes_transferred = bytes_transferred_;
return result;
}
} // namespace