stasis_cache_pattern.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2013, Digium, Inc.
  5. *
  6. * David M. Lee, II <dlee@digium.com>
  7. *
  8. * See http://www.asterisk.org for more information about
  9. * the Asterisk project. Please do not directly contact
  10. * any of the maintainers of this project for assistance;
  11. * the project provides a web site, mailing lists and IRC
  12. * channels for your use.
  13. *
  14. * This program is free software, distributed under the terms of
  15. * the GNU General Public License Version 2. See the LICENSE file
  16. * at the top of the source tree.
  17. */
  18. /*! \file
  19. *
  20. * \brief Typical cache pattern for Stasis topics.
  21. *
  22. * \author David M. Lee, II <dlee@digium.com>
  23. */
  24. /*** MODULEINFO
  25. <support_level>core</support_level>
  26. ***/
  27. #include "asterisk.h"
  28. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  29. #include "asterisk/astobj2.h"
  30. #include "asterisk/stasis_cache_pattern.h"
  31. struct stasis_cp_all {
  32. struct stasis_topic *topic;
  33. struct stasis_topic *topic_cached;
  34. struct stasis_cache *cache;
  35. struct stasis_forward *forward_all_to_cached;
  36. };
  37. struct stasis_cp_single {
  38. struct stasis_topic *topic;
  39. struct stasis_caching_topic *topic_cached;
  40. struct stasis_forward *forward_topic_to_all;
  41. struct stasis_forward *forward_cached_to_all;
  42. };
  43. static void all_dtor(void *obj)
  44. {
  45. struct stasis_cp_all *all = obj;
  46. ao2_cleanup(all->topic);
  47. all->topic = NULL;
  48. ao2_cleanup(all->topic_cached);
  49. all->topic_cached = NULL;
  50. ao2_cleanup(all->cache);
  51. all->cache = NULL;
  52. stasis_forward_cancel(all->forward_all_to_cached);
  53. all->forward_all_to_cached = NULL;
  54. }
  55. struct stasis_cp_all *stasis_cp_all_create(const char *name,
  56. snapshot_get_id id_fn)
  57. {
  58. RAII_VAR(char *, cached_name, NULL, ast_free);
  59. RAII_VAR(struct stasis_cp_all *, all, NULL, ao2_cleanup);
  60. all = ao2_alloc(sizeof(*all), all_dtor);
  61. if (!all) {
  62. return NULL;
  63. }
  64. ast_asprintf(&cached_name, "%s-cached", name);
  65. if (!cached_name) {
  66. return NULL;
  67. }
  68. all->topic = stasis_topic_create(name);
  69. all->topic_cached = stasis_topic_create(cached_name);
  70. all->cache = stasis_cache_create(id_fn);
  71. all->forward_all_to_cached =
  72. stasis_forward_all(all->topic, all->topic_cached);
  73. if (!all->topic || !all->topic_cached || !all->cache ||
  74. !all->forward_all_to_cached) {
  75. return NULL;
  76. }
  77. ao2_ref(all, +1);
  78. return all;
  79. }
  80. struct stasis_topic *stasis_cp_all_topic(struct stasis_cp_all *all)
  81. {
  82. if (!all) {
  83. return NULL;
  84. }
  85. return all->topic;
  86. }
  87. struct stasis_topic *stasis_cp_all_topic_cached(
  88. struct stasis_cp_all *all)
  89. {
  90. if (!all) {
  91. return NULL;
  92. }
  93. return all->topic_cached;
  94. }
  95. struct stasis_cache *stasis_cp_all_cache(struct stasis_cp_all *all)
  96. {
  97. if (!all) {
  98. return NULL;
  99. }
  100. return all->cache;
  101. }
  102. static void one_dtor(void *obj)
  103. {
  104. struct stasis_cp_single *one = obj;
  105. /* Should already be unsubscribed */
  106. ast_assert(one->topic_cached == NULL);
  107. ast_assert(one->forward_topic_to_all == NULL);
  108. ast_assert(one->forward_cached_to_all == NULL);
  109. ao2_cleanup(one->topic);
  110. one->topic = NULL;
  111. }
  112. struct stasis_cp_single *stasis_cp_single_create(struct stasis_cp_all *all,
  113. const char *name)
  114. {
  115. RAII_VAR(struct stasis_cp_single *, one, NULL, ao2_cleanup);
  116. one = ao2_alloc(sizeof(*one), one_dtor);
  117. if (!one) {
  118. return NULL;
  119. }
  120. one->topic = stasis_topic_create(name);
  121. if (!one->topic) {
  122. return NULL;
  123. }
  124. one->topic_cached = stasis_caching_topic_create(one->topic, all->cache);
  125. if (!one->topic_cached) {
  126. return NULL;
  127. }
  128. one->forward_topic_to_all = stasis_forward_all(one->topic, all->topic);
  129. if (!one->forward_topic_to_all) {
  130. return NULL;
  131. }
  132. one->forward_cached_to_all = stasis_forward_all(
  133. stasis_caching_get_topic(one->topic_cached), all->topic_cached);
  134. if (!one->forward_cached_to_all) {
  135. return NULL;
  136. }
  137. ao2_ref(one, +1);
  138. return one;
  139. }
  140. void stasis_cp_single_unsubscribe(struct stasis_cp_single *one)
  141. {
  142. if (!one) {
  143. return;
  144. }
  145. stasis_forward_cancel(one->forward_topic_to_all);
  146. one->forward_topic_to_all = NULL;
  147. stasis_forward_cancel(one->forward_cached_to_all);
  148. one->forward_cached_to_all = NULL;
  149. stasis_caching_unsubscribe(one->topic_cached);
  150. one->topic_cached = NULL;
  151. ao2_cleanup(one);
  152. }
  153. struct stasis_topic *stasis_cp_single_topic(struct stasis_cp_single *one)
  154. {
  155. if (!one) {
  156. return NULL;
  157. }
  158. return one->topic;
  159. }
  160. struct stasis_topic *stasis_cp_single_topic_cached(
  161. struct stasis_cp_single *one)
  162. {
  163. if (!one) {
  164. return NULL;
  165. }
  166. return stasis_caching_get_topic(one->topic_cached);
  167. }