More careful handling of custom request data destruction.

This commit is contained in:
Kishore Nallan 2022-09-06 19:16:50 +05:30
parent ea835bf17f
commit c5b55a4ca3
4 changed files with 33 additions and 20 deletions

View File

@ -3,21 +3,22 @@
#include <cstdlib>
#include <vector>
#include "collection.h"
#include "http_data.h"
struct deletion_state_t {
struct deletion_state_t: public req_state_t {
Collection* collection;
std::vector<std::pair<size_t, uint32_t*>> index_ids; // ids_len -> ids
std::vector<size_t> offsets;
size_t num_removed;
~deletion_state_t() {
~deletion_state_t() override {
for(auto& kv: index_ids) {
delete [] kv.second;
}
}
};
struct export_state_t {
struct export_state_t: public req_state_t {
Collection* collection;
std::vector<std::pair<size_t, uint32_t*>> index_ids;
std::vector<size_t> offsets;
@ -29,7 +30,7 @@ struct export_state_t {
rocksdb::Iterator* it = nullptr;
~export_state_t() {
~export_state_t() override {
for(auto& kv: index_ids) {
delete [] kv.second;
}

View File

@ -200,6 +200,11 @@ struct ip_addr_str_t {
char ip[IP_MAX_LEN];
};
struct req_state_t {
public:
virtual ~req_state_t() = default;
};
struct http_req {
static constexpr const char* AUTH_HEADER = "x-typesense-api-key";
static constexpr const char* AGENT_HEADER = "user-agent";
@ -220,7 +225,7 @@ struct http_req {
size_t body_index;
std::string metadata;
void* data;
req_state_t* data;
// for deffered processing of async handlers
h2o_custom_timer_t defer_timer;
@ -291,6 +296,9 @@ struct http_req {
<< client_ip << " " << full_url_path;
}
}
delete data;
data = nullptr;
}
void wait() {

View File

@ -592,6 +592,9 @@ bool get_export_documents(const std::shared_ptr<http_req>& req, const std::share
if(req->data == nullptr) {
export_state = new export_state_t();
// destruction of data is managed by req destructor
req->data = export_state;
std::string simple_filter_query;
if(req->params.count(FILTER_BY) != 0) {
@ -620,7 +623,6 @@ bool get_export_documents(const std::shared_ptr<http_req>& req, const std::share
req->last_chunk_aggregate = true;
res->final = true;
stream_response(req, res);
delete export_state;
return false;
}
@ -631,11 +633,9 @@ bool get_export_documents(const std::shared_ptr<http_req>& req, const std::share
export_state->collection = collection.get();
}
} else {
export_state = static_cast<export_state_t*>(req->data);
export_state = dynamic_cast<export_state_t*>(req->data);
}
req->data = export_state;
if(export_state->it != nullptr) {
rocksdb::Iterator* it = export_state->it;
@ -670,8 +670,6 @@ bool get_export_documents(const std::shared_ptr<http_req>& req, const std::share
} else {
req->last_chunk_aggregate = true;
res->final = true;
delete export_state;
req->data = nullptr;
}
}
} else {
@ -684,8 +682,6 @@ bool get_export_documents(const std::shared_ptr<http_req>& req, const std::share
} else {
req->last_chunk_aggregate = true;
res->final = true;
delete export_state;
req->data = nullptr;
}
}
@ -1038,6 +1034,9 @@ bool del_remove_documents(const std::shared_ptr<http_req>& req, const std::share
if(req->data == nullptr) {
deletion_state = new deletion_state_t{};
// destruction of data is managed by req destructor
req->data = deletion_state;
auto filter_ids_op = collection->get_filter_ids(simple_filter_query, deletion_state->index_ids);
if(!filter_ids_op.ok()) {
@ -1045,7 +1044,6 @@ bool del_remove_documents(const std::shared_ptr<http_req>& req, const std::share
req->last_chunk_aggregate = true;
res->final = true;
stream_response(req, res);
delete deletion_state;
return false;
}
@ -1054,9 +1052,8 @@ bool del_remove_documents(const std::shared_ptr<http_req>& req, const std::share
}
deletion_state->collection = collection.get();
deletion_state->num_removed = 0;
req->data = deletion_state;
} else {
deletion_state = static_cast<deletion_state_t*>(req->data);
deletion_state = dynamic_cast<deletion_state_t*>(req->data);
}
bool done = true;
@ -1077,10 +1074,8 @@ bool del_remove_documents(const std::shared_ptr<http_req>& req, const std::share
response["num_deleted"] = deletion_state->num_removed;
req->last_chunk_aggregate = true;
req->data = nullptr;
res->body = response.dump();
res->final = true;
delete deletion_state;
}
}

View File

@ -7,6 +7,14 @@
std::string HttpClient::api_key = "";
std::string HttpClient::ca_cert_path = "";
struct client_state_t: public req_state_t {
CURL* curl;
client_state_t(CURL* curl): curl(curl) {
}
};
long HttpClient::post_response(const std::string &url, const std::string &body, std::string &response,
std::map<std::string, std::string>& res_headers, long timeout_ms) {
CURL *curl = init_curl(url, response);
@ -204,7 +212,8 @@ size_t HttpClient::curl_write_async(char *buffer, size_t size, size_t nmemb, voi
// set headers if not already set
if(req_res->res->status_code == 0) {
CURL* curl = req_res->req->data;
client_state_t* client_state = dynamic_cast<client_state_t*>(req_res->req->data);
CURL* curl = client_state->curl;
long http_code = 500;
CURLcode res = curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &http_code);
if(res == CURLE_OK) {
@ -267,7 +276,7 @@ CURL *HttpClient::init_curl_async(const std::string& url, deferred_req_res_t* re
return nullptr;
}
req_res->req->data = curl;
req_res->req->data = new client_state_t(curl); // destruction of data is managed by req destructor
std::string api_key_header = std::string("x-typesense-api-key: ") + HttpClient::api_key;
chunk = curl_slist_append(chunk, api_key_header.c_str());