aboutsummaryrefslogtreecommitdiffstats
path: root/contrib
diff options
context:
space:
mode:
authorrobot-contrib <robot-contrib@yandex-team.com>2023-03-07 09:11:05 +0300
committerrobot-contrib <robot-contrib@yandex-team.com>2023-03-07 09:11:05 +0300
commit980f2a05eb72bde52c212d5c67f8860e45ef1b10 (patch)
treeaea8ee1e3d4e5c51e3de18069d4bc56a2021c31b /contrib
parentdb461a7619dcd5bc525a809660d32a5331638e85 (diff)
downloadydb-980f2a05eb72bde52c212d5c67f8860e45ef1b10.tar.gz
Update contrib/restricted/aws/aws-c-io to 0.13.17
Diffstat (limited to 'contrib')
-rw-r--r--contrib/restricted/aws/aws-c-io/include/aws/io/host_resolver.h49
-rw-r--r--contrib/restricted/aws/aws-c-io/source/host_resolver.c268
2 files changed, 263 insertions, 54 deletions
diff --git a/contrib/restricted/aws/aws-c-io/include/aws/io/host_resolver.h b/contrib/restricted/aws/aws-c-io/include/aws/io/host_resolver.h
index aed7430727..7733edfb87 100644
--- a/contrib/restricted/aws/aws-c-io/include/aws/io/host_resolver.h
+++ b/contrib/restricted/aws/aws-c-io/include/aws/io/host_resolver.h
@@ -76,10 +76,20 @@ struct aws_host_listener;
struct aws_host_listener_options;
+struct aws_host_resolver_purge_host_options {
+ /* the host to purge the cache for */
+ const struct aws_string *host;
+ /* Callback to invoke when the purge is complete */
+ aws_simple_completion_callback *on_host_purge_complete_callback;
+ /* user_data will be passed as it is in the callback. */
+ void *user_data;
+};
+
/** should you absolutely disdain the default implementation, feel free to implement your own. */
struct aws_host_resolver_vtable {
/** clean up everything you allocated, but not resolver itself. */
void (*destroy)(struct aws_host_resolver *resolver);
+
/** resolve the host by host_name, the user owns host_name, so it needs to be copied if you persist it,
* invoke res with the result. This function should never block. */
int (*resolve_host)(
@@ -88,12 +98,28 @@ struct aws_host_resolver_vtable {
aws_on_host_resolved_result_fn *res,
const struct aws_host_resolution_config *config,
void *user_data);
+
/** gives your implementation a hint that an address has some failed connections occuring. Do whatever you want (or
* nothing) about it.
*/
- int (*record_connection_failure)(struct aws_host_resolver *resolver, struct aws_host_address *address);
- /** wipe out anything you have cached. */
+ int (*record_connection_failure)(struct aws_host_resolver *resolver, const struct aws_host_address *address);
+
+ /**
+ * @Deprecated Use purge_cache_with_callback instead
+ * wipe out anything you have cached. */
int (*purge_cache)(struct aws_host_resolver *resolver);
+
+ /** wipe out anything you have cached. */
+ int (*purge_cache_with_callback)(
+ struct aws_host_resolver *resolver,
+ aws_simple_completion_callback *on_purge_cache_complete_callback,
+ void *user_data);
+
+ /** wipe out anything cached for a specific host */
+ int (*purge_host_cache)(
+ struct aws_host_resolver *resolver,
+ const struct aws_host_resolver_purge_host_options *options);
+
/** get number of addresses for a given host. */
size_t (*get_host_address_count)(
struct aws_host_resolver *resolver,
@@ -212,14 +238,31 @@ AWS_IO_API int aws_host_resolver_resolve_host(
*/
AWS_IO_API int aws_host_resolver_record_connection_failure(
struct aws_host_resolver *resolver,
- struct aws_host_address *address);
+ const struct aws_host_address *address);
/**
+ * @Deprecated Use purge_cache_with_callback instead
* calls purge_cache on the vtable.
*/
AWS_IO_API int aws_host_resolver_purge_cache(struct aws_host_resolver *resolver);
/**
+ * Calls aws_host_resolver_purge_cache_with_callback on the vtable which will wipe out everything host resolver has
+ * cached.
+ */
+AWS_IO_API int aws_host_resolver_purge_cache_with_callback(
+ struct aws_host_resolver *resolver,
+ aws_simple_completion_callback *on_purge_cache_complete_callback,
+ void *user_data);
+
+/**
+ * Removes the cache for a host asynchronously.
+ */
+AWS_IO_API int aws_host_resolver_purge_host_cache(
+ struct aws_host_resolver *resolver,
+ const struct aws_host_resolver_purge_host_options *options);
+
+/**
* get number of addresses for a given host.
*/
AWS_IO_API size_t aws_host_resolver_get_host_address_count(
diff --git a/contrib/restricted/aws/aws-c-io/source/host_resolver.c b/contrib/restricted/aws/aws-c-io/source/host_resolver.c
index 050f00a187..4854ab16b7 100644
--- a/contrib/restricted/aws/aws-c-io/source/host_resolver.c
+++ b/contrib/restricted/aws/aws-c-io/source/host_resolver.c
@@ -2,6 +2,7 @@
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
+#include <aws/io/event_loop.h>
#include <aws/io/host_resolver.h>
#include <aws/common/atomics.h>
@@ -11,6 +12,7 @@
#include <aws/common/lru_cache.h>
#include <aws/common/mutex.h>
#include <aws/common/string.h>
+#include <aws/common/task_scheduler.h>
#include <aws/common/thread.h>
#include <aws/io/logging.h>
@@ -22,18 +24,7 @@ const uint64_t NS_PER_SEC = 1000000000;
int aws_host_address_copy(const struct aws_host_address *from, struct aws_host_address *to) {
to->allocator = from->allocator;
to->address = aws_string_new_from_string(to->allocator, from->address);
-
- if (!to->address) {
- return AWS_OP_ERR;
- }
-
to->host = aws_string_new_from_string(to->allocator, from->host);
-
- if (!to->host) {
- aws_string_destroy((void *)to->address);
- return AWS_OP_ERR;
- }
-
to->record_type = from->record_type;
to->use_count = from->use_count;
to->connection_failure_count = from->connection_failure_count;
@@ -80,7 +71,37 @@ int aws_host_resolver_purge_cache(struct aws_host_resolver *resolver) {
return resolver->vtable->purge_cache(resolver);
}
-int aws_host_resolver_record_connection_failure(struct aws_host_resolver *resolver, struct aws_host_address *address) {
+int aws_host_resolver_purge_cache_with_callback(
+ struct aws_host_resolver *resolver,
+ aws_simple_completion_callback *on_purge_cache_complete_callback,
+ void *user_data) {
+ AWS_PRECONDITION(resolver);
+ AWS_PRECONDITION(resolver->vtable);
+
+ if (!resolver->vtable->purge_cache_with_callback) {
+ AWS_LOGF_ERROR(AWS_LS_IO_DNS, "purge_cache_with_callback function is not supported");
+ return aws_raise_error(AWS_ERROR_UNSUPPORTED_OPERATION);
+ }
+
+ return resolver->vtable->purge_cache_with_callback(resolver, on_purge_cache_complete_callback, user_data);
+}
+
+int aws_host_resolver_purge_host_cache(
+ struct aws_host_resolver *resolver,
+ const struct aws_host_resolver_purge_host_options *options) {
+ AWS_PRECONDITION(resolver);
+ AWS_PRECONDITION(resolver->vtable);
+
+ if (!resolver->vtable->purge_host_cache) {
+ AWS_LOGF_ERROR(AWS_LS_IO_DNS, "purge_host_cache function is not supported");
+ return aws_raise_error(AWS_ERROR_UNSUPPORTED_OPERATION);
+ }
+ return resolver->vtable->purge_host_cache(resolver, options);
+}
+
+int aws_host_resolver_record_connection_failure(
+ struct aws_host_resolver *resolver,
+ const struct aws_host_address *address) {
AWS_ASSERT(resolver->vtable && resolver->vtable->record_connection_failure);
return resolver->vtable->record_connection_failure(resolver, address);
}
@@ -153,6 +174,8 @@ struct default_host_resolver {
* Function to use to query current time. Overridable in construction options.
*/
aws_io_clock_fn *system_clock_fn;
+
+ struct aws_event_loop_group *event_loop_group;
};
/* Default host resolver implementation for listener. */
@@ -228,6 +251,8 @@ struct host_entry {
enum default_resolver_state state;
struct aws_array_list new_addresses;
struct aws_array_list expired_addresses;
+ aws_simple_completion_callback *on_host_purge_complete;
+ void *on_host_purge_complete_user_data;
};
/*
@@ -286,10 +311,42 @@ static void s_remove_host_listener_from_entry(
static void s_host_listener_destroy(struct host_listener *listener);
+struct host_purge_callback_options {
+ struct aws_allocator *allocator;
+ struct aws_ref_count ref_count;
+ aws_simple_completion_callback *on_purge_cache_complete_callback;
+ void *user_data;
+};
+
+static void s_host_purge_callback_options_destroy(void *user_data) {
+ struct host_purge_callback_options *options = user_data;
+ options->on_purge_cache_complete_callback(options->user_data);
+ aws_mem_release(options->allocator, options);
+}
+
+static struct host_purge_callback_options *s_host_purge_callback_options_new(
+ struct aws_allocator *allocator,
+ aws_simple_completion_callback *on_purge_cache_complete_callback,
+ void *user_data) {
+ struct host_purge_callback_options *purge_callback_options =
+ aws_mem_calloc(allocator, 1, sizeof(struct host_purge_callback_options));
+ purge_callback_options->allocator = allocator;
+ aws_ref_count_init(
+ &purge_callback_options->ref_count, purge_callback_options, s_host_purge_callback_options_destroy);
+ purge_callback_options->on_purge_cache_complete_callback = on_purge_cache_complete_callback;
+ purge_callback_options->user_data = user_data;
+ return purge_callback_options;
+}
+
+static void s_purge_cache_callback(void *user_data) {
+ struct host_purge_callback_options *purge_callback_options = user_data;
+ aws_ref_count_release(&purge_callback_options->ref_count);
+}
+
/*
* resolver lock must be held before calling this function
*/
-static void s_clear_default_resolver_entry_table(struct default_host_resolver *resolver) {
+static void s_clear_default_resolver_entry_table_synced(struct default_host_resolver *resolver) {
struct aws_hash_table *table = &resolver->host_entry_table;
for (struct aws_hash_iter iter = aws_hash_iter_begin(table); !aws_hash_iter_done(&iter);
aws_hash_iter_next(&iter)) {
@@ -300,18 +357,75 @@ static void s_clear_default_resolver_entry_table(struct default_host_resolver *r
aws_hash_table_clear(table);
}
-static int resolver_purge_cache(struct aws_host_resolver *resolver) {
+static int s_resolver_purge_cache(struct aws_host_resolver *resolver) {
struct default_host_resolver *default_host_resolver = resolver->impl;
aws_mutex_lock(&default_host_resolver->resolver_lock);
- s_clear_default_resolver_entry_table(default_host_resolver);
+ s_clear_default_resolver_entry_table_synced(default_host_resolver);
aws_mutex_unlock(&default_host_resolver->resolver_lock);
return AWS_OP_SUCCESS;
}
+static void s_purge_host_cache_callback_task(struct aws_task *task, void *arg, enum aws_task_status status) {
+ (void)status;
+ struct host_purge_callback_options *options = arg;
+ aws_mem_release(options->allocator, task);
+ aws_ref_count_release(&options->ref_count);
+}
+
+static void s_sechdule_purge_cache_callback_async(
+ struct default_host_resolver *default_host_resolver,
+ struct host_purge_callback_options *purge_callback_options) {
+
+ struct aws_task *task = aws_mem_calloc(default_host_resolver->allocator, 1, sizeof(struct aws_task));
+ aws_task_init(task, s_purge_host_cache_callback_task, purge_callback_options, "async_purge_host_callback_task");
+
+ struct aws_event_loop *loop = aws_event_loop_group_get_next_loop(default_host_resolver->event_loop_group);
+ AWS_FATAL_ASSERT(loop != NULL);
+ aws_event_loop_schedule_task_now(loop, task);
+}
+
+static int s_resolver_purge_cache_with_callback(
+ struct aws_host_resolver *resolver,
+ aws_simple_completion_callback *on_purge_cache_complete_callback,
+ void *user_data) {
+
+ if (!on_purge_cache_complete_callback) {
+ return s_resolver_purge_cache(resolver);
+ }
+
+ struct default_host_resolver *default_host_resolver = resolver->impl;
+ aws_mutex_lock(&default_host_resolver->resolver_lock);
+ struct aws_hash_table *table = &default_host_resolver->host_entry_table;
+
+ struct host_purge_callback_options *purge_callback_options = s_host_purge_callback_options_new(
+ default_host_resolver->allocator, on_purge_cache_complete_callback, user_data);
+
+ /* purge all cache */
+ for (struct aws_hash_iter iter = aws_hash_iter_begin(table); !aws_hash_iter_done(&iter);
+ aws_hash_iter_next(&iter)) {
+ struct host_entry *entry = iter.element.value;
+ /* acquire a refernce to wait for the callback to trigger */
+ aws_ref_count_acquire(&purge_callback_options->ref_count);
+ aws_mutex_lock(&entry->entry_lock);
+ entry->on_host_purge_complete = s_purge_cache_callback;
+ entry->on_host_purge_complete_user_data = purge_callback_options;
+ entry->state = DRS_SHUTTING_DOWN;
+ aws_mutex_unlock(&entry->entry_lock);
+ }
+
+ aws_hash_table_clear(table);
+ aws_mutex_unlock(&default_host_resolver->resolver_lock);
+
+ /* release the original reference async */
+ s_sechdule_purge_cache_callback_async(default_host_resolver, purge_callback_options);
+ return AWS_OP_SUCCESS;
+}
+
static void s_cleanup_default_resolver(struct aws_host_resolver *resolver) {
struct default_host_resolver *default_host_resolver = resolver->impl;
+ aws_event_loop_group_release(default_host_resolver->event_loop_group);
aws_hash_table_clean_up(&default_host_resolver->host_entry_table);
aws_hash_table_clean_up(&default_host_resolver->listener_entry_table);
@@ -337,7 +451,7 @@ static void resolver_destroy(struct aws_host_resolver *resolver) {
AWS_FATAL_ASSERT(default_host_resolver->state == DRS_ACTIVE);
- s_clear_default_resolver_entry_table(default_host_resolver);
+ s_clear_default_resolver_entry_table_synced(default_host_resolver);
default_host_resolver->state = DRS_SHUTTING_DOWN;
if (default_host_resolver->pending_host_entry_shutdown_completion_callbacks == 0) {
cleanup_resolver = true;
@@ -547,7 +661,58 @@ static inline void process_records(
}
}
-static int resolver_record_connection_failure(struct aws_host_resolver *resolver, struct aws_host_address *address) {
+static int s_resolver_purge_host_cache(
+ struct aws_host_resolver *resolver,
+ const struct aws_host_resolver_purge_host_options *options) {
+
+ AWS_PRECONDITION(resolver);
+ if (options == NULL) {
+ AWS_LOGF_ERROR(AWS_LS_IO_DNS, "Cannot purge host cache; options structure is NULL.");
+ return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
+ }
+
+ struct default_host_resolver *default_host_resolver = resolver->impl;
+ AWS_LOGF_INFO(AWS_LS_IO_DNS, "id=%p: purging record for %s", (void *)resolver, options->host->bytes);
+
+ aws_mutex_lock(&default_host_resolver->resolver_lock);
+
+ struct aws_hash_element *element = NULL;
+ aws_hash_table_find(&default_host_resolver->host_entry_table, options->host, &element);
+
+ /* Success if entry doesn't exist in cache. */
+ if (element == NULL) {
+ aws_mutex_unlock(&default_host_resolver->resolver_lock);
+ if (options->on_host_purge_complete_callback != NULL) {
+ /* Schedule completion callback asynchronouly */
+ struct host_purge_callback_options *purge_callback_options = s_host_purge_callback_options_new(
+ default_host_resolver->allocator, options->on_host_purge_complete_callback, options->user_data);
+
+ s_sechdule_purge_cache_callback_async(default_host_resolver, purge_callback_options);
+ }
+ return AWS_OP_SUCCESS;
+ }
+
+ struct host_entry *host_entry = element->value;
+ AWS_FATAL_ASSERT(host_entry);
+
+ /* Setup the on_host_purge_complete callback. */
+ aws_mutex_lock(&host_entry->entry_lock);
+ AWS_FATAL_ASSERT(!host_entry->on_host_purge_complete);
+ AWS_FATAL_ASSERT(!host_entry->on_host_purge_complete_user_data);
+ host_entry->on_host_purge_complete = options->on_host_purge_complete_callback;
+ host_entry->on_host_purge_complete_user_data = options->user_data;
+ aws_mutex_unlock(&host_entry->entry_lock);
+
+ s_shutdown_host_entry(host_entry);
+ aws_hash_table_remove_element(&default_host_resolver->host_entry_table, element);
+
+ aws_mutex_unlock(&default_host_resolver->resolver_lock);
+ return AWS_OP_SUCCESS;
+}
+
+static int resolver_record_connection_failure(
+ struct aws_host_resolver *resolver,
+ const struct aws_host_address *address) {
struct default_host_resolver *default_host_resolver = resolver->impl;
AWS_LOGF_INFO(
@@ -1211,6 +1376,10 @@ done:
aws_array_list_clean_up(&new_address_list);
aws_array_list_clean_up(&expired_address_list);
+ /* trigger the purge complete callback */
+ if (host_entry->on_host_purge_complete != NULL) {
+ host_entry->on_host_purge_complete(host_entry->on_host_purge_complete_user_data);
+ }
/* please don't fail */
aws_thread_current_at_exit(s_on_host_entry_shutdown_completion, host_entry);
}
@@ -1346,10 +1515,7 @@ static inline int create_and_init_host_entry(
new_host_entry->resolution_config = *config;
aws_condition_variable_init(&new_host_entry->entry_signal);
- if (aws_thread_init(&new_host_entry->resolver_thread, resolver->allocator)) {
- goto setup_host_entry_error;
- }
-
+ aws_thread_init(&new_host_entry->resolver_thread, resolver->allocator);
thread_init = true;
struct default_host_resolver *default_host_resolver = resolver->impl;
if (AWS_UNLIKELY(
@@ -1360,8 +1526,10 @@ static inline int create_and_init_host_entry(
struct aws_thread_options thread_options = *aws_default_thread_options();
thread_options.join_strategy = AWS_TJS_MANAGED;
thread_options.name = aws_byte_cursor_from_c_str("AwsHostResolver"); /* 15 characters is max for Linux */
-
- aws_thread_launch(&new_host_entry->resolver_thread, aws_host_resolver_thread, new_host_entry, &thread_options);
+ if (aws_thread_launch(
+ &new_host_entry->resolver_thread, aws_host_resolver_thread, new_host_entry, &thread_options)) {
+ goto setup_host_entry_error;
+ }
++default_host_resolver->pending_host_entry_shutdown_completion_callbacks;
return AWS_OP_SUCCESS;
@@ -1371,6 +1539,10 @@ setup_host_entry_error:
if (thread_init) {
aws_thread_clean_up(&new_host_entry->resolver_thread);
}
+ // If we registered a callback, clear it. So that we don’t trigger callback and return an error.
+ if (!aws_linked_list_empty(&new_host_entry->pending_resolution_callbacks)) {
+ aws_linked_list_remove(&pending_callback->node);
+ }
s_clean_up_host_entry(new_host_entry);
@@ -1446,37 +1618,31 @@ static int default_resolve_host(
/* these will all need to be copied so that we don't hold the lock during the callback. */
if (aaaa_record) {
struct aws_host_address aaaa_record_cpy;
- if (!aws_host_address_copy(aaaa_record, &aaaa_record_cpy)) {
- aws_array_list_push_back(&callback_address_list, &aaaa_record_cpy);
- AWS_LOGF_TRACE(
- AWS_LS_IO_DNS,
- "id=%p: vending address %s for host %s to caller",
- (void *)resolver,
- aaaa_record->address->bytes,
- host_entry->host_name->bytes);
- }
+ aws_host_address_copy(aaaa_record, &aaaa_record_cpy);
+ aws_array_list_push_back(&callback_address_list, &aaaa_record_cpy);
+ AWS_LOGF_TRACE(
+ AWS_LS_IO_DNS,
+ "id=%p: vending address %s for host %s to caller",
+ (void *)resolver,
+ aaaa_record->address->bytes,
+ host_entry->host_name->bytes);
}
if (a_record) {
struct aws_host_address a_record_cpy;
- if (!aws_host_address_copy(a_record, &a_record_cpy)) {
- aws_array_list_push_back(&callback_address_list, &a_record_cpy);
- AWS_LOGF_TRACE(
- AWS_LS_IO_DNS,
- "id=%p: vending address %s for host %s to caller",
- (void *)resolver,
- a_record->address->bytes,
- host_entry->host_name->bytes);
- }
+ aws_host_address_copy(a_record, &a_record_cpy);
+ aws_array_list_push_back(&callback_address_list, &a_record_cpy);
+ AWS_LOGF_TRACE(
+ AWS_LS_IO_DNS,
+ "id=%p: vending address %s for host %s to caller",
+ (void *)resolver,
+ a_record->address->bytes,
+ host_entry->host_name->bytes);
}
aws_mutex_unlock(&host_entry->entry_lock);
/* we don't want to do the callback WHILE we hold the lock someone may reentrantly call us. */
- if (aws_array_list_length(&callback_address_list)) {
- res(resolver, host_name, AWS_OP_SUCCESS, &callback_address_list, user_data);
- } else {
- res(resolver, host_name, aws_last_error(), NULL, user_data);
- result = AWS_OP_ERR;
- }
+ // TODO: Fire the callback asynchronously
+ res(resolver, host_name, AWS_OP_SUCCESS, &callback_address_list, user_data);
for (size_t i = 0; i < aws_array_list_length(&callback_address_list); ++i) {
struct aws_host_address *address_ptr = NULL;
@@ -1538,13 +1704,15 @@ static size_t default_get_host_address_count(
}
static struct aws_host_resolver_vtable s_vtable = {
- .purge_cache = resolver_purge_cache,
+ .purge_cache = s_resolver_purge_cache,
+ .purge_cache_with_callback = s_resolver_purge_cache_with_callback,
.resolve_host = default_resolve_host,
.record_connection_failure = resolver_record_connection_failure,
.get_host_address_count = default_get_host_address_count,
.add_host_listener = default_add_host_listener,
.remove_host_listener = default_remove_host_listener,
.destroy = resolver_destroy,
+ .purge_host_cache = s_resolver_purge_host_cache,
};
static void s_aws_host_resolver_destroy(struct aws_host_resolver *resolver) {
@@ -1557,9 +1725,6 @@ struct aws_host_resolver *aws_host_resolver_new_default(
const struct aws_host_resolver_default_options *options) {
AWS_FATAL_ASSERT(options != NULL);
- /* NOTE: we don't use el_group yet, but we will in the future. Also, we
- don't want host resolvers getting cleaned up after el_groups; this will force that
- in bindings, and encourage it in C land. */
AWS_ASSERT(options->el_group);
struct aws_host_resolver *resolver = NULL;
@@ -1587,6 +1752,7 @@ struct aws_host_resolver *aws_host_resolver_new_default(
resolver->allocator = allocator;
resolver->impl = default_host_resolver;
+ default_host_resolver->event_loop_group = aws_event_loop_group_acquire(options->el_group);
default_host_resolver->allocator = allocator;
default_host_resolver->pending_host_entry_shutdown_completion_callbacks = 0;
default_host_resolver->state = DRS_ACTIVE;