Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions mooncake-transfer-engine/tent/include/tent/metastore/http.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,15 @@ class HttpMetaStore : public MetaStore {
}

std::string encodeUrl(const std::string &key) {
char *newkey = curl_easy_escape(client_, key.c_str(), key.size());
std::string encodedKey(newkey);
char *newkey = curl_easy_escape(nullptr, key.c_str(), key.size());
std::string encodedKey(newkey ? newkey : "");
std::string url = endpoint_ + "?key=" + encodedKey;
curl_free(newkey);
if (newkey) curl_free(newkey);
return url;
}

private:
std::atomic<bool> connected_;
CURL *client_;
std::string endpoint_;
};
} // namespace tent
Expand Down
98 changes: 60 additions & 38 deletions mooncake-transfer-engine/tent/src/metastore/http.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,17 @@
#include "tent/metastore/http.h"

#include <glog/logging.h>
#include <mutex>

namespace mooncake {
namespace tent {

static std::once_flag g_curl_global_init_flag;
static void ensureCurlGlobalInit() {
std::call_once(g_curl_global_init_flag,
[]() { curl_global_init(CURL_GLOBAL_ALL); });

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should at least report when curl_global_init fails

}

HttpMetaStore::HttpMetaStore() {}

HttpMetaStore::~HttpMetaStore() { disconnect(); }
Expand All @@ -28,42 +35,49 @@ Status HttpMetaStore::connect(const std::string &endpoint) {
return Status::MetadataError(
"HTTP connection already established" LOC_MARK);
}
curl_global_init(CURL_GLOBAL_ALL);
client_ = curl_easy_init();
if (!client_) {
return Status::InternalError(
"HTTP cannot allocate curl objects" LOC_MARK);
}
ensureCurlGlobalInit();
endpoint_ = endpoint;
connected_ = true;
return Status::OK();
}

Status HttpMetaStore::disconnect() {
if (connected_) {
curl_easy_cleanup(client_);
curl_global_cleanup();
connected_ = false;
}
connected_ = false;
return Status::OK();
}

namespace {
struct ScopedCurl {
CURL *h{nullptr};
ScopedCurl() : h(curl_easy_init()) {}
~ScopedCurl() { if (h) curl_easy_cleanup(h); }
ScopedCurl(const ScopedCurl &) = delete;
ScopedCurl &operator=(const ScopedCurl &) = delete;
operator CURL *() const { return h; }
explicit operator bool() const { return h != nullptr; }
};
} // namespace

Status HttpMetaStore::get(const std::string &key, std::string &value) {
if (!connected_) {
return Status::MetadataError("HTTP connection not available" LOC_MARK);
}

curl_easy_reset(client_);
curl_easy_setopt(client_, CURLOPT_TIMEOUT_MS, 3000); // 3s timeout
ScopedCurl client;
if (!client) {
return Status::InternalError(
"HTTP cannot allocate curl handle" LOC_MARK);
}
curl_easy_setopt(client.h, CURLOPT_TIMEOUT_MS, 3000); // 3s timeout

std::string url = encodeUrl(key);
curl_easy_setopt(client_, CURLOPT_URL, url.c_str());
curl_easy_setopt(client_, CURLOPT_WRITEFUNCTION, writeCallback);
curl_easy_setopt(client.h, CURLOPT_URL, url.c_str());
curl_easy_setopt(client.h, CURLOPT_WRITEFUNCTION, writeCallback);

// get response body
std::string readBuffer;
curl_easy_setopt(client_, CURLOPT_WRITEDATA, &readBuffer);
CURLcode res = curl_easy_perform(client_);
curl_easy_setopt(client.h, CURLOPT_WRITEDATA, &readBuffer);
CURLcode res = curl_easy_perform(client.h);
if (res != CURLE_OK) {
return Status::MetadataError(
std::string("HTTP failed to post request: ") +
Expand All @@ -72,7 +86,7 @@ Status HttpMetaStore::get(const std::string &key, std::string &value) {

// Get the HTTP response code
long responseCode;
curl_easy_getinfo(client_, CURLINFO_RESPONSE_CODE, &responseCode);
curl_easy_getinfo(client.h, CURLINFO_RESPONSE_CODE, &responseCode);
if (responseCode == 404) {
return Status::InvalidEntry(key);
} else if (responseCode != 200) {
Expand All @@ -81,7 +95,7 @@ Status HttpMetaStore::get(const std::string &key, std::string &value) {
std::string("HTTP received unexpected response: ") + message +
LOC_MARK);
}
value = std::string(readBuffer);
value = std::move(readBuffer);
return Status::OK();
}

Expand All @@ -90,25 +104,29 @@ Status HttpMetaStore::set(const std::string &key, const std::string &value) {
return Status::MetadataError("HTTP connection not available" LOC_MARK);
}

curl_easy_reset(client_);
curl_easy_setopt(client_, CURLOPT_TIMEOUT_MS, 3000); // 3s timeout
ScopedCurl client;
if (!client) {
return Status::InternalError(
"HTTP cannot allocate curl handle" LOC_MARK);
}
curl_easy_setopt(client.h, CURLOPT_TIMEOUT_MS, 3000); // 3s timeout

std::string url = encodeUrl(key);
curl_easy_setopt(client_, CURLOPT_URL, url.c_str());
curl_easy_setopt(client_, CURLOPT_WRITEFUNCTION, writeCallback);
curl_easy_setopt(client_, CURLOPT_POSTFIELDS, value.c_str());
curl_easy_setopt(client_, CURLOPT_POSTFIELDSIZE, value.size());
curl_easy_setopt(client_, CURLOPT_CUSTOMREQUEST, "PUT");
curl_easy_setopt(client.h, CURLOPT_URL, url.c_str());
curl_easy_setopt(client.h, CURLOPT_WRITEFUNCTION, writeCallback);
curl_easy_setopt(client.h, CURLOPT_POSTFIELDS, value.c_str());
curl_easy_setopt(client.h, CURLOPT_POSTFIELDSIZE, value.size());
curl_easy_setopt(client.h, CURLOPT_CUSTOMREQUEST, "PUT");

// get response body
std::string readBuffer;
curl_easy_setopt(client_, CURLOPT_WRITEDATA, &readBuffer);
curl_easy_setopt(client.h, CURLOPT_WRITEDATA, &readBuffer);

// set content-type to application/json
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(client_, CURLOPT_HTTPHEADER, headers);
CURLcode res = curl_easy_perform(client_);
curl_easy_setopt(client.h, CURLOPT_HTTPHEADER, headers);
CURLcode res = curl_easy_perform(client.h);
curl_slist_free_all(headers); // free headers
if (res != CURLE_OK) {
return Status::MetadataError(
Expand All @@ -117,7 +135,7 @@ Status HttpMetaStore::set(const std::string &key, const std::string &value) {
}

long responseCode;
curl_easy_getinfo(client_, CURLINFO_RESPONSE_CODE, &responseCode);
curl_easy_getinfo(client.h, CURLINFO_RESPONSE_CODE, &responseCode);
if (responseCode != 200) {
std::string message = std::to_string(responseCode) + ": " + readBuffer;
return Status::MetadataError(
Expand All @@ -133,26 +151,30 @@ Status HttpMetaStore::remove(const std::string &key) {
return Status::MetadataError("HTTP connection not available" LOC_MARK);
}

curl_easy_reset(client_);
curl_easy_setopt(client_, CURLOPT_TIMEOUT_MS, 3000); // 3s timeout
ScopedCurl client;
if (!client) {
return Status::InternalError(
"HTTP cannot allocate curl handle" LOC_MARK);
}
curl_easy_setopt(client.h, CURLOPT_TIMEOUT_MS, 3000); // 3s timeout

std::string url = encodeUrl(key);
curl_easy_setopt(client_, CURLOPT_URL, url.c_str());
curl_easy_setopt(client_, CURLOPT_WRITEFUNCTION, writeCallback);
curl_easy_setopt(client_, CURLOPT_CUSTOMREQUEST, "DELETE");
curl_easy_setopt(client.h, CURLOPT_URL, url.c_str());
curl_easy_setopt(client.h, CURLOPT_WRITEFUNCTION, writeCallback);
curl_easy_setopt(client.h, CURLOPT_CUSTOMREQUEST, "DELETE");

// get response body
std::string readBuffer;
curl_easy_setopt(client_, CURLOPT_WRITEDATA, &readBuffer);
CURLcode res = curl_easy_perform(client_);
curl_easy_setopt(client.h, CURLOPT_WRITEDATA, &readBuffer);
CURLcode res = curl_easy_perform(client.h);
if (res != CURLE_OK) {
return Status::MetadataError(
std::string("HTTP failed to post request: ") +
curl_easy_strerror(res) + LOC_MARK);
}

long responseCode;
curl_easy_getinfo(client_, CURLINFO_RESPONSE_CODE, &responseCode);
curl_easy_getinfo(client.h, CURLINFO_RESPONSE_CODE, &responseCode);
if (responseCode != 200) {
std::string message = std::to_string(responseCode) + ": " + readBuffer;
return Status::MetadataError(
Expand Down
25 changes: 20 additions & 5 deletions mooncake-transfer-engine/tent/src/platform/cuda/cuda_probe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,10 +262,26 @@ Status CudaPlatform::probe(std::vector<Topology::NicEntry>& nic_list,
return Status::OK();
}

namespace {
struct PaddedPointerAttributes {
cudaPointerAttributes attr;
unsigned char pad[256];

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Padding is not safe enough without attr boundary check.

};

inline cudaError_t safePointerGetAttributes(cudaPointerAttributes* out,
const void* ptr) {
PaddedPointerAttributes buf;
memset(&buf, 0, sizeof(buf));
cudaError_t rc = cudaPointerGetAttributes(&buf.attr, ptr);
memcpy(out, &buf.attr, sizeof(cudaPointerAttributes));
return rc;
}
}

MemoryType CudaPlatform::getMemoryType(void* addr) {
cudaPointerAttributes attributes;
cudaError_t result;
result = cudaPointerGetAttributes(&attributes, addr);
memset(&attributes, 0, sizeof(attributes));
cudaError_t result = safePointerGetAttributes(&attributes, addr);
if (result != cudaSuccess) {
LOG(WARNING) << "cudaPointerGetAttributes: "
<< cudaGetErrorString(result);
Expand Down Expand Up @@ -297,9 +313,8 @@ const std::vector<RangeLocation> CudaPlatform::getLocation(void* start,
std::vector<RangeLocation> entries;

cudaPointerAttributes attributes;
cudaError_t result;

result = cudaPointerGetAttributes(&attributes, start);
memset(&attributes, 0, sizeof(attributes));
cudaError_t result = safePointerGetAttributes(&attributes, start);
if (result != cudaSuccess) {
LOG(WARNING) << "cudaPointerGetAttributes: "
<< cudaGetErrorString(result);
Expand Down
Loading