diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/curlOp.cpp | 41 | ||||
-rw-r--r-- | src/curlOp.hpp | 40 | ||||
-rw-r--r-- | src/ingestor.cpp | 21 | ||||
-rw-r--r-- | src/ingestor.hpp | 2 | ||||
-rw-r--r-- | src/sql.cpp | 4 | ||||
-rw-r--r-- | src/sql.hpp | 1 | ||||
-rw-r--r-- | src/sql/entityUpdateDetail.sql | 1 | ||||
-rw-r--r-- | src/uaLookup.cpp | 42 | ||||
-rw-r--r-- | src/uaLookup.hpp | 31 |
9 files changed, 127 insertions, 56 deletions
diff --git a/src/curlOp.cpp b/src/curlOp.cpp new file mode 100644 index 0000000..1a4ad11 --- /dev/null +++ b/src/curlOp.cpp @@ -0,0 +1,41 @@ +#include "curlOp.hpp" +#include <string_view> + +namespace WebStat { + namespace { + size_t + stringAppend(const char * ptr, size_t size, size_t nmemb, std::string * result) + { + result->append(ptr, nmemb * size); + return nmemb * size; + } + } + + CurlOperation::CurlOperation() : hnd {curl_easy_init()}, err {} + { + curl_easy_setopt(hnd.get(), CURLOPT_NOPROGRESS, 1L); + curl_easy_setopt(hnd.get(), CURLOPT_MAXREDIRS, 50L); + curl_easy_setopt(hnd.get(), CURLOPT_TCP_KEEPALIVE, 1L); + curl_easy_setopt(hnd.get(), CURLOPT_FAILONERROR, 1L); + curl_easy_setopt(hnd.get(), CURLOPT_ERRORBUFFER, err.data()); + curl_easy_setopt(hnd.get(), CURLOPT_WRITEDATA, &result); + curl_easy_setopt(hnd.get(), CURLOPT_WRITEFUNCTION, &stringAppend); + } + + void + CurlOperation::addForm(const char * name, const std::string_view data) + { + if (!mime) { + mime.reset(curl_mime_init(hnd.get())); + curl_easy_setopt(hnd.get(), CURLOPT_MIMEPOST, mime.get()); + } + auto part = curl_mime_addpart(mime.get()); + curl_mime_data(part, data.data(), data.length()); + curl_mime_name(part, name); + } + + void + CurlOperation::onError(DB::Connection *) const + { + } +} diff --git a/src/curlOp.hpp b/src/curlOp.hpp new file mode 100644 index 0000000..ce42fb4 --- /dev/null +++ b/src/curlOp.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include "util.hpp" +#include <connection_fwd.h> +#include <curl/curl.h> +#include <memory> +#include <stdexcept> +#include <string> + +namespace WebStat { + class CurlError : public std::runtime_error { + public: + explicit CurlError(CURLcode code, const char * msg) : std::runtime_error {msg}, code(code) { } + + CURLcode code; + }; + + using CurlPtr = std::unique_ptr<CURL, DeleteWith<&curl_easy_cleanup>>; + using CurlMimePtr = std::unique_ptr<curl_mime, DeleteWith<&curl_mime_free>>; + using CurlErrorBuf = std::array<char, CURL_ERROR_SIZE>; + using CurlMultiPtr = std::unique_ptr<CURLM, DeleteWith<&curl_multi_cleanup>>; + + class CurlOperation { + public: + CurlOperation(); + virtual ~CurlOperation() = default; + + SPECIAL_MEMBERS_DEFAULT_MOVE_NO_COPY(CurlOperation); + + void addForm(const char * name, std::string_view data); + + virtual void whenComplete(DB::Connection *) const = 0; + virtual void onError(DB::Connection *) const; + + CurlPtr hnd; + CurlMimePtr mime; + CurlErrorBuf err; + std::string result; + }; +} diff --git a/src/ingestor.cpp b/src/ingestor.cpp index 26bb289..c54ca53 100644 --- a/src/ingestor.cpp +++ b/src/ingestor.cpp @@ -1,5 +1,6 @@ #include "ingestor.hpp" #include "sql.hpp" +#include "uaLookup.hpp" #include "util.hpp" #include <connection.h> #include <dbTypes.h> @@ -94,7 +95,12 @@ namespace WebStat { while (auto msg = curl_multi_info_read(curl.get(), &remaining)) { if (msg->msg == CURLMSG_DONE) { if (auto operationItr = curlOperations.find(msg->easy_handle); operationItr != curlOperations.end()) { - if (msg->data.result == CURLE_OK) { } + if (msg->data.result == CURLE_OK) { + operationItr->second->whenComplete(dbpool->get().get()); + } + else { + operationItr->second->onError(dbpool->get().get()); + } curl_multi_remove_handle(curl.get(), msg->easy_handle); curlOperations.erase(operationItr); } @@ -186,7 +192,18 @@ namespace WebStat { values | std::views::take_while(&std::optional<Entity>::has_value), [this, &insert](auto && entity) { const auto & [entityId, type, value] = *entity; bindMany(insert, 0, entityId, ENTITY_TYPE_VALUES[std::to_underlying(type)], value); - insert->execute(); + if (insert->execute() > 0) { + switch (type) { + case EntityType::UserAgent: { + auto curlOp = curlGetUserAgentDetail(entityId, value, userAgentAPI.c_str()); + auto added = curlOperations.emplace(curlOp->hnd.get(), std::move(curlOp)); + curl_multi_add_handle(curl.get(), added.first->first); + break; + } + default: + break; + } + } existingEntities.emplace(std::get<0>(*entity)); }); } diff --git a/src/ingestor.hpp b/src/ingestor.hpp index b55886e..a0dd1b9 100644 --- a/src/ingestor.hpp +++ b/src/ingestor.hpp @@ -1,7 +1,7 @@ #pragma once +#include "curlOp.hpp" #include "logTypes.hpp" -#include "uaLookup.hpp" #include <c++11Helpers.h> #include <connectionPool.h> #include <connection_fwd.h> diff --git a/src/sql.cpp b/src/sql.cpp index fbfadd3..9c0d992 100644 --- a/src/sql.cpp +++ b/src/sql.cpp @@ -12,6 +12,9 @@ namespace WebStat::SQL { const std::string ENTITY_INSERT { #embed "sql/entityInsert.sql" }; + const std::string ENTITY_UPDATE_DETAIL { +#embed "sql/entityUpdateDetail.sql" + }; const std::string HOST_UPSERT { #embed "sql/hostUpsert.sql" }; @@ -19,6 +22,7 @@ namespace WebStat::SQL { const DB::CommandOptionsPtr VAR##_OPTS = std::make_shared<DB::CommandOptions>(std::hash<std::string> {}(VAR)) HASH_OPTS(ACCESS_LOG_INSERT); HASH_OPTS(ENTITY_INSERT); + HASH_OPTS(ENTITY_UPDATE_DETAIL); HASH_OPTS(HOST_UPSERT); #undef HASH_OPTS } diff --git a/src/sql.hpp b/src/sql.hpp index 8183513..f0dfb05 100644 --- a/src/sql.hpp +++ b/src/sql.hpp @@ -10,6 +10,7 @@ namespace WebStat::SQL { EMBED_DECLARE(ACCESS_LOG_INSERT); EMBED_DECLARE(ENTITY_INSERT); + EMBED_DECLARE(ENTITY_UPDATE_DETAIL); EMBED_DECLARE(HOST_UPSERT); #undef EMBED_DECLARE } diff --git a/src/sql/entityUpdateDetail.sql b/src/sql/entityUpdateDetail.sql new file mode 100644 index 0000000..9e5ea82 --- /dev/null +++ b/src/sql/entityUpdateDetail.sql @@ -0,0 +1 @@ +UPDATE entities SET detail = $2 WHERE id = $1 diff --git a/src/uaLookup.cpp b/src/uaLookup.cpp index 5b31065..dbef015 100644 --- a/src/uaLookup.cpp +++ b/src/uaLookup.cpp @@ -1,44 +1,24 @@ #include "uaLookup.hpp" -#include <memory> -#include <string_view> +#include "sql.hpp" +#include <connection.h> +#include <dbTypes.h> +#include <modifycommand.h> namespace WebStat { - namespace { - size_t - stringAppend(const char * ptr, size_t size, size_t nmemb, std::string * result) - { - result->append(ptr, nmemb * size); - return nmemb * size; - } - } - - CurlOperation::CurlOperation() : hnd {curl_easy_init()}, err {} - { - curl_easy_setopt(hnd.get(), CURLOPT_NOPROGRESS, 1L); - curl_easy_setopt(hnd.get(), CURLOPT_MAXREDIRS, 50L); - curl_easy_setopt(hnd.get(), CURLOPT_TCP_KEEPALIVE, 1L); - curl_easy_setopt(hnd.get(), CURLOPT_FAILONERROR, 1L); - curl_easy_setopt(hnd.get(), CURLOPT_ERRORBUFFER, err.data()); - curl_easy_setopt(hnd.get(), CURLOPT_WRITEDATA, &result); - curl_easy_setopt(hnd.get(), CURLOPT_WRITEFUNCTION, &stringAppend); - } + UserAgentLookupOperation::UserAgentLookupOperation(Crc32Value entityId) : entityId {entityId} { } void - CurlOperation::addForm(const char * name, const std::string_view data) + UserAgentLookupOperation::whenComplete(DB::Connection * dbconn) const { - if (!mime) { - mime.reset(curl_mime_init(hnd.get())); - curl_easy_setopt(hnd.get(), CURLOPT_MIMEPOST, mime.get()); - } - auto part = curl_mime_addpart(mime.get()); - curl_mime_data(part, data.data(), data.length()); - curl_mime_name(part, name); + auto upd = dbconn->modify(SQL::ENTITY_UPDATE_DETAIL, SQL::ENTITY_UPDATE_DETAIL_OPTS); + bindMany(upd, 0, entityId, result); + upd->execute(); } std::unique_ptr<CurlOperation> - curlGetUserAgentDetail(const std::string_view uas, const char * baseUrl) + curlGetUserAgentDetail(Crc32Value entityId, const std::string_view uas, const char * baseUrl) { - auto request = std::make_unique<CurlOperation>(); + auto request = std::make_unique<UserAgentLookupOperation>(entityId); curl_easy_setopt(request->hnd.get(), CURLOPT_URL, baseUrl); curl_easy_setopt( diff --git a/src/uaLookup.hpp b/src/uaLookup.hpp index 5529a40..9714253 100644 --- a/src/uaLookup.hpp +++ b/src/uaLookup.hpp @@ -1,34 +1,21 @@ #pragma once -#include "util.hpp" +#include "curlOp.hpp" +#include "logTypes.hpp" +#include <connection_fwd.h> #include <curl/curl.h> #include <memory> -#include <stdexcept> -#include <string> namespace WebStat { - class CurlError : public std::runtime_error { + class UserAgentLookupOperation : public CurlOperation { public: - explicit CurlError(CURLcode code, const char * msg) : std::runtime_error {msg}, code(code) { } + UserAgentLookupOperation(Crc32Value entityId); - CURLcode code; - }; - - using CurlPtr = std::unique_ptr<CURL, DeleteWith<&curl_easy_cleanup>>; - using CurlMimePtr = std::unique_ptr<curl_mime, DeleteWith<&curl_mime_free>>; - using CurlErrorBuf = std::array<char, CURL_ERROR_SIZE>; - using CurlMultiPtr = std::unique_ptr<CURLM, DeleteWith<&curl_multi_cleanup>>; - - class CurlOperation { - public: - CurlOperation(); - void addForm(const char * name, std::string_view data); + void whenComplete(DB::Connection *) const override; - CurlPtr hnd; - CurlMimePtr mime; - CurlErrorBuf err; - std::string result; + Crc32Value entityId; }; - std::unique_ptr<CurlOperation> curlGetUserAgentDetail(std::string_view uas, const char * baseUrl); + std::unique_ptr<CurlOperation> curlGetUserAgentDetail( + Crc32Value entityId, std::string_view uas, const char * baseUrl); } |