mirror of
https://github.com/WCBROW01/zblock.git
synced 2025-12-12 04:28:07 -05:00
Abstract out the last remaining SQL queries in timer_retrieve_feeds()
This commit is contained in:
65
feed_info.c
65
feed_info.c
@ -23,10 +23,24 @@ static const char *ZBLOCK_FEED_INFO_ERRORS[] = {
|
|||||||
"Invalid arguments provided",
|
"Invalid arguments provided",
|
||||||
"An error was encountered with the feed database",
|
"An error was encountered with the feed database",
|
||||||
"The feed already exists",
|
"The feed already exists",
|
||||||
"The feed does not exist"
|
"The feed does not exist",
|
||||||
|
"Finished getting feed info",
|
||||||
|
"Out of memory"
|
||||||
};
|
};
|
||||||
static_assert(sizeof(ZBLOCK_FEED_INFO_ERRORS) / sizeof(*ZBLOCK_FEED_INFO_ERRORS) == ZBLOCK_FEED_INFO_ERRORCOUNT, "Not all feed info errors implemented");
|
static_assert(sizeof(ZBLOCK_FEED_INFO_ERRORS) / sizeof(*ZBLOCK_FEED_INFO_ERRORS) == ZBLOCK_FEED_INFO_ERRORCOUNT, "Not all feed info errors implemented");
|
||||||
|
|
||||||
|
// free all information associated with a minimal feed info struct (does not assume the struct was allocated using malloc)
|
||||||
|
void zblock_feed_info_minimal_free(zblock_feed_info_minimal *feed_info) {
|
||||||
|
free(feed_info->last_pubDate);
|
||||||
|
free(feed_info->url);
|
||||||
|
}
|
||||||
|
|
||||||
|
// free all information associated with a feed info struct (does not assume the struct was allocated using malloc)
|
||||||
|
void zblock_feed_info_free(zblock_feed_info *feed_info) {
|
||||||
|
free(feed_info->title);
|
||||||
|
zblock_feed_info_minimal_free((zblock_feed_info_minimal *) feed_info);
|
||||||
|
}
|
||||||
|
|
||||||
// returns a string about the result of a feed_info function
|
// returns a string about the result of a feed_info function
|
||||||
const char *zblock_feed_info_strerror(zblock_feed_info_err error) {
|
const char *zblock_feed_info_strerror(zblock_feed_info_err error) {
|
||||||
return error < 0 || error >= ZBLOCK_FEED_INFO_ERRORCOUNT ? "Unspecified error" : ZBLOCK_FEED_INFO_ERRORS[error];
|
return error < 0 || error >= ZBLOCK_FEED_INFO_ERRORCOUNT ? "Unspecified error" : ZBLOCK_FEED_INFO_ERRORS[error];
|
||||||
@ -43,6 +57,49 @@ time_t pubDate_to_time_t(char *s) {
|
|||||||
return timegm(&tm);
|
return timegm(&tm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Begin retrieval of feed info objects.
|
||||||
|
zblock_feed_info_err zblock_feed_info_retrieve_list_begin(PGconn *conn) {
|
||||||
|
if (!conn) return ZBLOCK_FEED_INFO_INVALID_ARGS;
|
||||||
|
|
||||||
|
if (!PQsendQueryParams(
|
||||||
|
conn, "SELECT url, last_pubDate, channel_id from feeds",
|
||||||
|
0, NULL, NULL, NULL, NULL, 1
|
||||||
|
)) {
|
||||||
|
return ZBLOCK_FEED_INFO_DBERROR;
|
||||||
|
}
|
||||||
|
PQsetSingleRowMode(conn);
|
||||||
|
return ZBLOCK_FEED_INFO_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve the next feed list object.
|
||||||
|
// On error, no more objects can be retrieved and the returned object is invalid.
|
||||||
|
zblock_feed_info_err zblock_feed_info_retrieve_list_item(PGconn *conn, zblock_feed_info_minimal *feed_info) {
|
||||||
|
if (!conn || !feed_info) return ZBLOCK_FEED_INFO_INVALID_ARGS;
|
||||||
|
|
||||||
|
PGresult *res = PQgetResult(conn);
|
||||||
|
if (PQresultStatus(res) != PGRES_SINGLE_TUPLE) {
|
||||||
|
if (PQresultStatus(res) != PGRES_TUPLES_OK) {
|
||||||
|
log_error("Unable to retrieve feeds: %s", PQresultErrorMessage(res));
|
||||||
|
PQclear(res);
|
||||||
|
return ZBLOCK_FEED_INFO_DBERROR;
|
||||||
|
} else {
|
||||||
|
PQclear(res);
|
||||||
|
return ZBLOCK_FEED_INFO_FINISHED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
feed_info->url = strdup(PQgetvalue(res, 0, 0));
|
||||||
|
feed_info->last_pubDate = strdup(PQgetvalue(res, 0, 1));
|
||||||
|
if (!feed_info->url || !feed_info->last_pubDate) {
|
||||||
|
PQclear(res);
|
||||||
|
return ZBLOCK_FEED_INFO_NOMEM;
|
||||||
|
}
|
||||||
|
feed_info->channel_id = be64toh(*(uint64_t *) PQgetvalue(res, 0, 2));
|
||||||
|
|
||||||
|
PQclear(res);
|
||||||
|
return ZBLOCK_FEED_INFO_OK;
|
||||||
|
}
|
||||||
|
|
||||||
// check if the feed currently exists. the result is in the exists pointer.
|
// check if the feed currently exists. the result is in the exists pointer.
|
||||||
zblock_feed_info_err zblock_feed_info_exists(PGconn *conn, const char *url, u64snowflake channel_id, int *exists) {
|
zblock_feed_info_err zblock_feed_info_exists(PGconn *conn, const char *url, u64snowflake channel_id, int *exists) {
|
||||||
if (!conn || !exists) return ZBLOCK_FEED_INFO_INVALID_ARGS;
|
if (!conn || !exists) return ZBLOCK_FEED_INFO_INVALID_ARGS;
|
||||||
@ -149,11 +206,7 @@ zblock_feed_info_err zblock_feed_info_update(PGconn *conn, zblock_feed_info_mini
|
|||||||
);
|
);
|
||||||
|
|
||||||
zblock_feed_info_err result = ZBLOCK_FEED_INFO_OK;
|
zblock_feed_info_err result = ZBLOCK_FEED_INFO_OK;
|
||||||
if (PQresultStatus(update_res) != PGRES_COMMAND_OK) {
|
if (PQresultStatus(update_res) != PGRES_COMMAND_OK) result = ZBLOCK_FEED_INFO_DBERROR;
|
||||||
log_error("Failed to update feed: %s", PQresultErrorMessage(update_res));
|
|
||||||
result = ZBLOCK_FEED_INFO_DBERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
PQclear(update_res);
|
PQclear(update_res);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
15
feed_info.h
15
feed_info.h
@ -27,15 +27,30 @@ typedef enum {
|
|||||||
ZBLOCK_FEED_INFO_DBERROR,
|
ZBLOCK_FEED_INFO_DBERROR,
|
||||||
ZBLOCK_FEED_INFO_EXISTS,
|
ZBLOCK_FEED_INFO_EXISTS,
|
||||||
ZBLOCK_FEED_INFO_NOT_EXIST,
|
ZBLOCK_FEED_INFO_NOT_EXIST,
|
||||||
|
ZBLOCK_FEED_INFO_FINISHED,
|
||||||
|
ZBLOCK_FEED_INFO_NOMEM,
|
||||||
ZBLOCK_FEED_INFO_ERRORCOUNT
|
ZBLOCK_FEED_INFO_ERRORCOUNT
|
||||||
} zblock_feed_info_err;
|
} zblock_feed_info_err;
|
||||||
|
|
||||||
|
// free all information associated with a minimal feed info struct (does not assume the struct was allocated using malloc)
|
||||||
|
void zblock_feed_info_minimal_free(zblock_feed_info_minimal *feed_info);
|
||||||
|
|
||||||
|
// free all information associated with a feed info struct (does not assume the struct was allocated using malloc)
|
||||||
|
void zblock_feed_info_free(zblock_feed_info *feed_info);
|
||||||
|
|
||||||
// maybe change the function signature so you can actually do error handling with the result?
|
// maybe change the function signature so you can actually do error handling with the result?
|
||||||
time_t pubDate_to_time_t(char *s);
|
time_t pubDate_to_time_t(char *s);
|
||||||
|
|
||||||
// returns a string about the result of a feed_info function
|
// returns a string about the result of a feed_info function
|
||||||
const char *zblock_feed_info_strerror(zblock_feed_info_err error);
|
const char *zblock_feed_info_strerror(zblock_feed_info_err error);
|
||||||
|
|
||||||
|
// Begin retrieval of feed info objects.
|
||||||
|
zblock_feed_info_err zblock_feed_info_retrieve_list_begin(PGconn *conn);
|
||||||
|
|
||||||
|
// Retrieve the next feed list object.
|
||||||
|
// On error, no more objects can be retrieved and the returned object is invalid.
|
||||||
|
zblock_feed_info_err zblock_feed_info_retrieve_list_item(PGconn *conn, zblock_feed_info_minimal *feed_info);
|
||||||
|
|
||||||
// check if the feed currently exists. the result is in the exists pointer.
|
// check if the feed currently exists. the result is in the exists pointer.
|
||||||
zblock_feed_info_err zblock_feed_info_exists(PGconn *conn, const char *url, u64snowflake channel_id, int *exists);
|
zblock_feed_info_err zblock_feed_info_exists(PGconn *conn, const char *url, u64snowflake channel_id, int *exists);
|
||||||
|
|
||||||
|
|||||||
54
main.c
54
main.c
@ -70,64 +70,40 @@ static void timer_retrieve_feeds(struct discord *client, struct discord_timer *t
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PQsendQueryParams(
|
// Begin retrieval of feed list objects.
|
||||||
database_conn, "SELECT url, last_pubDate, channel_id from feeds",
|
if (zblock_feed_info_retrieve_list_begin(database_conn)) {
|
||||||
0, NULL, NULL, NULL, NULL, 1
|
|
||||||
)) {
|
|
||||||
log_error("Unable to retrieve feed list: %s", PQerrorMessage(database_conn));
|
log_error("Unable to retrieve feed list: %s", PQerrorMessage(database_conn));
|
||||||
|
curl_multi_cleanup(multi);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PQsetSingleRowMode(database_conn);
|
|
||||||
|
|
||||||
// put running handles up here so we can start transfers now instead of later
|
// put running handles up here so we can start transfers now instead of later
|
||||||
int running_handles, total_feeds = 0;
|
int running_handles, total_feeds = 0;
|
||||||
// get all the required feed info to send messages
|
// get all the required feed info to send messages
|
||||||
PGresult *database_res;
|
zblock_feed_info_minimal feed_info;
|
||||||
while ((database_res = PQgetResult(database_conn))) {
|
while (!zblock_feed_info_retrieve_list_item(database_conn, &feed_info)) {
|
||||||
if (PQresultStatus(database_res) != PGRES_SINGLE_TUPLE) {
|
|
||||||
if (PQresultStatus(database_res) != PGRES_TUPLES_OK) {
|
|
||||||
log_error("Unable to retrieve feeds: %s", PQresultErrorMessage(database_res));
|
|
||||||
}
|
|
||||||
goto db_loop_end;
|
|
||||||
}
|
|
||||||
|
|
||||||
++total_feeds;
|
++total_feeds;
|
||||||
zblock_feed_buffer *feed_buffer = malloc(sizeof(*feed_buffer));
|
zblock_feed_buffer *feed_buffer = malloc(sizeof(*feed_buffer));
|
||||||
if (!feed_buffer) {
|
if (!feed_buffer) {
|
||||||
log_error("Failure allocating feed buffer: %s", strerror(errno));
|
log_error("Failure allocating feed buffer: %s", strerror(errno));
|
||||||
goto db_loop_end;
|
continue;
|
||||||
}
|
}
|
||||||
feed_buffer->info.url = strdup(PQgetvalue(database_res, 0, 0));
|
feed_buffer->info = feed_info;
|
||||||
if (!feed_buffer->info.url) {
|
|
||||||
log_error("Failure allocating feed buffer: %s", strerror(errno));
|
|
||||||
free(feed_buffer);
|
|
||||||
goto db_loop_end;
|
|
||||||
}
|
|
||||||
feed_buffer->info.last_pubDate = strdup(PQgetvalue(database_res, 0, 1));
|
|
||||||
if (!feed_buffer->info.url) {
|
|
||||||
log_error("Failure allocating feed buffer: %s", strerror(errno));
|
|
||||||
free(feed_buffer->info.url);
|
|
||||||
free(feed_buffer);
|
|
||||||
goto db_loop_end;
|
|
||||||
}
|
|
||||||
feed_buffer->info.channel_id = be64toh(*(uint64_t *) PQgetvalue(database_res, 0, 2));
|
|
||||||
feed_buffer->fp = open_memstream(&feed_buffer->buf, &feed_buffer->bufsize);
|
feed_buffer->fp = open_memstream(&feed_buffer->buf, &feed_buffer->bufsize);
|
||||||
if (!feed_buffer->fp) {
|
if (!feed_buffer->fp) {
|
||||||
log_error("Unable to retrieve feed: %s", strerror(errno));
|
log_error("Unable to retrieve feed: %s", strerror(errno));
|
||||||
free(feed_buffer->info.last_pubDate);
|
zblock_feed_info_minimal_free(&feed_buffer->info);
|
||||||
free(feed_buffer->info.url);
|
|
||||||
free(feed_buffer);
|
free(feed_buffer);
|
||||||
goto db_loop_end;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
CURL *feed_handle = curl_easy_init();
|
CURL *feed_handle = curl_easy_init();
|
||||||
if (!feed_handle) {
|
if (!feed_handle) {
|
||||||
fclose(feed_buffer->fp);
|
fclose(feed_buffer->fp);
|
||||||
free(feed_buffer->buf);
|
free(feed_buffer->buf);
|
||||||
free(feed_buffer->info.last_pubDate);
|
zblock_feed_info_minimal_free(&feed_buffer->info);
|
||||||
free(feed_buffer->info.url);
|
|
||||||
free(feed_buffer);
|
free(feed_buffer);
|
||||||
goto db_loop_end;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
curl_easy_setopt(feed_handle, CURLOPT_URL, feed_buffer->info.url);
|
curl_easy_setopt(feed_handle, CURLOPT_URL, feed_buffer->info.url);
|
||||||
@ -139,15 +115,11 @@ static void timer_retrieve_feeds(struct discord *client, struct discord_timer *t
|
|||||||
curl_easy_cleanup(feed_handle);
|
curl_easy_cleanup(feed_handle);
|
||||||
fclose(feed_buffer->fp);
|
fclose(feed_buffer->fp);
|
||||||
free(feed_buffer->buf);
|
free(feed_buffer->buf);
|
||||||
free(feed_buffer->info.last_pubDate);
|
zblock_feed_info_minimal_free(&feed_buffer->info);
|
||||||
free(feed_buffer->info.url);
|
|
||||||
free(feed_buffer);
|
free(feed_buffer);
|
||||||
goto db_loop_end;
|
continue;
|
||||||
}
|
}
|
||||||
curl_multi_perform(multi, &running_handles);
|
curl_multi_perform(multi, &running_handles);
|
||||||
|
|
||||||
db_loop_end:
|
|
||||||
PQclear(database_res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int successful_feeds = 0;
|
int successful_feeds = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user