flat_con.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2004 FhG FOKUS
  5. * Copyright (C) 2008 iptelorg GmbH
  6. * Written by Jan Janak <[email protected]>
  7. *
  8. * This file is part of SER, a free SIP server.
  9. *
  10. * SER is free software; you can redistribute it and/or modify it under the
  11. * terms of the GNU General Public License as published by the Free Software
  12. * Foundation; either version 2 of the License, or (at your option) any later
  13. * version.
  14. *
  15. * SER is distributed in the hope that it will be useful, but WITHOUT ANY
  16. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  17. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  18. * details.
  19. *
  20. * You should have received a copy of the GNU General Public License along
  21. * with this program; if not, write to the Free Software Foundation, Inc.,
  22. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  23. */
  24. /** \addtogroup flatstore
  25. * @{
  26. */
  27. /** \file
  28. * Inmplementation of flatstore "connections".
  29. */
  30. #include "flat_con.h"
  31. #include "flatstore_mod.h"
  32. #include "flat_uri.h"
  33. #include "../../mem/mem.h"
  34. #include "../../dprint.h"
  35. #include "../../ut.h"
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <string.h>
  39. #include <errno.h>
  40. /** Free all memory allocated for a flat_con structure.
  41. * This function function frees all memory that is in use by
  42. * a flat_con structure.
  43. * @param con A generic db_con connection structure.
  44. * @param payload Flatstore specific payload to be freed.
  45. */
  46. static void flat_con_free(db_con_t* con, struct flat_con* payload)
  47. {
  48. int i;
  49. if (!payload) return;
  50. /* delete the structure only if there are no more references
  51. * to it in the connection pool
  52. */
  53. if (db_pool_remove((db_pool_entry_t*)payload) == 0) return;
  54. db_pool_entry_free(&payload->gen);
  55. if (payload->file) {
  56. for(i = 0; i < payload->n; i++) {
  57. if (payload->file[i].filename) pkg_free(payload->file[i].filename);
  58. if (payload->file[i].table.s) pkg_free(payload->file[i].table.s);
  59. if (payload->file[i].f) fclose(payload->file[i].f);
  60. }
  61. pkg_free(payload->file);
  62. }
  63. pkg_free(payload);
  64. }
  65. int flat_con(db_con_t* con)
  66. {
  67. struct flat_con* fcon;
  68. /* First try to lookup the connection in the connection pool and
  69. * re-use it if a match is found
  70. */
  71. fcon = (struct flat_con*)db_pool_get(con->uri);
  72. if (fcon) {
  73. DBG("flatstore: A handle to %.*s found in the connection pool\n",
  74. STR_FMT(&con->uri->body));
  75. goto found;
  76. }
  77. fcon = (struct flat_con*)pkg_malloc(sizeof(struct flat_con));
  78. if (fcon == NULL) {
  79. ERR("flatstore: No memory left\n");
  80. goto error;
  81. }
  82. memset(fcon, '\0', sizeof(struct flat_con));
  83. if (db_pool_entry_init(&fcon->gen, flat_con_free, con->uri) < 0) goto error;
  84. DBG("flastore: Preparing new file handles to files in %.*s\n",
  85. STR_FMT(&con->uri->body));
  86. /* Put the newly created flatstore connection into the pool */
  87. db_pool_put((struct db_pool_entry*)fcon);
  88. DBG("flatstore: Handle stored in connection pool\n");
  89. found:
  90. /* Attach driver payload to the db_con structure and set connect and
  91. * disconnect functions
  92. */
  93. DB_SET_PAYLOAD(con, fcon);
  94. con->connect = flat_con_connect;
  95. con->disconnect = flat_con_disconnect;
  96. return 0;
  97. error:
  98. if (fcon) {
  99. db_pool_entry_free(&fcon->gen);
  100. pkg_free(fcon);
  101. }
  102. return -1;
  103. }
  104. int flat_con_connect(db_con_t* con)
  105. {
  106. struct flat_con* fcon;
  107. int i;
  108. fcon = DB_GET_PAYLOAD(con);
  109. /* Do not reconnect already connected connections */
  110. if (fcon->flags & FLAT_OPENED) return 0;
  111. DBG("flatstore: Opening handles to files in '%.*s'\n",
  112. STR_FMT(&con->uri->body));
  113. /* FIXME: Make sure the directory exists, is accessible,
  114. * and we can create files there
  115. */
  116. DBG("flatstore: Directory '%.*s' opened successfully\n",
  117. STR_FMT(&con->uri->body));
  118. for(i = 0; i < fcon->n; i++) {
  119. if (fcon->file[i].f) {
  120. fclose(fcon->file[i].f);
  121. }
  122. fcon->file[i].f = fopen(fcon->file[i].filename, "a");
  123. if (fcon->file[i].f == NULL) {
  124. ERR("flatstore: Error while opening file handle to '%s': %s\n",
  125. fcon->file[i].filename, strerror(errno));
  126. return -1;
  127. }
  128. }
  129. fcon->flags |= FLAT_OPENED;
  130. return 0;
  131. }
  132. void flat_con_disconnect(db_con_t* con)
  133. {
  134. struct flat_con* fcon;
  135. int i;
  136. fcon = DB_GET_PAYLOAD(con);
  137. if ((fcon->flags & FLAT_OPENED) == 0) return;
  138. DBG("flatstore: Closing handles to files in '%.*s'\n",
  139. STR_FMT(&con->uri->body));
  140. for(i = 0; i < fcon->n; i++) {
  141. if (fcon->file[i].f == NULL) continue;
  142. fclose(fcon->file[i].f);
  143. fcon->file[i].f = NULL;
  144. }
  145. fcon->flags &= ~FLAT_OPENED;
  146. }
  147. /* returns a pkg_malloc'ed file name */
  148. static char* get_filename(str* dir, str* name)
  149. {
  150. char* buf, *p;
  151. int buf_len, total_len;
  152. buf_len = pathmax();
  153. total_len = dir->len + 1 /* / */ +
  154. name->len + 1 /* _ */+
  155. flat_pid.len +
  156. flat_suffix.len + 1 /* \0 */;
  157. if (buf_len < total_len) {
  158. ERR("flatstore: The path is too long (%d and PATHMAX is %d)\n",
  159. total_len, buf_len);
  160. return 0;
  161. }
  162. if ((buf = pkg_malloc(buf_len)) == NULL) {
  163. ERR("flatstore: No memory left\n");
  164. return 0;
  165. }
  166. p = buf;
  167. memcpy(p, dir->s, dir->len);
  168. p += dir->len;
  169. *p++ = '/';
  170. memcpy(p, name->s, name->len);
  171. p += name->len;
  172. *p++ = '_';
  173. memcpy(p, flat_pid.s, flat_pid.len);
  174. p += flat_pid.len;
  175. memcpy(p, flat_suffix.s, flat_suffix.len);
  176. p += flat_suffix.len;
  177. *p = '\0';
  178. return buf;
  179. }
  180. int flat_open_table(int* idx, db_con_t* con, str* name)
  181. {
  182. struct flat_uri* furi;
  183. struct flat_con* fcon;
  184. struct flat_file* new;
  185. int i;
  186. char* filename, *table;
  187. new = NULL;
  188. filename = NULL;
  189. table = NULL;
  190. fcon = DB_GET_PAYLOAD(con);
  191. furi = DB_GET_PAYLOAD(con->uri);
  192. for(i = 0; i < fcon->n; i++) {
  193. if (name->len == fcon->file[i].table.len &&
  194. !strncmp(name->s, fcon->file[i].table.s, name->len))
  195. break;
  196. }
  197. if (fcon->n == i) {
  198. /* Perform operations that can fail first (before resizing
  199. * fcon->file, so that we can fail gracefully if one of the
  200. * operations fail.
  201. */
  202. if ((filename = get_filename(&furi->path, name)) == NULL)
  203. goto no_mem;
  204. if ((table = pkg_malloc(name->len)) == NULL) goto no_mem;
  205. memcpy(table, name->s, name->len);
  206. new = pkg_realloc(fcon->file, sizeof(struct flat_file) * (fcon->n + 1));
  207. if (new == NULL) goto no_mem;
  208. fcon->file = new;
  209. new = new + fcon->n; /* Advance to the new (last) element */
  210. fcon->n++;
  211. new->table.s = table;
  212. new->table.len = name->len;
  213. new->filename = filename;
  214. /* Also open the file if we are connected already */
  215. if (fcon->flags & FLAT_OPENED) {
  216. if ((new->f = fopen(new->filename, "a")) == NULL) {
  217. ERR("flatstore: Error while opening file handle to '%s': %s\n",
  218. new->filename, strerror(errno));
  219. return -1;
  220. }
  221. } else {
  222. new->f = NULL;
  223. }
  224. *idx = fcon->n - 1;
  225. } else {
  226. *idx = i;
  227. }
  228. DBG("flatstore: Handle to file '%s' opened successfully\n",
  229. fcon->file[*idx].filename);
  230. return 0;
  231. no_mem:
  232. ERR("flatstore: No memory left\n");
  233. if (filename) pkg_free(filename);
  234. if (table) pkg_free(table);
  235. return -1;
  236. }
  237. /** @} */