diff options
Diffstat (limited to 'fluent-bit/lib/avro/src/memoize.c')
-rw-r--r-- | fluent-bit/lib/avro/src/memoize.c | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/fluent-bit/lib/avro/src/memoize.c b/fluent-bit/lib/avro/src/memoize.c new file mode 100644 index 000000000..933fecbd0 --- /dev/null +++ b/fluent-bit/lib/avro/src/memoize.c @@ -0,0 +1,165 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include <errno.h> +#include <string.h> + +#include "avro/data.h" +#include "avro/allocation.h" +#include "avro/errors.h" +#include "avro_private.h" +#include "st.h" + + +typedef struct avro_memoize_key { + void *key1; + void *key2; +} avro_memoize_key_t; + + +static int +avro_memoize_key_cmp(avro_memoize_key_t *a, avro_memoize_key_t *b) +{ + /* + * This isn't a proper cmp operation, since it always returns 1 + * if the keys are different. But that's okay for the hash + * table implementation we're using. + */ + + return (a->key1 != b->key1) || (a->key2 != b->key2); +} + + +static int +avro_memoize_key_hash(avro_memoize_key_t *a) +{ + return ((uintptr_t) a->key1) ^ ((uintptr_t) a->key2); +} + + +static struct st_hash_type avro_memoize_hash_type = { + HASH_FUNCTION_CAST avro_memoize_key_cmp, + HASH_FUNCTION_CAST avro_memoize_key_hash +}; + + +void +avro_memoize_init(avro_memoize_t *mem) +{ + memset(mem, 0, sizeof(avro_memoize_t)); + mem->cache = st_init_table(&avro_memoize_hash_type); +} + + +static int +avro_memoize_free_key(avro_memoize_key_t *key, void *result, void *dummy) +{ + AVRO_UNUSED(result); + AVRO_UNUSED(dummy); + avro_freet(avro_memoize_key_t, key); + return ST_CONTINUE; +} + + +void +avro_memoize_done(avro_memoize_t *mem) +{ + st_foreach((st_table *) mem->cache, HASH_FUNCTION_CAST avro_memoize_free_key, 0); + st_free_table((st_table *) mem->cache); + memset(mem, 0, sizeof(avro_memoize_t)); +} + + +int +avro_memoize_get(avro_memoize_t *mem, + void *key1, void *key2, + void **result) +{ + avro_memoize_key_t key; + key.key1 = key1; + key.key2 = key2; + + union { + st_data_t data; + void *value; + } val; + + if (st_lookup((st_table *) mem->cache, (st_data_t) &key, &val.data)) { + if (result) { + *result = val.value; + } + return 1; + } else { + return 0; + } +} + + +void +avro_memoize_set(avro_memoize_t *mem, + void *key1, void *key2, + void *result) +{ + /* + * First see if there's already a cached value for this key. If + * so, we don't want to allocate a new avro_memoize_key_t + * instance. + */ + + avro_memoize_key_t key; + key.key1 = key1; + key.key2 = key2; + + union { + st_data_t data; + void *value; + } val; + + if (st_lookup((st_table *) mem->cache, (st_data_t) &key, &val.data)) { + st_insert((st_table *) mem->cache, (st_data_t) &key, (st_data_t) result); + return; + } + + /* + * If it's a new key pair, then we do need to allocate. + */ + + avro_memoize_key_t *real_key = (avro_memoize_key_t *) avro_new(avro_memoize_key_t); + real_key->key1 = key1; + real_key->key2 = key2; + + st_insert((st_table *) mem->cache, (st_data_t) real_key, (st_data_t) result); +} + + +void +avro_memoize_delete(avro_memoize_t *mem, void *key1, void *key2) +{ + avro_memoize_key_t key; + key.key1 = key1; + key.key2 = key2; + + union { + st_data_t data; + avro_memoize_key_t *key; + } real_key; + + real_key.key = &key; + if (st_delete((st_table *) mem->cache, &real_key.data, NULL)) { + avro_freet(avro_memoize_key_t, real_key.key); + } +} |