/src/mod/applications/mod_mongo/mod_mongo.cpp

https://github.com/tzuryby/mod_conference-admin · C++ · 225 lines · 170 code · 45 blank · 10 comment · 45 complexity · ad38bb393517cb2fac0d9a4784d6ab2d MD5 · raw file

  1. #include <switch.h>
  2. #include "mod_mongo.h"
  3. #define DELIMITER ';'
  4. #define FIND_ONE_SYNTAX "mongo_find_one ns; query; fields"
  5. #define MAPREDUCE_SYNTAX "mongo_mapreduce ns; query"
  6. static struct {
  7. mongo_connection_pool_t *conn_pool;
  8. char *map;
  9. char *reduce;
  10. char *finalize;
  11. } globals;
  12. SWITCH_STANDARD_API(mongo_mapreduce_function)
  13. {
  14. switch_status_t status = SWITCH_STATUS_SUCCESS;
  15. DBClientBase *conn = NULL;
  16. char *ns = NULL, *json_query = NULL;
  17. ns = strdup(cmd);
  18. switch_assert(ns != NULL);
  19. if ((json_query = strchr(ns, DELIMITER))) {
  20. *json_query++ = '\0';
  21. }
  22. if (!zstr(ns) && !zstr(json_query)) {
  23. try {
  24. BSONObj query = fromjson(json_query);
  25. BSONObj out;
  26. BSONObjBuilder cmd;
  27. cmd.append("mapreduce", conn->nsGetCollection(ns));
  28. if (!zstr(globals.map)) {
  29. cmd.appendCode("map", globals.map);
  30. }
  31. if (!zstr(globals.reduce)) {
  32. cmd.appendCode("reduce", globals.reduce);
  33. }
  34. if (!zstr(globals.finalize)) {
  35. cmd.appendCode("finalize", globals.finalize);
  36. }
  37. if(!query.isEmpty()) {
  38. cmd.append("query", query);
  39. }
  40. cmd.append("out", BSON("inline" << 1));
  41. conn = mongo_connection_pool_get(globals.conn_pool);
  42. if (conn) {
  43. conn->runCommand(conn->nsGetDB(ns), cmd.done(), out);
  44. mongo_connection_pool_put(globals.conn_pool, conn);
  45. stream->write_function(stream, "-OK\n%s\n", out.toString().c_str());
  46. } else {
  47. stream->write_function(stream, "-ERR\nNo connection\n");
  48. }
  49. } catch (DBException &e) {
  50. if (conn) {
  51. mongo_connection_destroy(&conn);
  52. }
  53. stream->write_function(stream, "-ERR\n%s\n", e.toString().c_str());
  54. }
  55. } else {
  56. stream->write_function(stream, "-ERR\n%s\n", MAPREDUCE_SYNTAX);
  57. }
  58. switch_safe_free(ns);
  59. return status;
  60. }
  61. SWITCH_STANDARD_API(mongo_find_one_function)
  62. {
  63. switch_status_t status = SWITCH_STATUS_SUCCESS;
  64. char *ns = NULL, *json_query = NULL, *json_fields = NULL;
  65. ns = strdup(cmd);
  66. switch_assert(ns != NULL);
  67. if ((json_query = strchr(ns, DELIMITER))) {
  68. *json_query++ = '\0';
  69. if ((json_fields = strchr(json_query, DELIMITER))) {
  70. *json_fields++ = '\0';
  71. }
  72. }
  73. if (!zstr(ns) && !zstr(json_query) && !zstr(json_fields)) {
  74. DBClientBase *conn = NULL;
  75. try {
  76. BSONObj query = fromjson(json_query);
  77. BSONObj fields = fromjson(json_fields);
  78. conn = mongo_connection_pool_get(globals.conn_pool);
  79. if (conn) {
  80. BSONObj res = conn->findOne(ns, Query(query), &fields);
  81. mongo_connection_pool_put(globals.conn_pool, conn);
  82. stream->write_function(stream, "-OK\n%s\n", res.toString().c_str());
  83. } else {
  84. stream->write_function(stream, "-ERR\nNo connection\n");
  85. }
  86. } catch (DBException &e) {
  87. if (conn) {
  88. mongo_connection_destroy(&conn);
  89. }
  90. stream->write_function(stream, "-ERR\n%s\n", e.toString().c_str());
  91. }
  92. } else {
  93. stream->write_function(stream, "-ERR\n%s\n", FIND_ONE_SYNTAX);
  94. }
  95. switch_safe_free(ns);
  96. return status;
  97. }
  98. static switch_status_t config(void)
  99. {
  100. const char *cf = "mongo.conf";
  101. switch_xml_t cfg, xml, settings, param;
  102. switch_status_t status = SWITCH_STATUS_SUCCESS;
  103. const char *conn_str = "127.0.0.1";
  104. switch_size_t min_connections = 1, max_connections = 1;
  105. if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
  106. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", cf);
  107. return SWITCH_STATUS_GENERR;
  108. }
  109. if ((settings = switch_xml_child(cfg, "settings"))) {
  110. for (param = switch_xml_child(settings, "param"); param; param = param->next) {
  111. char *var = (char *) switch_xml_attr_soft(param, "name");
  112. char *val = (char *) switch_xml_attr_soft(param, "value");
  113. int tmp;
  114. if (!strcmp(var, "host")) {
  115. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "'host' is deprecated. use 'connection-string'\n");
  116. conn_str = val;
  117. } else if (!strcmp(var, "connection-string")) {
  118. conn_str = val;
  119. } else if (!strcmp(var, "min-connections")) {
  120. if ((tmp = atoi(val)) > 0) {
  121. min_connections = tmp;
  122. }
  123. } else if (!strcmp(var, "max-connections")) {
  124. if ((tmp = atoi(val)) > 0) {
  125. max_connections = tmp;
  126. }
  127. } else if (!strcmp(var, "map")) {
  128. globals.map = strdup(val);
  129. } else if (!strcmp(var, "reduce")) {
  130. globals.reduce = strdup(val);
  131. } else if (!strcmp(var, "finalize")) {
  132. globals.finalize = strdup(val);
  133. }
  134. }
  135. }
  136. if (mongo_connection_pool_create(&globals.conn_pool, min_connections, max_connections, conn_str) != SWITCH_STATUS_SUCCESS) {
  137. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Can't create connection pool\n");
  138. status = SWITCH_STATUS_GENERR;
  139. } else {
  140. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Mongo connection pool created [%s %d/%d]\n", conn_str, (int)min_connections, (int)max_connections);
  141. }
  142. switch_xml_free(xml);
  143. return status;
  144. }
  145. SWITCH_BEGIN_EXTERN_C
  146. SWITCH_MODULE_LOAD_FUNCTION(mod_mongo_load);
  147. SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_mongo_shutdown);
  148. SWITCH_MODULE_DEFINITION(mod_mongo, mod_mongo_load, mod_mongo_shutdown, NULL);
  149. SWITCH_MODULE_LOAD_FUNCTION(mod_mongo_load)
  150. {
  151. switch_api_interface_t *api_interface;
  152. switch_application_interface_t *app_interface;
  153. *module_interface = switch_loadable_module_create_module_interface(pool, modname);
  154. memset(&globals, 0, sizeof(globals));
  155. if (config() != SWITCH_STATUS_SUCCESS) {
  156. return SWITCH_STATUS_TERM;
  157. }
  158. SWITCH_ADD_API(api_interface, "mongo_find_one", "findOne", mongo_find_one_function, FIND_ONE_SYNTAX);
  159. SWITCH_ADD_API(api_interface, "mongo_mapreduce", "Map/Reduce", mongo_mapreduce_function, MAPREDUCE_SYNTAX);
  160. return SWITCH_STATUS_SUCCESS;
  161. }
  162. SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_mongo_shutdown)
  163. {
  164. mongo_connection_pool_destroy(&globals.conn_pool);
  165. switch_safe_free(globals.map);
  166. switch_safe_free(globals.reduce);
  167. switch_safe_free(globals.finalize);
  168. return SWITCH_STATUS_SUCCESS;
  169. }
  170. SWITCH_END_EXTERN_C
  171. /* For Emacs:
  172. * Local Variables:
  173. * mode:c
  174. * indent-tabs-mode:t
  175. * tab-width:4
  176. * c-basic-offset:4
  177. * End:
  178. * For VIM:
  179. * vim:set softtabstop=4 shiftwidth=4 tabstop=4
  180. */