datastore.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2007 - 2008, Digium, Inc.
  5. *
  6. * See http://www.asterisk.org for more information about
  7. * the Asterisk project. Please do not directly contact
  8. * any of the maintainers of this project for assistance;
  9. * the project provides a web site, mailing lists and IRC
  10. * channels for your use.
  11. *
  12. * This program is free software, distributed under the terms of
  13. * the GNU General Public License Version 2. See the LICENSE file
  14. * at the top of the source tree.
  15. */
  16. /*! \file
  17. *
  18. * \brief Asterisk datastore objects
  19. */
  20. /*** MODULEINFO
  21. <support_level>core</support_level>
  22. ***/
  23. #include "asterisk.h"
  24. #include "asterisk/_private.h"
  25. #include "asterisk/datastore.h"
  26. #include "asterisk/utils.h"
  27. #include "asterisk/astobj2.h"
  28. #include "asterisk/uuid.h"
  29. #include "asterisk/module.h"
  30. /*! \brief Number of buckets for datastore container */
  31. #define DATASTORE_BUCKETS 53
  32. struct ast_datastore *__ast_datastore_alloc(
  33. const struct ast_datastore_info *info, const char *uid, struct ast_module *mod,
  34. const char *file, int line, const char *function)
  35. {
  36. struct ast_datastore *datastore = NULL;
  37. /* Make sure we at least have type so we can identify this */
  38. if (!info) {
  39. return NULL;
  40. }
  41. datastore = __ast_calloc(1, sizeof(*datastore), file, line, function);
  42. if (!datastore) {
  43. return NULL;
  44. }
  45. datastore->info = info;
  46. datastore->mod = mod;
  47. if (!ast_strlen_zero(uid) && !(datastore->uid = ast_strdup(uid))) {
  48. ast_free(datastore);
  49. datastore = NULL;
  50. }
  51. ast_module_ref(mod);
  52. return datastore;
  53. }
  54. int ast_datastore_free(struct ast_datastore *datastore)
  55. {
  56. int res = 0;
  57. if (!datastore) {
  58. return 0;
  59. }
  60. /* Using the destroy function (if present) destroy the data */
  61. if (datastore->info->destroy != NULL && datastore->data != NULL) {
  62. datastore->info->destroy(datastore->data);
  63. datastore->data = NULL;
  64. }
  65. /* Free allocated UID memory */
  66. if (datastore->uid != NULL) {
  67. ast_free((void *) datastore->uid);
  68. datastore->uid = NULL;
  69. }
  70. ast_module_unref(datastore->mod);
  71. /* Finally free memory used by ourselves */
  72. ast_free(datastore);
  73. return res;
  74. }
  75. AO2_STRING_FIELD_HASH_FN(ast_datastore, uid);
  76. AO2_STRING_FIELD_CMP_FN(ast_datastore, uid);
  77. struct ao2_container *ast_datastores_alloc(void)
  78. {
  79. return ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0,
  80. DATASTORE_BUCKETS, ast_datastore_hash_fn, NULL, ast_datastore_cmp_fn);
  81. }
  82. int ast_datastores_add(struct ao2_container *datastores, struct ast_datastore *datastore)
  83. {
  84. ast_assert(datastore != NULL);
  85. ast_assert(datastore->info != NULL);
  86. ast_assert(!ast_strlen_zero(datastore->uid));
  87. if (!ao2_link(datastores, datastore)) {
  88. return -1;
  89. }
  90. return 0;
  91. }
  92. void ast_datastores_remove(struct ao2_container *datastores, const char *name)
  93. {
  94. ao2_find(datastores, name, OBJ_SEARCH_KEY | OBJ_UNLINK | OBJ_NODATA);
  95. }
  96. struct ast_datastore *ast_datastores_find(struct ao2_container *datastores, const char *name)
  97. {
  98. return ao2_find(datastores, name, OBJ_SEARCH_KEY);
  99. }
  100. static void datastore_destroy(void *obj)
  101. {
  102. struct ast_datastore *datastore = obj;
  103. /* Using the destroy function (if present) destroy the data */
  104. if (datastore->info->destroy != NULL && datastore->data != NULL) {
  105. datastore->info->destroy(datastore->data);
  106. datastore->data = NULL;
  107. }
  108. ast_free((void *) datastore->uid);
  109. datastore->uid = NULL;
  110. }
  111. struct ast_datastore *ast_datastores_alloc_datastore(const struct ast_datastore_info *info, const char *uid)
  112. {
  113. struct ast_datastore *datastore;
  114. char uuid_buf[AST_UUID_STR_LEN];
  115. const char *uid_ptr = uid;
  116. if (!info) {
  117. return NULL;
  118. }
  119. datastore = ao2_alloc(sizeof(*datastore), datastore_destroy);
  120. if (!datastore) {
  121. return NULL;
  122. }
  123. datastore->info = info;
  124. if (ast_strlen_zero(uid)) {
  125. /* They didn't provide an ID so we'll provide one ourself */
  126. uid_ptr = ast_uuid_generate_str(uuid_buf, sizeof(uuid_buf));
  127. }
  128. datastore->uid = ast_strdup(uid_ptr);
  129. if (!datastore->uid) {
  130. ao2_ref(datastore, -1);
  131. return NULL;
  132. }
  133. return datastore;
  134. }