asterisk/main/stasis_cache_pattern.c

239 lines
4.9 KiB
C

/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2013, Digium, Inc.
*
* David M. Lee, II <dlee@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief Typical cache pattern for Stasis topics.
*
* \author David M. Lee, II <dlee@digium.com>
*/
/*** MODULEINFO
<support_level>core</support_level>
***/
#include "asterisk.h"
#include "asterisk/astobj2.h"
#include "asterisk/stasis_cache_pattern.h"
struct stasis_cp_all {
struct stasis_topic *topic;
struct stasis_topic *topic_cached;
struct stasis_cache *cache;
struct stasis_forward *forward_all_to_cached;
};
struct stasis_cp_single {
struct stasis_topic *topic;
struct stasis_caching_topic *topic_cached;
struct stasis_forward *forward_topic_to_all;
struct stasis_forward *forward_cached_to_all;
};
static void all_dtor(void *obj)
{
struct stasis_cp_all *all = obj;
ao2_cleanup(all->topic);
all->topic = NULL;
ao2_cleanup(all->topic_cached);
all->topic_cached = NULL;
ao2_cleanup(all->cache);
all->cache = NULL;
stasis_forward_cancel(all->forward_all_to_cached);
all->forward_all_to_cached = NULL;
}
struct stasis_cp_all *stasis_cp_all_create(const char *name,
snapshot_get_id id_fn)
{
char *cached_name = NULL;
struct stasis_cp_all *all;
static int cache_id;
all = ao2_t_alloc(sizeof(*all), all_dtor, name);
if (!all) {
return NULL;
}
ast_asprintf(&cached_name, "cache_pattern:%d/%s", ast_atomic_fetchadd_int(&cache_id, +1), name);
if (!cached_name) {
ao2_ref(all, -1);
return NULL;
}
all->topic = stasis_topic_create(name);
all->topic_cached = stasis_topic_create(cached_name);
ast_free(cached_name);
all->cache = stasis_cache_create(id_fn);
all->forward_all_to_cached =
stasis_forward_all(all->topic, all->topic_cached);
if (!all->topic || !all->topic_cached || !all->cache ||
!all->forward_all_to_cached) {
ao2_ref(all, -1);
return NULL;
}
return all;
}
struct stasis_topic *stasis_cp_all_topic(struct stasis_cp_all *all)
{
if (!all) {
return NULL;
}
return all->topic;
}
struct stasis_topic *stasis_cp_all_topic_cached(
struct stasis_cp_all *all)
{
if (!all) {
return NULL;
}
return all->topic_cached;
}
struct stasis_cache *stasis_cp_all_cache(struct stasis_cp_all *all)
{
if (!all) {
return NULL;
}
return all->cache;
}
static void one_dtor(void *obj)
{
struct stasis_cp_single *one = obj;
/* Should already be unsubscribed */
ast_assert(one->topic_cached == NULL);
ast_assert(one->forward_topic_to_all == NULL);
ast_assert(one->forward_cached_to_all == NULL);
ao2_cleanup(one->topic);
one->topic = NULL;
}
struct stasis_cp_single *stasis_cp_single_create(struct stasis_cp_all *all,
const char *name)
{
struct stasis_cp_single *one;
one = stasis_cp_sink_create(all, name);
if (!one) {
return NULL;
}
one->forward_topic_to_all = stasis_forward_all(one->topic, all->topic);
one->forward_cached_to_all = stasis_forward_all(
stasis_caching_get_topic(one->topic_cached), all->topic_cached);
if (!one->forward_topic_to_all || !one->forward_cached_to_all) {
ao2_ref(one, -1);
return NULL;
}
return one;
}
struct stasis_cp_single *stasis_cp_sink_create(struct stasis_cp_all *all,
const char *name)
{
struct stasis_cp_single *one;
one = ao2_t_alloc(sizeof(*one), one_dtor, name);
if (!one) {
return NULL;
}
one->topic = stasis_topic_create(name);
if (!one->topic) {
ao2_ref(one, -1);
return NULL;
}
one->topic_cached = stasis_caching_topic_create(one->topic, all->cache);
if (!one->topic_cached) {
ao2_ref(one, -1);
return NULL;
}
return one;
}
void stasis_cp_single_unsubscribe(struct stasis_cp_single *one)
{
if (!one) {
return;
}
stasis_forward_cancel(one->forward_topic_to_all);
one->forward_topic_to_all = NULL;
stasis_forward_cancel(one->forward_cached_to_all);
one->forward_cached_to_all = NULL;
stasis_caching_unsubscribe(one->topic_cached);
one->topic_cached = NULL;
ao2_cleanup(one);
}
struct stasis_topic *stasis_cp_single_topic(struct stasis_cp_single *one)
{
if (!one) {
return NULL;
}
return one->topic;
}
struct stasis_topic *stasis_cp_single_topic_cached(
struct stasis_cp_single *one)
{
if (!one) {
return NULL;
}
return stasis_caching_get_topic(one->topic_cached);
}
int stasis_cp_single_accept_message_type(struct stasis_cp_single *one,
struct stasis_message_type *type)
{
if (!one) {
return -1;
}
return stasis_caching_accept_message_type(one->topic_cached, type);
}
int stasis_cp_single_set_filter(struct stasis_cp_single *one,
enum stasis_subscription_message_filter filter)
{
if (!one) {
return -1;
}
return stasis_caching_set_filter(one->topic_cached, filter);
}