diff --git a/include/core_api_utils.h b/include/core_api_utils.h index 067c5ace..b571bdd4 100644 --- a/include/core_api_utils.h +++ b/include/core_api_utils.h @@ -3,21 +3,22 @@ #include #include #include "collection.h" +#include "http_data.h" -struct deletion_state_t { +struct deletion_state_t: public req_state_t { Collection* collection; std::vector> index_ids; // ids_len -> ids std::vector 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> index_ids; std::vector 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; } diff --git a/include/http_data.h b/include/http_data.h index 3b6c08cc..9c4228d2 100644 --- a/include/http_data.h +++ b/include/http_data.h @@ -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() { diff --git a/src/core_api.cpp b/src/core_api.cpp index 4baf0edd..47dd6c68 100644 --- a/src/core_api.cpp +++ b/src/core_api.cpp @@ -592,6 +592,9 @@ bool get_export_documents(const std::shared_ptr& 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& 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& req, const std::share export_state->collection = collection.get(); } } else { - export_state = static_cast(req->data); + export_state = dynamic_cast(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& 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& 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& 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& 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& req, const std::share } deletion_state->collection = collection.get(); deletion_state->num_removed = 0; - req->data = deletion_state; } else { - deletion_state = static_cast(req->data); + deletion_state = dynamic_cast(req->data); } bool done = true; @@ -1077,10 +1074,8 @@ bool del_remove_documents(const std::shared_ptr& 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; } } diff --git a/src/http_client.cpp b/src/http_client.cpp index 04153b60..afc99e60 100644 --- a/src/http_client.cpp +++ b/src/http_client.cpp @@ -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& 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(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());